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 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1210 /* force a new aop if sizes differ */
1211 sym->usl.spillLoc->aop = NULL;
1213 sym->aop = op->aop = aop =
1214 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
1215 aop->size = getSize (sym->type);
1219 /* else must be a dummy iTemp */
1220 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1221 aop->size = getSize (sym->type);
1225 /* if the type is a bit register */
1226 if (sym->regType == REG_BIT)
1228 sym->aop = op->aop = aop = newAsmop (AOP_CRY);
1229 aop->size = sym->nRegs;//1???
1230 aop->aopu.aop_reg[0] = sym->regs[0];
1231 aop->aopu.aop_dir = sym->regs[0]->name;
1235 /* must be in a register */
1236 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1237 aop->size = sym->nRegs;
1238 for (i = 0; i < sym->nRegs; i++)
1239 aop->aopu.aop_reg[i] = sym->regs[i];
1242 /*-----------------------------------------------------------------*/
1243 /* freeAsmop - free up the asmop given to an operand */
1244 /*----------------------------------------------------------------*/
1246 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1263 /* depending on the asmop type only three cases need work
1264 AOP_R0, AOP_R1 & AOP_STK */
1272 emitcode ("pop", "ar0");
1276 bitVectUnSetBit (ic->rUsed, R0_IDX);
1284 emitcode ("pop", "ar1");
1288 bitVectUnSetBit (ic->rUsed, R1_IDX);
1294 int stk = aop->aopu.aop_stk + aop->size;
1295 bitVectUnSetBit (ic->rUsed, R0_IDX);
1296 bitVectUnSetBit (ic->rUsed, R1_IDX);
1298 getFreePtr (ic, &aop, FALSE);
1300 if (options.stack10bit)
1302 /* I'm not sure what to do here yet... */
1305 "*** Warning: probably generating bad code for "
1306 "10 bit stack mode.\n");
1311 emitcode ("mov", "a,_bp");
1312 emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1313 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1317 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1322 emitcode ("pop", "acc");
1323 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1326 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1329 freeAsmop (op, NULL, ic, TRUE);
1332 emitcode ("pop", "ar1");
1337 emitcode ("pop", "ar0");
1342 if (_G.dptr1InUse) {
1343 emitcode ("pop","dpx1");
1344 emitcode ("pop","dph1");
1345 emitcode ("pop","dpl1");
1350 emitcode ("pop","dpx");
1351 emitcode ("pop","dph");
1352 emitcode ("pop","dpl");
1358 /* all other cases just dealloc */
1364 OP_SYMBOL (op)->aop = NULL;
1365 /* if the symbol has a spill */
1367 SPIL_LOC (op)->aop = NULL;
1372 #define DEFAULT_ACC_WARNING 0
1373 static int saveAccWarn = DEFAULT_ACC_WARNING;
1376 /*-----------------------------------------------------------------*/
1377 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
1378 /* clobber the accumulator */
1379 /*-----------------------------------------------------------------*/
1381 aopGetUsesAcc (operand * oper, int offset)
1383 asmop * aop = AOP (oper);
1385 if (offset > (aop->size - 1))
1403 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1414 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1420 /* Error case --- will have been caught already */
1426 /*-------------------------------------------------------------------*/
1427 /* aopGet - for fetching value of the aop */
1429 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1430 /* in the accumulator. Set it to the name of a free register */
1431 /* if acc must be preserved; the register will be used to preserve */
1432 /* acc temporarily and to return the result byte. */
1433 /*-------------------------------------------------------------------*/
1435 aopGet (operand * oper,
1441 asmop * aop = AOP (oper);
1443 /* offset is greater than
1445 if (offset > (aop->size - 1) &&
1446 aop->type != AOP_LIT)
1449 /* depending on type */
1457 /* if we need to increment it */
1458 while (offset > aop->coff)
1460 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1464 while (offset < aop->coff)
1466 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1473 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1474 return (dname ? "acc" : "a");
1476 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1477 return Safe_strdup(buffer);
1480 assert(offset <= 3);
1481 return dptrn[aop->aopu.dptr][offset];
1486 if (aop->type == AOP_DPTR2)
1494 // if (aop->type != AOP_DPTR2)
1496 // if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1497 // emitcode(";", "spanky: saveAcc for DPTR");
1500 emitcode ("xch", "a, %s", saveAcc);
1505 while (offset > aop->coff)
1507 emitcode ("inc", "dptr");
1511 while (offset < aop->coff)
1513 emitcode ("lcall", "__decdptr");
1520 emitcode ("clr", "a");
1521 emitcode ("movc", "a,@a+dptr");
1525 emitcode ("movx", "a,@dptr");
1528 if (aop->type == AOP_DPTR2)
1536 emitcode ("xch", "a, %s", saveAcc);
1537 // if (strcmp(saveAcc, "_ap"))
1539 // emitcode(";", "spiffy: non _ap return from aopGet.");
1544 return (dname ? "acc" : "a");
1547 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1549 SNPRINTF(buffer, sizeof(buffer),
1550 "%s",aop->aopu.aop_immd.aop_immd2);
1554 SNPRINTF(buffer, sizeof(buffer),
1555 "#%s", aop->aopu.aop_immd.aop_immd1);
1561 tsprintf(buffer, sizeof(buffer),
1562 "#!his",aop->aopu.aop_immd.aop_immd1);
1565 tsprintf(buffer, sizeof(buffer),
1566 "#!hihis",aop->aopu.aop_immd.aop_immd1);
1569 tsprintf(buffer, sizeof(buffer),
1570 "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1572 default: /* should not need this (just in case) */
1573 SNPRINTF (buffer, sizeof(buffer),
1575 aop->aopu.aop_immd.aop_immd1,
1581 SNPRINTF (buffer, sizeof(buffer),
1582 "#%s", aop->aopu.aop_immd.aop_immd1);
1584 return Safe_strdup(buffer);
1587 if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1589 SNPRINTF (buffer, sizeof(buffer),
1591 aop->aopu.aop_dir, offset * 8);
1595 SNPRINTF (buffer, sizeof(buffer),
1602 SNPRINTF (buffer, sizeof(buffer),
1603 "%s", aop->aopu.aop_dir);
1606 return Safe_strdup(buffer);
1610 return aop->aopu.aop_reg[offset]->dname;
1612 return aop->aopu.aop_reg[offset]->name;
1615 emitcode ("clr", "a");
1616 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1617 emitcode ("rlc", "a");
1618 return (dname ? "acc" : "a");
1621 if (!offset && dname)
1623 return aop->aopu.aop_str[offset];
1626 return aopLiteral (aop->aopu.aop_lit, offset);
1630 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1634 return aop->aopu.aop_str[offset];
1638 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1639 "aopget got unsupported aop->type");
1642 return NULL; // not reached, but makes compiler happy.
1645 /*-----------------------------------------------------------------*/
1646 /* aopPutUsesAcc - indicates ahead of time whether aopPut() will */
1647 /* clobber the accumulator */
1648 /*-----------------------------------------------------------------*/
1650 aopPutUsesAcc (operand * oper, const char *s, int offset)
1652 asmop * aop = AOP (oper);
1654 if (offset > (aop->size - 1))
1664 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1670 return ((aop->paged) || (*s == '@'));
1674 return (!aop->aopu.aop_dir || strcmp(s, aop->aopu.aop_dir));
1682 /* Error case --- will have been caught already */
1688 /*-----------------------------------------------------------------*/
1689 /* aopPut - puts a string for a aop and indicates if acc is in use */
1690 /*-----------------------------------------------------------------*/
1692 aopPut (operand * result, const char *s, int offset)
1694 bool bvolatile = isOperandVolatile (result, FALSE);
1695 bool accuse = FALSE;
1696 asmop * aop = AOP (result);
1698 if (aop->size && offset > (aop->size - 1))
1700 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1701 "aopPut got offset > aop->size");
1705 /* will assign value to value */
1706 /* depending on where it is ofcourse */
1710 MOVA (s); /* read s in case it was volatile */
1715 if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1717 SNPRINTF (buffer, sizeof(buffer),
1719 aop->aopu.aop_dir, offset * 8);
1723 SNPRINTF (buffer, sizeof(buffer),
1725 aop->aopu.aop_dir, offset);
1729 SNPRINTF (buffer, sizeof(buffer),
1730 "%s", aop->aopu.aop_dir);
1733 if (strcmp (buffer, s) || bvolatile)
1735 emitcode ("mov", "%s,%s", buffer, s);
1737 if (!strcmp (buffer, "acc"))
1744 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1745 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1748 strcmp (s, "r0") == 0 ||
1749 strcmp (s, "r1") == 0 ||
1750 strcmp (s, "r2") == 0 ||
1751 strcmp (s, "r3") == 0 ||
1752 strcmp (s, "r4") == 0 ||
1753 strcmp (s, "r5") == 0 ||
1754 strcmp (s, "r6") == 0 ||
1755 strcmp (s, "r7") == 0)
1757 emitcode ("mov", "%s,%s",
1758 aop->aopu.aop_reg[offset]->dname, s);
1762 emitcode ("mov", "%s,%s",
1763 aop->aopu.aop_reg[offset]->name, s);
1769 emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1775 if (aop->type == AOP_DPTR2)
1783 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1784 "aopPut writing to code space");
1788 while (offset > aop->coff)
1791 emitcode ("inc", "dptr");
1794 while (offset < aop->coff)
1797 emitcode ("lcall", "__decdptr");
1802 /* if not in accumulator */
1805 emitcode ("movx", "@dptr,a");
1807 if (aop->type == AOP_DPTR2)
1815 while (offset > aop->coff)
1818 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1820 while (offset < aop->coff)
1823 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1830 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1835 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1837 else if (strcmp (s, "r0") == 0 ||
1838 strcmp (s, "r1") == 0 ||
1839 strcmp (s, "r2") == 0 ||
1840 strcmp (s, "r3") == 0 ||
1841 strcmp (s, "r4") == 0 ||
1842 strcmp (s, "r5") == 0 ||
1843 strcmp (s, "r6") == 0 ||
1844 strcmp (s, "r7") == 0)
1847 SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1848 emitcode ("mov", "@%s,%s",
1849 aop->aopu.aop_ptr->name, buffer);
1853 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1858 if (strcmp (s, "a") == 0)
1859 emitcode ("push", "acc");
1863 emitcode ("push", "acc");
1865 emitcode ("push", s);
1871 /* if not bit variable */
1872 if (!aop->aopu.aop_dir)
1874 /* inefficient: move carry into A and use jz/jnz */
1875 emitcode ("clr", "a");
1876 emitcode ("rlc", "a");
1882 emitcode ("clr", "%s", aop->aopu.aop_dir);
1884 emitcode ("setb", "%s", aop->aopu.aop_dir);
1885 else if (!strcmp (s, "c"))
1886 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1887 else if (strcmp (s, aop->aopu.aop_dir))
1890 /* set C, if a >= 1 */
1891 emitcode ("add", "a,#!constbyte",0xff);
1892 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1899 if (strcmp (aop->aopu.aop_str[offset], s) || bvolatile)
1900 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1906 if (!offset && (strcmp (s, "acc") == 0) && !bvolatile)
1909 if (strcmp (aop->aopu.aop_str[offset], s) && !bvolatile)
1910 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1914 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1915 "aopPut got unsupported aop->type");
1923 /*--------------------------------------------------------------------*/
1924 /* reAdjustPreg - points a register back to where it should (coff==0) */
1925 /*--------------------------------------------------------------------*/
1927 reAdjustPreg (asmop * aop)
1929 if ((aop->coff==0) || (aop->size <= 1))
1937 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1941 if (aop->type == AOP_DPTR2)
1948 emitcode ("lcall", "__decdptr");
1951 if (aop->type == AOP_DPTR2)
1960 /*-----------------------------------------------------------------*/
1961 /* opIsGptr: returns non-zero if the passed operand is */
1962 /* a generic pointer type. */
1963 /*-----------------------------------------------------------------*/
1965 opIsGptr (operand * op)
1967 sym_link *type = operandType (op);
1969 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1976 /*-----------------------------------------------------------------*/
1977 /* getDataSize - get the operand data size */
1978 /*-----------------------------------------------------------------*/
1980 getDataSize (operand * op)
1983 size = AOP_SIZE (op);
1984 if (size == GPTRSIZE)
1986 sym_link *type = operandType (op);
1987 if (IS_GENPTR (type))
1989 /* generic pointer; arithmetic operations
1990 * should ignore the high byte (pointer type).
1998 /*-----------------------------------------------------------------*/
1999 /* outAcc - output Acc */
2000 /*-----------------------------------------------------------------*/
2002 outAcc (operand * result)
2005 size = getDataSize (result);
2008 aopPut (result, "a", 0);
2011 /* unsigned or positive */
2014 aopPut (result, zero, offset++);
2019 /*-----------------------------------------------------------------*/
2020 /* outBitC - output a bit C */
2021 /*-----------------------------------------------------------------*/
2023 outBitC (operand * result)
2025 /* if the result is bit */
2026 if (AOP_TYPE (result) == AOP_CRY)
2028 aopPut (result, "c", 0);
2032 emitcode ("clr", "a");
2033 emitcode ("rlc", "a");
2038 /*-----------------------------------------------------------------*/
2039 /* toBoolean - emit code for orl a,operator(sizeop) */
2040 /*-----------------------------------------------------------------*/
2042 toBoolean (operand * oper)
2044 int size = AOP_SIZE (oper) - 1;
2048 /* The generic part of a generic pointer should
2049 * not participate in it's truth value.
2051 * i.e. 0x10000000 is zero.
2053 if (opIsGptr (oper))
2055 D (emitcode (";", "toBoolean: generic ptr special case."));
2059 _startLazyDPSEvaluation ();
2060 MOVA (aopGet (oper, 0, FALSE, FALSE, NULL));
2061 if (AOP_NEEDSACC (oper) && size && (AOP (oper)->type != AOP_ACC))
2064 emitcode("mov", "b,a");
2067 MOVA (aopGet (oper, offset++, FALSE, FALSE, NULL));
2068 emitcode ("orl", "b,a");
2070 MOVA (aopGet (oper, offset++, FALSE, FALSE, NULL));
2071 emitcode ("orl", "a,b");
2078 emitcode ("orl", "a,%s",
2079 aopGet (oper, offset++, FALSE, FALSE, NULL));
2082 _endLazyDPSEvaluation ();
2086 /*-----------------------------------------------------------------*/
2087 /* genNot - generate code for ! operation */
2088 /*-----------------------------------------------------------------*/
2094 D (emitcode (";", "genNot "));
2096 /* assign asmOps to operand & result */
2097 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2098 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
2100 /* if in bit space then a special case */
2101 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2103 /* if left==result then cpl bit */
2104 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2106 emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2110 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2111 emitcode ("cpl", "c");
2112 outBitC (IC_RESULT (ic));
2117 toBoolean (IC_LEFT (ic));
2119 /* set C, if a == 0 */
2120 tlbl = newiTempLabel (NULL);
2121 emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
2122 emitcode ("", "!tlabeldef", tlbl->key + 100);
2123 outBitC (IC_RESULT (ic));
2126 /* release the aops */
2127 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2128 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2132 /*-----------------------------------------------------------------*/
2133 /* genCpl - generate code for complement */
2134 /*-----------------------------------------------------------------*/
2141 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
2143 D(emitcode (";", "genCpl"));
2145 /* assign asmOps to operand & result */
2146 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2147 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
2149 /* special case if in bit space */
2150 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2154 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
2155 (SPEC_USIGN (letype) && IS_CHAR (letype)))
2157 /* promotion rules are responsible for this strange result:
2158 bit -> int -> ~int -> bit
2159 uchar -> int -> ~int -> bit
2161 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
2165 tlbl=newiTempLabel(NULL);
2166 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE, NULL);
2167 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
2168 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
2169 IS_AOP_PREG (IC_LEFT (ic)))
2171 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
2176 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
2178 emitcode ("", "%05d$:", tlbl->key + 100);
2179 outBitC (IC_RESULT(ic));
2183 size = AOP_SIZE (IC_RESULT (ic));
2184 _startLazyDPSEvaluation ();
2187 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL);
2189 emitcode ("cpl", "a");
2190 aopPut (IC_RESULT (ic), "a", offset++);
2192 _endLazyDPSEvaluation ();
2196 /* release the aops */
2197 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2198 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2201 /*-----------------------------------------------------------------*/
2202 /* genUminusFloat - unary minus for floating points */
2203 /*-----------------------------------------------------------------*/
2205 genUminusFloat (operand * op, operand * result)
2207 int size, offset = 0;
2210 D(emitcode (";", "genUminusFloat"));
2212 /* for this we just copy and then flip the bit */
2214 _startLazyDPSEvaluation ();
2215 size = AOP_SIZE (op) - 1;
2220 aopGet (op, offset, FALSE, FALSE, NULL),
2225 l = aopGet (op, offset, FALSE, FALSE, NULL);
2228 emitcode ("cpl", "acc.7");
2229 aopPut (result, "a", offset);
2230 _endLazyDPSEvaluation ();
2233 /*-----------------------------------------------------------------*/
2234 /* genUminus - unary minus code generation */
2235 /*-----------------------------------------------------------------*/
2237 genUminus (iCode * ic)
2242 D (emitcode (";", "genUminus "));
2245 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2246 aopOp (IC_RESULT (ic), ic, TRUE, (AOP_TYPE(IC_LEFT (ic)) == AOP_DPTR));
2248 /* if both in bit space then special
2250 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2251 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2254 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2255 emitcode ("cpl", "c");
2256 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2260 optype = operandType (IC_LEFT (ic));
2262 /* if float then do float stuff */
2263 if (IS_FLOAT (optype))
2265 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2269 /* otherwise subtract from zero */
2270 size = AOP_SIZE (IC_LEFT (ic));
2272 _startLazyDPSEvaluation ();
2275 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL);
2276 if (!strcmp (l, "a"))
2280 emitcode ("cpl", "a");
2281 emitcode ("addc", "a,#0");
2287 emitcode ("clr", "a");
2288 emitcode ("subb", "a,%s", l);
2290 aopPut (IC_RESULT (ic), "a", offset++);
2292 _endLazyDPSEvaluation ();
2294 /* if any remaining bytes in the result */
2295 /* we just need to propagate the sign */
2296 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))) != 0)
2298 emitcode ("rlc", "a");
2299 emitcode ("subb", "a,acc");
2301 aopPut (IC_RESULT (ic), "a", offset++);
2305 /* release the aops */
2306 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2307 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2310 /*-----------------------------------------------------------------*/
2311 /* savermask - saves registers in the mask */
2312 /*-----------------------------------------------------------------*/
2313 static void savermask(bitVect *rs_mask)
2316 if (options.useXstack)
2318 if (bitVectBitValue (rs_mask, R0_IDX))
2319 emitcode ("mov", "b,r0");
2320 emitcode ("mov", "r0,%s", spname);
2321 for (i = 0; i < ds390_nRegs; i++)
2323 if (bitVectBitValue (rs_mask, i))
2326 emitcode ("mov", "a,b");
2328 emitcode ("mov", "a,%s", REG_WITH_INDEX (i)->name);
2329 emitcode ("movx", "@r0,a");
2330 emitcode ("inc", "r0");
2333 emitcode ("mov", "%s,r0", spname);
2334 if (bitVectBitValue (rs_mask, R0_IDX))
2335 emitcode ("mov", "r0,b");
2339 bool bits_pushed = FALSE;
2340 for (i = 0; i < ds390_nRegs; i++)
2342 if (bitVectBitValue (rs_mask, i))
2344 bits_pushed = pushReg (i, bits_pushed);
2350 /*-----------------------------------------------------------------*/
2351 /* saveRegisters - will look for a call and save the registers */
2352 /*-----------------------------------------------------------------*/
2354 saveRegisters (iCode * lic)
2360 for (ic = lic; ic; ic = ic->next)
2361 if (ic->op == CALL || ic->op == PCALL)
2366 fprintf (stderr, "found parameter push with no function call\n");
2370 /* if the registers have been saved already or don't need to be then
2373 || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2376 /* special case if DPTR alive across a function call then must save it
2377 even though callee saves */
2378 if (IS_SYMOP(IC_LEFT(ic)) &&
2379 IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type))
2382 rsave = newBitVect(ic->rMask->size);
2383 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2384 if (bitVectBitValue(ic->rMask,i))
2385 rsave = bitVectSetBit(rsave,i);
2387 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2391 /* save the registers in use at this time but skip the
2392 ones for the result */
2393 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2394 ds390_rUmaskForOp (IC_RESULT(ic)));
2400 /*-----------------------------------------------------------------*/
2401 /* usavermask - restore registers with mask */
2402 /*-----------------------------------------------------------------*/
2403 static void unsavermask(bitVect *rs_mask)
2406 if (options.useXstack) {
2407 emitcode ("mov", "r0,%s", spname);
2408 for (i = ds390_nRegs; i >= 0; i--)
2410 if (bitVectBitValue (rs_mask, i))
2412 regs * reg = REG_WITH_INDEX (i);
2413 emitcode ("dec", "r0");
2414 emitcode ("movx", "a,@r0");
2417 emitcode ("push", "acc");
2421 emitcode ("mov", "%s,a", reg->name);
2425 emitcode ("mov", "%s,r0", spname);
2426 if (bitVectBitValue (rs_mask, R0_IDX))
2428 emitcode ("pop", "ar0");
2433 bool bits_popped = FALSE;
2434 for (i = ds390_nRegs; i >= 0; i--)
2436 if (bitVectBitValue (rs_mask, i))
2438 bits_popped = popReg (i, bits_popped);
2444 /*-----------------------------------------------------------------*/
2445 /* unsaveRegisters - pop the pushed registers */
2446 /*-----------------------------------------------------------------*/
2448 unsaveRegisters (iCode * ic)
2452 if (IS_SYMOP(IC_LEFT (ic)) &&
2453 IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2455 rsave = newBitVect(ic->rMask->size);
2456 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2457 if (bitVectBitValue(ic->rMask,i))
2458 rsave = bitVectSetBit(rsave,i);
2460 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2462 /* restore the registers in use at this time but skip the
2463 ones for the result */
2464 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2465 ds390_rUmaskForOp (IC_RESULT(ic)));
2471 /*-----------------------------------------------------------------*/
2473 /*-----------------------------------------------------------------*/
2475 pushSide (operand * oper, int size)
2478 _startLazyDPSEvaluation ();
2481 char *l = aopGet (oper, offset++, FALSE, TRUE, NULL);
2482 if (AOP_TYPE (oper) != AOP_REG &&
2483 AOP_TYPE (oper) != AOP_DIR &&
2487 emitcode ("push", "acc");
2491 emitcode ("push", "%s", l);
2494 _endLazyDPSEvaluation ();
2497 /*-----------------------------------------------------------------*/
2498 /* assignResultValue - also indicates if acc is in use afterwards */
2499 /*-----------------------------------------------------------------*/
2501 assignResultValue (operand * oper, operand * func)
2504 unsigned size = AOP_SIZE (oper);
2505 bool accuse = FALSE;
2506 bool pushedA = FALSE;
2508 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2514 if (size == fReturnSizeDS390)
2516 /* I don't think this case can ever happen... */
2517 /* ACC is the last part of this. If writing the result
2518 * uses ACC, we must preserve it.
2520 if (AOP_NEEDSACC(oper))
2522 emitcode(";", "assignResultValue special case for ACC.");
2523 emitcode("push", "acc");
2529 _startLazyDPSEvaluation ();
2532 accuse |= aopPut (oper, fReturn[offset], offset);
2535 _endLazyDPSEvaluation ();
2539 emitcode ("pop", "acc");
2540 accuse |= aopPut (oper, "a", offset);
2546 /*-----------------------------------------------------------------*/
2547 /* genXpush - pushes onto the external stack */
2548 /*-----------------------------------------------------------------*/
2550 genXpush (iCode * ic)
2552 asmop *aop = newAsmop (0);
2554 int size, offset = 0;
2556 D (emitcode (";", "genXpush "));
2558 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2559 r = getFreePtr (ic, &aop, FALSE);
2561 size = AOP_SIZE (IC_LEFT (ic));
2565 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
2566 emitcode ("mov", "%s,_spx", r->name);
2567 emitcode ("inc", "_spx"); // allocate space first
2568 emitcode ("movx", "@%s,a", r->name);
2572 // allocate space first
2573 emitcode ("mov", "%s,_spx", r->name);
2575 emitcode ("add", "a,#%d", size);
2576 emitcode ("mov", "_spx,a");
2578 _startLazyDPSEvaluation ();
2581 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE, NULL));
2582 emitcode ("movx", "@%s,a", r->name);
2583 emitcode ("inc", "%s", r->name);
2585 _endLazyDPSEvaluation ();
2588 freeAsmop (NULL, aop, ic, TRUE);
2589 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2592 /*-----------------------------------------------------------------*/
2593 /* genIpush - generate code for pushing this gets a little complex */
2594 /*-----------------------------------------------------------------*/
2596 genIpush (iCode * ic)
2598 int size, offset = 0;
2602 D (emitcode (";", "genIpush "));
2604 /* if this is not a parm push : ie. it is spill push
2605 and spill push is always done on the local stack */
2609 /* and the item is spilt then do nothing */
2610 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2613 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2614 size = AOP_SIZE (IC_LEFT (ic));
2615 /* push it on the stack */
2616 _startLazyDPSEvaluation ();
2619 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE, NULL);
2625 emitcode ("push", "%s", l);
2627 _endLazyDPSEvaluation ();
2631 /* this is a parameter push: in this case we call
2632 the routine to find the call and save those
2633 registers that need to be saved */
2636 /* if use external stack then call the external
2637 stack pushing routine */
2638 if (options.useXstack)
2644 /* then do the push */
2645 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2647 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2648 size = AOP_SIZE (IC_LEFT (ic));
2650 _startLazyDPSEvaluation ();
2653 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE, NULL);
2654 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2655 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2658 if (strcmp (l, prev) || *l == '@')
2660 emitcode ("push", "acc");
2664 emitcode ("push", "%s", l);
2668 _endLazyDPSEvaluation ();
2670 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2673 /*-----------------------------------------------------------------*/
2674 /* genIpop - recover the registers: can happen only for spilling */
2675 /*-----------------------------------------------------------------*/
2677 genIpop (iCode * ic)
2681 D (emitcode (";", "genIpop "));
2683 /* if the temp was not pushed then */
2684 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2687 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2688 size = AOP_SIZE (IC_LEFT (ic));
2689 offset = (size - 1);
2690 _startLazyDPSEvaluation ();
2693 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2694 FALSE, TRUE, NULL));
2696 _endLazyDPSEvaluation ();
2698 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2701 /*-----------------------------------------------------------------*/
2702 /* saveRBank - saves an entire register bank on the stack */
2703 /*-----------------------------------------------------------------*/
2705 saveRBank (int bank, iCode * ic, bool pushPsw)
2708 int count = 8 + (ds390_nBitRegs/8) + (pushPsw ? 1 : 0);
2712 if (options.useXstack)
2716 /* Assume r0 is available for use. */
2717 r = REG_WITH_INDEX (R0_IDX);;
2722 r = getFreePtr (ic, &aop, FALSE);
2724 // allocate space first
2725 emitcode ("mov", "%s,_spx", r->name);
2727 emitcode ("add", "a,#%d", count);
2728 emitcode ("mov", "_spx,a");
2731 for (i = 0; i < 8; i++) /* only R0-R7 needs saving */
2733 if (options.useXstack)
2735 emitcode ("mov", "a,(%s+%d)",
2736 regs390[i].base, 8 * bank + regs390[i].offset);
2737 emitcode ("movx", "@%s,a", r->name);
2739 emitcode ("inc", "%s", r->name);
2742 emitcode ("push", "(%s+%d)",
2743 regs390[i].base, 8 * bank + regs390[i].offset);
2746 if (ds390_nBitRegs > 0)
2748 if (options.useXstack)
2750 emitcode ("mov", "a,bits");
2751 emitcode ("movx", "@%s,a", r->name);
2753 emitcode ("inc", "%s", r->name);
2757 emitcode ("push", "bits");
2764 if (options.useXstack)
2766 emitcode ("mov", "a,psw");
2767 emitcode ("movx", "@%s,a", r->name);
2771 emitcode ("push", "psw");
2774 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2779 freeAsmop (NULL, aop, ic, TRUE);
2788 /*-----------------------------------------------------------------*/
2789 /* unsaveRBank - restores the register bank from stack */
2790 /*-----------------------------------------------------------------*/
2792 unsaveRBank (int bank, iCode * ic, bool popPsw)
2798 if (options.useXstack)
2802 /* Assume r0 is available for use. */
2803 r = REG_WITH_INDEX (R0_IDX);;
2808 r = getFreePtr (ic, &aop, FALSE);
2810 emitcode ("mov", "%s,_spx", r->name);
2815 if (options.useXstack)
2817 emitcode ("dec", "%s", r->name);
2818 emitcode ("movx", "a,@%s", r->name);
2819 emitcode ("mov", "psw,a");
2823 emitcode ("pop", "psw");
2827 if (ds390_nBitRegs > 0)
2829 if (options.useXstack)
2831 emitcode ("dec", "%s", r->name);
2832 emitcode ("movx", "a,@%s", r->name);
2833 emitcode ("mov", "bits,a");
2837 emitcode ("pop", "bits");
2841 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2843 if (options.useXstack)
2845 emitcode ("dec", "%s", r->name);
2846 emitcode ("movx", "a,@%s", r->name);
2847 emitcode ("mov", "(%s+%d),a",
2848 regs390[i].base, 8 * bank + regs390[i].offset);
2852 emitcode ("pop", "(%s+%d)",
2853 regs390[i].base, 8 * bank + regs390[i].offset);
2857 if (options.useXstack)
2859 emitcode ("mov", "_spx,%s", r->name);
2864 freeAsmop (NULL, aop, ic, TRUE);
2868 /*-----------------------------------------------------------------*/
2869 /* genSend - gen code for SEND */
2870 /*-----------------------------------------------------------------*/
2871 static void genSend(set *sendSet)
2876 static int rb1_count = 0;
2878 /* first we do all bit parameters */
2879 for (sic = setFirstItem (sendSet); sic;
2880 sic = setNextItem (sendSet))
2882 if (sic->argreg > 12)
2884 int bit = sic->argreg-13;
2886 aopOp (IC_LEFT (sic), sic, FALSE,
2887 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2889 /* if left is a literal then
2890 we know what the value is */
2891 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2893 if (((int) operandLitValue (IC_LEFT (sic))))
2894 emitcode ("setb", "b[%d]", bit);
2896 emitcode ("clr", "b[%d]", bit);
2898 else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2900 char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2901 if (strcmp (l, "c"))
2902 emitcode ("mov", "c,%s", l);
2903 emitcode ("mov", "b[%d],c", bit);
2908 toBoolean (IC_LEFT (sic));
2909 /* set C, if a >= 1 */
2910 emitcode ("add", "a,#0xff");
2911 emitcode ("mov", "b[%d],c", bit);
2916 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2922 saveRegisters (setFirstItem (sendSet));
2923 emitcode ("mov", "bits,b");
2926 /* then we do all other parameters */
2927 for (sic = setFirstItem (sendSet); sic;
2928 sic = setNextItem (sendSet))
2930 if (sic->argreg <= 12)
2932 int size, offset = 0;
2934 size=getSize(operandType(IC_LEFT(sic)));
2935 D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2936 if (sendCount == 0) { /* first parameter */
2937 // we know that dpl(hxb) is the result, so
2939 _startLazyDPSEvaluation ();
2941 aopOp (IC_LEFT (sic), sic, FALSE,
2942 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2944 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2948 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE, NULL);
2949 if (strcmp (l, fReturn[offset]))
2951 emitcode ("mov", "%s,%s", fReturn[offset], l);
2955 _endLazyDPSEvaluation ();
2956 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2958 } else { /* if more parameter in registers */
2959 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2961 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (IC_LEFT (sic), offset++,
2962 FALSE, FALSE, NULL));
2964 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2972 adjustEsp(const char *reg)
2974 emitcode ("anl","%s,#3", reg);
2975 if (TARGET_IS_DS400)
2977 emitcode ("orl","%s,#!constbyte",
2979 (options.stack_loc >> 8) & 0xff);
2983 /*-----------------------------------------------------------------*/
2984 /* selectRegBank - emit code to select the register bank */
2985 /*-----------------------------------------------------------------*/
2987 selectRegBank (short bank, bool keepFlags)
2989 /* if f.e. result is in carry */
2992 emitcode ("anl", "psw,#0xE7");
2994 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2998 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
3002 /*-----------------------------------------------------------------*/
3003 /* genCall - generates a call statement */
3004 /*-----------------------------------------------------------------*/
3006 genCall (iCode * ic)
3010 bool restoreBank = FALSE;
3011 bool swapBanks = FALSE;
3012 bool accuse = FALSE;
3013 bool accPushed = FALSE;
3014 bool resultInF0 = FALSE;
3015 bool assignResultGenerated = FALSE;
3017 D (emitcode (";", "genCall "));
3019 /* if we are calling a not _naked function that is not using
3020 the same register bank then we need to save the
3021 destination registers on the stack */
3022 dtype = operandType (IC_LEFT (ic));
3023 etype = getSpec(dtype);
3024 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
3025 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3026 IFFUNC_ISISR (currFunc->type))
3030 /* This is unexpected; the bank should have been saved in
3033 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
3039 /* if caller saves & we have not saved then */
3043 /* if send set is not empty then assign */
3044 /* We've saved all the registers we care about;
3045 * therefore, we may clobber any register not used
3046 * in the calling convention (i.e. anything not in
3051 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
3052 genSend(reverseSet(_G.sendSet));
3054 genSend(_G.sendSet);
3061 emitcode ("mov", "psw,#!constbyte",
3062 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3066 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
3067 OP_SYMBOL (IC_LEFT (ic))->rname :
3068 OP_SYMBOL (IC_LEFT (ic))->name));
3072 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
3075 /* if we need assign a result value */
3076 if ((IS_ITEMP (IC_RESULT (ic)) &&
3077 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3078 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3079 OP_SYMBOL (IC_RESULT (ic))->accuse ||
3080 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3081 IS_TRUE_SYMOP (IC_RESULT (ic)))
3083 if (isOperandInFarSpace (IC_RESULT (ic))
3084 && getSize (operandType (IC_RESULT (ic))) <= 2)
3086 int size = getSize (operandType (IC_RESULT (ic)));
3087 bool pushedB = FALSE;
3089 /* Special case for 1 or 2 byte return in far space. */
3094 emitcode ("mov", "b,%s", fReturn[1]);
3098 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
3103 aopPut (IC_RESULT (ic), "a", 0);
3107 aopPut (IC_RESULT (ic), "b", 1);
3109 assignResultGenerated = TRUE;
3110 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3114 bool pushedB = pushB ();
3115 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
3118 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3119 assignResultGenerated = TRUE;
3120 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3124 /* adjust the stack for parameters if required */
3128 if (options.stack10bit) {
3129 if (ic->parmBytes <= 10) {
3130 emitcode(";","stack adjustment for parms");
3131 for (i=0; i < ic->parmBytes ; i++) {
3132 emitcode("pop","acc");
3136 emitcode ("clr","c");
3137 emitcode ("mov","a,sp");
3138 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
3139 emitcode ("mov","sp,a");
3140 emitcode ("mov","a,esp");
3142 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
3143 emitcode ("mov","esp,a");
3147 if (ic->parmBytes > 3)
3151 emitcode ("push", "acc");
3154 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3155 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3156 !assignResultGenerated)
3158 emitcode ("mov", "F0,c");
3161 emitcode ("mov", "a,%s", spname);
3162 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
3163 emitcode ("mov", "%s,a", spname);
3165 /* unsaveRegisters from xstack needs acc, but */
3166 /* unsaveRegisters from stack needs this popped */
3167 if (accPushed && !options.useXstack)
3169 emitcode ("pop", "acc");
3174 for (i = 0; i < ic->parmBytes; i++)
3175 emitcode ("dec", "%s", spname);
3179 /* if we had saved some registers then unsave them */
3180 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3182 if (accuse && !accPushed && options.useXstack)
3184 /* xstack needs acc, but doesn't touch normal stack */
3185 emitcode ("push", "acc");
3188 unsaveRegisters (ic);
3191 /* if register bank was saved then pop them */
3193 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
3195 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
3198 emitcode ("mov", "c,F0");
3200 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
3201 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3202 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3206 emitcode ("pop", "acc");
3209 /*-----------------------------------------------------------------*/
3210 /* genPcall - generates a call by pointer statement */
3211 /*-----------------------------------------------------------------*/
3213 genPcall (iCode * ic)
3217 symbol *rlbl = newiTempLabel (NULL);
3218 bool restoreBank=FALSE;
3219 bool resultInF0 = FALSE;
3221 D (emitcode (";", "genPcall "));
3223 dtype = operandType (IC_LEFT (ic))->next;
3224 etype = getSpec(dtype);
3225 /* if caller saves & we have not saved then */
3229 /* if we are calling a not _naked function that is not using
3230 the same register bank then we need to save the
3231 destination registers on the stack */
3232 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
3233 IFFUNC_ISISR (currFunc->type) &&
3234 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
3235 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3239 /* push the return address on to the stack */
3240 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
3241 emitcode ("push", "acc");
3242 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
3243 emitcode ("push", "acc");
3245 if (options.model == MODEL_FLAT24)
3247 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
3248 emitcode ("push", "acc");
3251 /* now push the calling address */
3252 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3254 pushSide (IC_LEFT (ic), FPTRSIZE);
3256 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3258 /* if send set is not empty the assign */
3261 genSend(reverseSet(_G.sendSet));
3265 emitcode ("ret", "");
3266 emitcode ("", "!tlabeldef", (rlbl->key + 100));
3269 /* if we need assign a result value */
3270 if ((IS_ITEMP (IC_RESULT (ic)) &&
3271 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3272 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3273 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3274 IS_TRUE_SYMOP (IC_RESULT (ic)))
3278 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
3281 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3283 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3286 /* adjust the stack for parameters if required */
3290 if (options.stack10bit) {
3291 if (ic->parmBytes <= 10) {
3292 emitcode(";","stack adjustment for parms");
3293 for (i=0; i < ic->parmBytes ; i++) {
3294 emitcode("pop","acc");
3297 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3298 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3300 emitcode ("mov", "F0,c");
3305 emitcode ("clr","c");
3306 emitcode ("mov","a,sp");
3307 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
3308 emitcode ("mov","sp,a");
3309 emitcode ("mov","a,esp");
3311 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
3312 emitcode ("mov","esp,a");
3316 if (ic->parmBytes > 3) {
3317 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3318 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3320 emitcode ("mov", "F0,c");
3324 emitcode ("mov", "a,%s", spname);
3325 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
3326 emitcode ("mov", "%s,a", spname);
3329 for (i = 0; i < ic->parmBytes; i++)
3330 emitcode ("dec", "%s", spname);
3333 /* if register bank was saved then unsave them */
3335 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3337 /* if we had saved some registers then unsave them */
3339 unsaveRegisters (ic);
3341 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3344 emitcode ("mov", "c,F0");
3346 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
3347 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3348 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3352 /*-----------------------------------------------------------------*/
3353 /* resultRemat - result is rematerializable */
3354 /*-----------------------------------------------------------------*/
3356 resultRemat (iCode * ic)
3358 if (SKIP_IC (ic) || ic->op == IFX)
3361 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3363 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3364 if (sym->remat && !POINTER_SET (ic))
3371 #if defined(__BORLANDC__) || defined(_MSC_VER)
3372 #define STRCASECMP stricmp
3374 #define STRCASECMP strcasecmp
3377 /*-----------------------------------------------------------------*/
3378 /* inExcludeList - return 1 if the string is in exclude Reg list */
3379 /*-----------------------------------------------------------------*/
3381 regsCmp(void *p1, void *p2)
3383 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3387 inExcludeList (char *s)
3389 const char *p = setFirstItem(options.excludeRegsSet);
3391 if (p == NULL || STRCASECMP(p, "none") == 0)
3395 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3398 /*-----------------------------------------------------------------*/
3399 /* genFunction - generated code for function entry */
3400 /*-----------------------------------------------------------------*/
3402 genFunction (iCode * ic)
3404 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3406 bool switchedPSW = FALSE;
3407 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3409 D (emitcode (";", "genFunction "));
3412 /* create the function header */
3413 emitcode (";", "-----------------------------------------");
3414 emitcode (";", " function %s", sym->name);
3415 emitcode (";", "-----------------------------------------");
3417 emitcode ("", "%s:", sym->rname);
3418 ftype = operandType (IC_LEFT (ic));
3419 _G.currentFunc = sym;
3421 if (IFFUNC_ISNAKED(ftype))
3423 emitcode(";", "naked function: no prologue.");
3427 if (options.stack_probe)
3428 emitcode ("lcall","__stack_probe");
3430 /* here we need to generate the equates for the
3431 register bank if required */
3432 if (FUNC_REGBANK (ftype) != rbank)
3436 rbank = FUNC_REGBANK (ftype);
3437 for (i = 0; i < ds390_nRegs; i++)
3439 if (regs390[i].print) {
3440 if (strcmp (regs390[i].base, "0") == 0)
3441 emitcode ("", "%s !equ !constbyte",
3443 8 * rbank + regs390[i].offset);
3445 emitcode ("", "%s !equ %s + !constbyte",
3448 8 * rbank + regs390[i].offset);
3453 /* if this is an interrupt service routine then
3454 save acc, b, dpl, dph */
3455 if (IFFUNC_ISISR (sym->type))
3457 if (!inExcludeList ("acc"))
3458 emitcode ("push", "acc");
3459 if (!inExcludeList ("b"))
3460 emitcode ("push", "b");
3461 if (!inExcludeList ("dpl"))
3462 emitcode ("push", "dpl");
3463 if (!inExcludeList ("dph"))
3464 emitcode ("push", "dph");
3465 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3467 emitcode ("push", "dpx");
3468 /* Make sure we're using standard DPTR */
3469 emitcode ("push", "dps");
3470 emitcode ("mov", "dps,#0");
3471 if (options.stack10bit)
3473 /* This ISR could conceivably use DPTR2. Better save it. */
3474 emitcode ("push", "dpl1");
3475 emitcode ("push", "dph1");
3476 emitcode ("push", "dpx1");
3477 emitcode ("push", DP2_RESULT_REG);
3480 /* if this isr has no bank i.e. is going to
3481 run with bank 0 , then we need to save more
3483 if (!FUNC_REGBANK (sym->type))
3487 /* if this function does not call any other
3488 function then we can be economical and
3489 save only those registers that are used */
3490 if (!IFFUNC_HASFCALL(sym->type))
3492 /* if any registers used */
3495 bool bits_pushed = FALSE;
3496 /* save the registers used */
3497 for (i = 0; i < sym->regsUsed->size; i++)
3499 if (bitVectBitValue (sym->regsUsed, i))
3500 bits_pushed = pushReg (i, bits_pushed);
3506 /* this function has a function call. We cannot
3507 determine register usage so we will have to push the
3509 saveRBank (0, ic, FALSE);
3510 if (options.parms_in_bank1) {
3511 for (i=0; i < 8 ; i++ ) {
3512 emitcode ("push","%s",rb1regs[i]);
3519 /* This ISR uses a non-zero bank.
3521 * We assume that the bank is available for our
3524 * However, if this ISR calls a function which uses some
3525 * other bank, we must save that bank entirely.
3527 unsigned long banksToSave = 0;
3529 if (IFFUNC_HASFCALL(sym->type))
3532 #define MAX_REGISTER_BANKS 4
3537 for (i = ic; i; i = i->next)
3539 if (i->op == ENDFUNCTION)
3541 /* we got to the end OK. */
3549 dtype = operandType (IC_LEFT(i));
3551 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3553 /* Mark this bank for saving. */
3554 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3556 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3560 banksToSave |= (1 << FUNC_REGBANK(dtype));
3563 /* And note that we don't need to do it in
3571 /* This is a mess; we have no idea what
3572 * register bank the called function might
3575 * The only thing I can think of to do is
3576 * throw a warning and hope.
3578 werror(W_FUNCPTR_IN_USING_ISR);
3582 if (banksToSave && options.useXstack)
3584 /* Since we aren't passing it an ic,
3585 * saveRBank will assume r0 is available to abuse.
3587 * So switch to our (trashable) bank now, so
3588 * the caller's R0 isn't trashed.
3590 emitcode ("push", "psw");
3591 emitcode ("mov", "psw,#!constbyte",
3592 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3596 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3598 if (banksToSave & (1 << ix))
3600 saveRBank(ix, NULL, FALSE);
3604 // TODO: this needs a closer look
3605 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3610 /* if callee-save to be used for this function
3611 then save the registers being used in this function */
3612 if (IFFUNC_CALLEESAVES(sym->type))
3616 /* if any registers used */
3619 bool bits_pushed = FALSE;
3620 /* save the registers used */
3621 for (i = 0; i < sym->regsUsed->size; i++)
3623 if (bitVectBitValue (sym->regsUsed, i))
3625 bits_pushed = pushReg (i, bits_pushed);
3633 /* set the register bank to the desired value */
3634 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3637 emitcode ("push", "psw");
3638 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3642 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3643 if (options.stack10bit) {
3644 emitcode ("push","_bpx");
3645 emitcode ("push","_bpx+1");
3646 emitcode ("mov","_bpx,%s",spname);
3647 emitcode ("mov","_bpx+1,esp");
3648 adjustEsp("_bpx+1");
3650 if (options.useXstack)
3652 emitcode ("mov", "r0,%s", spname);
3653 emitcode ("mov", "a,_bp");
3654 emitcode ("movx", "@r0,a");
3655 emitcode ("inc", "%s", spname);
3657 /* set up the stack */
3658 emitcode ("push", "_bp"); /* save the callers stack */
3660 emitcode ("mov", "_bp,%s", spname);
3664 /* adjust the stack for the function */
3667 if (options.stack10bit) {
3668 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
3669 assert (sym->recvSize <= 4);
3670 if (sym->stack <= 8) {
3671 while (i--) emitcode ("push","acc");
3674 emitcode ("mov","a,sp");
3675 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3676 emitcode ("mov","sp,a");
3677 emitcode ("mov","a,esp");
3679 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3680 emitcode ("mov","esp,a");
3685 werror (W_STACK_OVERFLOW, sym->name);
3687 if (i > 3 && sym->recvSize < 4) {
3689 emitcode ("mov", "a,sp");
3690 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3691 emitcode ("mov", "sp,a");
3695 emitcode ("inc", "sp");
3702 emitcode ("mov", "a,_spx");
3703 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3704 emitcode ("mov", "_spx,a");
3707 /* if critical function then turn interrupts off */
3708 if (IFFUNC_ISCRITICAL (ftype))
3710 symbol *tlbl = newiTempLabel (NULL);
3711 emitcode ("setb", "c");
3712 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3713 emitcode ("clr", "c");
3714 emitcode ("", "%05d$:", (tlbl->key + 100));
3715 emitcode ("push", "psw"); /* save old ea via c in psw */
3719 /*-----------------------------------------------------------------*/
3720 /* genEndFunction - generates epilogue for functions */
3721 /*-----------------------------------------------------------------*/
3723 genEndFunction (iCode * ic)
3725 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3726 lineNode *lnp = lineCurr;
3728 bitVect *regsUsedPrologue;
3729 bitVect *regsUnneeded;
3732 D (emitcode (";", "genEndFunction "););
3734 _G.currentFunc = NULL;
3735 if (IFFUNC_ISNAKED(sym->type))
3737 emitcode(";", "naked function: no epilogue.");
3738 if (options.debug && currFunc)
3739 debugFile->writeEndFunction (currFunc, ic, 0);
3743 if (IFFUNC_ISCRITICAL (sym->type))
3745 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3747 emitcode ("rlc", "a"); /* save c in a */
3748 emitcode ("pop", "psw"); /* restore ea via c in psw */
3749 emitcode ("mov", "ea,c");
3750 emitcode ("rrc", "a"); /* restore c from a */
3754 emitcode ("pop", "psw"); /* restore ea via c in psw */
3755 emitcode ("mov", "ea,c");
3759 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3760 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3762 if (options.stack10bit) {
3764 emitcode ("mov", "sp,_bpx", spname);
3765 emitcode ("mov", "esp,_bpx+1", spname);
3768 emitcode ("mov", "%s,_bp", spname);
3772 /* if use external stack but some variables were
3773 added to the local stack then decrement the
3775 if (options.useXstack && sym->stack) {
3776 emitcode ("mov", "a,sp");
3777 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3778 emitcode ("mov", "sp,a");
3782 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3783 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3785 if (options.useXstack) {
3786 emitcode ("mov", "r0,%s", spname);
3787 emitcode ("movx", "a,@r0");
3788 emitcode ("mov", "_bp,a");
3789 emitcode ("dec", "%s", spname);
3791 if (options.stack10bit) {
3792 emitcode ("pop", "_bpx+1");
3793 emitcode ("pop", "_bpx");
3795 emitcode ("pop", "_bp");
3800 /* restore the register bank */
3801 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3803 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3804 || !options.useXstack)
3806 /* Special case of ISR using non-zero bank with useXstack
3809 emitcode ("pop", "psw");
3813 if (IFFUNC_ISISR (sym->type))
3816 /* now we need to restore the registers */
3817 /* if this isr has no bank i.e. is going to
3818 run with bank 0 , then we need to save more
3820 if (!FUNC_REGBANK (sym->type))
3823 /* if this function does not call any other
3824 function then we can be economical and
3825 save only those registers that are used */
3826 if (!IFFUNC_HASFCALL(sym->type))
3828 /* if any registers used */
3831 bool bits_popped = FALSE;
3832 /* save the registers used */
3833 for (i = sym->regsUsed->size; i >= 0; i--)
3835 if (bitVectBitValue (sym->regsUsed, i))
3836 bits_popped = popReg (i, bits_popped);
3842 /* this function has a function call. We cannot
3843 determine register usage so we will have to pop the
3845 if (options.parms_in_bank1) {
3846 for (i = 7 ; i >= 0 ; i-- ) {
3847 emitcode ("pop","%s",rb1regs[i]);
3850 unsaveRBank (0, ic, FALSE);
3855 /* This ISR uses a non-zero bank.
3857 * Restore any register banks saved by genFunction
3860 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3863 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3865 if (savedBanks & (1 << ix))
3867 unsaveRBank(ix, NULL, FALSE);
3871 if (options.useXstack)
3873 /* Restore bank AFTER calling unsaveRBank,
3874 * since it can trash r0.
3876 emitcode ("pop", "psw");
3880 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3882 if (options.stack10bit)
3884 emitcode ("pop", DP2_RESULT_REG);
3885 emitcode ("pop", "dpx1");
3886 emitcode ("pop", "dph1");
3887 emitcode ("pop", "dpl1");
3889 emitcode ("pop", "dps");
3890 emitcode ("pop", "dpx");
3892 if (!inExcludeList ("dph"))
3893 emitcode ("pop", "dph");
3894 if (!inExcludeList ("dpl"))
3895 emitcode ("pop", "dpl");
3896 if (!inExcludeList ("b"))
3897 emitcode ("pop", "b");
3898 if (!inExcludeList ("acc"))
3899 emitcode ("pop", "acc");
3901 /* if debug then send end of function */
3902 if (options.debug && currFunc)
3904 debugFile->writeEndFunction (currFunc, ic, 1);
3907 emitcode ("reti", "");
3911 if (IFFUNC_CALLEESAVES(sym->type))
3915 /* if any registers used */
3918 /* save the registers used */
3919 for (i = sym->regsUsed->size; i >= 0; i--)
3921 if (bitVectBitValue (sym->regsUsed, i))
3922 emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3927 /* if debug then send end of function */
3928 if (options.debug && currFunc)
3930 debugFile->writeEndFunction (currFunc, ic, 1);
3933 emitcode ("ret", "");
3936 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3939 /* If this was an interrupt handler using bank 0 that called another */
3940 /* function, then all registers must be saved; nothing to optimized. */
3941 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3942 && !FUNC_REGBANK(sym->type))
3945 /* There are no push/pops to optimize if not callee-saves or ISR */
3946 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3949 /* If there were stack parameters, we cannot optimize without also */
3950 /* fixing all of the stack offsets; this is too dificult to consider. */
3951 if (FUNC_HASSTACKPARM(sym->type))
3954 /* Compute the registers actually used */
3955 regsUsed = newBitVect (ds390_nRegs);
3956 regsUsedPrologue = newBitVect (ds390_nRegs);
3959 if (lnp->ic && lnp->ic->op == FUNCTION)
3960 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3962 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3964 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3965 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3972 if (bitVectBitValue (regsUsedPrologue, DPS_IDX)
3973 && !bitVectBitValue (regsUsed, DPS_IDX))
3975 bitVectUnSetBit (regsUsedPrologue, DPS_IDX);
3978 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3979 && !bitVectBitValue (regsUsed, CND_IDX))
3981 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3982 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3983 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3984 bitVectUnSetBit (regsUsed, CND_IDX);
3987 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3989 /* If this was an interrupt handler that called another function */
3990 /* function, then assume working registers may be modified by it. */
3991 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3993 regsUsed = bitVectSetBit (regsUsed, AP_IDX);
3994 regsUsed = bitVectSetBit (regsUsed, DPX1_IDX);
3995 regsUsed = bitVectSetBit (regsUsed, DPL1_IDX);
3996 regsUsed = bitVectSetBit (regsUsed, DPH1_IDX);
3997 regsUsed = bitVectSetBit (regsUsed, DPX_IDX);
3998 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3999 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
4000 regsUsed = bitVectSetBit (regsUsed, DPS_IDX);
4001 regsUsed = bitVectSetBit (regsUsed, B_IDX);
4002 regsUsed = bitVectSetBit (regsUsed, A_IDX);
4003 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
4006 /* Remove the unneeded push/pops */
4007 regsUnneeded = newBitVect (ds390_nRegs);
4010 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
4012 if (!strncmp(lnp->line, "push", 4))
4014 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
4015 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4017 connectLine (lnp->prev, lnp->next);
4018 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4021 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
4023 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
4024 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4026 connectLine (lnp->prev, lnp->next);
4027 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4034 for (idx = 0; idx < regsUnneeded->size; idx++)
4035 if (bitVectBitValue (regsUnneeded, idx))
4036 emitcode ("", ";\teliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
4038 freeBitVect (regsUnneeded);
4039 freeBitVect (regsUsed);
4040 freeBitVect (regsUsedPrologue);
4043 /*-----------------------------------------------------------------*/
4044 /* genJavaNativeRet - generate code for return JavaNative */
4045 /*-----------------------------------------------------------------*/
4046 static void genJavaNativeRet(iCode *ic)
4050 aopOp (IC_LEFT (ic), ic, FALSE,
4051 AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
4052 size = AOP_SIZE (IC_LEFT (ic));
4056 /* it is assigned to GPR0-R3 then push them */
4057 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
4058 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
4059 for (i = 0 ; i < size ; i++ ) {
4060 emitcode ("push","%s",
4061 aopGet(IC_LEFT(ic),i,FALSE,TRUE,DP2_RESULT_REG));
4063 for (i = (size-1) ; i >= 0 ; i--) {
4064 emitcode ("pop","a%s",javaRet[i]);
4067 for (i = 0 ; i < size ; i++)
4068 emitcode ("mov","%s,%s",javaRet[i],
4069 aopGet(IC_LEFT(ic),i,FALSE,TRUE,DP2_RESULT_REG));
4071 for (i = size ; i < 4 ; i++ )
4072 emitcode ("mov","%s,#0",javaRet[i]);
4076 /*-----------------------------------------------------------------*/
4077 /* genRet - generate code for return statement */
4078 /*-----------------------------------------------------------------*/
4082 int size, offset = 0, pushed = 0;
4084 D (emitcode (";", "genRet"));
4086 /* if we have no return value then
4087 just generate the "ret" */
4091 /* if this is a JavaNative function then return
4092 value in different register */
4093 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
4094 genJavaNativeRet(ic);
4097 /* we have something to return then
4098 move the return value into place */
4099 aopOp (IC_LEFT (ic), ic, FALSE,
4100 (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
4101 size = AOP_SIZE (IC_LEFT (ic));
4103 _startLazyDPSEvaluation ();
4105 if (IS_BIT(_G.currentFunc->etype))
4107 movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4114 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
4116 l = aopGet (IC_LEFT (ic), offset++,
4118 emitcode ("push", "%s", l);
4123 /* Since A is the last element of fReturn,
4124 * it is OK to clobber it in the aopGet.
4126 l = aopGet (IC_LEFT (ic), offset,
4127 FALSE, FALSE, NULL);
4128 if (strcmp (fReturn[offset], l))
4129 emitcode ("mov", "%s,%s", fReturn[offset++], l);
4132 _endLazyDPSEvaluation ();
4137 if (strcmp (fReturn[pushed], "a"))
4138 emitcode ("pop", fReturn[pushed]);
4140 emitcode ("pop", "acc");
4142 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4145 /* generate a jump to the return label
4146 if the next is not the return statement */
4147 if (!(ic->next && ic->next->op == LABEL &&
4148 IC_LABEL (ic->next) == returnLabel))
4150 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
4154 /*-----------------------------------------------------------------*/
4155 /* genLabel - generates a label */
4156 /*-----------------------------------------------------------------*/
4158 genLabel (iCode * ic)
4160 /* special case never generate */
4161 if (IC_LABEL (ic) == entryLabel)
4164 D (emitcode (";", "genLabel "));
4166 emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
4169 /*-----------------------------------------------------------------*/
4170 /* genGoto - generates a ljmp */
4171 /*-----------------------------------------------------------------*/
4173 genGoto (iCode * ic)
4175 D (emitcode (";", "genGoto "));
4177 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
4180 /*-----------------------------------------------------------------*/
4181 /* findLabelBackwards: walks back through the iCode chain looking */
4182 /* for the given label. Returns number of iCode instructions */
4183 /* between that label and given ic. */
4184 /* Returns zero if label not found. */
4185 /*-----------------------------------------------------------------*/
4187 findLabelBackwards (iCode * ic, int key)
4196 /* If we have any pushes or pops, we cannot predict the distance.
4197 I don't like this at all, this should be dealt with in the
4199 if (ic->op == IPUSH || ic->op == IPOP) {
4203 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4205 /* printf("findLabelBackwards = %d\n", count); */
4213 /*-----------------------------------------------------------------*/
4214 /* genPlusIncr :- does addition with increment if possible */
4215 /*-----------------------------------------------------------------*/
4217 genPlusIncr (iCode * ic)
4219 unsigned int icount;
4220 unsigned int size = getDataSize (IC_RESULT (ic));
4222 /* will try to generate an increment */
4223 /* if the right side is not a literal
4225 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4228 /* if the literal value of the right hand side
4229 is greater than 4 then it is not worth it */
4230 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4233 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4234 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4236 emitcode("inc","%s",aopGet(IC_RESULT(ic),0,FALSE,FALSE,NULL));
4240 /* if increment 16 bits in register */
4242 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4243 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4244 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4253 /* If the next instruction is a goto and the goto target
4254 * is <= 5 instructions previous to this, we can generate
4255 * jumps straight to that target.
4257 if (ic->next && ic->next->op == GOTO
4258 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4261 D(emitcode (";", "tail increment optimized (range %d)", labelRange););
4262 tlbl = IC_LABEL (ic->next);
4267 tlbl = newiTempLabel (NULL);
4270 l = aopGet (IC_RESULT (ic), LSB, FALSE, FALSE, NULL);
4271 emitcode ("inc", "%s", l);
4273 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4274 IS_AOP_PREG (IC_RESULT (ic)))
4276 emitcode ("cjne", "%s,%s,!tlabel", l, zero, tlbl->key + 100);
4280 emitcode ("clr", "a");
4281 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4284 l = aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE, NULL);
4285 emitcode ("inc", "%s", l);
4288 if (!strcmp(l, "acc"))
4290 emitcode("jnz", "!tlabel", tlbl->key + 100);
4292 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4293 IS_AOP_PREG (IC_RESULT (ic)))
4295 emitcode ("cjne", "%s,%s,!tlabel", l, zero, tlbl->key + 100);
4299 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4302 l = aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE, NULL);
4303 emitcode ("inc", "%s", l);
4307 if (!strcmp(l, "acc"))
4309 emitcode("jnz", "!tlabel", tlbl->key + 100);
4311 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4312 IS_AOP_PREG (IC_RESULT (ic)))
4314 emitcode ("cjne", "%s,%s,!tlabel", l, zero, tlbl->key + 100);
4318 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4321 l = aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE, NULL);
4322 emitcode ("inc", "%s", l);
4327 emitcode ("", "!tlabeldef", tlbl->key + 100);
4332 if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
4333 !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
4334 options.model == MODEL_FLAT24 )
4336 if (IC_RESULT(ic)->isGptr)
4338 emitcode ("mov", "b,%s", aopGet(IC_LEFT (ic), 3, FALSE, FALSE, NULL));
4342 emitcode ("mov", "dpx,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE, NULL));
4344 emitcode ("mov", "dph,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE, NULL));
4346 emitcode ("mov", "dpl,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4350 emitcode ("inc", "dptr");
4354 if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
4355 AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
4357 emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
4359 emitcode ("inc", "dptr");
4360 emitcode ("mov", "dps,#0");
4364 /* if the sizes are greater than 1 then we cannot */
4365 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4366 AOP_SIZE (IC_LEFT (ic)) > 1)
4369 /* we can if the aops of the left & result match or
4370 if they are in registers and the registers are the
4373 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4374 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4375 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4379 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4380 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
4381 aopPut (IC_RESULT (ic), "a", 0);
4385 _startLazyDPSEvaluation ();
4388 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4390 _endLazyDPSEvaluation ();
4399 /*-----------------------------------------------------------------*/
4400 /* outBitAcc - output a bit in acc */
4401 /*-----------------------------------------------------------------*/
4403 outBitAcc (operand * result)
4405 symbol *tlbl = newiTempLabel (NULL);
4406 /* if the result is a bit */
4407 if (AOP_TYPE (result) == AOP_CRY)
4409 aopPut (result, "a", 0);
4413 emitcode ("jz", "!tlabel", tlbl->key + 100);
4414 emitcode ("mov", "a,%s", one);
4415 emitcode ("", "!tlabeldef", tlbl->key + 100);
4420 /*-----------------------------------------------------------------*/
4421 /* genPlusBits - generates code for addition of two bits */
4422 /*-----------------------------------------------------------------*/
4424 genPlusBits (iCode * ic)
4426 D (emitcode (";", "genPlusBits "));
4428 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4430 symbol *lbl = newiTempLabel (NULL);
4431 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4432 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4433 emitcode ("cpl", "c");
4434 emitcode ("", "!tlabeldef", (lbl->key + 100));
4435 outBitC (IC_RESULT (ic));
4439 emitcode ("clr", "a");
4440 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4441 emitcode ("rlc", "a");
4442 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4443 emitcode ("addc", "a,%s", zero);
4444 outAcc (IC_RESULT (ic));
4449 adjustArithmeticResult (iCode * ic)
4451 if (opIsGptr (IC_RESULT (ic)) &&
4452 opIsGptr (IC_LEFT (ic)) &&
4453 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4455 aopPut (IC_RESULT (ic),
4456 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE, NULL),
4460 if (opIsGptr (IC_RESULT (ic)) &&
4461 opIsGptr (IC_RIGHT (ic)) &&
4462 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4464 aopPut (IC_RESULT (ic),
4465 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE, NULL),
4469 if (opIsGptr (IC_RESULT (ic)) &&
4470 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4471 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4472 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4473 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4476 SNPRINTF (buffer, sizeof(buffer),
4477 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4478 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4482 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
4483 // generates the result if possible. If result is generated, returns TRUE; otherwise
4484 // returns false and caller must deal with fact that result isn't aopOp'd.
4485 bool aopOp3(iCode * ic)
4487 bool dp1InUse, dp2InUse;
4490 // First, generate the right opcode. DPTR may be used if neither left nor result are
4493 // D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
4494 // AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
4495 // AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
4496 // AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
4498 // D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
4499 // AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
4500 // AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
4501 // AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
4504 // Right uses DPTR unless left or result is an AOP_STR; however,
4505 // if right is an AOP_STR, it must use DPTR regardless.
4506 if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
4507 && !AOP_IS_STR(IC_RIGHT(ic)))
4516 aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
4518 // if the right used DPTR, left MUST use DPTR2.
4519 // if the right used DPTR2, left MUST use DPTR.
4520 // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
4521 // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
4522 // enabling us to assign DPTR to result.
4524 if (AOP_USESDPTR(IC_RIGHT(ic)))
4528 else if (AOP_USESDPTR2(IC_RIGHT(ic)))
4534 if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
4544 aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
4547 // We've op'd the left & right. So, if left or right are the same operand as result,
4548 // we know aopOp will succeed, and we can just do it & bail.
4549 if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)))
4551 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4554 if (isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
4556 // D(emitcode(";", "aopOp3: (left | right) & result equal"););
4557 aopOp(IC_RESULT(ic),ic,TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4561 // Operands may be equivalent (but not equal) if they share a spill location. If
4562 // so, use the same DPTR or DPTR2.
4563 if (operandsEqu (IC_LEFT(ic), IC_RESULT(ic)))
4565 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4568 if (operandsEqu (IC_RIGHT(ic), IC_RESULT(ic)))
4570 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4574 // Note which dptrs are currently in use.
4575 dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
4576 dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
4578 // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
4580 if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
4585 // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
4586 if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
4591 // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
4592 if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
4597 aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
4599 // Some sanity checking...
4600 if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
4603 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
4604 __FILE__, __LINE__, ic->filename, ic->lineno);
4605 emitcode(";", ">>> unexpected DPTR here.");
4608 if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
4611 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
4612 __FILE__, __LINE__, ic->filename, ic->lineno);
4613 emitcode(";", ">>> unexpected DPTR2 here.");
4619 // Macro to aopOp all three operands of an ic. If this cannot be done,
4620 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
4621 // will be set TRUE. The caller must then handle the case specially, noting
4622 // that the IC_RESULT operand is not aopOp'd.
4624 #define AOP_OP_3_NOFATAL(ic, rc) \
4625 do { rc = !aopOp3(ic); } while (0)
4627 // aopOp the left & right operands of an ic.
4628 #define AOP_OP_2(ic) \
4629 aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
4630 aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
4632 // convienience macro.
4633 #define AOP_SET_LOCALS(ic) \
4634 left = IC_LEFT(ic); \
4635 right = IC_RIGHT(ic); \
4636 result = IC_RESULT(ic);
4639 // Given an integer value of pushedSize bytes on the stack,
4640 // adjust it to be resultSize bytes, either by discarding
4641 // the most significant bytes or by zero-padding.
4643 // On exit from this macro, pushedSize will have been adjusted to
4644 // equal resultSize, and ACC may be trashed.
4645 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
4646 /* If the pushed data is bigger than the result, \
4647 * simply discard unused bytes. Icky, but works. \
4649 while (pushedSize > resultSize) \
4651 D (emitcode (";", "discarding unused result byte."););\
4652 emitcode ("pop", "acc"); \
4655 if (pushedSize < resultSize) \
4657 emitcode ("clr", "a"); \
4658 /* Conversly, we haven't pushed enough here. \
4659 * just zero-pad, and all is well. \
4661 while (pushedSize < resultSize) \
4663 emitcode("push", "acc"); \
4667 assert(pushedSize == resultSize);
4669 /*-----------------------------------------------------------------*/
4670 /* genPlus - generates code for addition */
4671 /*-----------------------------------------------------------------*/
4673 genPlus (iCode * ic)
4675 int size, offset = 0;
4678 bool swappedLR = FALSE;
4680 D (emitcode (";", "genPlus "));
4682 /* special cases :- */
4683 if ( AOP_IS_STR(IC_LEFT(ic)) &&
4684 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
4685 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4686 size = (int)floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
4688 while (size--) emitcode ("inc","dptr");
4690 emitcode ("mov","a,dpl");
4691 emitcode ("add","a,#!constbyte",size & 0xff);
4692 emitcode ("mov","dpl,a");
4693 emitcode ("mov","a,dph");
4694 emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
4695 emitcode ("mov","dph,a");
4696 emitcode ("mov","a,dpx");
4697 emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
4698 emitcode ("mov","dpx,a");
4700 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4703 if ( IS_SYMOP(IC_LEFT(ic)) &&
4704 OP_SYMBOL(IC_LEFT(ic))->remat &&
4705 isOperandInFarSpace(IC_RIGHT(ic))) {
4706 operand *op = IC_RIGHT(ic);
4707 IC_RIGHT(ic) = IC_LEFT(ic);
4711 AOP_OP_3_NOFATAL (ic, pushResult);
4715 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4720 /* if literal, literal on the right or
4721 if left requires ACC or right is already
4723 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4724 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4725 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4727 operand *t = IC_RIGHT (ic);
4728 IC_RIGHT (ic) = IC_LEFT (ic);
4731 emitcode (";", "Swapped plus args.");
4734 /* if both left & right are in bit
4736 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4737 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4743 /* if left in bit space & right literal */
4744 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4745 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4747 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4748 /* if result in bit space */
4749 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4751 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4752 emitcode ("cpl", "c");
4753 outBitC (IC_RESULT (ic));
4757 size = getDataSize (IC_RESULT (ic));
4758 _startLazyDPSEvaluation ();
4761 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4762 emitcode ("addc", "a,%s", zero);
4763 aopPut (IC_RESULT (ic), "a", offset++);
4765 _endLazyDPSEvaluation ();
4770 /* if I can do an increment instead
4771 of add then GOOD for ME */
4772 if (genPlusIncr (ic) == TRUE)
4774 emitcode (";", "did genPlusIncr");
4779 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4781 _startLazyDPSEvaluation ();
4784 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4786 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
4788 emitcode ("add", "a,%s",
4789 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4791 emitcode ("addc", "a,%s",
4792 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4796 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4798 /* right is going to use ACC or we would have taken the
4801 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4803 D(emitcode(";", "+ AOP_ACC special case."););
4804 emitcode("xch", "a, %s", DP2_RESULT_REG);
4806 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4809 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4812 emitcode("add", "a, %s", DP2_RESULT_REG);
4816 emitcode ("add", "a,%s",
4817 aopGet (IC_LEFT(ic), offset, FALSE, FALSE,
4823 emitcode ("addc", "a,%s",
4824 aopGet (IC_LEFT (ic), offset, FALSE, FALSE,
4830 aopPut (IC_RESULT (ic), "a", offset);
4834 emitcode ("push", "acc");
4838 _endLazyDPSEvaluation ();
4842 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4844 size = getDataSize (IC_LEFT (ic));
4845 rSize = getDataSize (IC_RESULT (ic));
4847 ADJUST_PUSHED_RESULT(size, rSize);
4849 _startLazyDPSEvaluation ();
4852 emitcode ("pop", "acc");
4853 aopPut (IC_RESULT (ic), "a", size);
4855 _endLazyDPSEvaluation ();
4858 adjustArithmeticResult (ic);
4861 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4864 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4865 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4869 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4870 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4874 /*-----------------------------------------------------------------*/
4875 /* genMinusDec :- does subtraction with decrement if possible */
4876 /*-----------------------------------------------------------------*/
4878 genMinusDec (iCode * ic)
4880 unsigned int icount;
4881 unsigned int size = getDataSize (IC_RESULT (ic));
4883 /* will try to generate an increment */
4884 /* if the right side is not a literal
4886 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4889 /* if the literal value of the right hand side
4890 is greater than 4 then it is not worth it */
4891 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4894 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4895 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4897 emitcode("dec","%s",aopGet(IC_RESULT(ic),0,FALSE,FALSE,NULL));
4901 /* if decrement 16 bits in register */
4902 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4903 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4904 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4913 /* If the next instruction is a goto and the goto target
4914 * is <= 5 instructions previous to this, we can generate
4915 * jumps straight to that target.
4917 if (ic->next && ic->next->op == GOTO
4918 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4921 emitcode (";", "tail decrement optimized (range %d)", labelRange);
4922 tlbl = IC_LABEL (ic->next);
4927 tlbl = newiTempLabel (NULL);
4931 l = aopGet (IC_RESULT (ic), LSB, FALSE, FALSE, NULL);
4932 emitcode ("dec", "%s", l);
4934 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4935 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4936 IS_AOP_PREG (IC_RESULT (ic)))
4938 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4942 emitcode ("mov", "a,#!constbyte",0xff);
4943 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4945 l = aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE, NULL);
4946 emitcode ("dec", "%s", l);
4949 if (!strcmp(l, "acc"))
4951 emitcode("jnz", "!tlabel", tlbl->key + 100);
4953 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4954 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4955 IS_AOP_PREG (IC_RESULT (ic)))
4957 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4961 emitcode ("mov", "a,#!constbyte",0xff);
4962 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4964 l = aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE, NULL);
4965 emitcode ("dec", "%s", l);
4969 if (!strcmp(l, "acc"))
4971 emitcode("jnz", "!tlabel", tlbl->key + 100);
4973 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4974 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4975 IS_AOP_PREG (IC_RESULT (ic)))
4977 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4981 emitcode ("mov", "a,#!constbyte",0xff);
4982 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4984 l = aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE, NULL);
4985 emitcode ("dec", "%s", l);
4989 emitcode ("", "!tlabeldef", tlbl->key + 100);
4994 /* if the sizes are greater than 1 then we cannot */
4995 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4996 AOP_SIZE (IC_LEFT (ic)) > 1)
4999 /* we can if the aops of the left & result match or
5000 if they are in registers and the registers are the
5003 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
5004 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
5005 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5009 if (aopGetUsesAcc (IC_LEFT (ic), 0))
5011 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL));
5016 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL);
5019 _startLazyDPSEvaluation ();
5022 emitcode ("dec", "%s", l);
5024 _endLazyDPSEvaluation ();
5026 if (AOP_NEEDSACC (IC_RESULT (ic)))
5027 aopPut (IC_RESULT (ic), "a", 0);
5035 /*-----------------------------------------------------------------*/
5036 /* addSign - complete with sign */
5037 /*-----------------------------------------------------------------*/
5039 addSign (operand * result, int offset, int sign)
5041 int size = (getDataSize (result) - offset);
5044 _startLazyDPSEvaluation();
5047 emitcode ("rlc", "a");
5048 emitcode ("subb", "a,acc");
5051 aopPut (result, "a", offset++);
5058 aopPut (result, zero, offset++);
5061 _endLazyDPSEvaluation();
5065 /*-----------------------------------------------------------------*/
5066 /* genMinusBits - generates code for subtraction of two bits */
5067 /*-----------------------------------------------------------------*/
5069 genMinusBits (iCode * ic)
5071 symbol *lbl = newiTempLabel (NULL);
5073 D (emitcode (";", "genMinusBits "));
5075 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
5077 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
5078 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
5079 emitcode ("cpl", "c");
5080 emitcode ("", "!tlabeldef", (lbl->key + 100));
5081 outBitC (IC_RESULT (ic));
5085 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
5086 emitcode ("subb", "a,acc");
5087 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
5088 emitcode ("inc", "a");
5089 emitcode ("", "!tlabeldef", (lbl->key + 100));
5090 aopPut (IC_RESULT (ic), "a", 0);
5091 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
5095 /*-----------------------------------------------------------------*/
5096 /* genMinus - generates code for subtraction */
5097 /*-----------------------------------------------------------------*/
5099 genMinus (iCode * ic)
5101 int size, offset = 0;
5106 D (emitcode (";", "genMinus "));
5108 AOP_OP_3_NOFATAL(ic, pushResult);
5112 /* special cases :- */
5113 /* if both left & right are in bit space */
5114 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
5115 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
5121 /* if I can do an decrement instead
5122 of subtract then GOOD for ME */
5123 if (genMinusDec (ic) == TRUE)
5128 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
5130 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
5136 lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5141 /* if literal, add a,#-lit, else normal subb */
5142 _startLazyDPSEvaluation ();
5144 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
5145 if (AOP_USESDPTR(IC_RIGHT(ic))) {
5146 emitcode ("mov","b,%s",
5147 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
5148 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
5149 emitcode ("subb","a,b");
5151 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
5152 emitcode ("subb", "a,%s",
5153 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE,
5157 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
5158 /* first add without previous c */
5160 if (!size && lit==-1) {
5161 emitcode ("dec", "a");
5163 emitcode ("add", "a,#!constbyte",
5164 (unsigned int) (lit & 0x0FFL));
5167 emitcode ("addc", "a,#!constbyte",
5168 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5173 emitcode ("push", "acc");
5175 aopPut (IC_RESULT (ic), "a", offset);
5179 _endLazyDPSEvaluation ();
5183 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
5185 size = getDataSize (IC_LEFT (ic));
5186 rSize = getDataSize (IC_RESULT (ic));
5188 ADJUST_PUSHED_RESULT(size, rSize);
5190 _startLazyDPSEvaluation ();
5193 emitcode ("pop", "acc");
5194 aopPut (IC_RESULT (ic), "a", size);
5196 _endLazyDPSEvaluation ();
5199 adjustArithmeticResult (ic);
5202 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5203 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5204 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5208 /*-----------------------------------------------------------------*/
5209 /* genMultbits :- multiplication of bits */
5210 /*-----------------------------------------------------------------*/
5212 genMultbits (operand * left,
5217 D(emitcode (";", "genMultbits"));
5219 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5220 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5221 aopOp(result, ic, TRUE, FALSE);
5225 /*-----------------------------------------------------------------*/
5226 /* genMultOneByte : 8*8=8/16 bit multiplication */
5227 /*-----------------------------------------------------------------*/
5229 genMultOneByte (operand * left,
5236 bool runtimeSign, compiletimeSign;
5237 bool lUnsigned, rUnsigned, pushedB;
5239 /* (if two literals: the value is computed before) */
5240 /* if one literal, literal on the right */
5241 if (AOP_TYPE (left) == AOP_LIT)
5246 /* emitcode (";", "swapped left and right"); */
5248 /* if no literal, unsigned on the right: shorter code */
5249 if ( AOP_TYPE (right) != AOP_LIT
5250 && SPEC_USIGN (getSpec (operandType (left))))
5257 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5258 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5262 if ((lUnsigned && rUnsigned)
5263 /* sorry, I don't know how to get size
5264 without calling aopOp (result,...);
5265 see Feature Request */
5266 /* || size == 1 */ ) /* no, this is not a bug; with a 1 byte result there's
5267 no need to take care about the signedness! */
5269 /* just an unsigned 8 * 8 = 8 multiply
5271 /* emitcode (";","unsigned"); */
5272 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
5273 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
5274 emitcode ("mul", "ab");
5277 aopOp (result, ic, TRUE, FALSE);
5278 size = AOP_SIZE (result);
5280 if (size < 1 || size > 2)
5282 /* this should never happen */
5283 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
5284 size, __FILE__, lineno);
5288 aopPut (result, "a", 0);
5291 aopPut (result, "b", 1);
5297 /* we have to do a signed multiply */
5298 /* emitcode (";", "signed"); */
5300 /* now sign adjust for both left & right */
5302 /* let's see what's needed: */
5303 /* apply negative sign during runtime */
5304 runtimeSign = FALSE;
5305 /* negative sign from literals */
5306 compiletimeSign = FALSE;
5310 if (AOP_TYPE(left) == AOP_LIT)
5312 /* signed literal */
5313 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5315 compiletimeSign = TRUE;
5318 /* signed but not literal */
5324 if (AOP_TYPE(right) == AOP_LIT)
5326 /* signed literal */
5327 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5329 compiletimeSign ^= TRUE;
5332 /* signed but not literal */
5336 /* initialize F0, which stores the runtime sign */
5339 if (compiletimeSign)
5340 emitcode ("setb", "F0"); /* set sign flag */
5342 emitcode ("clr", "F0"); /* reset sign flag */
5345 /* save the signs of the operands */
5346 if (AOP_TYPE(right) == AOP_LIT)
5348 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5350 if (!rUnsigned && val < 0)
5351 emitcode ("mov", "b,#!constbyte", -val);
5353 emitcode ("mov", "b,#!constbyte", (unsigned char) val);
5355 else /* ! literal */
5357 if (rUnsigned) /* emitcode (";", "signed"); */
5358 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
5361 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
5362 lbl = newiTempLabel (NULL);
5363 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5364 emitcode ("cpl", "F0"); /* complement sign flag */
5365 emitcode ("cpl", "a"); /* 2's complement */
5366 emitcode ("inc", "a");
5367 emitcode ("", "!tlabeldef", lbl->key + 100);
5368 emitcode ("mov", "b,a");
5372 if (AOP_TYPE(left) == AOP_LIT)
5374 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5376 if (!lUnsigned && val < 0)
5377 emitcode ("mov", "a,#!constbyte", -val);
5379 emitcode ("mov", "a,#!constbyte", (unsigned char) val);
5381 else /* ! literal */
5383 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
5385 if (!lUnsigned) /* emitcode (";", "signed"); */
5387 lbl = newiTempLabel (NULL);
5388 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5389 emitcode ("cpl", "F0"); /* complement sign flag */
5390 emitcode ("cpl", "a"); /* 2's complement */
5391 emitcode ("inc", "a");
5392 emitcode ("", "!tlabeldef", lbl->key + 100);
5396 /* now the multiplication */
5397 emitcode ("mul", "ab");
5399 aopOp(result, ic, TRUE, FALSE);
5400 size = AOP_SIZE (result);
5402 if (size < 1 || size > 2)
5404 /* this should never happen */
5405 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
5406 size, __FILE__, lineno);
5410 if (runtimeSign || compiletimeSign)
5412 lbl = newiTempLabel (NULL);
5414 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5415 emitcode ("cpl", "a"); /* lsb 2's complement */
5417 emitcode ("inc", "a"); /* inc doesn't set carry flag */
5420 emitcode ("add", "a,#1"); /* this sets carry flag */
5421 emitcode ("xch", "a,b");
5422 emitcode ("cpl", "a"); /* msb 2's complement */
5423 emitcode ("addc", "a,#0");
5424 emitcode ("xch", "a,b");
5426 emitcode ("", "!tlabeldef", lbl->key + 100);
5428 aopPut (result, "a", 0);
5431 aopPut (result, "b", 1);
5436 /*-----------------------------------------------------------------*/
5437 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
5438 /*-----------------------------------------------------------------*/
5439 static void genMultTwoByte (operand *left, operand *right,
5440 operand *result, iCode *ic)
5442 sym_link *retype = getSpec(operandType(right));
5443 sym_link *letype = getSpec(operandType(left));
5444 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5447 if (AOP_TYPE (left) == AOP_LIT) {
5452 /* save EA bit in F1 */
5453 lbl = newiTempLabel(NULL);
5454 emitcode ("setb","F1");
5455 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5456 emitcode ("clr","F1");
5457 emitcode("","!tlabeldef",lbl->key+100);
5459 /* load up MB with right */
5461 emitcode("clr","F0");
5462 if (AOP_TYPE(right) == AOP_LIT) {
5463 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5465 emitcode("setb","F0");
5468 emitcode ("mov","mb,#!constbyte",val & 0xff);
5469 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5471 lbl = newiTempLabel(NULL);
5472 emitcode ("mov","b,%s",aopGet(right,0,FALSE,FALSE,NULL));
5473 emitcode ("mov","a,%s",aopGet(right,1,FALSE,FALSE,NULL));
5474 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5475 emitcode ("xch", "a,b");
5476 emitcode ("cpl","a");
5477 emitcode ("add", "a,#1");
5478 emitcode ("xch", "a,b");
5479 emitcode ("cpl", "a"); // msb
5480 emitcode ("addc", "a,#0");
5481 emitcode ("setb","F0");
5482 emitcode ("","!tlabeldef",lbl->key+100);
5483 emitcode ("mov","mb,b");
5484 emitcode ("mov","mb,a");
5487 emitcode ("mov","mb,%s",aopGet(right,0,FALSE,FALSE,NULL));
5488 emitcode ("mov","mb,%s",aopGet(right,1,FALSE,FALSE,NULL));
5490 /* load up MA with left */
5492 lbl = newiTempLabel(NULL);
5493 emitcode ("mov","b,%s",aopGet(left,0,FALSE,FALSE,NULL));
5494 emitcode ("mov","a,%s",aopGet(left,1,FALSE,FALSE,NULL));
5495 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5496 emitcode ("xch", "a,b");
5497 emitcode ("cpl","a");
5498 emitcode ("add", "a,#1");
5499 emitcode ("xch", "a,b");
5500 emitcode ("cpl", "a"); // msb
5501 emitcode ("addc","a,#0");
5502 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5503 emitcode ("setb","F0");
5504 emitcode ("","!tlabeldef",lbl->key+100);
5505 emitcode ("mov","ma,b");
5506 emitcode ("mov","ma,a");
5508 emitcode ("mov","ma,%s",aopGet(left,0,FALSE,FALSE,NULL));
5509 emitcode ("mov","ma,%s",aopGet(left,1,FALSE,FALSE,NULL));
5511 /* wait for multiplication to finish */
5512 lbl = newiTempLabel(NULL);
5513 emitcode("","!tlabeldef", lbl->key+100);
5514 emitcode("mov","a,mcnt1");
5515 emitcode("anl","a,#!constbyte",0x80);
5516 emitcode("jnz","!tlabel",lbl->key+100);
5518 freeAsmop (left, NULL, ic, TRUE);
5519 freeAsmop (right, NULL, ic,TRUE);
5520 aopOp(result, ic, TRUE, FALSE);
5522 /* if unsigned then simple */
5524 emitcode ("mov","a,ma");
5525 if (AOP_SIZE(result) >= 4) aopPut(result,"a",3);
5526 emitcode ("mov","a,ma");
5527 if (AOP_SIZE(result) >= 3) aopPut(result,"a",2);
5528 aopPut(result,"ma",1);
5529 aopPut(result,"ma",0);
5531 emitcode("push","ma");
5532 emitcode("push","ma");
5533 emitcode("push","ma");
5535 /* negate result if needed */
5536 lbl = newiTempLabel(NULL);
5537 emitcode("jnb","F0,!tlabel",lbl->key+100);
5538 emitcode("cpl","a");
5539 emitcode("add","a,#1");
5540 emitcode("","!tlabeldef", lbl->key+100);
5541 if (AOP_TYPE(result) == AOP_ACC)
5543 D(emitcode(";", "ACC special case."););
5544 /* We know result is the only live aop, and
5545 * it's obviously not a DPTR2, so AP is available.
5547 emitcode("mov", "%s,acc", DP2_RESULT_REG);
5551 aopPut(result,"a",0);
5554 emitcode("pop","acc");
5555 lbl = newiTempLabel(NULL);
5556 emitcode("jnb","F0,!tlabel",lbl->key+100);
5557 emitcode("cpl","a");
5558 emitcode("addc","a,#0");
5559 emitcode("","!tlabeldef", lbl->key+100);
5560 aopPut(result,"a",1);
5561 emitcode("pop","acc");
5562 if (AOP_SIZE(result) >= 3) {
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",2);
5570 emitcode("pop","acc");
5571 if (AOP_SIZE(result) >= 4) {
5572 lbl = newiTempLabel(NULL);
5573 emitcode("jnb","F0,!tlabel",lbl->key+100);
5574 emitcode("cpl","a");
5575 emitcode("addc","a,#0");
5576 emitcode("","!tlabeldef", lbl->key+100);
5577 aopPut(result,"a",3);
5579 if (AOP_TYPE(result) == AOP_ACC)
5581 /* We stashed the result away above. */
5582 emitcode("mov", "acc,%s", DP2_RESULT_REG);
5586 freeAsmop (result, NULL, ic, TRUE);
5588 /* restore EA bit in F1 */
5589 lbl = newiTempLabel(NULL);
5590 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5591 emitcode ("setb","EA");
5592 emitcode("","!tlabeldef",lbl->key+100);
5596 /*-----------------------------------------------------------------*/
5597 /* genMult - generates code for multiplication */
5598 /*-----------------------------------------------------------------*/
5600 genMult (iCode * ic)
5602 operand *left = IC_LEFT (ic);
5603 operand *right = IC_RIGHT (ic);
5604 operand *result = IC_RESULT (ic);
5606 D (emitcode (";", "genMult "));
5608 /* assign the asmops */
5611 /* special cases first */
5613 if (AOP_TYPE (left) == AOP_CRY &&
5614 AOP_TYPE (right) == AOP_CRY)
5616 genMultbits (left, right, result, ic);
5620 /* if both are of size == 1 */
5621 if (AOP_SIZE (left) == 1 &&
5622 AOP_SIZE (right) == 1)
5624 genMultOneByte (left, right, result, ic);
5628 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5629 /* use the ds390 ARITHMETIC accel UNIT */
5630 genMultTwoByte (left, right, result, ic);
5633 /* should have been converted to function call */
5637 freeAsmop (result, NULL, ic, TRUE);
5638 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5639 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5642 /*-----------------------------------------------------------------*/
5643 /* genDivbits :- division of bits */
5644 /*-----------------------------------------------------------------*/
5646 genDivbits (operand * left,
5654 D(emitcode ("; genDivbits",""));
5658 /* the result must be bit */
5659 LOAD_AB_FOR_DIV (left, right, l);
5660 emitcode ("div", "ab");
5661 emitcode ("rrc", "a");
5662 aopOp(result, ic, TRUE, FALSE);
5666 aopPut (result, "c", 0);
5669 /*-----------------------------------------------------------------*/
5670 /* genDivOneByte : 8 bit division */
5671 /*-----------------------------------------------------------------*/
5673 genDivOneByte (operand * left,
5678 bool lUnsigned, rUnsigned, pushedB;
5679 bool runtimeSign, compiletimeSign;
5684 D(emitcode ("; genDivOneByte",""));
5687 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5688 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5692 /* signed or unsigned */
5693 if (lUnsigned && rUnsigned)
5695 /* unsigned is easy */
5696 LOAD_AB_FOR_DIV (left, right, l);
5697 emitcode ("div", "ab");
5700 aopOp (result, ic, TRUE, FALSE);
5701 aopPut (result, "a", 0);
5704 size = AOP_SIZE (result) - 1;
5707 aopPut (result, zero, offset++);
5713 /* signed is a little bit more difficult */
5715 /* now sign adjust for both left & right */
5717 /* let's see what's needed: */
5718 /* apply negative sign during runtime */
5719 runtimeSign = FALSE;
5720 /* negative sign from literals */
5721 compiletimeSign = FALSE;
5725 if (AOP_TYPE(left) == AOP_LIT)
5727 /* signed literal */
5728 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5730 compiletimeSign = TRUE;
5733 /* signed but not literal */
5739 if (AOP_TYPE(right) == AOP_LIT)
5741 /* signed literal */
5742 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5744 compiletimeSign ^= TRUE;
5747 /* signed but not literal */
5751 /* initialize F0, which stores the runtime sign */
5754 if (compiletimeSign)
5755 emitcode ("setb", "F0"); /* set sign flag */
5757 emitcode ("clr", "F0"); /* reset sign flag */
5760 /* save the signs of the operands */
5761 if (AOP_TYPE(right) == AOP_LIT)
5763 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5765 if (!rUnsigned && val < 0)
5766 emitcode ("mov", "b,#0x%02x", -val);
5768 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5770 else /* ! literal */
5773 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
5776 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
5777 lbl = newiTempLabel (NULL);
5778 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5779 emitcode ("cpl", "F0"); /* complement sign flag */
5780 emitcode ("cpl", "a"); /* 2's complement */
5781 emitcode ("inc", "a");
5782 emitcode ("", "!tlabeldef", lbl->key + 100);
5783 emitcode ("mov", "b,a");
5787 if (AOP_TYPE(left) == AOP_LIT)
5789 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5791 if (!lUnsigned && val < 0)
5792 emitcode ("mov", "a,#0x%02x", -val);
5794 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5796 else /* ! literal */
5798 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
5802 lbl = newiTempLabel (NULL);
5803 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5804 emitcode ("cpl", "F0"); /* complement sign flag */
5805 emitcode ("cpl", "a"); /* 2's complement */
5806 emitcode ("inc", "a");
5807 emitcode ("", "!tlabeldef", lbl->key + 100);
5811 /* now the division */
5812 emitcode ("nop", "; workaround for DS80C390 div bug.");
5813 emitcode ("div", "ab");
5815 if (runtimeSign || compiletimeSign)
5817 lbl = newiTempLabel (NULL);
5819 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5820 emitcode ("cpl", "a"); /* lsb 2's complement */
5821 emitcode ("inc", "a");
5822 emitcode ("", "!tlabeldef", lbl->key + 100);
5825 aopOp (result, ic, TRUE, FALSE);
5826 size = AOP_SIZE (result) - 1;
5830 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5831 then the result will be in b, a */
5832 emitcode ("mov", "b,a"); /* 1 */
5833 /* msb is 0x00 or 0xff depending on the sign */
5836 emitcode ("mov", "c,F0");
5837 emitcode ("subb", "a,acc");
5838 emitcode ("xch", "a,b"); /* 2 */
5840 aopPut (result, "b", offset++); /* write msb's */
5842 else /* compiletimeSign */
5844 aopPut (result, "#0xff", offset++); /* write msb's */
5846 aopPut (result, "a", 0); /* 3: write lsb */
5851 aopOp(result, ic, TRUE, FALSE);
5852 size = AOP_SIZE (result) - 1;
5854 aopPut (result, "a", 0);
5856 aopPut (result, zero, offset++);
5862 /*-----------------------------------------------------------------*/
5863 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
5864 /*-----------------------------------------------------------------*/
5865 static void genDivTwoByte (operand *left, operand *right,
5866 operand *result, iCode *ic)
5868 sym_link *retype = getSpec(operandType(right));
5869 sym_link *letype = getSpec(operandType(left));
5870 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5873 /* save EA bit in F1 */
5874 lbl = newiTempLabel(NULL);
5875 emitcode ("setb","F1");
5876 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5877 emitcode ("clr","F1");
5878 emitcode("","!tlabeldef",lbl->key+100);
5880 /* load up MA with left */
5882 emitcode("clr","F0");
5883 lbl = newiTempLabel(NULL);
5884 emitcode ("mov","b,%s",aopGet(left,0,FALSE,FALSE,NULL));
5885 emitcode ("mov","a,%s",aopGet(left,1,FALSE,FALSE,NULL));
5886 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5887 emitcode ("xch", "a,b");
5888 emitcode ("cpl","a");
5889 emitcode ("add", "a,#1");
5890 emitcode ("xch", "a,b");
5891 emitcode ("cpl", "a"); // msb
5892 emitcode ("addc","a,#0");
5893 emitcode ("setb","F0");
5894 emitcode ("","!tlabeldef",lbl->key+100);
5895 emitcode ("mov","ma,b");
5896 emitcode ("mov","ma,a");
5898 emitcode ("mov","ma,%s",aopGet(left,0,FALSE,FALSE,NULL));
5899 emitcode ("mov","ma,%s",aopGet(left,1,FALSE,FALSE,NULL));
5902 /* load up MB with right */
5904 if (AOP_TYPE(right) == AOP_LIT) {
5905 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5907 lbl = newiTempLabel(NULL);
5908 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5909 emitcode("setb","F0");
5910 emitcode ("","!tlabeldef",lbl->key+100);
5913 emitcode ("mov","mb,#!constbyte",val & 0xff);
5914 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5916 lbl = newiTempLabel(NULL);
5917 emitcode ("mov","b,%s",aopGet(right,0,FALSE,FALSE,NULL));
5918 emitcode ("mov","a,%s",aopGet(right,1,FALSE,FALSE,NULL));
5919 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5920 emitcode ("xch", "a,b");
5921 emitcode ("cpl","a");
5922 emitcode ("add", "a,#1");
5923 emitcode ("xch", "a,b");
5924 emitcode ("cpl", "a"); // msb
5925 emitcode ("addc", "a,#0");
5926 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5927 emitcode ("setb","F0");
5928 emitcode ("","!tlabeldef",lbl->key+100);
5929 emitcode ("mov","mb,b");
5930 emitcode ("mov","mb,a");
5933 emitcode ("mov","mb,%s",aopGet(right,0,FALSE,FALSE,NULL));
5934 emitcode ("mov","mb,%s",aopGet(right,1,FALSE,FALSE,NULL));
5937 /* wait for multiplication to finish */
5938 lbl = newiTempLabel(NULL);
5939 emitcode("","!tlabeldef", lbl->key+100);
5940 emitcode("mov","a,mcnt1");
5941 emitcode("anl","a,#!constbyte",0x80);
5942 emitcode("jnz","!tlabel",lbl->key+100);
5944 freeAsmop (left, NULL, ic, TRUE);
5945 freeAsmop (right, NULL, ic,TRUE);
5946 aopOp(result, ic, TRUE, FALSE);
5948 /* if unsigned then simple */
5950 aopPut(result,"ma",1);
5951 aopPut(result,"ma",0);
5953 emitcode("push","ma");
5955 /* negate result if needed */
5956 lbl = newiTempLabel(NULL);
5957 emitcode("jnb","F0,!tlabel",lbl->key+100);
5958 emitcode("cpl","a");
5959 emitcode("add","a,#1");
5960 emitcode("","!tlabeldef", lbl->key+100);
5961 aopPut(result,"a",0);
5962 emitcode("pop","acc");
5963 lbl = newiTempLabel(NULL);
5964 emitcode("jnb","F0,!tlabel",lbl->key+100);
5965 emitcode("cpl","a");
5966 emitcode("addc","a,#0");
5967 emitcode("","!tlabeldef", lbl->key+100);
5968 aopPut(result,"a",1);
5970 freeAsmop (result, NULL, ic, TRUE);
5971 /* restore EA bit in F1 */
5972 lbl = newiTempLabel(NULL);
5973 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5974 emitcode ("setb","EA");
5975 emitcode("","!tlabeldef",lbl->key+100);
5979 /*-----------------------------------------------------------------*/
5980 /* genDiv - generates code for division */
5981 /*-----------------------------------------------------------------*/
5985 operand *left = IC_LEFT (ic);
5986 operand *right = IC_RIGHT (ic);
5987 operand *result = IC_RESULT (ic);
5989 D (emitcode (";", "genDiv "));
5991 /* assign the amsops */
5994 /* special cases first */
5996 if (AOP_TYPE (left) == AOP_CRY &&
5997 AOP_TYPE (right) == AOP_CRY)
5999 genDivbits (left, right, result, ic);
6003 /* if both are of size == 1 */
6004 if (AOP_SIZE (left) == 1 &&
6005 AOP_SIZE (right) == 1)
6007 genDivOneByte (left, right, result, ic);
6011 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
6012 /* use the ds390 ARITHMETIC accel UNIT */
6013 genDivTwoByte (left, right, result, ic);
6016 /* should have been converted to function call */
6019 freeAsmop (result, NULL, ic, TRUE);
6020 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6021 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6024 /*-----------------------------------------------------------------*/
6025 /* genModbits :- modulus of bits */
6026 /*-----------------------------------------------------------------*/
6028 genModbits (operand * left,
6036 D(emitcode ("; genModbits",""));
6040 /* the result must be bit */
6041 LOAD_AB_FOR_DIV (left, right, l);
6042 emitcode ("div", "ab");
6043 emitcode ("mov", "a,b");
6044 emitcode ("rrc", "a");
6045 aopOp(result, ic, TRUE, FALSE);
6049 aopPut (result, "c", 0);
6052 /*-----------------------------------------------------------------*/
6053 /* genModOneByte : 8 bit modulus */
6054 /*-----------------------------------------------------------------*/
6056 genModOneByte (operand * left,
6061 bool lUnsigned, rUnsigned, pushedB;
6062 bool runtimeSign, compiletimeSign;
6067 D(emitcode ("; genModOneByte",""));
6070 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
6071 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
6075 /* signed or unsigned */
6076 if (lUnsigned && rUnsigned)
6078 /* unsigned is easy */
6079 LOAD_AB_FOR_DIV (left, right, l);
6080 emitcode ("div", "ab");
6081 aopOp (result, ic, TRUE, FALSE);
6082 aopPut (result, "b", 0);
6084 for (size = AOP_SIZE (result) - 1; size--;)
6085 aopPut (result, zero, offset++);
6091 /* signed is a little bit more difficult */
6093 /* now sign adjust for both left & right */
6095 /* modulus: sign of the right operand has no influence on the result! */
6096 if (AOP_TYPE(right) == AOP_LIT)
6098 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
6100 if (!rUnsigned && val < 0)
6101 emitcode ("mov", "b,#0x%02x", -val);
6103 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
6105 else /* not literal */
6108 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
6111 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
6112 lbl = newiTempLabel (NULL);
6113 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
6114 emitcode ("cpl", "a"); /* 2's complement */
6115 emitcode ("inc", "a");
6116 emitcode ("", "!tlabeldef", lbl->key + 100);
6117 emitcode ("mov", "b,a");
6121 /* let's see what's needed: */
6122 /* apply negative sign during runtime */
6123 runtimeSign = FALSE;
6124 /* negative sign from literals */
6125 compiletimeSign = FALSE;
6127 /* sign adjust left side */
6128 if (AOP_TYPE(left) == AOP_LIT)
6130 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
6132 if (!lUnsigned && val < 0)
6134 compiletimeSign = TRUE; /* set sign flag */
6135 emitcode ("mov", "a,#0x%02x", -val);
6138 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
6140 else /* ! literal */
6142 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
6147 emitcode ("clr", "F0"); /* clear sign flag */
6149 lbl = newiTempLabel (NULL);
6150 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
6151 emitcode ("setb", "F0"); /* set sign flag */
6152 emitcode ("cpl", "a"); /* 2's complement */
6153 emitcode ("inc", "a");
6154 emitcode ("", "!tlabeldef", lbl->key + 100);
6158 /* now the modulus */
6159 emitcode ("nop", "; workaround for DS80C390 div bug.");
6160 emitcode ("div", "ab");
6162 if (runtimeSign || compiletimeSign)
6164 emitcode ("mov", "a,b");
6165 lbl = newiTempLabel (NULL);
6167 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
6168 emitcode ("cpl", "a"); /* lsb 2's complement */
6169 emitcode ("inc", "a");
6170 emitcode ("", "!tlabeldef", lbl->key + 100);
6173 aopOp (result, ic, TRUE, FALSE);
6174 size = AOP_SIZE (result) - 1;
6178 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
6179 then the result will be in b, a */
6180 emitcode ("mov", "b,a"); /* 1 */
6181 /* msb is 0x00 or 0xff depending on the sign */
6184 emitcode ("mov", "c,F0");
6185 emitcode ("subb", "a,acc");
6186 emitcode ("xch", "a,b"); /* 2 */
6188 aopPut (result, "b", offset++); /* write msb's */
6190 else /* compiletimeSign */
6192 aopPut (result, "#0xff", offset++); /* write msb's */
6194 aopPut (result, "a", 0); /* 3: write lsb */
6199 aopOp(result, ic, TRUE, FALSE);
6200 size = AOP_SIZE (result) - 1;
6202 aopPut (result, "b", 0);
6204 aopPut (result, zero, offset++);
6210 /*-----------------------------------------------------------------*/
6211 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
6212 /*-----------------------------------------------------------------*/
6213 static void genModTwoByte (operand *left, operand *right,
6214 operand *result, iCode *ic)
6216 sym_link *retype = getSpec(operandType(right));
6217 sym_link *letype = getSpec(operandType(left));
6218 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
6221 /* load up MA with left */
6222 /* save EA bit in F1 */
6223 lbl = newiTempLabel(NULL);
6224 emitcode ("setb","F1");
6225 emitcode ("jbc","EA,!tlabel",lbl->key+100);
6226 emitcode ("clr","F1");
6227 emitcode("","!tlabeldef",lbl->key+100);
6230 lbl = newiTempLabel(NULL);
6231 emitcode ("mov","b,%s",aopGet(left,0,FALSE,FALSE,NULL));
6232 emitcode ("mov","a,%s",aopGet(left,1,FALSE,FALSE,NULL));
6233 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
6234 emitcode ("xch", "a,b");
6235 emitcode ("cpl","a");
6236 emitcode ("add", "a,#1");
6237 emitcode ("xch", "a,b");
6238 emitcode ("cpl", "a"); // msb
6239 emitcode ("addc","a,#0");
6240 emitcode ("","!tlabeldef",lbl->key+100);
6241 emitcode ("mov","ma,b");
6242 emitcode ("mov","ma,a");
6244 emitcode ("mov","ma,%s",aopGet(left,0,FALSE,FALSE,NULL));
6245 emitcode ("mov","ma,%s",aopGet(left,1,FALSE,FALSE,NULL));
6248 /* load up MB with right */
6250 if (AOP_TYPE(right) == AOP_LIT) {
6251 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
6255 emitcode ("mov","mb,#!constbyte",val & 0xff);
6256 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
6258 lbl = newiTempLabel(NULL);
6259 emitcode ("mov","b,%s",aopGet(right,0,FALSE,FALSE,NULL));
6260 emitcode ("mov","a,%s",aopGet(right,1,FALSE,FALSE,NULL));
6261 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
6262 emitcode ("xch", "a,b");
6263 emitcode ("cpl","a");
6264 emitcode ("add", "a,#1");
6265 emitcode ("xch", "a,b");
6266 emitcode ("cpl", "a"); // msb
6267 emitcode ("addc", "a,#0");
6268 emitcode ("","!tlabeldef",lbl->key+100);
6269 emitcode ("mov","mb,b");
6270 emitcode ("mov","mb,a");
6273 emitcode ("mov","mb,%s",aopGet(right,0,FALSE,FALSE,NULL));
6274 emitcode ("mov","mb,%s",aopGet(right,1,FALSE,FALSE,NULL));
6277 /* wait for multiplication to finish */
6278 lbl = newiTempLabel(NULL);
6279 emitcode("","!tlabeldef", lbl->key+100);
6280 emitcode("mov","a,mcnt1");
6281 emitcode("anl","a,#!constbyte",0x80);
6282 emitcode("jnz","!tlabel",lbl->key+100);
6284 freeAsmop (left, NULL, ic, TRUE);
6285 freeAsmop (right, NULL, ic,TRUE);
6286 aopOp(result, ic, TRUE, FALSE);
6288 aopPut(result,"mb",1);
6289 aopPut(result,"mb",0);
6290 freeAsmop (result, NULL, ic, TRUE);
6292 /* restore EA bit in F1 */
6293 lbl = newiTempLabel(NULL);
6294 emitcode ("jnb","F1,!tlabel",lbl->key+100);
6295 emitcode ("setb","EA");
6296 emitcode("","!tlabeldef",lbl->key+100);
6300 /*-----------------------------------------------------------------*/
6301 /* genMod - generates code for division */
6302 /*-----------------------------------------------------------------*/
6306 operand *left = IC_LEFT (ic);
6307 operand *right = IC_RIGHT (ic);
6308 operand *result = IC_RESULT (ic);
6310 D (emitcode (";", "genMod "));
6312 /* assign the asmops */
6315 /* special cases first */
6317 if (AOP_TYPE (left) == AOP_CRY &&
6318 AOP_TYPE (right) == AOP_CRY)
6320 genModbits (left, right, result, ic);
6324 /* if both are of size == 1 */
6325 if (AOP_SIZE (left) == 1 &&
6326 AOP_SIZE (right) == 1)
6328 genModOneByte (left, right, result, ic);
6332 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
6333 /* use the ds390 ARITHMETIC accel UNIT */
6334 genModTwoByte (left, right, result, ic);
6338 /* should have been converted to function call */
6342 freeAsmop (result, NULL, ic, TRUE);
6343 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6344 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6347 /*-----------------------------------------------------------------*/
6348 /* genIfxJump :- will create a jump depending on the ifx */
6349 /*-----------------------------------------------------------------*/
6351 genIfxJump (iCode * ic, char *jval)
6354 symbol *tlbl = newiTempLabel (NULL);
6357 D (emitcode (";", "genIfxJump"));
6359 /* if true label then we jump if condition
6363 jlbl = IC_TRUE (ic);
6364 inst = ((strcmp (jval, "a") == 0 ? "jz" :
6365 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
6369 /* false label is present */
6370 jlbl = IC_FALSE (ic);
6371 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
6372 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
6374 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
6375 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
6377 emitcode (inst, "!tlabel", tlbl->key + 100);
6378 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
6379 emitcode ("", "!tlabeldef", tlbl->key + 100);
6381 /* mark the icode as generated */
6385 /*-----------------------------------------------------------------*/
6386 /* genCmp :- greater or less than comparison */
6387 /*-----------------------------------------------------------------*/
6389 genCmp (operand * left, operand * right,
6390 iCode * ic, iCode * ifx, int sign)
6392 int size, offset = 0;
6393 unsigned long lit = 0L;
6396 D (emitcode (";", "genCmp"));
6398 result = IC_RESULT (ic);
6400 /* if left & right are bit variables */
6401 if (AOP_TYPE (left) == AOP_CRY &&
6402 AOP_TYPE (right) == AOP_CRY)
6404 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6405 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6409 /* subtract right from left if at the
6410 end the carry flag is set then we know that
6411 left is greater than right */
6412 size = max (AOP_SIZE (left), AOP_SIZE (right));
6414 /* if unsigned char cmp with lit, do cjne left,#right,zz */
6415 if ((size == 1) && !sign &&
6416 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
6418 symbol *lbl = newiTempLabel (NULL);
6419 emitcode ("cjne", "%s,%s,!tlabel",
6420 aopGet (left, offset, FALSE, FALSE, NULL),
6421 aopGet (right, offset, FALSE, FALSE, NULL),
6423 emitcode ("", "!tlabeldef", lbl->key + 100);
6427 if (AOP_TYPE (right) == AOP_LIT)
6429 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6430 /* optimize if(x < 0) or if(x >= 0) */
6439 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
6441 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6442 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6444 aopOp (result, ic, FALSE, FALSE);
6446 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
6448 freeAsmop (result, NULL, ic, TRUE);
6449 genIfxJump (ifx, "acc.7");
6454 emitcode ("rlc", "a");
6456 goto release_freedLR;
6464 // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
6465 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
6466 // emitcode (";", "genCmp #2");
6467 if (sign && (size == 0))
6469 // emitcode (";", "genCmp #3");
6470 emitcode ("xrl", "a,#!constbyte",0x80);
6471 if (AOP_TYPE (right) == AOP_LIT)
6473 unsigned long lit = (unsigned long)
6474 floatFromVal (AOP (right)->aopu.aop_lit);
6475 // emitcode (";", "genCmp #3.1");
6476 emitcode ("subb", "a,#!constbyte",
6477 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
6481 // emitcode (";", "genCmp #3.2");
6483 MOVB (aopGet (right, offset++, FALSE, FALSE, "b"));
6484 saveAccWarn = DEFAULT_ACC_WARNING;
6485 emitcode ("xrl", "b,#!constbyte",0x80);
6486 emitcode ("subb", "a,b");
6493 // emitcode (";", "genCmp #4");
6495 s = aopGet (right, offset++, FALSE, FALSE, "b");
6496 saveAccWarn = DEFAULT_ACC_WARNING;
6498 emitcode ("subb", "a,%s", s);
6505 /* Don't need the left & right operands any more; do need the result. */
6506 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6507 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6509 aopOp (result, ic, FALSE, FALSE);
6513 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6519 /* if the result is used in the next
6520 ifx conditional branch then generate
6521 code a little differently */
6524 genIfxJump (ifx, "c");
6530 /* leave the result in acc */
6532 freeAsmop (result, NULL, ic, TRUE);
6535 /*-----------------------------------------------------------------*/
6536 /* genCmpGt :- greater than comparison */
6537 /*-----------------------------------------------------------------*/
6539 genCmpGt (iCode * ic, iCode * ifx)
6541 operand *left, *right;
6542 sym_link *letype, *retype;
6545 D (emitcode (";", "genCmpGt"));
6547 left = IC_LEFT (ic);
6548 right = IC_RIGHT (ic);
6550 letype = getSpec (operandType (left));
6551 retype = getSpec (operandType (right));
6552 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6554 /* assign the left & right amsops */
6557 genCmp (right, left, ic, ifx, sign);
6560 /*-----------------------------------------------------------------*/
6561 /* genCmpLt - less than comparisons */
6562 /*-----------------------------------------------------------------*/
6564 genCmpLt (iCode * ic, iCode * ifx)
6566 operand *left, *right;
6567 sym_link *letype, *retype;
6570 D (emitcode (";", "genCmpLt "));
6572 left = IC_LEFT (ic);
6573 right = IC_RIGHT (ic);
6575 letype = getSpec (operandType (left));
6576 retype = getSpec (operandType (right));
6577 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6579 /* assign the left & right amsops */
6582 genCmp (left, right, ic, ifx, sign);
6585 /*-----------------------------------------------------------------*/
6586 /* gencjneshort - compare and jump if not equal */
6587 /*-----------------------------------------------------------------*/
6589 gencjneshort (operand * left, operand * right, symbol * lbl)
6591 int size = max (AOP_SIZE (left), AOP_SIZE (right));
6593 unsigned long lit = 0L;
6595 D (emitcode (";", "gencjneshort"));
6597 /* if the left side is a literal or
6598 if the right is in a pointer register and left
6600 if ((AOP_TYPE (left) == AOP_LIT) ||
6601 (AOP_TYPE (left) == AOP_IMMD) ||
6602 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6609 if (AOP_TYPE (right) == AOP_LIT)
6610 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6612 if (opIsGptr (left) || opIsGptr (right))
6614 /* We are comparing a generic pointer to something.
6615 * Exclude the generic type byte from the comparison.
6618 D (emitcode (";", "cjneshort: generic ptr special case."););
6622 /* if the right side is a literal then anything goes */
6623 if (AOP_TYPE (right) == AOP_LIT &&
6624 AOP_TYPE (left) != AOP_DIR)
6628 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
6629 emitcode ("cjne", "a,%s,!tlabel",
6630 aopGet (right, offset, FALSE, FALSE, NULL),
6636 /* if the right side is in a register or in direct space or
6637 if the left is a pointer register & right is not */
6638 else if (AOP_TYPE (right) == AOP_REG ||
6639 AOP_TYPE (right) == AOP_DIR ||
6640 AOP_TYPE (right) == AOP_LIT ||
6641 AOP_TYPE (right) == AOP_IMMD ||
6642 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6643 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6647 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
6648 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6649 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6650 emitcode ("jnz", "!tlabel", lbl->key + 100);
6652 emitcode ("cjne", "a,%s,!tlabel",
6653 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG),
6660 /* right is a pointer reg need both a & b */
6663 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
6664 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
6665 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
6671 /*-----------------------------------------------------------------*/
6672 /* gencjne - compare and jump if not equal */
6673 /*-----------------------------------------------------------------*/
6675 gencjne (operand * left, operand * right, symbol * lbl)
6677 symbol *tlbl = newiTempLabel (NULL);
6679 D (emitcode (";", "gencjne"));
6681 gencjneshort (left, right, lbl);
6683 emitcode ("mov", "a,%s", one);
6684 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
6685 emitcode ("", "!tlabeldef", lbl->key + 100);
6686 emitcode ("clr", "a");
6687 emitcode ("", "!tlabeldef", tlbl->key + 100);
6690 /*-----------------------------------------------------------------*/
6691 /* genCmpEq - generates code for equal to */
6692 /*-----------------------------------------------------------------*/
6694 genCmpEq (iCode * ic, iCode * ifx)
6696 operand *left, *right, *result;
6698 D (emitcode (";", "genCmpEq"));
6701 AOP_SET_LOCALS (ic);
6703 /* if literal, literal on the right or
6704 if the right is in a pointer register and left
6706 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6707 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6709 operand *t = IC_RIGHT (ic);
6710 IC_RIGHT (ic) = IC_LEFT (ic);
6714 if (ifx && /* !AOP_SIZE(result) */
6715 OP_SYMBOL (result) &&
6716 OP_SYMBOL (result)->regType == REG_CND)
6719 /* if they are both bit variables */
6720 if (AOP_TYPE (left) == AOP_CRY &&
6721 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6723 if (AOP_TYPE (right) == AOP_LIT)
6725 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6728 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6729 emitcode ("cpl", "c");
6733 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6737 emitcode ("clr", "c");
6739 /* AOP_TYPE(right) == AOP_CRY */
6743 symbol *lbl = newiTempLabel (NULL);
6744 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6745 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6746 emitcode ("cpl", "c");
6747 emitcode ("", "!tlabeldef", (lbl->key + 100));
6749 /* if true label then we jump if condition
6751 tlbl = newiTempLabel (NULL);
6754 emitcode ("jnc", "!tlabel", tlbl->key + 100);
6755 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6759 emitcode ("jc", "!tlabel", tlbl->key + 100);
6760 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6762 emitcode ("", "!tlabeldef", tlbl->key + 100);
6766 tlbl = newiTempLabel (NULL);
6767 gencjneshort (left, right, tlbl);
6770 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6771 emitcode ("", "!tlabeldef", tlbl->key + 100);
6775 symbol *lbl = newiTempLabel (NULL);
6776 emitcode ("sjmp", "!tlabel", lbl->key + 100);
6777 emitcode ("", "!tlabeldef", tlbl->key + 100);
6778 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6779 emitcode ("", "!tlabeldef", lbl->key + 100);
6782 /* mark the icode as generated */
6785 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6786 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6790 /* if they are both bit variables */
6791 if (AOP_TYPE (left) == AOP_CRY &&
6792 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6794 if (AOP_TYPE (right) == AOP_LIT)
6796 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6799 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6800 emitcode ("cpl", "c");
6804 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6808 emitcode ("clr", "c");
6810 /* AOP_TYPE(right) == AOP_CRY */
6814 symbol *lbl = newiTempLabel (NULL);
6815 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6816 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6817 emitcode ("cpl", "c");
6818 emitcode ("", "!tlabeldef", (lbl->key + 100));
6821 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6822 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6824 aopOp (result, ic, TRUE, FALSE);
6827 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6834 genIfxJump (ifx, "c");
6837 /* if the result is used in an arithmetic operation
6838 then put the result in place */
6843 gencjne (left, right, newiTempLabel (NULL));
6845 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6846 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6848 aopOp (result, ic, TRUE, FALSE);
6850 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6852 aopPut (result, "a", 0);
6857 genIfxJump (ifx, "a");
6860 /* if the result is used in an arithmetic operation
6861 then put the result in place */
6862 if (AOP_TYPE (result) != AOP_CRY)
6864 /* leave the result in acc */
6868 freeAsmop (result, NULL, ic, TRUE);
6871 /*-----------------------------------------------------------------*/
6872 /* ifxForOp - returns the icode containing the ifx for operand */
6873 /*-----------------------------------------------------------------*/
6875 ifxForOp (operand * op, iCode * ic)
6877 /* if true symbol then needs to be assigned */
6878 if (IS_TRUE_SYMOP (op))
6881 /* if this has register type condition and
6882 the next instruction is ifx with the same operand
6883 and live to of the operand is upto the ifx only then */
6885 ic->next->op == IFX &&
6886 IC_COND (ic->next)->key == op->key &&
6887 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6893 /*-----------------------------------------------------------------*/
6894 /* hasInc - operand is incremented before any other use */
6895 /*-----------------------------------------------------------------*/
6897 hasInc (operand *op, iCode *ic, int osize)
6899 sym_link *type = operandType(op);
6900 sym_link *retype = getSpec (type);
6901 iCode *lic = ic->next;
6904 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6905 if (!IS_SYMOP(op)) return NULL;
6907 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6908 if (IS_AGGREGATE(type->next)) return NULL;
6909 if (osize != (isize = getSize(type->next))) return NULL;
6912 /* if operand of the form op = op + <sizeof *op> */
6913 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6914 isOperandEqual(IC_RESULT(lic),op) &&
6915 isOperandLiteral(IC_RIGHT(lic)) &&
6916 operandLitValue(IC_RIGHT(lic)) == isize) {
6919 /* if the operand used or deffed */
6920 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6923 /* if GOTO or IFX */
6924 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6930 /*-----------------------------------------------------------------*/
6931 /* genAndOp - for && operation */
6932 /*-----------------------------------------------------------------*/
6934 genAndOp (iCode * ic)
6936 operand *left, *right, *result;
6939 D (emitcode (";", "genAndOp "));
6941 /* note here that && operations that are in an
6942 if statement are taken away by backPatchLabels
6943 only those used in arthmetic operations remain */
6945 AOP_SET_LOCALS (ic);
6947 /* if both are bit variables */
6948 if (AOP_TYPE (left) == AOP_CRY &&
6949 AOP_TYPE (right) == AOP_CRY)
6951 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6952 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6953 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6954 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6956 aopOp (result,ic,FALSE, FALSE);
6961 tlbl = newiTempLabel (NULL);
6963 emitcode ("jz", "!tlabel", tlbl->key + 100);
6965 emitcode ("", "!tlabeldef", tlbl->key + 100);
6966 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6967 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6969 aopOp (result,ic,FALSE, FALSE);
6972 freeAsmop (result, NULL, ic, TRUE);
6976 /*-----------------------------------------------------------------*/
6977 /* genOrOp - for || operation */
6978 /*-----------------------------------------------------------------*/
6980 genOrOp (iCode * ic)
6982 operand *left, *right, *result;
6985 D (emitcode (";", "genOrOp "));
6987 /* note here that || operations that are in an
6988 if statement are taken away by backPatchLabels
6989 only those used in arthmetic operations remain */
6991 AOP_SET_LOCALS (ic);
6993 /* if both are bit variables */
6994 if (AOP_TYPE (left) == AOP_CRY &&
6995 AOP_TYPE (right) == AOP_CRY)
6997 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6998 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6999 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7000 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7002 aopOp (result,ic,FALSE, FALSE);
7008 tlbl = newiTempLabel (NULL);
7010 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7012 emitcode ("", "!tlabeldef", tlbl->key + 100);
7013 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7014 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7016 aopOp (result,ic,FALSE, FALSE);
7021 freeAsmop (result, NULL, ic, TRUE);
7024 /*-----------------------------------------------------------------*/
7025 /* isLiteralBit - test if lit == 2^n */
7026 /*-----------------------------------------------------------------*/
7028 isLiteralBit (unsigned long lit)
7030 unsigned long pw[32] =
7031 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
7032 0x100L, 0x200L, 0x400L, 0x800L,
7033 0x1000L, 0x2000L, 0x4000L, 0x8000L,
7034 0x10000L, 0x20000L, 0x40000L, 0x80000L,
7035 0x100000L, 0x200000L, 0x400000L, 0x800000L,
7036 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
7037 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
7040 for (idx = 0; idx < 32; idx++)
7046 /*-----------------------------------------------------------------*/
7047 /* continueIfTrue - */
7048 /*-----------------------------------------------------------------*/
7050 continueIfTrue (iCode * ic)
7053 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
7057 /*-----------------------------------------------------------------*/
7059 /*-----------------------------------------------------------------*/
7061 jumpIfTrue (iCode * ic)
7064 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
7068 /*-----------------------------------------------------------------*/
7069 /* jmpTrueOrFalse - */
7070 /*-----------------------------------------------------------------*/
7072 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
7074 // ugly but optimized by peephole
7077 symbol *nlbl = newiTempLabel (NULL);
7078 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
7079 emitcode ("", "!tlabeldef", tlbl->key + 100);
7080 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
7081 emitcode ("", "!tlabeldef", nlbl->key + 100);
7085 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
7086 emitcode ("", "!tlabeldef", tlbl->key + 100);
7091 // Generate code to perform a bit-wise logic operation
7092 // on two operands in far space (assumed to already have been
7093 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
7094 // in far space. This requires pushing the result on the stack
7095 // then popping it into the result.
7097 genFarFarLogicOp(iCode *ic, char *logicOp)
7099 int size, resultSize, compSize;
7103 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
7104 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
7105 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
7107 _startLazyDPSEvaluation();
7108 for (size = compSize; (size--); offset++)
7110 MOVA (aopGet (IC_LEFT(ic), offset, FALSE, FALSE, NULL));
7111 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
7112 MOVA (aopGet (IC_RIGHT(ic), offset, FALSE, FALSE, NULL));
7114 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
7115 emitcode ("push", "acc");
7117 _endLazyDPSEvaluation();
7119 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7120 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7121 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
7123 resultSize = AOP_SIZE(IC_RESULT(ic));
7125 ADJUST_PUSHED_RESULT(compSize, resultSize);
7127 _startLazyDPSEvaluation();
7130 emitcode ("pop", "acc");
7131 aopPut (IC_RESULT (ic), "a", compSize);
7133 _endLazyDPSEvaluation();
7134 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
7138 /*-----------------------------------------------------------------*/
7139 /* genAnd - code for and */
7140 /*-----------------------------------------------------------------*/
7142 genAnd (iCode * ic, iCode * ifx)
7144 operand *left, *right, *result;
7145 int size, offset = 0;
7146 unsigned long lit = 0L;
7151 D (emitcode (";", "genAnd"));
7153 AOP_OP_3_NOFATAL (ic, pushResult);
7154 AOP_SET_LOCALS (ic);
7158 genFarFarLogicOp(ic, "anl");
7163 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7165 AOP_TYPE (left), AOP_TYPE (right));
7166 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7168 AOP_SIZE (left), AOP_SIZE (right));
7171 /* if left is a literal & right is not then exchange them */
7172 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7173 #ifdef LOGIC_OPS_BROKEN
7174 || AOP_NEEDSACC (left)
7178 operand *tmp = right;
7183 /* if result = right then exchange left and right */
7184 if (sameRegs (AOP (result), AOP (right)))
7186 operand *tmp = right;
7191 /* if right is bit then exchange them */
7192 if (AOP_TYPE (right) == AOP_CRY &&
7193 AOP_TYPE (left) != AOP_CRY)
7195 operand *tmp = right;
7199 if (AOP_TYPE (right) == AOP_LIT)
7200 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7202 size = AOP_SIZE (result);
7205 // result = bit & yy;
7206 if (AOP_TYPE (left) == AOP_CRY)
7208 // c = bit & literal;
7209 if (AOP_TYPE (right) == AOP_LIT)
7213 if (size && sameRegs (AOP (result), AOP (left)))
7216 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7221 if (size && (AOP_TYPE (result) == AOP_CRY))
7223 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
7226 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7231 emitcode ("clr", "c");
7236 if (AOP_TYPE (right) == AOP_CRY)
7239 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7240 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
7245 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
7247 emitcode ("rrc", "a");
7248 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
7256 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7257 genIfxJump (ifx, "c");
7261 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7262 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7263 if ((AOP_TYPE (right) == AOP_LIT) &&
7264 (AOP_TYPE (result) == AOP_CRY) &&
7265 (AOP_TYPE (left) != AOP_CRY))
7267 int posbit = isLiteralBit (lit);
7272 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE, NULL));
7276 switch (posbit & 0x07)
7278 case 0: emitcode ("rrc", "a");
7280 case 7: emitcode ("rlc", "a");
7282 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
7291 SNPRINTF (buffer, sizeof(buffer),
7292 "acc.%d", posbit & 0x07);
7293 genIfxJump (ifx, buffer);
7297 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
7304 symbol *tlbl = newiTempLabel (NULL);
7305 int sizel = AOP_SIZE (left);
7307 emitcode ("setb", "c");
7310 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
7312 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7314 if ((posbit = isLiteralBit (bytelit)) != 0)
7315 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
7318 if (bytelit != 0x0FFL)
7319 emitcode ("anl", "a,%s",
7320 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG));
7321 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7326 // bit = left & literal
7329 emitcode ("clr", "c");
7330 emitcode ("", "!tlabeldef", tlbl->key + 100);
7332 // if(left & literal)
7336 jmpTrueOrFalse (ifx, tlbl);
7338 emitcode ("", "!tlabeldef", tlbl->key + 100);
7346 /* if left is same as result */
7347 if (sameRegs (AOP (result), AOP (left)))
7349 for (; size--; offset++)
7351 if (AOP_TYPE (right) == AOP_LIT)
7353 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7354 if (bytelit == 0x0FF)
7356 /* dummy read of volatile operand */
7357 if (isOperandVolatile (left, FALSE))
7358 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7362 else if (bytelit == 0)
7364 aopPut (result, zero, offset);
7366 else if (IS_AOP_PREG (result))
7368 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7369 emitcode ("anl", "a,%s",
7370 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG));
7371 aopPut (result, "a", offset);
7374 emitcode ("anl", "%s,%s",
7375 aopGet (left, offset, FALSE, TRUE, NULL),
7376 aopGet (right, offset, FALSE, FALSE, NULL));
7380 if (AOP_TYPE (left) == AOP_ACC)
7381 emitcode ("anl", "a,%s",
7382 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7385 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7386 if (IS_AOP_PREG (result))
7388 emitcode ("anl", "a,%s",
7389 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7390 aopPut (result, "a", offset);
7393 emitcode ("anl", "%s,a",
7394 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7401 // left & result in different registers
7402 if (AOP_TYPE (result) == AOP_CRY)
7405 // if(size), result in bit
7406 // if(!size && ifx), conditional oper: if(left & right)
7407 symbol *tlbl = newiTempLabel (NULL);
7408 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
7410 emitcode ("setb", "c");
7413 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7414 emitcode ("anl", "a,%s",
7415 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7417 if (AOP_TYPE(left)==AOP_ACC)
7419 bool pushedB = pushB ();
7420 emitcode("mov", "b,a");
7421 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7422 emitcode("anl", "a,b");
7427 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7428 emitcode ("anl", "a,%s",
7429 aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7432 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7438 emitcode ("", "!tlabeldef", tlbl->key + 100);
7442 jmpTrueOrFalse (ifx, tlbl);
7444 emitcode ("", "!tlabeldef", tlbl->key + 100);
7448 for (; (size--); offset++)
7451 // result = left & right
7452 if (AOP_TYPE (right) == AOP_LIT)
7454 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7455 if (bytelit == 0x0FF)
7458 aopGet (left, offset, FALSE, FALSE, NULL),
7462 else if (bytelit == 0)
7464 /* dummy read of volatile operand */
7465 if (isOperandVolatile (left, FALSE))
7466 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7467 aopPut (result, zero, offset);
7470 D (emitcode (";", "better literal AND."););
7471 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7472 emitcode ("anl", "a, %s", aopGet (right, offset,
7473 FALSE, FALSE, DP2_RESULT_REG));
7478 // faster than result <- left, anl result,right
7479 // and better if result is SFR
7480 if (AOP_TYPE (left) == AOP_ACC)
7482 emitcode ("anl", "a,%s",
7483 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7487 char *rOp = aopGet (right, offset, FALSE, FALSE, NULL);
7488 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7490 emitcode("mov", "b,a");
7494 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7495 emitcode ("anl", "a,%s", rOp);
7498 aopPut (result, "a", offset);
7504 freeAsmop (result, NULL, ic, TRUE);
7505 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7506 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7509 /*-----------------------------------------------------------------*/
7510 /* genOr - code for or */
7511 /*-----------------------------------------------------------------*/
7513 genOr (iCode * ic, iCode * ifx)
7515 operand *left, *right, *result;
7516 int size, offset = 0;
7517 unsigned long lit = 0L;
7521 D (emitcode (";", "genOr "));
7523 AOP_OP_3_NOFATAL (ic, pushResult);
7524 AOP_SET_LOCALS (ic);
7528 genFarFarLogicOp(ic, "orl");
7534 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7536 AOP_TYPE (left), AOP_TYPE (right));
7537 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7539 AOP_SIZE (left), AOP_SIZE (right));
7542 /* if left is a literal & right is not then exchange them */
7543 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7544 #ifdef LOGIC_OPS_BROKEN
7545 || AOP_NEEDSACC (left) // I think this is a net loss now.
7549 operand *tmp = right;
7554 /* if result = right then exchange them */
7555 if (sameRegs (AOP (result), AOP (right)))
7557 operand *tmp = right;
7562 /* if right is bit then exchange them */
7563 if (AOP_TYPE (right) == AOP_CRY &&
7564 AOP_TYPE (left) != AOP_CRY)
7566 operand *tmp = right;
7570 if (AOP_TYPE (right) == AOP_LIT)
7571 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7573 size = AOP_SIZE (result);
7577 if (AOP_TYPE (left) == AOP_CRY)
7579 if (AOP_TYPE (right) == AOP_LIT)
7581 // c = bit | literal;
7584 // lit != 0 => result = 1
7585 if (AOP_TYPE (result) == AOP_CRY)
7588 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7590 continueIfTrue (ifx);
7593 emitcode ("setb", "c");
7597 // lit == 0 => result = left
7598 if (size && sameRegs (AOP (result), AOP (left)))
7600 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7605 if (AOP_TYPE (right) == AOP_CRY)
7608 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7609 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7614 symbol *tlbl = newiTempLabel (NULL);
7615 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
7616 emitcode ("setb", "c");
7617 emitcode ("jb", "%s,!tlabel",
7618 AOP (left)->aopu.aop_dir, tlbl->key + 100);
7620 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7621 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7623 jmpTrueOrFalse (ifx, tlbl);
7629 emitcode ("", "!tlabeldef", tlbl->key + 100);
7638 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7639 genIfxJump (ifx, "c");
7643 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7644 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7645 if ((AOP_TYPE (right) == AOP_LIT) &&
7646 (AOP_TYPE (result) == AOP_CRY) &&
7647 (AOP_TYPE (left) != AOP_CRY))
7653 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7655 continueIfTrue (ifx);
7660 // lit = 0, result = boolean(left)
7662 emitcode ("setb", "c");
7666 symbol *tlbl = newiTempLabel (NULL);
7667 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7669 emitcode ("", "!tlabeldef", tlbl->key + 100);
7673 genIfxJump (ifx, "a");
7681 /* if left is same as result */
7682 if (sameRegs (AOP (result), AOP (left)))
7684 for (; size--; offset++)
7686 if (AOP_TYPE (right) == AOP_LIT)
7688 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7691 /* dummy read of volatile operand */
7692 if (isOperandVolatile (left, FALSE))
7693 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7697 else if (bytelit == 0x0FF)
7699 aopPut (result, "#0xFF", offset);
7701 else if (IS_AOP_PREG (left))
7703 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7704 emitcode ("orl", "a,%s",
7705 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7706 aopPut (result, "a", offset);
7710 emitcode ("orl", "%s,%s",
7711 aopGet (left, offset, FALSE, TRUE, NULL),
7712 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7717 if (AOP_TYPE (left) == AOP_ACC)
7719 emitcode ("orl", "a,%s",
7720 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7724 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7725 if (IS_AOP_PREG (left))
7727 emitcode ("orl", "a,%s",
7728 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7729 aopPut (result, "a", offset);
7733 emitcode ("orl", "%s,a",
7734 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7742 // left & result in different registers
7743 if (AOP_TYPE (result) == AOP_CRY)
7746 // if(size), result in bit
7747 // if(!size && ifx), conditional oper: if(left | right)
7748 symbol *tlbl = newiTempLabel (NULL);
7749 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7751 emitcode ("setb", "c");
7754 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7755 emitcode ("orl", "a,%s",
7756 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7758 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7759 emitcode ("orl", "a,%s",
7760 aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7762 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7768 emitcode ("", "!tlabeldef", tlbl->key + 100);
7772 jmpTrueOrFalse (ifx, tlbl);
7774 emitcode ("", "!tlabeldef", tlbl->key + 100);
7778 _startLazyDPSEvaluation();
7779 for (; (size--); offset++)
7782 // result = left | right
7783 if (AOP_TYPE (right) == AOP_LIT)
7785 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7789 aopGet (left, offset, FALSE, FALSE, NULL),
7793 else if (bytelit == 0x0FF)
7795 /* dummy read of volatile operand */
7796 if (isOperandVolatile (left, FALSE))
7797 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7798 aopPut (result, "#0xFF", offset);
7801 D (emitcode (";", "better literal OR."););
7802 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7803 emitcode ("orl", "a, %s",
7804 aopGet (right, offset,
7805 FALSE, FALSE, DP2_RESULT_REG));
7810 // faster than result <- left, anl result,right
7811 // and better if result is SFR
7812 if (AOP_TYPE (left) == AOP_ACC)
7814 emitcode ("orl", "a,%s",
7815 aopGet (right, offset,
7816 FALSE, FALSE, DP2_RESULT_REG));
7820 char *rOp = aopGet (right, offset, FALSE, FALSE, NULL);
7822 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7824 emitcode("mov", "b,a");
7828 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7829 emitcode ("orl", "a,%s", rOp);
7832 aopPut (result, "a", offset);
7834 _endLazyDPSEvaluation();
7839 freeAsmop (result, NULL, ic, TRUE);
7840 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7841 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7844 /*-----------------------------------------------------------------*/
7845 /* genXor - code for xclusive or */
7846 /*-----------------------------------------------------------------*/
7848 genXor (iCode * ic, iCode * ifx)
7850 operand *left, *right, *result;
7851 int size, offset = 0;
7852 unsigned long lit = 0L;
7856 D (emitcode (";", "genXor "));
7858 AOP_OP_3_NOFATAL (ic, pushResult);
7859 AOP_SET_LOCALS (ic);
7863 genFarFarLogicOp(ic, "xrl");
7868 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7870 AOP_TYPE (left), AOP_TYPE (right));
7871 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7873 AOP_SIZE (left), AOP_SIZE (right));
7876 /* if left is a literal & right is not ||
7877 if left needs acc & right does not */
7878 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7879 #ifdef LOGIC_OPS_BROKEN
7880 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
7884 operand *tmp = right;
7889 /* if result = right then exchange them */
7890 if (sameRegs (AOP (result), AOP (right)))
7892 operand *tmp = right;
7897 /* if right is bit then exchange them */
7898 if (AOP_TYPE (right) == AOP_CRY &&
7899 AOP_TYPE (left) != AOP_CRY)
7901 operand *tmp = right;
7905 if (AOP_TYPE (right) == AOP_LIT)
7906 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7908 size = AOP_SIZE (result);
7912 if (AOP_TYPE (left) == AOP_CRY)
7914 if (AOP_TYPE (right) == AOP_LIT)
7916 // c = bit & literal;
7919 // lit>>1 != 0 => result = 1
7920 if (AOP_TYPE (result) == AOP_CRY)
7923 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7925 continueIfTrue (ifx);
7928 emitcode ("setb", "c");
7935 // lit == 0, result = left
7936 if (size && sameRegs (AOP (result), AOP (left)))
7938 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7942 // lit == 1, result = not(left)
7943 if (size && sameRegs (AOP (result), AOP (left)))
7945 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7950 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7951 emitcode ("cpl", "c");
7960 symbol *tlbl = newiTempLabel (NULL);
7961 if (AOP_TYPE (right) == AOP_CRY)
7964 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7968 int sizer = AOP_SIZE (right);
7970 // if val>>1 != 0, result = 1
7971 emitcode ("setb", "c");
7974 MOVA (aopGet (right, sizer - 1, FALSE, FALSE, NULL));
7976 // test the msb of the lsb
7977 emitcode ("anl", "a,#!constbyte",0xfe);
7978 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7982 emitcode ("rrc", "a");
7984 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7985 emitcode ("cpl", "c");
7986 emitcode ("", "!tlabeldef", (tlbl->key + 100));
7993 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7994 genIfxJump (ifx, "c");
7998 /* if left is same as result */
7999 if (sameRegs (AOP (result), AOP (left)))
8001 for (; size--; offset++)
8003 if (AOP_TYPE (right) == AOP_LIT)
8005 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
8008 /* dummy read of volatile operand */
8009 if (isOperandVolatile (left, FALSE))
8010 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8014 else if (IS_AOP_PREG (left))
8016 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8017 emitcode ("xrl", "a,%s",
8018 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG));
8019 aopPut (result, "a", offset);
8023 emitcode ("xrl", "%s,%s",
8024 aopGet (left, offset, FALSE, TRUE, NULL),
8025 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8030 if (AOP_TYPE (left) == AOP_ACC)
8031 emitcode ("xrl", "a,%s",
8032 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8035 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
8036 if (IS_AOP_PREG (left))
8038 emitcode ("xrl", "a,%s",
8039 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
8040 aopPut (result, "a", offset);
8043 emitcode ("xrl", "%s,a",
8044 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
8051 // left & result in different registers
8052 if (AOP_TYPE (result) == AOP_CRY)
8055 // if(size), result in bit
8056 // if(!size && ifx), conditional oper: if(left ^ right)
8057 symbol *tlbl = newiTempLabel (NULL);
8058 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
8061 emitcode ("setb", "c");
8064 if ((AOP_TYPE (right) == AOP_LIT) &&
8065 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
8067 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8071 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
8072 emitcode ("xrl", "a,%s",
8073 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8075 char *rOp = aopGet (right, offset, FALSE, FALSE, NULL);
8076 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
8078 emitcode("mov", "b,a");
8082 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8083 emitcode ("xrl", "a,%s", rOp);
8086 emitcode ("jnz", "!tlabel", tlbl->key + 100);
8092 emitcode ("", "!tlabeldef", tlbl->key + 100);
8096 jmpTrueOrFalse (ifx, tlbl);
8100 for (; (size--); offset++)
8103 // result = left ^ right
8104 if (AOP_TYPE (right) == AOP_LIT)
8106 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
8110 aopGet (left, offset, FALSE, FALSE, NULL),
8114 D (emitcode (";", "better literal XOR."););
8115 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8116 emitcode ("xrl", "a, %s",
8117 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8121 // faster than result <- left, anl result,right
8122 // and better if result is SFR
8123 if (AOP_TYPE (left) == AOP_ACC)
8125 emitcode ("xrl", "a,%s",
8126 aopGet (right, offset,
8127 FALSE, FALSE, DP2_RESULT_REG));
8131 char *rOp = aopGet (right, offset, FALSE, FALSE, NULL);
8132 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
8134 emitcode("mov", "b,a");
8138 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8139 emitcode ("xrl", "a,%s", rOp);
8142 aopPut (result, "a", offset);
8148 freeAsmop (result, NULL, ic, TRUE);
8149 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
8150 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
8153 /*-----------------------------------------------------------------*/
8154 /* genInline - write the inline code out */
8155 /*-----------------------------------------------------------------*/
8157 genInline (iCode * ic)
8159 char *buffer, *bp, *bp1;
8161 D (emitcode (";", "genInline "));
8163 _G.inLine += (!options.asmpeep);
8165 buffer = bp = bp1 = Safe_strdup(IC_INLINE(ic));
8167 /* emit each line as a code */
8178 /* Add \n for labels, not dirs such as c:\mydir */
8179 if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
8193 /* emitcode("",buffer); */
8194 _G.inLine -= (!options.asmpeep);
8197 /*-----------------------------------------------------------------*/
8198 /* genRRC - rotate right with carry */
8199 /*-----------------------------------------------------------------*/
8203 operand *left, *result;
8207 D (emitcode (";", "genRRC"));
8209 /* rotate right with carry */
8210 left = IC_LEFT (ic);
8211 result = IC_RESULT (ic);
8212 aopOp (left, ic, FALSE, FALSE);
8213 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8215 /* move it to the result */
8216 size = AOP_SIZE (result);
8220 _startLazyDPSEvaluation ();
8223 l = aopGet (left, offset, FALSE, FALSE, NULL);
8225 emitcode ("rrc", "a");
8226 if (AOP_SIZE (result) > 1)
8227 aopPut (result, "a", offset--);
8229 _endLazyDPSEvaluation ();
8231 /* now we need to put the carry into the
8232 highest order byte of the result */
8233 if (AOP_SIZE (result) > 1)
8235 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE, NULL);
8238 emitcode ("mov", "acc.7,c");
8239 aopPut (result, "a", AOP_SIZE (result) - 1);
8240 freeAsmop (result, NULL, ic, TRUE);
8241 freeAsmop (left, NULL, ic, TRUE);
8244 /*-----------------------------------------------------------------*/
8245 /* genRLC - generate code for rotate left with carry */
8246 /*-----------------------------------------------------------------*/
8250 operand *left, *result;
8254 D (emitcode (";", "genRLC "));
8256 /* rotate right with carry */
8257 left = IC_LEFT (ic);
8258 result = IC_RESULT (ic);
8259 aopOp (left, ic, FALSE, FALSE);
8260 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8262 /* move it to the result */
8263 size = AOP_SIZE (result);
8267 l = aopGet (left, offset, FALSE, FALSE, NULL);
8269 emitcode ("add", "a,acc");
8270 if (AOP_SIZE (result) > 1)
8272 aopPut (result, "a", offset++);
8275 _startLazyDPSEvaluation ();
8278 l = aopGet (left, offset, FALSE, FALSE, NULL);
8280 emitcode ("rlc", "a");
8281 if (AOP_SIZE (result) > 1)
8282 aopPut (result, "a", offset++);
8284 _endLazyDPSEvaluation ();
8286 /* now we need to put the carry into the
8287 highest order byte of the result */
8288 if (AOP_SIZE (result) > 1)
8290 l = aopGet (result, 0, FALSE, FALSE, NULL);
8293 emitcode ("mov", "acc.0,c");
8294 aopPut (result, "a", 0);
8295 freeAsmop (result, NULL, ic, TRUE);
8296 freeAsmop (left, NULL, ic, TRUE);
8299 /*-----------------------------------------------------------------*/
8300 /* genGetHbit - generates code get highest order bit */
8301 /*-----------------------------------------------------------------*/
8303 genGetHbit (iCode * ic)
8305 operand *left, *result;
8307 D (emitcode (";", "genGetHbit"));
8309 left = IC_LEFT (ic);
8310 result = IC_RESULT (ic);
8311 aopOp (left, ic, FALSE, FALSE);
8312 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8314 /* get the highest order byte into a */
8315 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
8316 if (AOP_TYPE (result) == AOP_CRY)
8318 emitcode ("rlc", "a");
8323 emitcode ("rl", "a");
8324 emitcode ("anl", "a,#1");
8329 freeAsmop (result, NULL, ic, TRUE);
8330 freeAsmop (left, NULL, ic, TRUE);
8333 /*-----------------------------------------------------------------*/
8334 /* genSwap - generates code to swap nibbles or bytes */
8335 /*-----------------------------------------------------------------*/
8337 genSwap (iCode * ic)
8339 operand *left, *result;
8341 D(emitcode ("; genSwap",""));
8343 left = IC_LEFT (ic);
8344 result = IC_RESULT (ic);
8345 aopOp (left, ic, FALSE, FALSE);
8346 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8348 _startLazyDPSEvaluation ();
8349 switch (AOP_SIZE (left))
8351 case 1: /* swap nibbles in byte */
8352 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
8353 emitcode ("swap", "a");
8354 aopPut (result, "a", 0);
8356 case 2: /* swap bytes in word */
8357 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
8359 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
8360 aopPut (result, aopGet (left, 1, FALSE, FALSE, NULL), 0);
8361 aopPut (result, "a", 1);
8363 else if (operandsEqu (left, result))
8366 bool pushedB = FALSE, leftInB = FALSE;
8368 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
8369 if (AOP_NEEDSACC (left) || AOP_NEEDSACC (result))
8372 emitcode ("mov", "b,a");
8376 aopPut (result, aopGet (left, 1, FALSE, FALSE, NULL), 0);
8377 aopPut (result, reg, 1);
8384 aopPut (result, aopGet (left, 1, FALSE, FALSE, NULL), 0);
8385 aopPut (result, aopGet (left, 0, FALSE, FALSE, NULL), 1);
8389 wassertl(FALSE, "unsupported SWAP operand size");
8391 _endLazyDPSEvaluation ();
8393 freeAsmop (result, NULL, ic, TRUE);
8394 freeAsmop (left, NULL, ic, TRUE);
8397 /*-----------------------------------------------------------------*/
8398 /* AccRol - rotate left accumulator by known count */
8399 /*-----------------------------------------------------------------*/
8401 AccRol (int shCount)
8403 shCount &= 0x0007; // shCount : 0..7
8410 emitcode ("rl", "a");
8413 emitcode ("rl", "a");
8414 emitcode ("rl", "a");
8417 emitcode ("swap", "a");
8418 emitcode ("rr", "a");
8421 emitcode ("swap", "a");
8424 emitcode ("swap", "a");
8425 emitcode ("rl", "a");
8428 emitcode ("rr", "a");
8429 emitcode ("rr", "a");
8432 emitcode ("rr", "a");
8437 /*-----------------------------------------------------------------*/
8438 /* AccLsh - left shift accumulator by known count */
8439 /*-----------------------------------------------------------------*/
8441 AccLsh (int shCount)
8446 emitcode ("add", "a,acc");
8447 else if (shCount == 2)
8449 emitcode ("add", "a,acc");
8450 emitcode ("add", "a,acc");
8454 /* rotate left accumulator */
8456 /* and kill the lower order bits */
8457 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
8462 /*-----------------------------------------------------------------*/
8463 /* AccRsh - right shift accumulator by known count */
8464 /*-----------------------------------------------------------------*/
8466 AccRsh (int shCount)
8473 emitcode ("rrc", "a");
8477 /* rotate right accumulator */
8478 AccRol (8 - shCount);
8479 /* and kill the higher order bits */
8480 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
8485 #ifdef BETTER_LITERAL_SHIFT
8486 /*-----------------------------------------------------------------*/
8487 /* AccSRsh - signed right shift accumulator by known count */
8488 /*-----------------------------------------------------------------*/
8490 AccSRsh (int shCount)
8497 emitcode ("mov", "c,acc.7");
8498 emitcode ("rrc", "a");
8500 else if (shCount == 2)
8502 emitcode ("mov", "c,acc.7");
8503 emitcode ("rrc", "a");
8504 emitcode ("mov", "c,acc.7");
8505 emitcode ("rrc", "a");
8509 tlbl = newiTempLabel (NULL);
8510 /* rotate right accumulator */
8511 AccRol (8 - shCount);
8512 /* and kill the higher order bits */
8513 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
8514 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8515 emitcode ("orl", "a,#!constbyte",
8516 (unsigned char) ~SRMask[shCount]);
8517 emitcode ("", "!tlabeldef", tlbl->key + 100);
8523 #ifdef BETTER_LITERAL_SHIFT
8524 /*-----------------------------------------------------------------*/
8525 /* shiftR1Left2Result - shift right one byte from left to result */
8526 /*-----------------------------------------------------------------*/
8528 shiftR1Left2Result (operand * left, int offl,
8529 operand * result, int offr,
8530 int shCount, int sign)
8532 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
8533 /* shift right accumulator */
8538 aopPut (result, "a", offr);
8542 #ifdef BETTER_LITERAL_SHIFT
8543 /*-----------------------------------------------------------------*/
8544 /* shiftL1Left2Result - shift left one byte from left to result */
8545 /*-----------------------------------------------------------------*/
8547 shiftL1Left2Result (operand * left, int offl,
8548 operand * result, int offr, int shCount)
8551 l = aopGet (left, offl, FALSE, FALSE, NULL);
8553 /* shift left accumulator */
8555 aopPut (result, "a", offr);
8559 #ifdef BETTER_LITERAL_SHIFT
8560 /*-----------------------------------------------------------------*/
8561 /* movLeft2Result - move byte from left to result */
8562 /*-----------------------------------------------------------------*/
8564 movLeft2Result (operand * left, int offl,
8565 operand * result, int offr, int sign)
8568 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8570 l = aopGet (left, offl, FALSE, FALSE, NULL);
8572 if (*l == '@' && (IS_AOP_PREG (result)))
8574 emitcode ("mov", "a,%s", l);
8575 aopPut (result, "a", offr);
8581 aopPut (result, l, offr);
8585 /* MSB sign in acc.7 ! */
8586 if (getDataSize (left) == offl + 1)
8589 aopPut (result, "a", offr);
8597 #ifdef BETTER_LITERAL_SHIFT
8598 /*-----------------------------------------------------------------*/
8599 /* AccAXRrl1 - right rotate a:x by 1 */
8600 /*-----------------------------------------------------------------*/
8604 emitcode ("mov", "c,acc.0");
8605 emitcode ("xch", "a,%s", x);
8606 emitcode ("rrc", "a");
8607 emitcode ("xch", "a,%s", x);
8608 emitcode ("rrc", "a");
8612 #ifdef BETTER_LITERAL_SHIFT
8614 /*-----------------------------------------------------------------*/
8615 /* AccAXLrl1 - left rotate a:x by 1 */
8616 /*-----------------------------------------------------------------*/
8620 emitcode ("mov", "c,acc.7");
8621 emitcode ("xch", "a,%s", x);
8622 emitcode ("rlc", "a");
8623 emitcode ("xch", "a,%s", x);
8624 emitcode ("rlc", "a");
8628 #ifdef BETTER_LITERAL_SHIFT
8629 /*-----------------------------------------------------------------*/
8630 /* AccAXRsh1 - right shift c->a:x->c by 1 */
8631 /*-----------------------------------------------------------------*/
8635 emitcode ("rrc", "a");
8636 emitcode ("xch", "a,%s", x);
8637 emitcode ("rrc", "a");
8638 emitcode ("xch", "a,%s", x);
8642 #ifdef BETTER_LITERAL_SHIFT
8643 /*-----------------------------------------------------------------*/
8644 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8645 /*-----------------------------------------------------------------*/
8649 emitcode ("xch", "a,%s", x);
8650 emitcode ("add", "a,acc");
8651 emitcode ("xch", "a,%s", x);
8652 emitcode ("rlc", "a");
8656 #ifdef BETTER_LITERAL_SHIFT
8657 /*-----------------------------------------------------------------*/
8658 /* AccAXLsh - left shift a:x by known count (0..7) */
8659 /*-----------------------------------------------------------------*/
8661 AccAXLsh (char *x, int shCount)
8676 case 5: // AAAAABBB:CCCCCDDD
8678 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8680 emitcode ("anl", "a,#!constbyte",
8681 SLMask[shCount]); // BBB00000:CCCCCDDD
8683 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8685 AccRol (shCount); // DDDCCCCC:BBB00000
8687 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8689 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8691 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8693 emitcode ("anl", "a,#!constbyte",
8694 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8696 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8698 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8701 case 6: // AAAAAABB:CCCCCCDD
8702 emitcode ("anl", "a,#!constbyte",
8703 SRMask[shCount]); // 000000BB:CCCCCCDD
8705 AccAXRrl1 (x); // D000000B:BCCCCCCD
8706 AccAXRrl1 (x); // DD000000:BBCCCCCC
8707 emitcode ("xch", "a,%s", x); // BBCCCCCC:DD000000
8709 emitcode ("mov", "c,acc.0"); // c = B
8710 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8711 emitcode("rrc","a");
8712 emitcode("xch","a,%s", x);
8713 emitcode("rrc","a");
8714 emitcode("mov","c,acc.0"); //<< get correct bit
8715 emitcode("xch","a,%s", x);
8717 emitcode("rrc","a");
8718 emitcode("xch","a,%s", x);
8719 emitcode("rrc","a");
8720 emitcode("xch","a,%s", x);
8723 case 7: // a:x <<= 7
8725 emitcode ("anl", "a,#!constbyte",
8726 SRMask[shCount]); // 0000000B:CCCCCCCD
8728 AccAXRrl1 (x); // D0000000:BCCCCCCC
8730 emitcode ("xch", "a,%s", x); // BCCCCCCC:D0000000
8739 #ifdef BETTER_LITERAL_SHIFT
8741 /*-----------------------------------------------------------------*/
8742 /* AccAXRsh - right shift a:x known count (0..7) */
8743 /*-----------------------------------------------------------------*/
8745 AccAXRsh (char *x, int shCount)
8753 AccAXRsh1 (x); // 0->a:x
8758 AccAXRsh1 (x); // 0->a:x
8761 AccAXRsh1 (x); // 0->a:x
8766 case 5: // AAAAABBB:CCCCCDDD = a:x
8768 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8770 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8772 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8774 emitcode ("anl", "a,#!constbyte",
8775 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8777 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8779 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8781 emitcode ("anl", "a,#!constbyte",
8782 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8784 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8786 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8788 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8791 case 6: // AABBBBBB:CCDDDDDD
8793 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDE
8794 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8796 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8798 emitcode ("anl", "a,#!constbyte",
8799 SRMask[shCount]); // 000000AA:BBBBBBCC
8802 case 7: // ABBBBBBB:CDDDDDDD
8804 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8806 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8808 emitcode ("anl", "a,#!constbyte",
8809 SRMask[shCount]); // 0000000A:BBBBBBBC
8818 #ifdef BETTER_LITERAL_SHIFT
8819 /*-----------------------------------------------------------------*/
8820 /* AccAXRshS - right shift signed a:x known count (0..7) */
8821 /*-----------------------------------------------------------------*/
8823 AccAXRshS (char *x, int shCount)
8831 emitcode ("mov", "c,acc.7");
8832 AccAXRsh1 (x); // s->a:x
8836 emitcode ("mov", "c,acc.7");
8837 AccAXRsh1 (x); // s->a:x
8839 emitcode ("mov", "c,acc.7");
8840 AccAXRsh1 (x); // s->a:x
8845 case 5: // AAAAABBB:CCCCCDDD = a:x
8847 tlbl = newiTempLabel (NULL);
8848 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8850 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8852 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8854 emitcode ("anl", "a,#!constbyte",
8855 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8857 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8859 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8861 emitcode ("anl", "a,#!constbyte",
8862 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8864 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8866 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8868 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8870 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8871 emitcode ("orl", "a,#!constbyte",
8872 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8874 emitcode ("", "!tlabeldef", tlbl->key + 100);
8875 break; // SSSSAAAA:BBBCCCCC
8877 case 6: // AABBBBBB:CCDDDDDD
8879 tlbl = newiTempLabel (NULL);
8881 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8882 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8884 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8886 emitcode ("anl", "a,#!constbyte",
8887 SRMask[shCount]); // 000000AA:BBBBBBCC
8889 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8890 emitcode ("orl", "a,#!constbyte",
8891 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8893 emitcode ("", "!tlabeldef", tlbl->key + 100);
8895 case 7: // ABBBBBBB:CDDDDDDD
8897 tlbl = newiTempLabel (NULL);
8899 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8901 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8903 emitcode ("anl", "a,#!constbyte",
8904 SRMask[shCount]); // 0000000A:BBBBBBBC
8906 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8907 emitcode ("orl", "a,#!constbyte",
8908 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8910 emitcode ("", "!tlabeldef", tlbl->key + 100);
8918 #ifdef BETTER_LITERAL_SHIFT
8920 _loadLeftIntoAx(char **lsb,
8926 // Get the initial value from left into a pair of registers.
8927 // MSB must be in A, LSB can be any register.
8929 // If the result is held in registers, it is an optimization
8930 // if the LSB can be held in the register which will hold the,
8931 // result LSB since this saves us from having to copy it into
8932 // the result following AccAXLsh.
8934 // If the result is addressed indirectly, this is not a gain.
8935 if (AOP_NEEDSACC(result))
8939 _startLazyDPSEvaluation();
8940 if (AOP_TYPE(left) == AOP_DPTR2)
8943 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE, NULL));
8944 // get LSB in DP2_RESULT_REG.
8945 leftByte = aopGet (left, offl, FALSE, FALSE, DP2_RESULT_REG);
8946 assert(!strcmp(leftByte, DP2_RESULT_REG));
8950 // get LSB into DP2_RESULT_REG
8951 leftByte = aopGet (left, offl, FALSE, FALSE, NULL);
8952 if (strcmp(leftByte, DP2_RESULT_REG))
8955 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
8958 leftByte = aopGet (left, offl + MSB16, FALSE, FALSE, NULL);
8959 assert(strcmp(leftByte, DP2_RESULT_REG));
8962 _endLazyDPSEvaluation();
8963 *lsb = DP2_RESULT_REG;
8967 if (sameRegs (AOP (result), AOP (left)) &&
8968 ((offl + MSB16) == offr))
8970 /* don't crash result[offr] */
8971 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
8972 emitcode ("xch", "a,%s",
8973 aopGet (left, offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
8977 movLeft2Result (left, offl, result, offr, 0);
8978 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE, NULL));
8980 *lsb = aopGet (result, offr, FALSE, FALSE, DP2_RESULT_REG);
8981 assert(strcmp(*lsb,"a"));
8986 _storeAxResults(char *lsb,
8990 _startLazyDPSEvaluation();
8991 if (AOP_NEEDSACC(result))
8993 /* We have to explicitly update the result LSB.
8995 emitcode ("xch","a,%s", lsb);
8996 aopPut (result, "a", offr);
8997 emitcode ("mov","a,%s", lsb);
8999 if (getDataSize (result) > 1)
9001 aopPut (result, "a", offr + MSB16);
9003 _endLazyDPSEvaluation();
9006 /*-----------------------------------------------------------------*/
9007 /* shiftL2Left2Result - shift left two bytes from left to result */
9008 /*-----------------------------------------------------------------*/
9010 shiftL2Left2Result (operand * left, int offl,
9011 operand * result, int offr, int shCount)
9015 _loadLeftIntoAx(&lsb, left, result, offl, offr);
9017 AccAXLsh (lsb, shCount);
9019 _storeAxResults(lsb, result, offr);
9023 #ifdef BETTER_LITERAL_SHIFT
9024 /*-----------------------------------------------------------------*/
9025 /* shiftR2Left2Result - shift right two bytes from left to result */
9026 /*-----------------------------------------------------------------*/
9028 shiftR2Left2Result (operand * left, int offl,
9029 operand * result, int offr,
9030 int shCount, int sign)
9034 _loadLeftIntoAx(&lsb, left, result, offl, offr);
9036 /* a:x >> shCount (x = lsb(result)) */
9039 AccAXRshS(lsb, shCount);
9043 AccAXRsh(lsb, shCount);
9046 _storeAxResults(lsb, result, offr);
9050 /*-----------------------------------------------------------------*/
9051 /* shiftLLeftOrResult - shift left one byte from left, or to result */
9052 /*-----------------------------------------------------------------*/
9054 shiftLLeftOrResult (operand * left, int offl,
9055 operand * result, int offr, int shCount)
9057 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
9058 /* shift left accumulator */
9060 /* or with result */
9061 emitcode ("orl", "a,%s",
9062 aopGet (result, offr, FALSE, FALSE, DP2_RESULT_REG));
9063 /* back to result */
9064 aopPut (result, "a", offr);
9069 /*-----------------------------------------------------------------*/
9070 /* shiftRLeftOrResult - shift right one byte from left,or to result */
9071 /*-----------------------------------------------------------------*/
9073 shiftRLeftOrResult (operand * left, int offl,
9074 operand * result, int offr, int shCount)
9076 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
9077 /* shift right accumulator */
9079 /* or with result */
9080 emitcode ("orl", "a,%s",
9081 aopGet (result, offr, FALSE, FALSE, DP2_RESULT_REG));
9082 /* back to result */
9083 aopPut (result, "a", offr);
9087 #ifdef BETTER_LITERAL_SHIFT
9088 /*-----------------------------------------------------------------*/
9089 /* genlshOne - left shift a one byte quantity by known count */
9090 /*-----------------------------------------------------------------*/
9092 genlshOne (operand * result, operand * left, int shCount)
9094 D (emitcode (";", "genlshOne "));
9096 shiftL1Left2Result (left, LSB, result, LSB, shCount);
9100 #ifdef BETTER_LITERAL_SHIFT
9101 /*-----------------------------------------------------------------*/
9102 /* genlshTwo - left shift two bytes by known amount != 0 */
9103 /*-----------------------------------------------------------------*/
9105 genlshTwo (operand * result, operand * left, int shCount)
9109 D (emitcode (";", "genlshTwo"));
9111 size = getDataSize (result);
9113 /* if shCount >= 8 */
9118 _startLazyDPSEvaluation();
9124 _endLazyDPSEvaluation();
9125 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9126 aopPut (result, zero, LSB);
9130 movLeft2Result (left, LSB, result, MSB16, 0);
9131 aopPut (result, zero, LSB);
9132 _endLazyDPSEvaluation();
9137 aopPut (result, zero, LSB);
9138 _endLazyDPSEvaluation();
9142 /* 1 <= shCount <= 7 */
9146 shiftL1Left2Result (left, LSB, result, LSB, shCount);
9148 shiftL2Left2Result (left, LSB, result, LSB, shCount);
9155 /*-----------------------------------------------------------------*/
9156 /* shiftLLong - shift left one long from left to result */
9157 /* offl = LSB or MSB16 */
9158 /*-----------------------------------------------------------------*/
9160 shiftLLong (operand * left, operand * result, int offr)
9163 int size = AOP_SIZE (result);
9165 if (size >= LSB + offr)
9167 l = aopGet (left, LSB, FALSE, FALSE, NULL);
9169 emitcode ("add", "a,acc");
9170 if (sameRegs (AOP (left), AOP (result)) &&
9171 size >= MSB16 + offr && offr != LSB)
9172 emitcode ("xch", "a,%s",
9173 aopGet (left, LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
9175 aopPut (result, "a", LSB + offr);
9178 if (size >= MSB16 + offr)
9180 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
9182 l = aopGet (left, MSB16, FALSE, FALSE, TRUE);
9185 emitcode ("rlc", "a");
9186 if (sameRegs (AOP (left), AOP (result)) &&
9187 size >= MSB24 + offr && offr != LSB)
9188 emitcode ("xch", "a,%s",
9189 aopGet (left, MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
9191 aopPut (result, "a", MSB16 + offr);
9194 if (size >= MSB24 + offr)
9196 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
9198 l = aopGet (left, MSB24, FALSE, FALSE, NULL);
9201 emitcode ("rlc", "a");
9202 if (sameRegs (AOP (left), AOP (result)) &&
9203 size >= MSB32 + offr && offr != LSB)
9204 emitcode ("xch", "a,%s",
9205 aopGet (left, MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
9207 aopPut (result, "a", MSB24 + offr);
9210 if (size > MSB32 + offr)
9212 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
9214 l = aopGet (left, MSB32, FALSE, FALSE, NULL);
9217 emitcode ("rlc", "a");
9218 aopPut (result, "a", MSB32 + offr);
9221 aopPut (result, zero, LSB);
9227 /*-----------------------------------------------------------------*/
9228 /* genlshFour - shift four byte by a known amount != 0 */
9229 /*-----------------------------------------------------------------*/
9231 genlshFour (operand * result, operand * left, int shCount)
9235 D (emitcode (";", "genlshFour "));
9237 size = AOP_SIZE (result);
9239 /* if shifting more that 3 bytes */
9244 /* lowest order of left goes to the highest
9245 order of the destination */
9246 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
9248 movLeft2Result (left, LSB, result, MSB32, 0);
9249 aopPut (result, zero, LSB);
9250 aopPut (result, zero, MSB16);
9251 aopPut (result, zero, MSB24);
9255 /* more than two bytes */
9256 else if (shCount >= 16)
9258 /* lower order two bytes goes to higher order two bytes */
9260 /* if some more remaining */
9262 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
9265 movLeft2Result (left, MSB16, result, MSB32, 0);
9266 movLeft2Result (left, LSB, result, MSB24, 0);
9268 aopPut (result, zero, MSB16);
9269 aopPut (result, zero, LSB);
9273 /* if more than 1 byte */
9274 else if (shCount >= 8)
9276 /* lower order three bytes goes to higher order three bytes */
9281 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9283 movLeft2Result (left, LSB, result, MSB16, 0);
9289 movLeft2Result (left, MSB24, result, MSB32, 0);
9290 movLeft2Result (left, MSB16, result, MSB24, 0);
9291 movLeft2Result (left, LSB, result, MSB16, 0);
9292 aopPut (result, zero, LSB);
9294 else if (shCount == 1)
9295 shiftLLong (left, result, MSB16);
9298 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
9299 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9300 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
9301 aopPut (result, zero, LSB);
9306 /* 1 <= shCount <= 7 */
9307 else if (shCount <= 2)
9309 shiftLLong (left, result, LSB);
9311 shiftLLong (result, result, LSB);
9313 /* 3 <= shCount <= 7, optimize */
9316 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
9317 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
9318 shiftL2Left2Result (left, LSB, result, LSB, shCount);
9323 #ifdef BETTER_LITERAL_SHIFT
9324 /*-----------------------------------------------------------------*/
9325 /* genLeftShiftLiteral - left shifting by known count */
9326 /*-----------------------------------------------------------------*/
9328 genLeftShiftLiteral (operand * left,
9333 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9336 size = getSize (operandType (result));
9338 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
9340 /* We only handle certain easy cases so far. */
9342 && (shCount < (size * 8))
9346 D(emitcode (";", "genLeftShiftLiteral wimping out"););
9350 freeAsmop (right, NULL, ic, TRUE);
9352 aopOp(left, ic, FALSE, FALSE);
9353 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
9356 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
9358 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
9359 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
9361 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
9364 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
9366 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
9367 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
9369 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
9375 emitcode ("; shift left ", "result %d, left %d", size,
9379 /* I suppose that the left size >= result size */
9382 _startLazyDPSEvaluation();
9385 movLeft2Result (left, size, result, size, 0);
9387 _endLazyDPSEvaluation();
9389 else if (shCount >= (size * 8))
9391 _startLazyDPSEvaluation();
9394 aopPut (result, zero, size);
9396 _endLazyDPSEvaluation();
9403 genlshOne (result, left, shCount);
9407 genlshTwo (result, left, shCount);
9411 genlshFour (result, left, shCount);
9415 fprintf(stderr, "*** ack! mystery literal shift!\n");
9419 freeAsmop (result, NULL, ic, TRUE);
9420 freeAsmop (left, NULL, ic, TRUE);
9425 /*-----------------------------------------------------------------*/
9426 /* genLeftShift - generates code for left shifting */
9427 /*-----------------------------------------------------------------*/
9429 genLeftShift (iCode * ic)
9431 operand *left, *right, *result;
9434 symbol *tlbl, *tlbl1;
9437 D (emitcode (";", "genLeftShift "));
9439 right = IC_RIGHT (ic);
9440 left = IC_LEFT (ic);
9441 result = IC_RESULT (ic);
9443 aopOp (right, ic, FALSE, FALSE);
9446 #ifdef BETTER_LITERAL_SHIFT
9447 /* if the shift count is known then do it
9448 as efficiently as possible */
9449 if (AOP_TYPE (right) == AOP_LIT)
9451 if (genLeftShiftLiteral (left, right, result, ic))
9458 /* shift count is unknown then we have to form
9459 a loop get the loop count in B : Note: we take
9460 only the lower order byte since shifting
9461 more that 32 bits make no sense anyway, ( the
9462 largest size of an object can be only 32 bits ) */
9465 if (AOP_TYPE (right) == AOP_LIT)
9467 /* Really should be handled by genLeftShiftLiteral,
9468 * but since I'm too lazy to fix that today, at least we can make
9469 * some small improvement.
9471 emitcode("mov", "b,#!constbyte",
9472 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9476 MOVB (aopGet (right, 0, FALSE, FALSE, "b"));
9477 emitcode ("inc", "b");
9479 freeAsmop (right, NULL, ic, TRUE);
9480 aopOp (left, ic, FALSE, FALSE);
9481 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9483 /* now move the left to the result if they are not the same */
9484 if (!sameRegs (AOP (left), AOP (result)) &&
9485 AOP_SIZE (result) > 1)
9488 size = AOP_SIZE (result);
9490 _startLazyDPSEvaluation ();
9493 l = aopGet (left, offset, FALSE, TRUE, NULL);
9494 if (*l == '@' && (IS_AOP_PREG (result)))
9497 emitcode ("mov", "a,%s", l);
9498 aopPut (result, "a", offset);
9501 aopPut (result, l, offset);
9504 _endLazyDPSEvaluation ();
9507 tlbl = newiTempLabel (NULL);
9508 size = AOP_SIZE (result);
9510 tlbl1 = newiTempLabel (NULL);
9512 /* if it is only one byte then */
9515 symbol *tlbl1 = newiTempLabel (NULL);
9517 l = aopGet (left, 0, FALSE, FALSE, NULL);
9519 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9520 emitcode ("", "!tlabeldef", tlbl->key + 100);
9521 emitcode ("add", "a,acc");
9522 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9523 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9525 aopPut (result, "a", 0);
9529 reAdjustPreg (AOP (result));
9531 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9532 emitcode ("", "!tlabeldef", tlbl->key + 100);
9533 l = aopGet (result, offset, FALSE, FALSE, NULL);
9535 emitcode ("add", "a,acc");
9536 aopPut (result, "a", offset++);
9537 _startLazyDPSEvaluation ();
9540 l = aopGet (result, offset, FALSE, FALSE, NULL);
9542 emitcode ("rlc", "a");
9543 aopPut (result, "a", offset++);
9545 _endLazyDPSEvaluation ();
9546 reAdjustPreg (AOP (result));
9548 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9549 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9552 freeAsmop (result, NULL, ic, TRUE);
9553 freeAsmop (left, NULL, ic, TRUE);
9556 #ifdef BETTER_LITERAL_SHIFT
9557 /*-----------------------------------------------------------------*/
9558 /* genrshOne - right shift a one byte quantity by known count */
9559 /*-----------------------------------------------------------------*/
9561 genrshOne (operand * result, operand * left,
9562 int shCount, int sign)
9564 D (emitcode (";", "genrshOne"));
9565 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9569 #ifdef BETTER_LITERAL_SHIFT
9570 /*-----------------------------------------------------------------*/
9571 /* genrshTwo - right shift two bytes by known amount != 0 */
9572 /*-----------------------------------------------------------------*/
9574 genrshTwo (operand * result, operand * left,
9575 int shCount, int sign)
9577 D (emitcode (";", "genrshTwo"));
9579 /* if shCount >= 8 */
9583 _startLazyDPSEvaluation();
9585 shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9587 movLeft2Result (left, MSB16, result, LSB, sign);
9588 addSign (result, MSB16, sign);
9589 _endLazyDPSEvaluation();
9592 /* 1 <= shCount <= 7 */
9594 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9598 /*-----------------------------------------------------------------*/
9599 /* shiftRLong - shift right one long from left to result */
9600 /* offl = LSB or MSB16 */
9601 /*-----------------------------------------------------------------*/
9603 shiftRLong (operand * left, int offl,
9604 operand * result, int sign)
9606 int isSameRegs=sameRegs(AOP(left),AOP(result));
9608 if (isSameRegs && offl>1) {
9609 // we are in big trouble, but this shouldn't happen
9610 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9613 MOVA (aopGet (left, MSB32, FALSE, FALSE, NULL));
9620 emitcode ("rlc", "a");
9621 emitcode ("subb", "a,acc");
9622 emitcode ("xch", "a,%s",
9623 aopGet(left, MSB32, FALSE, FALSE, DP2_RESULT_REG));
9627 aopPut (result, zero, MSB32);
9633 emitcode ("clr", "c");
9637 emitcode ("mov", "c,acc.7");
9640 emitcode ("rrc", "a");
9642 if (isSameRegs && offl==MSB16) {
9644 "a,%s",aopGet (left, MSB24, FALSE, FALSE, DP2_RESULT_REG));
9646 aopPut (result, "a", MSB32);
9647 MOVA (aopGet (left, MSB24, FALSE, FALSE, NULL));
9650 emitcode ("rrc", "a");
9651 if (isSameRegs && offl==1) {
9652 emitcode ("xch", "a,%s",
9653 aopGet (left, MSB16, FALSE, FALSE, DP2_RESULT_REG));
9655 aopPut (result, "a", MSB24);
9656 MOVA (aopGet (left, MSB16, FALSE, FALSE, NULL));
9658 emitcode ("rrc", "a");
9659 aopPut (result, "a", MSB16 - offl);
9663 MOVA (aopGet (left, LSB, FALSE, FALSE, NULL));
9664 emitcode ("rrc", "a");
9665 aopPut (result, "a", LSB);
9669 /*-----------------------------------------------------------------*/
9670 /* genrshFour - shift four byte by a known amount != 0 */
9671 /*-----------------------------------------------------------------*/
9673 genrshFour (operand * result, operand * left,
9674 int shCount, int sign)
9676 D (emitcode (";", "genrshFour"));
9678 /* if shifting more that 3 bytes */
9682 _startLazyDPSEvaluation();
9684 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9686 movLeft2Result (left, MSB32, result, LSB, sign);
9687 addSign (result, MSB16, sign);
9688 _endLazyDPSEvaluation();
9690 else if (shCount >= 16)
9693 _startLazyDPSEvaluation();
9695 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9698 movLeft2Result (left, MSB24, result, LSB, 0);
9699 movLeft2Result (left, MSB32, result, MSB16, sign);
9701 addSign (result, MSB24, sign);
9702 _endLazyDPSEvaluation();
9704 else if (shCount >= 8)
9707 _startLazyDPSEvaluation();
9710 shiftRLong (left, MSB16, result, sign);
9712 else if (shCount == 0)
9714 movLeft2Result (left, MSB16, result, LSB, 0);
9715 movLeft2Result (left, MSB24, result, MSB16, 0);
9716 movLeft2Result (left, MSB32, result, MSB24, sign);
9717 addSign (result, MSB32, sign);
9721 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9722 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9723 /* the last shift is signed */
9724 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9725 addSign (result, MSB32, sign);
9727 _endLazyDPSEvaluation();
9731 /* 1 <= shCount <= 7 */
9734 shiftRLong (left, LSB, result, sign);
9736 shiftRLong (result, LSB, result, sign);
9740 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9741 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9742 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9747 #ifdef BETTER_LITERAL_SHIFT
9748 /*-----------------------------------------------------------------*/
9749 /* genRightShiftLiteral - right shifting by known count */
9750 /*-----------------------------------------------------------------*/
9752 genRightShiftLiteral (operand * left,
9758 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9761 size = getSize (operandType (result));
9763 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
9765 /* We only handle certain easy cases so far. */
9767 && (shCount < (size * 8))
9772 D(emitcode (";", "genRightShiftLiteral wimping out"););
9776 freeAsmop (right, NULL, ic, TRUE);
9778 aopOp (left, ic, FALSE, FALSE);
9779 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9782 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9786 /* test the LEFT size !!! */
9788 /* I suppose that the left size >= result size */
9791 size = getDataSize (result);
9792 _startLazyDPSEvaluation();
9794 movLeft2Result (left, size, result, size, 0);
9795 _endLazyDPSEvaluation();
9797 else if (shCount >= (size * 8))
9801 /* get sign in acc.7 */
9802 MOVA (aopGet (left, size - 1, FALSE, FALSE, NULL));
9804 addSign (result, LSB, sign);
9811 genrshOne (result, left, shCount, sign);
9815 genrshTwo (result, left, shCount, sign);
9819 genrshFour (result, left, shCount, sign);
9826 freeAsmop (result, NULL, ic, TRUE);
9827 freeAsmop (left, NULL, ic, TRUE);
9833 /*-----------------------------------------------------------------*/
9834 /* genSignedRightShift - right shift of signed number */
9835 /*-----------------------------------------------------------------*/
9837 genSignedRightShift (iCode * ic)
9839 operand *right, *left, *result;
9842 symbol *tlbl, *tlbl1;
9845 D (emitcode (";", "genSignedRightShift"));
9847 /* we do it the hard way put the shift count in b
9848 and loop thru preserving the sign */
9850 right = IC_RIGHT (ic);
9851 left = IC_LEFT (ic);
9852 result = IC_RESULT (ic);
9854 aopOp (right, ic, FALSE, FALSE);
9856 #ifdef BETTER_LITERAL_SHIFT
9857 if (AOP_TYPE (right) == AOP_LIT)
9859 if (genRightShiftLiteral (left, right, result, ic, 1))
9865 /* shift count is unknown then we have to form
9866 a loop get the loop count in B : Note: we take
9867 only the lower order byte since shifting
9868 more that 32 bits make no sense anyway, ( the
9869 largest size of an object can be only 32 bits ) */
9872 if (AOP_TYPE (right) == AOP_LIT)
9874 /* Really should be handled by genRightShiftLiteral,
9875 * but since I'm too lazy to fix that today, at least we can make
9876 * some small improvement.
9878 emitcode("mov", "b,#!constbyte",
9879 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9883 MOVB (aopGet (right, 0, FALSE, FALSE, "b"));
9884 emitcode ("inc", "b");
9886 freeAsmop (right, NULL, ic, TRUE);
9887 aopOp (left, ic, FALSE, FALSE);
9888 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9890 /* now move the left to the result if they are not the
9892 if (!sameRegs (AOP (left), AOP (result)) &&
9893 AOP_SIZE (result) > 1)
9896 size = AOP_SIZE (result);
9898 _startLazyDPSEvaluation ();
9901 l = aopGet (left, offset, FALSE, TRUE, NULL);
9902 if (*l == '@' && IS_AOP_PREG (result))
9905 emitcode ("mov", "a,%s", l);
9906 aopPut (result, "a", offset);
9909 aopPut (result, l, offset);
9912 _endLazyDPSEvaluation ();
9915 /* mov the highest order bit to OVR */
9916 tlbl = newiTempLabel (NULL);
9917 tlbl1 = newiTempLabel (NULL);
9919 size = AOP_SIZE (result);
9921 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
9922 emitcode ("rlc", "a");
9923 emitcode ("mov", "ov,c");
9924 /* if it is only one byte then */
9927 l = aopGet (left, 0, FALSE, FALSE, NULL);
9929 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9930 emitcode ("", "!tlabeldef", tlbl->key + 100);
9931 emitcode ("mov", "c,ov");
9932 emitcode ("rrc", "a");
9933 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9934 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9936 aopPut (result, "a", 0);
9940 reAdjustPreg (AOP (result));
9941 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9942 emitcode ("", "!tlabeldef", tlbl->key + 100);
9943 emitcode ("mov", "c,ov");
9944 _startLazyDPSEvaluation ();
9947 l = aopGet (result, offset, FALSE, FALSE, NULL);
9949 emitcode ("rrc", "a");
9950 aopPut (result, "a", offset--);
9952 _endLazyDPSEvaluation ();
9953 reAdjustPreg (AOP (result));
9954 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9955 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9959 freeAsmop (result, NULL, ic, TRUE);
9960 freeAsmop (left, NULL, ic, TRUE);
9963 /*-----------------------------------------------------------------*/
9964 /* genRightShift - generate code for right shifting */
9965 /*-----------------------------------------------------------------*/
9967 genRightShift (iCode * ic)
9969 operand *right, *left, *result;
9973 symbol *tlbl, *tlbl1;
9976 D (emitcode (";", "genRightShift"));
9978 /* if signed then we do it the hard way preserve the
9979 sign bit moving it inwards */
9980 letype = getSpec (operandType (IC_LEFT (ic)));
9982 if (!SPEC_USIGN (letype))
9984 genSignedRightShift (ic);
9988 /* signed & unsigned types are treated the same : i.e. the
9989 signed is NOT propagated inwards : quoting from the
9990 ANSI - standard : "for E1 >> E2, is equivalent to division
9991 by 2**E2 if unsigned or if it has a non-negative value,
9992 otherwise the result is implementation defined ", MY definition
9993 is that the sign does not get propagated */
9995 right = IC_RIGHT (ic);
9996 left = IC_LEFT (ic);
9997 result = IC_RESULT (ic);
9999 aopOp (right, ic, FALSE, FALSE);
10001 #ifdef BETTER_LITERAL_SHIFT
10002 /* if the shift count is known then do it
10003 as efficiently as possible */
10004 if (AOP_TYPE (right) == AOP_LIT)
10006 if (genRightShiftLiteral (left, right, result, ic, 0))
10013 /* shift count is unknown then we have to form
10014 a loop get the loop count in B : Note: we take
10015 only the lower order byte since shifting
10016 more that 32 bits make no sense anyway, ( the
10017 largest size of an object can be only 32 bits ) */
10019 pushedB = pushB ();
10020 if (AOP_TYPE (right) == AOP_LIT)
10022 /* Really should be handled by genRightShiftLiteral,
10023 * but since I'm too lazy to fix that today, at least we can make
10024 * some small improvement.
10026 emitcode("mov", "b,#!constbyte",
10027 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
10031 MOVB (aopGet (right, 0, FALSE, FALSE, "b"));
10032 emitcode ("inc", "b");
10034 freeAsmop (right, NULL, ic, TRUE);
10035 aopOp (left, ic, FALSE, FALSE);
10036 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
10038 /* now move the left to the result if they are not the
10040 if (!sameRegs (AOP (left), AOP (result)) &&
10041 AOP_SIZE (result) > 1)
10043 size = AOP_SIZE (result);
10045 _startLazyDPSEvaluation ();
10048 l = aopGet (left, offset, FALSE, TRUE, NULL);
10049 if (*l == '@' && IS_AOP_PREG (result))
10052 emitcode ("mov", "a,%s", l);
10053 aopPut (result, "a", offset);
10056 aopPut (result, l, offset);
10059 _endLazyDPSEvaluation ();
10062 tlbl = newiTempLabel (NULL);
10063 tlbl1 = newiTempLabel (NULL);
10064 size = AOP_SIZE (result);
10067 /* if it is only one byte then */
10070 l = aopGet (left, 0, FALSE, FALSE, NULL);
10072 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10073 emitcode ("", "!tlabeldef", tlbl->key + 100);
10075 emitcode ("rrc", "a");
10076 emitcode ("", "!tlabeldef", tlbl1->key + 100);
10077 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10079 aopPut (result, "a", 0);
10083 reAdjustPreg (AOP (result));
10084 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10085 emitcode ("", "!tlabeldef", tlbl->key + 100);
10087 _startLazyDPSEvaluation ();
10090 l = aopGet (result, offset, FALSE, FALSE, NULL);
10092 emitcode ("rrc", "a");
10093 aopPut (result, "a", offset--);
10095 _endLazyDPSEvaluation ();
10096 reAdjustPreg (AOP (result));
10098 emitcode ("", "!tlabeldef", tlbl1->key + 100);
10099 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10103 freeAsmop (result, NULL, ic, TRUE);
10104 freeAsmop (left, NULL, ic, TRUE);
10107 /*-----------------------------------------------------------------*/
10108 /* emitPtrByteGet - emits code to get a byte into A through a */
10109 /* pointer register (R0, R1, or DPTR). The */
10110 /* original value of A can be preserved in B. */
10111 /*-----------------------------------------------------------------*/
10113 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
10120 emitcode ("mov", "b,a");
10121 emitcode ("mov", "a,@%s", rname);
10126 emitcode ("mov", "b,a");
10127 emitcode ("movx", "a,@%s", rname);
10132 emitcode ("mov", "b,a");
10133 emitcode ("movx", "a,@dptr");
10138 emitcode ("mov", "b,a");
10139 emitcode ("clr", "a");
10140 emitcode ("movc", "a,@a+dptr");
10146 emitcode ("push", "b");
10147 emitcode ("push", "acc");
10149 emitcode ("lcall", "__gptrget");
10151 emitcode ("pop", "b");
10156 /*-----------------------------------------------------------------*/
10157 /* emitPtrByteSet - emits code to set a byte from src through a */
10158 /* pointer register (R0, R1, or DPTR). */
10159 /*-----------------------------------------------------------------*/
10161 emitPtrByteSet (char *rname, int p_type, char *src)
10170 emitcode ("mov", "@%s,a", rname);
10173 emitcode ("mov", "@%s,%s", rname, src);
10178 emitcode ("movx", "@%s,a", rname);
10183 emitcode ("movx", "@dptr,a");
10188 emitcode ("lcall", "__gptrput");
10193 /*-----------------------------------------------------------------*/
10194 /* genUnpackBits - generates code for unpacking bits */
10195 /*-----------------------------------------------------------------*/
10197 genUnpackBits (operand * result, char *rname, int ptype)
10199 int offset = 0; /* result byte offset */
10200 int rsize; /* result size */
10201 int rlen = 0; /* remaining bitfield length */
10202 sym_link *etype; /* bitfield type information */
10203 int blen; /* bitfield length */
10204 int bstr; /* bitfield starting bit within byte */
10206 D(emitcode ("; genUnpackBits",""));
10208 etype = getSpec (operandType (result));
10209 rsize = getSize (operandType (result));
10210 blen = SPEC_BLEN (etype);
10211 bstr = SPEC_BSTR (etype);
10213 /* If the bitfield length is less than a byte */
10216 emitPtrByteGet (rname, ptype, FALSE);
10218 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
10219 if (!SPEC_USIGN (etype))
10221 /* signed bitfield */
10222 symbol *tlbl = newiTempLabel (NULL);
10224 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
10225 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
10226 emitcode ("", "%05d$:", tlbl->key + 100);
10228 aopPut (result, "a", offset++);
10232 /* Bit field did not fit in a byte. Copy all
10233 but the partial byte at the end. */
10234 for (rlen=blen;rlen>=8;rlen-=8)
10236 emitPtrByteGet (rname, ptype, FALSE);
10237 aopPut (result, "a", offset++);
10239 emitcode ("inc", "%s", rname);
10242 /* Handle the partial byte at the end */
10245 emitPtrByteGet (rname, ptype, FALSE);
10246 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
10247 if (!SPEC_USIGN (etype))
10249 /* signed bitfield */
10250 symbol *tlbl = newiTempLabel (NULL);
10252 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
10253 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
10254 emitcode ("", "%05d$:", tlbl->key + 100);
10256 aopPut (result, "a", offset++);
10260 if (offset < rsize)
10264 if (SPEC_USIGN (etype))
10268 /* signed bitfield: sign extension with 0x00 or 0xff */
10269 emitcode ("rlc", "a");
10270 emitcode ("subb", "a,acc");
10276 aopPut (result, source, offset++);
10281 /*-----------------------------------------------------------------*/
10282 /* genDataPointerGet - generates code when ptr offset is known */
10283 /*-----------------------------------------------------------------*/
10285 genDataPointerGet (operand * left,
10291 int size, offset = 0;
10292 aopOp (result, ic, TRUE, FALSE);
10294 /* get the string representation of the name */
10295 l = aopGet (left, 0, FALSE, TRUE, NULL);
10296 size = AOP_SIZE (result);
10297 _startLazyDPSEvaluation ();
10302 SNPRINTF (buffer, sizeof(buffer),
10303 "(%s + %d)", l + 1, offset);
10307 SNPRINTF (buffer, sizeof(buffer),
10310 aopPut (result, buffer, offset++);
10312 _endLazyDPSEvaluation ();
10314 freeAsmop (result, NULL, ic, TRUE);
10315 freeAsmop (left, NULL, ic, TRUE);
10318 /*-----------------------------------------------------------------*/
10319 /* genNearPointerGet - emitcode for near pointer fetch */
10320 /*-----------------------------------------------------------------*/
10322 genNearPointerGet (operand * left,
10330 sym_link *rtype, *retype, *letype;
10331 sym_link *ltype = operandType (left);
10334 rtype = operandType (result);
10335 retype = getSpec (rtype);
10336 letype = getSpec (ltype);
10338 aopOp (left, ic, FALSE, FALSE);
10340 /* if left is rematerialisable and
10341 result is not bitfield variable type and
10342 the left is pointer to data space i.e
10343 lower 128 bytes of space */
10344 if (AOP_TYPE (left) == AOP_IMMD &&
10345 !IS_BITFIELD (retype) &&
10346 !IS_BITFIELD (letype) &&
10347 DCL_TYPE (ltype) == POINTER)
10349 genDataPointerGet (left, result, ic);
10353 /* if the value is already in a pointer register
10354 then don't need anything more */
10355 if (!AOP_INPREG (AOP (left)))
10357 /* otherwise get a free pointer register */
10358 aop = newAsmop (0);
10359 preg = getFreePtr (ic, &aop, FALSE);
10360 emitcode ("mov", "%s,%s",
10362 aopGet (left, 0, FALSE, TRUE, DP2_RESULT_REG));
10363 rname = preg->name;
10366 rname = aopGet (left, 0, FALSE, FALSE, DP2_RESULT_REG);
10368 freeAsmop (left, NULL, ic, TRUE);
10369 aopOp (result, ic, FALSE, FALSE);
10371 /* if bitfield then unpack the bits */
10372 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10373 genUnpackBits (result, rname, POINTER);
10376 /* we have can just get the values */
10377 int size = AOP_SIZE (result);
10382 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
10385 emitcode ("mov", "a,@%s", rname);
10386 aopPut (result, "a", offset);
10390 SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
10391 aopPut (result, buffer, offset);
10395 emitcode ("inc", "%s", rname);
10399 /* now some housekeeping stuff */
10400 if (aop) /* we had to allocate for this iCode */
10402 if (pi) { /* post increment present */
10403 aopPut (left, rname, 0);
10405 freeAsmop (NULL, aop, ic, TRUE);
10409 /* we did not allocate which means left
10410 already in a pointer register, then
10411 if size > 0 && this could be used again
10412 we have to point it back to where it
10414 if (AOP_SIZE (result) > 1 &&
10415 !OP_SYMBOL (left)->remat &&
10416 (OP_SYMBOL (left)->liveTo > ic->seq ||
10420 int size = AOP_SIZE (result) - 1;
10422 emitcode ("dec", "%s", rname);
10427 freeAsmop (result, NULL, ic, TRUE);
10428 if (pi) pi->generated = 1;
10431 /*-----------------------------------------------------------------*/
10432 /* genPagedPointerGet - emitcode for paged pointer fetch */
10433 /*-----------------------------------------------------------------*/
10435 genPagedPointerGet (operand * left,
10443 sym_link *rtype, *retype, *letype;
10445 rtype = operandType (result);
10446 retype = getSpec (rtype);
10447 letype = getSpec (operandType (left));
10448 aopOp (left, ic, FALSE, FALSE);
10450 /* if the value is already in a pointer register
10451 then don't need anything more */
10452 if (!AOP_INPREG (AOP (left)))
10454 /* otherwise get a free pointer register */
10455 aop = newAsmop (0);
10456 preg = getFreePtr (ic, &aop, FALSE);
10457 emitcode ("mov", "%s,%s",
10459 aopGet (left, 0, FALSE, TRUE, NULL));
10460 rname = preg->name;
10463 rname = aopGet (left, 0, FALSE, FALSE, NULL);
10465 freeAsmop (left, NULL, ic, TRUE);
10466 aopOp (result, ic, FALSE, FALSE);
10468 /* if bitfield then unpack the bits */
10469 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10470 genUnpackBits (result, rname, PPOINTER);
10473 /* we have can just get the values */
10474 int size = AOP_SIZE (result);
10480 emitcode ("movx", "a,@%s", rname);
10481 aopPut (result, "a", offset);
10486 emitcode ("inc", "%s", rname);
10490 /* now some housekeeping stuff */
10491 if (aop) /* we had to allocate for this iCode */
10493 if (pi) aopPut (left, rname, 0);
10494 freeAsmop (NULL, aop, ic, TRUE);
10498 /* we did not allocate which means left
10499 already in a pointer register, then
10500 if size > 0 && this could be used again
10501 we have to point it back to where it
10503 if (AOP_SIZE (result) > 1 &&
10504 !OP_SYMBOL (left)->remat &&
10505 (OP_SYMBOL (left)->liveTo > ic->seq ||
10509 int size = AOP_SIZE (result) - 1;
10511 emitcode ("dec", "%s", rname);
10516 freeAsmop (result, NULL, ic, TRUE);
10517 if (pi) pi->generated = 1;
10520 /*-----------------------------------------------------------------*/
10521 /* genFarPointerGet - get value from far space */
10522 /*-----------------------------------------------------------------*/
10524 genFarPointerGet (operand * left,
10525 operand * result, iCode * ic, iCode *pi)
10527 int size, offset, dopi=1;
10528 sym_link *retype = getSpec (operandType (result));
10529 sym_link *letype = getSpec (operandType (left));
10530 D (emitcode (";", "genFarPointerGet"););
10532 aopOp (left, ic, FALSE, FALSE);
10534 /* if the operand is already in dptr
10535 then we do nothing else we move the value to dptr */
10536 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
10538 /* if this is rematerializable */
10539 if (AOP_TYPE (left) == AOP_IMMD)
10541 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
10545 /* we need to get it byte by byte */
10546 _startLazyDPSEvaluation ();
10547 if (AOP_TYPE (left) != AOP_DPTR)
10549 emitcode ("mov", "dpl,%s", aopGet (left, 0, FALSE, FALSE, NULL));
10550 emitcode ("mov", "dph,%s", aopGet (left, 1, FALSE, FALSE, NULL));
10551 if (options.model == MODEL_FLAT24)
10552 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10556 /* We need to generate a load to DPTR indirect through DPTR. */
10557 D (emitcode (";", "genFarPointerGet -- indirection special case."););
10558 emitcode ("push", "%s", aopGet (left, 0, FALSE, TRUE, NULL));
10559 emitcode ("push", "%s", aopGet (left, 1, FALSE, TRUE, NULL));
10560 if (options.model == MODEL_FLAT24)
10561 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10562 emitcode ("pop", "dph");
10563 emitcode ("pop", "dpl");
10566 _endLazyDPSEvaluation ();
10569 /* so dptr know contains the address */
10570 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10572 /* if bit then unpack */
10573 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
10574 if (AOP_INDPTRn(left)) {
10575 genSetDPTR(AOP(left)->aopu.dptr);
10577 genUnpackBits (result, "dptr", FPOINTER);
10578 if (AOP_INDPTRn(left)) {
10583 size = AOP_SIZE (result);
10586 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10588 genSetDPTR(AOP(left)->aopu.dptr);
10589 emitcode ("movx", "a,@dptr");
10590 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10591 emitcode ("inc", "dptr");
10593 aopPut (result, "a", offset++);
10596 _startLazyDPSEvaluation ();
10598 if (AOP_INDPTRn(left)) {
10599 genSetDPTR(AOP(left)->aopu.dptr);
10605 emitcode ("movx", "a,@dptr");
10606 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10607 emitcode ("inc", "dptr");
10609 aopPut (result, "a", offset++);
10611 _endLazyDPSEvaluation ();
10614 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10615 if (!AOP_INDPTRn(left)) {
10616 _startLazyDPSEvaluation ();
10617 aopPut (left, "dpl", 0);
10618 aopPut (left, "dph", 1);
10619 if (options.model == MODEL_FLAT24)
10620 aopPut (left, "dpx", 2);
10621 _endLazyDPSEvaluation ();
10624 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
10625 AOP_SIZE(result) > 1 &&
10627 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
10629 size = AOP_SIZE (result) - 1;
10630 if (AOP_INDPTRn(left)) {
10631 genSetDPTR(AOP(left)->aopu.dptr);
10633 while (size--) emitcode ("lcall","__decdptr");
10634 if (AOP_INDPTRn(left)) {
10639 freeAsmop (left, NULL, ic, TRUE);
10640 freeAsmop (result, NULL, ic, TRUE);
10643 /*-----------------------------------------------------------------*/
10644 /* genCodePointerGet - get value from code space */
10645 /*-----------------------------------------------------------------*/
10647 genCodePointerGet (operand * left,
10648 operand * result, iCode * ic, iCode *pi)
10650 int size, offset, dopi=1;
10651 sym_link *retype = getSpec (operandType (result));
10653 aopOp (left, ic, FALSE, FALSE);
10655 /* if the operand is already in dptr
10656 then we do nothing else we move the value to dptr */
10657 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
10659 /* if this is rematerializable */
10660 if (AOP_TYPE (left) == AOP_IMMD)
10662 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
10665 { /* we need to get it byte by byte */
10666 _startLazyDPSEvaluation ();
10667 if (AOP_TYPE (left) != AOP_DPTR)
10669 emitcode ("mov", "dpl,%s", aopGet (left, 0, FALSE, FALSE, NULL));
10670 emitcode ("mov", "dph,%s", aopGet (left, 1, FALSE, FALSE, NULL));
10671 if (options.model == MODEL_FLAT24)
10672 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10676 /* We need to generate a load to DPTR indirect through DPTR. */
10677 D (emitcode (";", "gencodePointerGet -- indirection special case."););
10678 emitcode ("push", "%s", aopGet (left, 0, FALSE, TRUE, NULL));
10679 emitcode ("push", "%s", aopGet (left, 1, FALSE, TRUE, NULL));
10680 if (options.model == MODEL_FLAT24)
10681 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10682 emitcode ("pop", "dph");
10683 emitcode ("pop", "dpl");
10686 _endLazyDPSEvaluation ();
10689 /* so dptr know contains the address */
10690 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10692 /* if bit then unpack */
10693 if (IS_BITFIELD (retype)) {
10694 if (AOP_INDPTRn(left)) {
10695 genSetDPTR(AOP(left)->aopu.dptr);
10697 genUnpackBits (result, "dptr", CPOINTER);
10698 if (AOP_INDPTRn(left)) {
10703 size = AOP_SIZE (result);
10705 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10707 genSetDPTR(AOP(left)->aopu.dptr);
10708 emitcode ("clr", "a");
10709 emitcode ("movc", "a,@a+dptr");
10710 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10711 emitcode ("inc", "dptr");
10713 aopPut (result, "a", offset++);
10716 _startLazyDPSEvaluation ();
10719 if (AOP_INDPTRn(left)) {
10720 genSetDPTR(AOP(left)->aopu.dptr);
10726 emitcode ("clr", "a");
10727 emitcode ("movc", "a,@a+dptr");
10728 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10729 emitcode ("inc", "dptr");
10730 aopPut (result, "a", offset++);
10732 _endLazyDPSEvaluation ();
10735 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10736 if (!AOP_INDPTRn(left)) {
10737 _startLazyDPSEvaluation ();
10739 aopPut (left, "dpl", 0);
10740 aopPut (left, "dph", 1);
10741 if (options.model == MODEL_FLAT24)
10742 aopPut (left, "dpx", 2);
10744 _endLazyDPSEvaluation ();
10747 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
10748 AOP_SIZE(result) > 1 &&
10749 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10751 size = AOP_SIZE (result) - 1;
10752 if (AOP_INDPTRn(left)) {
10753 genSetDPTR(AOP(left)->aopu.dptr);
10755 while (size--) emitcode ("lcall","__decdptr");
10756 if (AOP_INDPTRn(left)) {
10761 freeAsmop (result, NULL, ic, TRUE);
10762 freeAsmop (left, NULL, ic, TRUE);
10765 /*-----------------------------------------------------------------*/
10766 /* genGenPointerGet - gget value from generic pointer space */
10767 /*-----------------------------------------------------------------*/
10769 genGenPointerGet (operand * left,
10770 operand * result, iCode * ic, iCode * pi)
10774 sym_link *retype = getSpec (operandType (result));
10775 sym_link *letype = getSpec (operandType (left));
10777 D (emitcode (";", "genGenPointerGet"));
10779 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
10781 pushedB = pushB ();
10782 /* if the operand is already in dptr
10783 then we do nothing else we move the value to dptr */
10784 if (AOP_TYPE (left) != AOP_STR)
10786 /* if this is rematerializable */
10787 if (AOP_TYPE (left) == AOP_IMMD)
10789 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
10790 if (AOP(left)->aopu.aop_immd.from_cast_remat)
10792 MOVB (aopGet (left, AOP_SIZE(left)-1, FALSE, FALSE, NULL));
10796 emitcode ("mov", "b,#%d", pointerCode (retype));
10800 { /* we need to get it byte by byte */
10801 _startLazyDPSEvaluation ();
10802 emitcode ("mov", "dpl,%s", aopGet (left,0,FALSE,FALSE,NULL));
10803 emitcode ("mov", "dph,%s", aopGet (left,1,FALSE,FALSE,NULL));
10804 if (options.model == MODEL_FLAT24) {
10805 emitcode ("mov", "dpx,%s", aopGet (left,2,FALSE,FALSE,NULL));
10806 emitcode ("mov", "b,%s", aopGet (left,3,FALSE,FALSE,NULL));
10808 emitcode ("mov", "b,%s", aopGet (left,2,FALSE,FALSE,NULL));
10810 _endLazyDPSEvaluation ();
10814 /* so dptr-b now contains the address */
10815 aopOp (result, ic, FALSE, TRUE);
10817 /* if bit then unpack */
10818 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10820 genUnpackBits (result, "dptr", GPOINTER);
10824 size = AOP_SIZE (result);
10831 // Get two bytes at a time, results in _AP & A.
10832 // dptr will be incremented ONCE by __gptrgetWord.
10834 // Note: any change here must be coordinated
10835 // with the implementation of __gptrgetWord
10836 // in device/lib/_gptrget.c
10837 emitcode ("lcall", "__gptrgetWord");
10838 aopPut (result, DP2_RESULT_REG, offset++);
10839 aopPut (result, "a", offset++);
10844 // Only one byte to get.
10845 emitcode ("lcall", "__gptrget");
10846 aopPut (result, "a", offset++);
10849 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
10851 emitcode ("inc", "dptr");
10856 if (pi && AOP_TYPE (left) != AOP_IMMD) {
10857 _startLazyDPSEvaluation ();
10859 aopPut (left, "dpl", 0);
10860 aopPut (left, "dph", 1);
10861 if (options.model == MODEL_FLAT24) {
10862 aopPut (left, "dpx", 2);
10863 aopPut (left, "b", 3);
10864 } else aopPut (left, "b", 2);
10866 _endLazyDPSEvaluation ();
10869 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
10870 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10872 size = AOP_SIZE (result) - 1;
10873 while (size--) emitcode ("lcall","__decdptr");
10877 freeAsmop (result, NULL, ic, TRUE);
10878 freeAsmop (left, NULL, ic, TRUE);
10881 /*-----------------------------------------------------------------*/
10882 /* genPointerGet - generate code for pointer get */
10883 /*-----------------------------------------------------------------*/
10885 genPointerGet (iCode * ic, iCode *pi)
10887 operand *left, *result;
10888 sym_link *type, *etype;
10891 D (emitcode (";", "genPointerGet "));
10893 left = IC_LEFT (ic);
10894 result = IC_RESULT (ic);
10896 /* depending on the type of pointer we need to
10897 move it to the correct pointer register */
10898 type = operandType (left);
10899 etype = getSpec (type);
10900 /* if left is of type of pointer then it is simple */
10901 if (IS_PTR (type) && !IS_FUNC (type->next))
10902 p_type = DCL_TYPE (type);
10905 /* we have to go by the storage class */
10906 p_type = PTR_TYPE (SPEC_OCLS (etype));
10909 /* special case when cast remat */
10910 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10911 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10913 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10914 type = operandType (left);
10915 p_type = DCL_TYPE (type);
10917 /* now that we have the pointer type we assign
10918 the pointer values */
10924 genNearPointerGet (left, result, ic, pi);
10928 genPagedPointerGet (left, result, ic, pi);
10932 genFarPointerGet (left, result, ic, pi);
10936 genCodePointerGet (left, result, ic, pi);
10940 genGenPointerGet (left, result, ic, pi);
10945 /*-----------------------------------------------------------------*/
10946 /* genPackBits - generates code for packed bit storage */
10947 /*-----------------------------------------------------------------*/
10949 genPackBits (sym_link * etype,
10951 char *rname, int p_type)
10953 int offset = 0; /* source byte offset */
10954 int rlen = 0; /* remaining bitfield length */
10955 int blen; /* bitfield length */
10956 int bstr; /* bitfield starting bit within byte */
10957 int litval; /* source literal value (if AOP_LIT) */
10958 unsigned char mask; /* bitmask within current byte */
10960 D(emitcode ("; genPackBits",""));
10962 blen = SPEC_BLEN (etype);
10963 bstr = SPEC_BSTR (etype);
10965 /* If the bitfield length is less than a byte */
10968 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10969 (unsigned char) (0xFF >> (8 - bstr)));
10971 if (AOP_TYPE (right) == AOP_LIT)
10973 /* Case with a bitfield length <8 and literal source
10975 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10977 litval &= (~mask) & 0xff;
10978 emitPtrByteGet (rname, p_type, FALSE);
10979 if ((mask|litval)!=0xff)
10980 emitcode ("anl","a,#!constbyte", mask);
10982 emitcode ("orl","a,#!constbyte", litval);
10986 if ((blen==1) && (p_type!=GPOINTER))
10988 /* Case with a bitfield length == 1 and no generic pointer
10990 if (AOP_TYPE (right) == AOP_CRY)
10991 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10994 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
10995 emitcode ("rrc","a");
10997 emitPtrByteGet (rname, p_type, FALSE);
10998 emitcode ("mov","acc.%d,c",bstr);
11003 /* Case with a bitfield length < 8 and arbitrary source
11005 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
11006 /* shift and mask source value */
11008 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
11010 pushedB = pushB ();
11011 /* transfer A to B and get next byte */
11012 emitPtrByteGet (rname, p_type, TRUE);
11014 emitcode ("anl", "a,#!constbyte", mask);
11015 emitcode ("orl", "a,b");
11016 if (p_type == GPOINTER)
11017 emitcode ("pop", "b");
11023 emitPtrByteSet (rname, p_type, "a");
11027 /* Bit length is greater than 7 bits. In this case, copy */
11028 /* all except the partial byte at the end */
11029 for (rlen=blen;rlen>=8;rlen-=8)
11031 emitPtrByteSet (rname, p_type,
11032 aopGet (right, offset++, FALSE, TRUE, NULL) );
11034 emitcode ("inc", "%s", rname);
11037 /* If there was a partial byte at the end */
11040 mask = (((unsigned char) -1 << rlen) & 0xff);
11042 if (AOP_TYPE (right) == AOP_LIT)
11044 /* Case with partial byte and literal source
11046 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
11047 litval >>= (blen-rlen);
11048 litval &= (~mask) & 0xff;
11049 emitPtrByteGet (rname, p_type, FALSE);
11050 if ((mask|litval)!=0xff)
11051 emitcode ("anl","a,#!constbyte", mask);
11053 emitcode ("orl","a,#!constbyte", litval);
11058 /* Case with partial byte and arbitrary source
11060 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11061 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
11063 pushedB = pushB ();
11064 /* transfer A to B and get next byte */
11065 emitPtrByteGet (rname, p_type, TRUE);
11067 emitcode ("anl", "a,#!constbyte", mask);
11068 emitcode ("orl", "a,b");
11069 if (p_type == GPOINTER)
11070 emitcode ("pop", "b");
11074 emitPtrByteSet (rname, p_type, "a");
11079 /*-----------------------------------------------------------------*/
11080 /* genDataPointerSet - remat pointer to data space */
11081 /*-----------------------------------------------------------------*/
11083 genDataPointerSet (operand * right,
11087 int size, offset = 0;
11088 char *l, buffer[256];
11090 D (emitcode (";", "genDataPointerSet"));
11092 aopOp (right, ic, FALSE, FALSE);
11094 l = aopGet (result, 0, FALSE, TRUE, NULL);
11095 size = AOP_SIZE (right);
11099 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l + 1, offset);
11101 SNPRINTF (buffer, sizeof(buffer), "%s", l + 1);
11102 emitcode ("mov", "%s,%s", buffer,
11103 aopGet (right, offset++, FALSE, FALSE, NULL));
11106 freeAsmop (result, NULL, ic, TRUE);
11107 freeAsmop (right, NULL, ic, TRUE);
11110 /*-----------------------------------------------------------------*/
11111 /* genNearPointerSet - emitcode for near pointer put */
11112 /*-----------------------------------------------------------------*/
11114 genNearPointerSet (operand * right,
11121 sym_link *retype, *letype;
11122 sym_link *ptype = operandType (result);
11124 D(emitcode (";", "genNearPointerSet"));
11126 retype = getSpec (operandType (right));
11127 letype = getSpec (ptype);
11129 aopOp (result, ic, FALSE, FALSE);
11131 /* if the result is rematerializable &
11132 in data space & not a bit variable */
11133 if (AOP_TYPE (result) == AOP_IMMD &&
11134 DCL_TYPE (ptype) == POINTER &&
11135 !IS_BITVAR (retype) &&
11136 !IS_BITVAR (letype))
11138 genDataPointerSet (right, result, ic);
11142 /* if the value is already in a pointer register
11143 then don't need anything more */
11144 if (!AOP_INPREG (AOP (result)))
11146 /* otherwise get a free pointer register */
11149 aop = newAsmop (0);
11150 preg = getFreePtr (ic, &aop, FALSE);
11151 emitcode ("mov", "%s,%s",
11153 aopGet (result, 0, FALSE, TRUE, NULL));
11154 rname = preg->name;
11158 rname = aopGet (result, 0, FALSE, FALSE, NULL);
11161 aopOp (right, ic, FALSE, FALSE);
11163 /* if bitfield then unpack the bits */
11164 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11165 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
11168 /* we have can just get the values */
11169 int size = AOP_SIZE (right);
11174 l = aopGet (right, offset, FALSE, TRUE, NULL);
11178 emitcode ("mov", "@%s,a", rname);
11181 emitcode ("mov", "@%s,%s", rname, l);
11183 emitcode ("inc", "%s", rname);
11188 /* now some housekeeping stuff */
11189 if (aop) /* we had to allocate for this iCode */
11191 if (pi) aopPut (result,rname,0);
11192 freeAsmop (NULL, aop, ic, TRUE);
11196 /* we did not allocate which means left
11197 already in a pointer register, then
11198 if size > 0 && this could be used again
11199 we have to point it back to where it
11201 if (AOP_SIZE (right) > 1 &&
11202 !OP_SYMBOL (result)->remat &&
11203 (OP_SYMBOL (result)->liveTo > ic->seq ||
11207 int size = AOP_SIZE (right) - 1;
11209 emitcode ("dec", "%s", rname);
11214 if (pi) pi->generated = 1;
11215 freeAsmop (result, NULL, ic, TRUE);
11216 freeAsmop (right, NULL, ic, TRUE);
11219 /*-----------------------------------------------------------------*/
11220 /* genPagedPointerSet - emitcode for Paged pointer put */
11221 /*-----------------------------------------------------------------*/
11223 genPagedPointerSet (operand * right,
11230 sym_link *retype, *letype;
11232 D (emitcode (";", "genPagedPointerSet"));
11234 retype = getSpec (operandType (right));
11235 letype = getSpec (operandType (result));
11237 aopOp (result, ic, FALSE, FALSE);
11239 /* if the value is already in a pointer register
11240 then don't need anything more */
11241 if (!AOP_INPREG (AOP (result)))
11243 /* otherwise get a free pointer register */
11246 aop = newAsmop (0);
11247 preg = getFreePtr (ic, &aop, FALSE);
11248 emitcode ("mov", "%s,%s",
11250 aopGet (result, 0, FALSE, TRUE, NULL));
11251 rname = preg->name;
11254 rname = aopGet (result, 0, FALSE, FALSE, NULL);
11256 aopOp (right, ic, FALSE, FALSE);
11258 /* if bitfield then unpack the bits */
11259 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11260 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
11263 /* we have can just get the values */
11264 int size = AOP_SIZE (right);
11269 l = aopGet (right, offset, FALSE, TRUE, NULL);
11271 emitcode ("movx", "@%s,a", rname);
11274 emitcode ("inc", "%s", rname);
11280 /* now some housekeeping stuff */
11284 aopPut (result, rname, 0);
11285 /* we had to allocate for this iCode */
11286 freeAsmop (NULL, aop, ic, TRUE);
11290 /* we did not allocate which means left
11291 already in a pointer register, then
11292 if size > 0 && this could be used again
11293 we have to point it back to where it
11295 if (AOP_SIZE (right) > 1 &&
11296 !OP_SYMBOL (result)->remat &&
11297 (OP_SYMBOL (result)->liveTo > ic->seq ||
11301 int size = AOP_SIZE (right) - 1;
11303 emitcode ("dec", "%s", rname);
11308 if (pi) pi->generated = 1;
11309 freeAsmop (result, NULL, ic, TRUE);
11310 freeAsmop (right, NULL, ic, TRUE);
11313 /*-----------------------------------------------------------------*/
11314 /* genFarPointerSet - set value from far space */
11315 /*-----------------------------------------------------------------*/
11317 genFarPointerSet (operand * right,
11318 operand * result, iCode * ic, iCode *pi)
11320 int size, offset, dopi=1;
11321 sym_link *retype = getSpec (operandType (right));
11322 sym_link *letype = getSpec (operandType (result));
11324 aopOp (result, ic, FALSE, FALSE);
11326 /* if the operand is already in dptr
11327 then we do nothing else we move the value to dptr */
11328 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
11330 /* if this is remateriazable */
11331 if (AOP_TYPE (result) == AOP_IMMD)
11332 emitcode ("mov", "dptr,%s",
11333 aopGet (result, 0, TRUE, FALSE, NULL));
11336 /* we need to get it byte by byte */
11337 _startLazyDPSEvaluation ();
11338 if (AOP_TYPE (result) != AOP_DPTR)
11340 emitcode ("mov", "dpl,%s", aopGet (result, 0, FALSE, FALSE, NULL));
11341 emitcode ("mov", "dph,%s", aopGet (result, 1, FALSE, FALSE, NULL));
11342 if (options.model == MODEL_FLAT24)
11343 emitcode ("mov", "dpx,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11347 /* We need to generate a load to DPTR indirect through DPTR. */
11348 D (emitcode (";", "genFarPointerSet -- indirection special case."););
11350 emitcode ("push", "%s", aopGet (result, 0, FALSE, TRUE, NULL));
11351 emitcode ("push", "%s", aopGet (result, 1, FALSE, TRUE, NULL));
11352 if (options.model == MODEL_FLAT24)
11353 emitcode ("mov", "dpx,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11354 emitcode ("pop", "dph");
11355 emitcode ("pop", "dpl");
11358 _endLazyDPSEvaluation ();
11361 /* so dptr know contains the address */
11362 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
11364 /* if bit then unpack */
11365 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11367 if (AOP_INDPTRn(result)) {
11368 genSetDPTR(AOP(result)->aopu.dptr);
11370 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
11371 if (AOP_INDPTRn(result)) {
11375 size = AOP_SIZE (right);
11377 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
11379 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11381 genSetDPTR(AOP(result)->aopu.dptr);
11382 emitcode ("movx", "@dptr,a");
11383 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
11384 emitcode ("inc", "dptr");
11388 _startLazyDPSEvaluation ();
11390 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11392 if (AOP_INDPTRn(result)) {
11393 genSetDPTR(AOP(result)->aopu.dptr);
11399 emitcode ("movx", "@dptr,a");
11400 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
11401 emitcode ("inc", "dptr");
11403 _endLazyDPSEvaluation ();
11407 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
11408 if (!AOP_INDPTRn(result)) {
11409 _startLazyDPSEvaluation ();
11411 aopPut (result,"dpl",0);
11412 aopPut (result,"dph",1);
11413 if (options.model == MODEL_FLAT24)
11414 aopPut (result,"dpx",2);
11416 _endLazyDPSEvaluation ();
11419 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
11420 AOP_SIZE(right) > 1 &&
11421 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
11423 size = AOP_SIZE (right) - 1;
11424 if (AOP_INDPTRn(result)) {
11425 genSetDPTR(AOP(result)->aopu.dptr);
11427 while (size--) emitcode ("lcall","__decdptr");
11428 if (AOP_INDPTRn(result)) {
11432 freeAsmop (result, NULL, ic, TRUE);
11433 freeAsmop (right, NULL, ic, TRUE);
11436 /*-----------------------------------------------------------------*/
11437 /* genGenPointerSet - set value from generic pointer space */
11438 /*-----------------------------------------------------------------*/
11440 genGenPointerSet (operand * right,
11441 operand * result, iCode * ic, iCode *pi)
11445 sym_link *retype = getSpec (operandType (right));
11446 sym_link *letype = getSpec (operandType (result));
11448 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
11450 pushedB = pushB ();
11451 /* if the operand is already in dptr
11452 then we do nothing else we move the value to dptr */
11453 if (AOP_TYPE (result) != AOP_STR)
11455 _startLazyDPSEvaluation ();
11456 /* if this is remateriazable */
11457 if (AOP_TYPE (result) == AOP_IMMD)
11459 emitcode ("mov", "dptr,%s", aopGet (result, 0, TRUE, FALSE, NULL));
11460 if (AOP(result)->aopu.aop_immd.from_cast_remat)
11462 MOVB (aopGet (result, AOP_SIZE(result)-1, FALSE, FALSE, NULL));
11467 "b,%s + 1", aopGet (result, 0, TRUE, FALSE, NULL));
11471 { /* we need to get it byte by byte */
11472 emitcode ("mov", "dpl,%s", aopGet (result, 0, FALSE, FALSE, NULL));
11473 emitcode ("mov", "dph,%s", aopGet (result, 1, FALSE, FALSE, NULL));
11474 if (options.model == MODEL_FLAT24) {
11475 emitcode ("mov", "dpx,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11476 emitcode ("mov", "b,%s", aopGet (result, 3, FALSE, FALSE, NULL));
11478 emitcode ("mov", "b,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11481 _endLazyDPSEvaluation ();
11483 /* so dptr + b now contains the address */
11484 aopOp (right, ic, FALSE, TRUE);
11486 /* if bit then unpack */
11487 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11489 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
11493 size = AOP_SIZE (right);
11496 _startLazyDPSEvaluation ();
11501 // Set two bytes at a time, passed in _AP & A.
11502 // dptr will be incremented ONCE by __gptrputWord.
11504 // Note: any change here must be coordinated
11505 // with the implementation of __gptrputWord
11506 // in device/lib/_gptrput.c
11507 emitcode("mov", "_ap, %s",
11508 aopGet (right, offset++, FALSE, FALSE, NULL));
11509 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11513 emitcode ("lcall", "__gptrputWord");
11518 // Only one byte to put.
11519 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11523 emitcode ("lcall", "__gptrput");
11526 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
11528 emitcode ("inc", "dptr");
11531 _endLazyDPSEvaluation ();
11534 if (pi && AOP_TYPE (result) != AOP_IMMD) {
11535 _startLazyDPSEvaluation ();
11537 aopPut (result, "dpl",0);
11538 aopPut (result, "dph",1);
11539 if (options.model == MODEL_FLAT24) {
11540 aopPut (result, "dpx",2);
11541 aopPut (result, "b",3);
11543 aopPut (result, "b",2);
11545 _endLazyDPSEvaluation ();
11548 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
11549 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
11551 size = AOP_SIZE (right) - 1;
11552 while (size--) emitcode ("lcall","__decdptr");
11556 freeAsmop (result, NULL, ic, TRUE);
11557 freeAsmop (right, NULL, ic, TRUE);
11560 /*-----------------------------------------------------------------*/
11561 /* genPointerSet - stores the value into a pointer location */
11562 /*-----------------------------------------------------------------*/
11564 genPointerSet (iCode * ic, iCode *pi)
11566 operand *right, *result;
11567 sym_link *type, *etype;
11570 D (emitcode (";", "genPointerSet"));
11572 right = IC_RIGHT (ic);
11573 result = IC_RESULT (ic);
11575 /* depending on the type of pointer we need to
11576 move it to the correct pointer register */
11577 type = operandType (result);
11578 etype = getSpec (type);
11579 /* if left is of type of pointer then it is simple */
11580 if (IS_PTR (type) && !IS_FUNC (type->next))
11582 p_type = DCL_TYPE (type);
11586 /* we have to go by the storage class */
11587 p_type = PTR_TYPE (SPEC_OCLS (etype));
11590 /* special case when cast remat */
11591 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
11592 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
11593 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
11594 type = operandType (result);
11595 p_type = DCL_TYPE (type);
11598 /* now that we have the pointer type we assign
11599 the pointer values */
11605 genNearPointerSet (right, result, ic, pi);
11609 genPagedPointerSet (right, result, ic, pi);
11613 genFarPointerSet (right, result, ic, pi);
11617 genGenPointerSet (right, result, ic, pi);
11621 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11622 "genPointerSet: illegal pointer type");
11626 /*-----------------------------------------------------------------*/
11627 /* genIfx - generate code for Ifx statement */
11628 /*-----------------------------------------------------------------*/
11630 genIfx (iCode * ic, iCode * popIc)
11632 operand *cond = IC_COND (ic);
11636 D (emitcode (";", "genIfx "));
11638 aopOp (cond, ic, FALSE, FALSE);
11640 /* get the value into acc */
11641 if (AOP_TYPE (cond) != AOP_CRY)
11648 if (AOP(cond)->aopu.aop_dir)
11649 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
11652 /* the result is now in the accumulator or a directly addressable bit */
11653 freeAsmop (cond, NULL, ic, TRUE);
11655 /* if there was something to be popped then do it */
11659 /* if the condition is a bit variable */
11662 genIfxJump (ic, dup);
11664 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
11666 genIfxJump (ic, SPIL_LOC (cond)->rname);
11668 else if (isbit && !IS_ITEMP (cond))
11670 genIfxJump (ic, OP_SYMBOL (cond)->rname);
11674 genIfxJump (ic, "a");
11680 /*-----------------------------------------------------------------*/
11681 /* genAddrOf - generates code for address of */
11682 /*-----------------------------------------------------------------*/
11684 genAddrOf (iCode * ic)
11686 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11689 D (emitcode (";", "genAddrOf"));
11691 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11693 /* if the operand is on the stack then we
11694 need to get the stack offset of this
11699 /* if 10 bit stack */
11700 if (options.stack10bit) {
11704 tsprintf(buff, sizeof(buff),
11705 "#!constbyte",(options.stack_loc >> 16) & 0xff);
11706 /* if it has an offset then we need to compute it */
11707 /* emitcode ("subb", "a,#!constbyte", */
11708 /* -((sym->stack < 0) ? */
11709 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11710 /* ((short) sym->stack)) & 0xff); */
11711 /* emitcode ("mov","b,a"); */
11712 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
11713 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11714 /* ((short) sym->stack)) >> 8) & 0xff); */
11716 emitcode ("mov", "a,_bpx");
11717 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
11718 ((char) (sym->stack - _G.nRegsSaved)) :
11719 ((char) sym->stack )) & 0xff);
11720 emitcode ("mov", "b,a");
11721 emitcode ("mov", "a,_bpx+1");
11723 offset = (((sym->stack < 0) ?
11724 ((short) (sym->stack - _G.nRegsSaved)) :
11725 ((short) sym->stack )) >> 8) & 0xff;
11727 emitcode ("addc","a,#!constbyte", offset);
11729 aopPut (IC_RESULT (ic), "b", 0);
11730 aopPut (IC_RESULT (ic), "a", 1);
11731 aopPut (IC_RESULT (ic), buff, 2);
11733 /* we can just move _bp */
11734 aopPut (IC_RESULT (ic), "_bpx", 0);
11735 aopPut (IC_RESULT (ic), "_bpx+1", 1);
11736 aopPut (IC_RESULT (ic), buff, 2);
11739 /* if it has an offset then we need to compute it */
11742 emitcode ("mov", "a,_bp");
11743 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
11744 aopPut (IC_RESULT (ic), "a", 0);
11748 /* we can just move _bp */
11749 aopPut (IC_RESULT (ic), "_bp", 0);
11751 /* fill the result with zero */
11752 size = AOP_SIZE (IC_RESULT (ic)) - 1;
11755 if (options.stack10bit && size < (FPTRSIZE - 1)) {
11757 "*** warning: pointer to stack var truncated.\n");
11763 aopPut (IC_RESULT (ic), zero, offset++);
11769 /* object not on stack then we need the name */
11770 size = AOP_SIZE (IC_RESULT (ic));
11775 char s[SDCC_NAME_MAX];
11779 tsprintf(s, sizeof(s), "#!his",sym->rname);
11782 tsprintf(s, sizeof(s), "#!hihis",sym->rname);
11785 tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
11787 default: /* should not need this (just in case) */
11788 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
11795 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11798 aopPut (IC_RESULT (ic), s, offset++);
11802 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11806 #if 0 // obsolete, and buggy for != xdata
11807 /*-----------------------------------------------------------------*/
11808 /* genArrayInit - generates code for address of */
11809 /*-----------------------------------------------------------------*/
11811 genArrayInit (iCode * ic)
11813 literalList *iLoop;
11815 int elementSize = 0, eIndex;
11816 unsigned val, lastVal;
11818 operand *left=IC_LEFT(ic);
11820 D (emitcode (";", "genArrayInit "););
11822 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
11824 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
11826 // Load immediate value into DPTR.
11827 emitcode("mov", "dptr, %s",
11828 aopGet (IC_LEFT(ic), 0, TRUE, FALSE, NULL));
11830 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
11833 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11834 "Unexpected operand to genArrayInit.\n");
11837 // a regression because of SDCCcse.c:1.52
11838 emitcode ("mov", "dpl,%s", aopGet (left, 0, FALSE, FALSE, NULL));
11839 emitcode ("mov", "dph,%s", aopGet (left, 1, FALSE, FALSE, NULL));
11840 if (options.model == MODEL_FLAT24)
11841 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
11845 type = operandType(IC_LEFT(ic));
11847 if (type && type->next)
11849 elementSize = getSize(type->next);
11853 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11854 "can't determine element size in genArrayInit.\n");
11858 iLoop = IC_ARRAYILIST(ic);
11863 bool firstpass = TRUE;
11865 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
11866 iLoop->count, (int)iLoop->literalValue, elementSize);
11872 symbol *tlbl = NULL;
11874 count = ix > 256 ? 256 : ix;
11878 tlbl = newiTempLabel (NULL);
11879 if (firstpass || (count & 0xff))
11881 emitcode("mov", "b, #!constbyte", count & 0xff);
11884 emitcode ("", "!tlabeldef", tlbl->key + 100);
11889 for (eIndex = 0; eIndex < elementSize; eIndex++)
11891 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
11892 if (val != lastVal)
11894 emitcode("mov", "a, #!constbyte", val);
11898 emitcode("movx", "@dptr, a");
11899 emitcode("inc", "dptr");
11904 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
11910 iLoop = iLoop->next;
11913 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
11917 /*-----------------------------------------------------------------*/
11918 /* genFarFarAssign - assignment when both are in far space */
11919 /*-----------------------------------------------------------------*/
11921 genFarFarAssign (operand * result, operand * right, iCode * ic)
11923 int size = AOP_SIZE (right);
11925 symbol *rSym = NULL;
11929 /* quick & easy case. */
11930 D(emitcode(";","genFarFarAssign (1 byte case)"););
11931 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
11932 freeAsmop (right, NULL, ic, FALSE);
11933 /* now assign DPTR to result */
11935 aopOp(result, ic, FALSE, FALSE);
11937 aopPut (result, "a", 0);
11938 freeAsmop(result, NULL, ic, FALSE);
11942 /* See if we've got an underlying symbol to abuse. */
11943 if (IS_SYMOP(result) && OP_SYMBOL(result))
11945 if (IS_TRUE_SYMOP(result))
11947 rSym = OP_SYMBOL(result);
11949 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
11951 rSym = OP_SYMBOL(result)->usl.spillLoc;
11955 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
11957 /* We can use the '390 auto-toggle feature to good effect here. */
11959 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
11960 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11961 emitcode ("mov", "dptr,#%s", rSym->rname);
11962 /* DP2 = result, DP1 = right, DP1 is current. */
11965 emitcode("movx", "a,@dptr");
11966 emitcode("movx", "@dptr,a");
11969 emitcode("inc", "dptr");
11970 emitcode("inc", "dptr");
11973 emitcode("mov", "dps,#0");
11974 freeAsmop (right, NULL, ic, FALSE);
11976 some alternative code for processors without auto-toggle
11977 no time to test now, so later well put in...kpb
11978 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
11979 emitcode("mov", "dps,#1"); /* Select DPTR2. */
11980 emitcode ("mov", "dptr,#%s", rSym->rname);
11981 /* DP2 = result, DP1 = right, DP1 is current. */
11985 emitcode("movx", "a,@dptr");
11987 emitcode("inc", "dptr");
11988 emitcode("inc", "dps");
11989 emitcode("movx", "@dptr,a");
11991 emitcode("inc", "dptr");
11992 emitcode("inc", "dps");
11994 emitcode("mov", "dps,#0");
11995 freeAsmop (right, NULL, ic, FALSE);
12000 D (emitcode (";", "genFarFarAssign"););
12001 aopOp (result, ic, TRUE, TRUE);
12003 _startLazyDPSEvaluation ();
12008 aopGet (right, offset, FALSE, FALSE, NULL), offset);
12011 _endLazyDPSEvaluation ();
12012 freeAsmop (result, NULL, ic, FALSE);
12013 freeAsmop (right, NULL, ic, FALSE);
12017 /*-----------------------------------------------------------------*/
12018 /* genAssign - generate code for assignment */
12019 /*-----------------------------------------------------------------*/
12021 genAssign (iCode * ic)
12023 operand *result, *right;
12025 unsigned long lit = 0L;
12027 D (emitcode (";", "genAssign "));
12029 result = IC_RESULT (ic);
12030 right = IC_RIGHT (ic);
12032 /* if they are the same */
12033 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
12036 aopOp (right, ic, FALSE, FALSE);
12038 emitcode (";", "genAssign: resultIsFar = %s",
12039 isOperandInFarSpace (result) ?
12042 /* special case both in far space */
12043 if ((AOP_TYPE (right) == AOP_DPTR ||
12044 AOP_TYPE (right) == AOP_DPTR2) &&
12045 /* IS_TRUE_SYMOP(result) && */
12046 isOperandInFarSpace (result))
12048 genFarFarAssign (result, right, ic);
12052 aopOp (result, ic, TRUE, FALSE);
12054 /* if they are the same registers */
12055 if (sameRegs (AOP (right), AOP (result)))
12058 /* if the result is a bit */
12059 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
12061 /* if the right size is a literal then
12062 we know what the value is */
12063 if (AOP_TYPE (right) == AOP_LIT)
12065 if (((int) operandLitValue (right)))
12066 aopPut (result, one, 0);
12068 aopPut (result, zero, 0);
12072 /* the right is also a bit variable */
12073 if (AOP_TYPE (right) == AOP_CRY)
12075 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12076 aopPut (result, "c", 0);
12080 /* we need to or */
12082 aopPut (result, "a", 0);
12086 /* bit variables done */
12088 size = AOP_SIZE (result);
12090 if (AOP_TYPE (right) == AOP_LIT)
12091 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
12094 (AOP_TYPE (result) != AOP_REG) &&
12095 (AOP_TYPE (right) == AOP_LIT) &&
12096 !IS_FLOAT (operandType (right)))
12098 _startLazyDPSEvaluation ();
12099 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
12102 aopGet (right, offset, FALSE, FALSE, NULL),
12107 /* And now fill the rest with zeros. */
12110 emitcode ("clr", "a");
12114 aopPut (result, "a", offset++);
12116 _endLazyDPSEvaluation ();
12120 _startLazyDPSEvaluation ();
12124 aopGet (right, offset, FALSE, FALSE, NULL),
12128 _endLazyDPSEvaluation ();
12132 freeAsmop (result, NULL, ic, TRUE);
12133 freeAsmop (right, NULL, ic, TRUE);
12136 /*-----------------------------------------------------------------*/
12137 /* genJumpTab - generates code for jump table */
12138 /*-----------------------------------------------------------------*/
12140 genJumpTab (iCode * ic)
12145 D (emitcode (";", "genJumpTab ");
12148 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
12149 /* get the condition into accumulator */
12150 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE, NULL);
12152 /* multiply by four! */
12153 emitcode ("add", "a,acc");
12154 emitcode ("add", "a,acc");
12155 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
12157 jtab = newiTempLabel (NULL);
12158 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
12159 emitcode ("jmp", "@a+dptr");
12160 emitcode ("", "!tlabeldef", jtab->key + 100);
12161 /* now generate the jump labels */
12162 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
12163 jtab = setNextItem (IC_JTLABELS (ic)))
12164 emitcode ("ljmp", "!tlabel", jtab->key + 100);
12168 /*-----------------------------------------------------------------*/
12169 /* genCast - gen code for casting */
12170 /*-----------------------------------------------------------------*/
12172 genCast (iCode * ic)
12174 operand *result = IC_RESULT (ic);
12175 sym_link *ctype = operandType (IC_LEFT (ic));
12176 sym_link *rtype = operandType (IC_RIGHT (ic));
12177 operand *right = IC_RIGHT (ic);
12180 D (emitcode (";", "genCast "));
12182 /* if they are equivalent then do nothing */
12183 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
12186 aopOp (right, ic, FALSE, AOP_IS_STR (result));
12187 aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
12189 /* if the result is a bit */
12190 if (IS_BITVAR (OP_SYMBOL (result)->type)
12191 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
12193 /* if the right size is a literal then
12194 we know what the value is */
12195 if (AOP_TYPE (right) == AOP_LIT)
12197 if (((int) operandLitValue (right)))
12198 aopPut (result, one, 0);
12200 aopPut (result, zero, 0);
12205 /* the right is also a bit variable */
12206 if (AOP_TYPE (right) == AOP_CRY)
12208 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12209 aopPut (result, "c", 0);
12213 /* we need to or */
12215 aopPut (result, "a", 0);
12219 /* if they are the same size : or less */
12220 if (AOP_SIZE (result) <= AOP_SIZE (right))
12223 /* if they are in the same place */
12224 if (sameRegs (AOP (right), AOP (result)))
12227 /* if they in different places then copy */
12228 size = AOP_SIZE (result);
12230 _startLazyDPSEvaluation ();
12234 aopGet (right, offset, FALSE, FALSE, NULL),
12238 _endLazyDPSEvaluation ();
12242 /* if the result is of type pointer */
12243 if (IS_PTR (ctype))
12247 sym_link *type = operandType (right);
12249 /* pointer to generic pointer */
12250 if (IS_GENPTR (ctype))
12254 p_type = DCL_TYPE (type);
12258 #if OLD_CAST_BEHAVIOR
12259 /* KV: we are converting a non-pointer type to
12260 * a generic pointer. This (ifdef'd out) code
12261 * says that the resulting generic pointer
12262 * should have the same class as the storage
12263 * location of the non-pointer variable.
12265 * For example, converting an int (which happens
12266 * to be stored in DATA space) to a pointer results
12267 * in a DATA generic pointer; if the original int
12268 * in XDATA space, so will be the resulting pointer.
12270 * I don't like that behavior, and thus this change:
12271 * all such conversions will be forced to XDATA and
12272 * throw a warning. If you want some non-XDATA
12273 * type, or you want to suppress the warning, you
12274 * must go through an intermediate cast, like so:
12276 * char _generic *gp = (char _xdata *)(intVar);
12278 sym_link *etype = getSpec (type);
12280 /* we have to go by the storage class */
12281 if (SPEC_OCLS (etype) != generic)
12283 p_type = PTR_TYPE (SPEC_OCLS (etype));
12288 /* Converting unknown class (i.e. register variable)
12289 * to generic pointer. This is not good, but
12290 * we'll make a guess (and throw a warning).
12293 werror (W_INT_TO_GEN_PTR_CAST);
12297 /* the first two bytes are known */
12298 size = GPTRSIZE - 1;
12300 _startLazyDPSEvaluation ();
12304 aopGet (right, offset, FALSE, FALSE, NULL),
12308 _endLazyDPSEvaluation ();
12310 /* the last byte depending on type */
12312 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
12317 // pointerTypeToGPByte will have bitched.
12321 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%x", gpVal);
12322 aopPut (result, gpValStr, GPTRSIZE - 1);
12327 /* just copy the pointers */
12328 size = AOP_SIZE (result);
12330 _startLazyDPSEvaluation ();
12334 aopGet (right, offset, FALSE, FALSE, NULL),
12338 _endLazyDPSEvaluation ();
12342 /* so we now know that the size of destination is greater
12343 than the size of the source */
12344 /* we move to result for the size of source */
12345 size = AOP_SIZE (right);
12347 _startLazyDPSEvaluation ();
12351 aopGet (right, offset, FALSE, FALSE, NULL),
12355 _endLazyDPSEvaluation ();
12357 /* now depending on the sign of the source && destination */
12358 size = AOP_SIZE (result) - AOP_SIZE (right);
12359 /* if unsigned or not an integral type */
12360 /* also, if the source is a bit, we don't need to sign extend, because
12361 * it can't possibly have set the sign bit.
12363 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
12367 aopPut (result, zero, offset++);
12372 /* we need to extend the sign :{ */
12373 MOVA (aopGet (right, AOP_SIZE (right) - 1,
12374 FALSE, FALSE, NULL));
12375 emitcode ("rlc", "a");
12376 emitcode ("subb", "a,acc");
12378 aopPut (result, "a", offset++);
12381 /* we are done hurray !!!! */
12384 freeAsmop (right, NULL, ic, TRUE);
12385 freeAsmop (result, NULL, ic, TRUE);
12389 /*-----------------------------------------------------------------*/
12390 /* genDjnz - generate decrement & jump if not zero instrucion */
12391 /*-----------------------------------------------------------------*/
12393 genDjnz (iCode * ic, iCode * ifx)
12395 symbol *lbl, *lbl1;
12399 /* if the if condition has a false label
12400 then we cannot save */
12401 if (IC_FALSE (ifx))
12404 /* if the minus is not of the form
12406 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
12407 !IS_OP_LITERAL (IC_RIGHT (ic)))
12410 if (operandLitValue (IC_RIGHT (ic)) != 1)
12413 /* if the size of this greater than one then no
12415 if (getSize (operandType (IC_RESULT (ic))) > 1)
12418 /* otherwise we can save BIG */
12419 D(emitcode(";", "genDjnz"););
12421 lbl = newiTempLabel (NULL);
12422 lbl1 = newiTempLabel (NULL);
12424 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
12426 if (AOP_NEEDSACC(IC_RESULT(ic)))
12428 /* If the result is accessed indirectly via
12429 * the accumulator, we must explicitly write
12430 * it back after the decrement.
12432 char *rByte = aopGet(IC_RESULT(ic), 0, FALSE, FALSE, NULL);
12434 if (strcmp(rByte, "a"))
12436 /* Something is hopelessly wrong */
12437 fprintf(stderr, "*** warning: internal error at %s:%d\n",
12438 __FILE__, __LINE__);
12439 /* We can just give up; the generated code will be inefficient,
12440 * but what the hey.
12442 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
12445 emitcode ("dec", "%s", rByte);
12446 aopPut(IC_RESULT(ic), rByte, 0);
12447 emitcode ("jnz", "!tlabel", lbl->key + 100);
12449 else if (IS_AOP_PREG (IC_RESULT (ic)))
12451 emitcode ("dec", "%s",
12452 aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL));
12453 emitcode ("mov", "a,%s", aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL));
12454 emitcode ("jnz", "!tlabel", lbl->key + 100);
12458 emitcode ("djnz", "%s,!tlabel", aopGet (IC_RESULT (ic), 0, FALSE, TRUE, NULL),
12461 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
12462 emitcode ("", "!tlabeldef", lbl->key + 100);
12463 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
12464 emitcode ("", "!tlabeldef", lbl1->key + 100);
12466 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
12467 ifx->generated = 1;
12471 /*-----------------------------------------------------------------*/
12472 /* genReceive - generate code for a receive iCode */
12473 /*-----------------------------------------------------------------*/
12475 genReceive (iCode * ic)
12477 int size = getSize (operandType (IC_RESULT (ic)));
12481 D (emitcode (";", "genReceive "));
12483 if (ic->argreg == 1)
12485 /* first parameter */
12486 if (AOP_IS_STR(IC_RESULT(ic)))
12488 /* Nothing to do: it's already in the proper place. */
12495 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
12496 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
12497 IS_TRUE_SYMOP (IC_RESULT (ic)));
12500 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
12503 /* Sanity checking... */
12504 if (AOP_USESDPTR(IC_RESULT(ic)))
12506 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12507 "genReceive got unexpected DPTR.");
12509 assignResultValue (IC_RESULT (ic), NULL);
12512 else if (ic->argreg > 12)
12513 { /* bit parameters */
12514 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
12516 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
12517 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
12518 outBitC(IC_RESULT (ic));
12523 /* second receive onwards */
12524 /* this gets a little tricky since unused receives will be
12525 eliminated, we have saved the reg in the type field . and
12526 we use that to figure out which register to use */
12527 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
12528 rb1off = ic->argreg;
12531 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
12534 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
12537 /*-----------------------------------------------------------------*/
12538 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
12539 /*-----------------------------------------------------------------*/
12540 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
12542 operand *from , *to , *count;
12547 /* we know it has to be 3 parameters */
12548 assert (nparms == 3);
12550 rsave = newBitVect(16);
12551 /* save DPTR if it needs to be saved */
12552 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12553 if (bitVectBitValue(ic->rMask,i))
12554 rsave = bitVectSetBit(rsave,i);
12556 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12557 ds390_rUmaskForOp (IC_RESULT(ic))));
12564 aopOp (from, ic->next, FALSE, FALSE);
12566 /* get from into DPTR1 */
12567 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12568 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12569 if (options.model == MODEL_FLAT24) {
12570 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12573 freeAsmop (from, NULL, ic, FALSE);
12574 aopOp (to, ic, FALSE, FALSE);
12575 /* get "to" into DPTR */
12576 /* if the operand is already in dptr
12577 then we do nothing else we move the value to dptr */
12578 if (AOP_TYPE (to) != AOP_STR) {
12579 /* if already in DPTR then we need to push */
12580 if (AOP_TYPE(to) == AOP_DPTR) {
12581 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12582 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12583 if (options.model == MODEL_FLAT24)
12584 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12585 emitcode ("pop", "dph");
12586 emitcode ("pop", "dpl");
12588 _startLazyDPSEvaluation ();
12589 /* if this is remateriazable */
12590 if (AOP_TYPE (to) == AOP_IMMD) {
12591 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12592 } else { /* we need to get it byte by byte */
12593 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12594 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12595 if (options.model == MODEL_FLAT24) {
12596 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12599 _endLazyDPSEvaluation ();
12602 freeAsmop (to, NULL, ic, FALSE);
12603 _G.dptrInUse = _G.dptr1InUse = 1;
12604 aopOp (count, ic->next->next, FALSE,FALSE);
12605 lbl =newiTempLabel(NULL);
12607 /* now for the actual copy */
12608 if (AOP_TYPE(count) == AOP_LIT &&
12609 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12610 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12612 emitcode ("lcall","__bi_memcpyc2x_s");
12614 emitcode ("lcall","__bi_memcpyx2x_s");
12616 freeAsmop (count, NULL, ic, FALSE);
12618 symbol *lbl1 = newiTempLabel(NULL);
12620 emitcode (";"," Auto increment but no djnz");
12621 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12622 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12623 freeAsmop (count, NULL, ic, FALSE);
12624 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12625 emitcode ("","!tlabeldef",lbl->key+100);
12627 emitcode ("clr","a");
12628 emitcode ("movc", "a,@a+dptr");
12630 emitcode ("movx", "a,@dptr");
12631 emitcode ("movx", "@dptr,a");
12632 emitcode ("inc", "dptr");
12633 emitcode ("inc", "dptr");
12634 emitcode ("mov","a,b");
12635 emitcode ("orl","a,_ap");
12636 emitcode ("jz","!tlabel",lbl1->key+100);
12637 emitcode ("mov","a,_ap");
12638 emitcode ("add","a,#!constbyte",0xFF);
12639 emitcode ("mov","_ap,a");
12640 emitcode ("mov","a,b");
12641 emitcode ("addc","a,#!constbyte",0xFF);
12642 emitcode ("mov","b,a");
12643 emitcode ("sjmp","!tlabel",lbl->key+100);
12644 emitcode ("","!tlabeldef",lbl1->key+100);
12646 emitcode ("mov", "dps,#0");
12647 _G.dptrInUse = _G.dptr1InUse = 0;
12648 unsavermask(rsave);
12652 /*-----------------------------------------------------------------*/
12653 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
12654 /*-----------------------------------------------------------------*/
12655 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
12657 operand *from , *to , *count;
12662 /* we know it has to be 3 parameters */
12663 assert (nparms == 3);
12665 rsave = newBitVect(16);
12666 /* save DPTR if it needs to be saved */
12667 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12668 if (bitVectBitValue(ic->rMask,i))
12669 rsave = bitVectSetBit(rsave,i);
12671 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12672 ds390_rUmaskForOp (IC_RESULT(ic))));
12679 aopOp (from, ic->next, FALSE, FALSE);
12681 /* get from into DPTR1 */
12682 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12683 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12684 if (options.model == MODEL_FLAT24) {
12685 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12688 freeAsmop (from, NULL, ic, FALSE);
12689 aopOp (to, ic, FALSE, FALSE);
12690 /* get "to" into DPTR */
12691 /* if the operand is already in dptr
12692 then we do nothing else we move the value to dptr */
12693 if (AOP_TYPE (to) != AOP_STR) {
12694 /* if already in DPTR then we need to push */
12695 if (AOP_TYPE(to) == AOP_DPTR) {
12696 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12697 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12698 if (options.model == MODEL_FLAT24)
12699 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12700 emitcode ("pop", "dph");
12701 emitcode ("pop", "dpl");
12703 _startLazyDPSEvaluation ();
12704 /* if this is remateriazable */
12705 if (AOP_TYPE (to) == AOP_IMMD) {
12706 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12707 } else { /* we need to get it byte by byte */
12708 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12709 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12710 if (options.model == MODEL_FLAT24) {
12711 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12714 _endLazyDPSEvaluation ();
12717 freeAsmop (to, NULL, ic, FALSE);
12718 _G.dptrInUse = _G.dptr1InUse = 1;
12719 aopOp (count, ic->next->next, FALSE,FALSE);
12720 lbl =newiTempLabel(NULL);
12721 lbl2 =newiTempLabel(NULL);
12723 /* now for the actual compare */
12724 if (AOP_TYPE(count) == AOP_LIT &&
12725 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12726 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12728 emitcode("lcall","__bi_memcmpc2x_s");
12730 emitcode("lcall","__bi_memcmpx2x_s");
12731 freeAsmop (count, NULL, ic, FALSE);
12732 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12733 aopPut(IC_RESULT(ic),"a",0);
12734 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12736 symbol *lbl1 = newiTempLabel(NULL);
12738 emitcode("push","ar0");
12739 emitcode (";"," Auto increment but no djnz");
12740 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12741 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12742 freeAsmop (count, NULL, ic, FALSE);
12743 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12744 emitcode ("","!tlabeldef",lbl->key+100);
12746 emitcode ("clr","a");
12747 emitcode ("movc", "a,@a+dptr");
12749 emitcode ("movx", "a,@dptr");
12750 emitcode ("mov","r0,a");
12751 emitcode ("movx", "a,@dptr");
12752 emitcode ("clr","c");
12753 emitcode ("subb","a,r0");
12754 emitcode ("jnz","!tlabel",lbl2->key+100);
12755 emitcode ("inc", "dptr");
12756 emitcode ("inc", "dptr");
12757 emitcode ("mov","a,b");
12758 emitcode ("orl","a,_ap");
12759 emitcode ("jz","!tlabel",lbl1->key+100);
12760 emitcode ("mov","a,_ap");
12761 emitcode ("add","a,#!constbyte",0xFF);
12762 emitcode ("mov","_ap,a");
12763 emitcode ("mov","a,b");
12764 emitcode ("addc","a,#!constbyte",0xFF);
12765 emitcode ("mov","b,a");
12766 emitcode ("sjmp","!tlabel",lbl->key+100);
12767 emitcode ("","!tlabeldef",lbl1->key+100);
12768 emitcode ("clr","a");
12769 emitcode ("","!tlabeldef",lbl2->key+100);
12770 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12771 aopPut(IC_RESULT(ic),"a",0);
12772 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12773 emitcode("pop","ar0");
12774 emitcode ("mov", "dps,#0");
12776 _G.dptrInUse = _G.dptr1InUse = 0;
12777 unsavermask(rsave);
12781 /*-----------------------------------------------------------------*/
12782 /* genInp - gen code for __builtin_inp read data from a mem mapped */
12783 /* port, first parameter output area second parameter pointer to */
12784 /* port third parameter count */
12785 /*-----------------------------------------------------------------*/
12786 static void genInp( iCode *ic, int nparms, operand **parms)
12788 operand *from , *to , *count;
12793 /* we know it has to be 3 parameters */
12794 assert (nparms == 3);
12796 rsave = newBitVect(16);
12797 /* save DPTR if it needs to be saved */
12798 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12799 if (bitVectBitValue(ic->rMask,i))
12800 rsave = bitVectSetBit(rsave,i);
12802 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12803 ds390_rUmaskForOp (IC_RESULT(ic))));
12810 aopOp (from, ic->next, FALSE, FALSE);
12812 /* get from into DPTR1 */
12813 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12814 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12815 if (options.model == MODEL_FLAT24) {
12816 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12819 freeAsmop (from, NULL, ic, FALSE);
12820 aopOp (to, ic, FALSE, FALSE);
12821 /* get "to" into DPTR */
12822 /* if the operand is already in dptr
12823 then we do nothing else we move the value to dptr */
12824 if (AOP_TYPE (to) != AOP_STR) {
12825 /* if already in DPTR then we need to push */
12826 if (AOP_TYPE(to) == AOP_DPTR) {
12827 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12828 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12829 if (options.model == MODEL_FLAT24)
12830 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12831 emitcode ("pop", "dph");
12832 emitcode ("pop", "dpl");
12834 _startLazyDPSEvaluation ();
12835 /* if this is remateriazable */
12836 if (AOP_TYPE (to) == AOP_IMMD) {
12837 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12838 } else { /* we need to get it byte by byte */
12839 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12840 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12841 if (options.model == MODEL_FLAT24) {
12842 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12845 _endLazyDPSEvaluation ();
12848 freeAsmop (to, NULL, ic, FALSE);
12850 _G.dptrInUse = _G.dptr1InUse = 1;
12851 aopOp (count, ic->next->next, FALSE,FALSE);
12852 lbl =newiTempLabel(NULL);
12854 /* now for the actual copy */
12855 if (AOP_TYPE(count) == AOP_LIT &&
12856 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12857 emitcode (";","OH JOY auto increment with djnz (very fast)");
12858 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12859 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12860 freeAsmop (count, NULL, ic, FALSE);
12861 emitcode ("","!tlabeldef",lbl->key+100);
12862 emitcode ("movx", "a,@dptr"); /* read data from port */
12863 emitcode ("dec","dps"); /* switch to DPTR */
12864 emitcode ("movx", "@dptr,a"); /* save into location */
12865 emitcode ("inc", "dptr"); /* point to next area */
12866 emitcode ("inc","dps"); /* switch to DPTR2 */
12867 emitcode ("djnz","b,!tlabel",lbl->key+100);
12869 symbol *lbl1 = newiTempLabel(NULL);
12871 emitcode (";"," Auto increment but no djnz");
12872 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12873 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12874 freeAsmop (count, NULL, ic, FALSE);
12875 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12876 emitcode ("","!tlabeldef",lbl->key+100);
12877 emitcode ("movx", "a,@dptr");
12878 emitcode ("dec","dps"); /* switch to DPTR */
12879 emitcode ("movx", "@dptr,a");
12880 emitcode ("inc", "dptr");
12881 emitcode ("inc","dps"); /* switch to DPTR2 */
12882 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
12883 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
12884 emitcode ("mov","a,b");
12885 emitcode ("orl","a,_ap");
12886 emitcode ("jz","!tlabel",lbl1->key+100);
12887 emitcode ("mov","a,_ap");
12888 emitcode ("add","a,#!constbyte",0xFF);
12889 emitcode ("mov","_ap,a");
12890 emitcode ("mov","a,b");
12891 emitcode ("addc","a,#!constbyte",0xFF);
12892 emitcode ("mov","b,a");
12893 emitcode ("sjmp","!tlabel",lbl->key+100);
12894 emitcode ("","!tlabeldef",lbl1->key+100);
12896 emitcode ("mov", "dps,#0");
12897 _G.dptrInUse = _G.dptr1InUse = 0;
12898 unsavermask(rsave);
12902 /*-----------------------------------------------------------------*/
12903 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
12904 /* port, first parameter output area second parameter pointer to */
12905 /* port third parameter count */
12906 /*-----------------------------------------------------------------*/
12907 static void genOutp( iCode *ic, int nparms, operand **parms)
12909 operand *from , *to , *count;
12914 /* we know it has to be 3 parameters */
12915 assert (nparms == 3);
12917 rsave = newBitVect(16);
12918 /* save DPTR if it needs to be saved */
12919 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12920 if (bitVectBitValue(ic->rMask,i))
12921 rsave = bitVectSetBit(rsave,i);
12923 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12924 ds390_rUmaskForOp (IC_RESULT(ic))));
12931 aopOp (from, ic->next, FALSE, FALSE);
12933 /* get from into DPTR1 */
12934 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12935 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12936 if (options.model == MODEL_FLAT24) {
12937 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12940 freeAsmop (from, NULL, ic, FALSE);
12941 aopOp (to, ic, FALSE, FALSE);
12942 /* get "to" into DPTR */
12943 /* if the operand is already in dptr
12944 then we do nothing else we move the value to dptr */
12945 if (AOP_TYPE (to) != AOP_STR) {
12946 /* if already in DPTR then we need to push */
12947 if (AOP_TYPE(to) == AOP_DPTR) {
12948 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12949 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12950 if (options.model == MODEL_FLAT24)
12951 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12952 emitcode ("pop", "dph");
12953 emitcode ("pop", "dpl");
12955 _startLazyDPSEvaluation ();
12956 /* if this is remateriazable */
12957 if (AOP_TYPE (to) == AOP_IMMD) {
12958 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12959 } else { /* we need to get it byte by byte */
12960 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12961 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12962 if (options.model == MODEL_FLAT24) {
12963 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12966 _endLazyDPSEvaluation ();
12969 freeAsmop (to, NULL, ic, FALSE);
12971 _G.dptrInUse = _G.dptr1InUse = 1;
12972 aopOp (count, ic->next->next, FALSE,FALSE);
12973 lbl =newiTempLabel(NULL);
12975 /* now for the actual copy */
12976 if (AOP_TYPE(count) == AOP_LIT &&
12977 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12978 emitcode (";","OH JOY auto increment with djnz (very fast)");
12979 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
12980 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12981 emitcode ("","!tlabeldef",lbl->key+100);
12982 emitcode ("movx", "a,@dptr"); /* read data from port */
12983 emitcode ("inc","dps"); /* switch to DPTR2 */
12984 emitcode ("movx", "@dptr,a"); /* save into location */
12985 emitcode ("inc", "dptr"); /* point to next area */
12986 emitcode ("dec","dps"); /* switch to DPTR */
12987 emitcode ("djnz","b,!tlabel",lbl->key+100);
12988 freeAsmop (count, NULL, ic, FALSE);
12990 symbol *lbl1 = newiTempLabel(NULL);
12992 emitcode (";"," Auto increment but no djnz");
12993 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12994 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12995 freeAsmop (count, NULL, ic, FALSE);
12996 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
12997 emitcode ("","!tlabeldef",lbl->key+100);
12998 emitcode ("movx", "a,@dptr");
12999 emitcode ("inc", "dptr");
13000 emitcode ("inc","dps"); /* switch to DPTR2 */
13001 emitcode ("movx", "@dptr,a");
13002 emitcode ("dec","dps"); /* switch to DPTR */
13003 emitcode ("mov","a,b");
13004 emitcode ("orl","a,_ap");
13005 emitcode ("jz","!tlabel",lbl1->key+100);
13006 emitcode ("mov","a,_ap");
13007 emitcode ("add","a,#!constbyte",0xFF);
13008 emitcode ("mov","_ap,a");
13009 emitcode ("mov","a,b");
13010 emitcode ("addc","a,#!constbyte",0xFF);
13011 emitcode ("mov","b,a");
13012 emitcode ("sjmp","!tlabel",lbl->key+100);
13013 emitcode ("","!tlabeldef",lbl1->key+100);
13015 emitcode ("mov", "dps,#0");
13016 _G.dptrInUse = _G.dptr1InUse = 0;
13017 unsavermask(rsave);
13021 /*-----------------------------------------------------------------*/
13022 /* genSwapW - swap lower & high order bytes */
13023 /*-----------------------------------------------------------------*/
13024 static void genSwapW(iCode *ic, int nparms, operand **parms)
13028 assert (nparms==1);
13031 dest=IC_RESULT(ic);
13033 assert(getSize(operandType(src))==2);
13035 aopOp (src, ic, FALSE, FALSE);
13036 emitcode ("mov","a,%s",aopGet(src,0,FALSE,FALSE,NULL));
13038 MOVB(aopGet(src,1,FALSE,FALSE,"b"));
13040 freeAsmop (src, NULL, ic, FALSE);
13042 aopOp (dest,ic, FALSE, FALSE);
13043 aopPut(dest,"b",0);
13044 aopPut(dest,"a",1);
13045 freeAsmop (dest, NULL, ic, FALSE);
13048 /*-----------------------------------------------------------------*/
13049 /* genMemsetX - gencode for memSetX data */
13050 /*-----------------------------------------------------------------*/
13051 static void genMemsetX(iCode *ic, int nparms, operand **parms)
13053 operand *to , *val , *count;
13059 /* we know it has to be 3 parameters */
13060 assert (nparms == 3);
13066 /* save DPTR if it needs to be saved */
13067 rsave = newBitVect(16);
13068 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
13069 if (bitVectBitValue(ic->rMask,i))
13070 rsave = bitVectSetBit(rsave,i);
13072 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
13073 ds390_rUmaskForOp (IC_RESULT(ic))));
13076 aopOp (to, ic, FALSE, FALSE);
13077 /* get "to" into DPTR */
13078 /* if the operand is already in dptr
13079 then we do nothing else we move the value to dptr */
13080 if (AOP_TYPE (to) != AOP_STR) {
13081 /* if already in DPTR then we need to push */
13082 if (AOP_TYPE(to) == AOP_DPTR) {
13083 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
13084 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
13085 if (options.model == MODEL_FLAT24)
13086 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
13087 emitcode ("pop", "dph");
13088 emitcode ("pop", "dpl");
13090 _startLazyDPSEvaluation ();
13091 /* if this is remateriazable */
13092 if (AOP_TYPE (to) == AOP_IMMD) {
13093 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
13094 } else { /* we need to get it byte by byte */
13095 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
13096 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
13097 if (options.model == MODEL_FLAT24) {
13098 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
13101 _endLazyDPSEvaluation ();
13104 freeAsmop (to, NULL, ic, FALSE);
13106 aopOp (val, ic->next->next, FALSE,FALSE);
13107 aopOp (count, ic->next->next, FALSE,FALSE);
13108 lbl =newiTempLabel(NULL);
13109 /* now for the actual copy */
13110 if (AOP_TYPE(count) == AOP_LIT &&
13111 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
13112 l = aopGet(val, 0, FALSE, FALSE, NULL);
13113 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
13115 emitcode ("","!tlabeldef",lbl->key+100);
13116 emitcode ("movx", "@dptr,a");
13117 emitcode ("inc", "dptr");
13118 emitcode ("djnz","b,!tlabel",lbl->key+100);
13120 symbol *lbl1 = newiTempLabel(NULL);
13122 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
13123 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
13124 emitcode ("","!tlabeldef",lbl->key+100);
13125 MOVA (aopGet(val, 0, FALSE, FALSE, NULL));
13126 emitcode ("movx", "@dptr,a");
13127 emitcode ("inc", "dptr");
13128 emitcode ("mov","a,b");
13129 emitcode ("orl","a,_ap");
13130 emitcode ("jz","!tlabel",lbl1->key+100);
13131 emitcode ("mov","a,_ap");
13132 emitcode ("add","a,#!constbyte",0xFF);
13133 emitcode ("mov","_ap,a");
13134 emitcode ("mov","a,b");
13135 emitcode ("addc","a,#!constbyte",0xFF);
13136 emitcode ("mov","b,a");
13137 emitcode ("sjmp","!tlabel",lbl->key+100);
13138 emitcode ("","!tlabeldef",lbl1->key+100);
13140 freeAsmop (count, NULL, ic, FALSE);
13141 unsavermask(rsave);
13144 /*-----------------------------------------------------------------*/
13145 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
13146 /*-----------------------------------------------------------------*/
13147 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
13150 operand *pnum, *result;
13153 assert (nparms==1);
13154 /* save registers that need to be saved */
13155 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13156 ds390_rUmaskForOp (IC_RESULT(ic))));
13159 aopOp (pnum, ic, FALSE, FALSE);
13160 emitcode ("mov","a,%s",aopGet(pnum,0,FALSE,FALSE,DP2_RESULT_REG));
13161 freeAsmop (pnum, NULL, ic, FALSE);
13162 emitcode ("lcall","NatLib_LoadPrimitive");
13163 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
13164 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
13165 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
13166 for (i = (size-1) ; i >= 0 ; i-- ) {
13167 emitcode ("push","a%s",javaRet[i]);
13169 for (i=0; i < size ; i++ ) {
13170 emitcode ("pop","a%s",
13171 aopGet(result,i,FALSE,FALSE,DP2_RESULT_REG));
13174 for (i = 0 ; i < size ; i++ ) {
13175 aopPut(result,javaRet[i],i);
13178 freeAsmop (result, NULL, ic, FALSE);
13179 unsavermask(rsave);
13182 /*-----------------------------------------------------------------*/
13183 /* genNatLibLoadPointer - calls TINI api function to load pointer */
13184 /*-----------------------------------------------------------------*/
13185 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
13188 operand *pnum, *result;
13192 assert (nparms==1);
13193 /* save registers that need to be saved */
13194 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13195 ds390_rUmaskForOp (IC_RESULT(ic))));
13198 aopOp (pnum, ic, FALSE, FALSE);
13199 emitcode ("mov","a,%s",aopGet(pnum,0,FALSE,FALSE,DP2_RESULT_REG));
13200 freeAsmop (pnum, NULL, ic, FALSE);
13201 emitcode ("lcall","NatLib_LoadPointer");
13202 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
13203 if (AOP_TYPE(result)!=AOP_STR) {
13204 for (i = 0 ; i < size ; i++ ) {
13205 aopPut(result,fReturn[i],i);
13208 freeAsmop (result, NULL, ic, FALSE);
13209 unsavermask(rsave);
13212 /*-----------------------------------------------------------------*/
13213 /* genNatLibInstallStateBlock - */
13214 /*-----------------------------------------------------------------*/
13215 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
13216 operand **parms, const char *name)
13219 operand *psb, *handle;
13220 assert (nparms==2);
13222 /* save registers that need to be saved */
13223 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13224 ds390_rUmaskForOp (IC_RESULT(ic))));
13228 /* put pointer to state block into DPTR1 */
13229 aopOp (psb, ic, FALSE, FALSE);
13230 if (AOP_TYPE (psb) == AOP_IMMD) {
13231 emitcode ("mov","dps,#1");
13232 emitcode ("mov", "dptr,%s",
13233 aopGet (psb, 0, TRUE, FALSE, DP2_RESULT_REG));
13234 emitcode ("mov","dps,#0");
13236 emitcode ("mov","dpl1,%s",aopGet(psb,0,FALSE,FALSE,DP2_RESULT_REG));
13237 emitcode ("mov","dph1,%s",aopGet(psb,1,FALSE,FALSE,DP2_RESULT_REG));
13238 emitcode ("mov","dpx1,%s",aopGet(psb,2,FALSE,FALSE,DP2_RESULT_REG));
13240 freeAsmop (psb, NULL, ic, FALSE);
13242 /* put libraryID into DPTR */
13243 emitcode ("mov","dptr,#LibraryID");
13245 /* put handle into r3:r2 */
13246 aopOp (handle, ic, FALSE, FALSE);
13247 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13248 emitcode ("push","%s",aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13249 emitcode ("push","%s",aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13250 emitcode ("pop","ar3");
13251 emitcode ("pop","ar2");
13253 emitcode ("mov","r2,%s",aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13254 emitcode ("mov","r3,%s",aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13256 freeAsmop (psb, NULL, ic, FALSE);
13258 /* make the call */
13259 emitcode ("lcall","NatLib_Install%sStateBlock",name);
13261 /* put return value into place*/
13263 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
13265 aopPut(IC_RESULT(ic),"a",0);
13266 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13267 unsavermask(rsave);
13270 /*-----------------------------------------------------------------*/
13271 /* genNatLibRemoveStateBlock - */
13272 /*-----------------------------------------------------------------*/
13273 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
13279 /* save registers that need to be saved */
13280 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13281 ds390_rUmaskForOp (IC_RESULT(ic))));
13283 /* put libraryID into DPTR */
13284 emitcode ("mov","dptr,#LibraryID");
13285 /* make the call */
13286 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
13287 unsavermask(rsave);
13290 /*-----------------------------------------------------------------*/
13291 /* genNatLibGetStateBlock - */
13292 /*-----------------------------------------------------------------*/
13293 static void genNatLibGetStateBlock(iCode *ic,int nparms,
13294 operand **parms,const char *name)
13297 symbol *lbl = newiTempLabel(NULL);
13300 /* save registers that need to be saved */
13301 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13302 ds390_rUmaskForOp (IC_RESULT(ic))));
13304 /* put libraryID into DPTR */
13305 emitcode ("mov","dptr,#LibraryID");
13306 /* make the call */
13307 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
13308 emitcode ("jnz","!tlabel",lbl->key+100);
13310 /* put return value into place */
13311 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
13312 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
13313 emitcode ("push","ar3");
13314 emitcode ("push","ar2");
13315 emitcode ("pop","%s",
13316 aopGet(IC_RESULT(ic),0,FALSE,TRUE,DP2_RESULT_REG));
13317 emitcode ("pop","%s",
13318 aopGet(IC_RESULT(ic),1,FALSE,TRUE,DP2_RESULT_REG));
13320 aopPut(IC_RESULT(ic),"r2",0);
13321 aopPut(IC_RESULT(ic),"r3",1);
13323 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13324 emitcode ("","!tlabeldef",lbl->key+100);
13325 unsavermask(rsave);
13328 /*-----------------------------------------------------------------*/
13329 /* genMMMalloc - */
13330 /*-----------------------------------------------------------------*/
13331 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
13332 int size, const char *name)
13337 symbol *lbl = newiTempLabel(NULL);
13339 assert (nparms == 1);
13340 /* save registers that need to be saved */
13341 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13342 ds390_rUmaskForOp (IC_RESULT(ic))));
13345 aopOp (bsize,ic,FALSE,FALSE);
13347 /* put the size in R4-R2 */
13348 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
13349 emitcode("push","%s",aopGet(bsize,0,FALSE,TRUE,DP2_RESULT_REG));
13350 emitcode("push","%s",aopGet(bsize,1,FALSE,TRUE,DP2_RESULT_REG));
13352 emitcode("push","%s",aopGet(bsize,2,FALSE,TRUE,DP2_RESULT_REG));
13353 emitcode("pop","ar4");
13355 emitcode("pop","ar3");
13356 emitcode("pop","ar2");
13358 emitcode ("mov","r2,%s",aopGet(bsize,0,FALSE,TRUE,DP2_RESULT_REG));
13359 emitcode ("mov","r3,%s",aopGet(bsize,1,FALSE,TRUE,DP2_RESULT_REG));
13361 emitcode("mov","r4,%s",aopGet(bsize,2,FALSE,TRUE,DP2_RESULT_REG));
13364 freeAsmop (bsize, NULL, ic, FALSE);
13366 /* make the call */
13367 emitcode ("lcall","MM_%s",name);
13368 emitcode ("jz","!tlabel",lbl->key+100);
13369 emitcode ("mov","r2,#!constbyte",0xff);
13370 emitcode ("mov","r3,#!constbyte",0xff);
13371 emitcode ("","!tlabeldef",lbl->key+100);
13372 /* we don't care about the pointer : we just save the handle */
13373 rsym = OP_SYMBOL(IC_RESULT(ic));
13374 if (rsym->liveFrom != rsym->liveTo) {
13375 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
13376 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
13377 emitcode ("push","ar3");
13378 emitcode ("push","ar2");
13379 emitcode ("pop","%s",
13380 aopGet(IC_RESULT(ic),0,FALSE,TRUE,DP2_RESULT_REG));
13381 emitcode ("pop","%s",
13382 aopGet(IC_RESULT(ic),1,FALSE,TRUE,DP2_RESULT_REG));
13384 aopPut(IC_RESULT(ic),"r2",0);
13385 aopPut(IC_RESULT(ic),"r3",1);
13387 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13389 unsavermask(rsave);
13392 /*-----------------------------------------------------------------*/
13394 /*-----------------------------------------------------------------*/
13395 static void genMMDeref (iCode *ic,int nparms, operand **parms)
13400 assert (nparms == 1);
13401 /* save registers that need to be saved */
13402 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13403 ds390_rUmaskForOp (IC_RESULT(ic))));
13406 aopOp (handle,ic,FALSE,FALSE);
13408 /* put the size in R4-R2 */
13409 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13410 emitcode("push","%s",
13411 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13412 emitcode("push","%s",
13413 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13414 emitcode("pop","ar3");
13415 emitcode("pop","ar2");
13417 emitcode ("mov","r2,%s",
13418 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13419 emitcode ("mov","r3,%s",
13420 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13422 freeAsmop (handle, NULL, ic, FALSE);
13424 /* make the call */
13425 emitcode ("lcall","MM_Deref");
13428 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13429 if (rsym->liveFrom != rsym->liveTo) {
13430 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13431 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
13432 _startLazyDPSEvaluation ();
13434 aopPut(IC_RESULT(ic),"dpl",0);
13435 aopPut(IC_RESULT(ic),"dph",1);
13436 aopPut(IC_RESULT(ic),"dpx",2);
13438 _endLazyDPSEvaluation ();
13443 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13444 unsavermask(rsave);
13447 /*-----------------------------------------------------------------*/
13448 /* genMMUnrestrictedPersist - */
13449 /*-----------------------------------------------------------------*/
13450 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
13455 assert (nparms == 1);
13456 /* save registers that need to be saved */
13457 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13458 ds390_rUmaskForOp (IC_RESULT(ic))));
13461 aopOp (handle,ic,FALSE,FALSE);
13463 /* put the size in R3-R2 */
13464 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13465 emitcode("push","%s",
13466 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13467 emitcode("push","%s",
13468 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13469 emitcode("pop","ar3");
13470 emitcode("pop","ar2");
13472 emitcode ("mov","r2,%s",
13473 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13474 emitcode ("mov","r3,%s",
13475 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13477 freeAsmop (handle, NULL, ic, FALSE);
13479 /* make the call */
13480 emitcode ("lcall","MM_UnrestrictedPersist");
13483 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13484 if (rsym->liveFrom != rsym->liveTo) {
13485 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13486 aopPut(IC_RESULT(ic),"a",0);
13487 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13490 unsavermask(rsave);
13493 /*-----------------------------------------------------------------*/
13494 /* genSystemExecJavaProcess - */
13495 /*-----------------------------------------------------------------*/
13496 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
13499 operand *handle, *pp;
13501 assert (nparms==2);
13502 /* save registers that need to be saved */
13503 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13504 ds390_rUmaskForOp (IC_RESULT(ic))));
13509 /* put the handle in R3-R2 */
13510 aopOp (handle,ic,FALSE,FALSE);
13511 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13512 emitcode("push","%s",
13513 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13514 emitcode("push","%s",
13515 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13516 emitcode("pop","ar3");
13517 emitcode("pop","ar2");
13519 emitcode ("mov","r2,%s",
13520 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13521 emitcode ("mov","r3,%s",
13522 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13524 freeAsmop (handle, NULL, ic, FALSE);
13526 /* put pointer in DPTR */
13527 aopOp (pp,ic,FALSE,FALSE);
13528 if (AOP_TYPE(pp) == AOP_IMMD) {
13529 emitcode ("mov", "dptr,%s",
13530 aopGet (pp, 0, TRUE, FALSE, NULL));
13531 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
13532 emitcode ("mov","dpl,%s",aopGet(pp,0,FALSE,FALSE,NULL));
13533 emitcode ("mov","dph,%s",aopGet(pp,1,FALSE,FALSE,NULL));
13534 emitcode ("mov","dpx,%s",aopGet(pp,2,FALSE,FALSE,NULL));
13536 freeAsmop (handle, NULL, ic, FALSE);
13538 /* make the call */
13539 emitcode ("lcall","System_ExecJavaProcess");
13541 /* put result in place */
13543 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13544 if (rsym->liveFrom != rsym->liveTo) {
13545 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13546 aopPut(IC_RESULT(ic),"a",0);
13547 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13551 unsavermask(rsave);
13554 /*-----------------------------------------------------------------*/
13555 /* genSystemRTCRegisters - */
13556 /*-----------------------------------------------------------------*/
13557 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
13563 assert (nparms==1);
13564 /* save registers that need to be saved */
13565 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13566 ds390_rUmaskForOp (IC_RESULT(ic))));
13569 /* put pointer in DPTR */
13570 aopOp (pp,ic,FALSE,FALSE);
13571 if (AOP_TYPE (pp) == AOP_IMMD) {
13572 emitcode ("mov","dps,#1");
13573 emitcode ("mov", "dptr,%s",
13574 aopGet (pp, 0, TRUE, FALSE, NULL));
13575 emitcode ("mov","dps,#0");
13577 emitcode ("mov","dpl1,%s",
13578 aopGet(pp,0,FALSE,FALSE,DP2_RESULT_REG));
13579 emitcode ("mov","dph1,%s",
13580 aopGet(pp,1,FALSE,FALSE,DP2_RESULT_REG));
13581 emitcode ("mov","dpx1,%s",
13582 aopGet(pp,2,FALSE,FALSE,DP2_RESULT_REG));
13584 freeAsmop (pp, NULL, ic, FALSE);
13586 /* make the call */
13587 emitcode ("lcall","System_%sRTCRegisters",name);
13589 unsavermask(rsave);
13592 /*-----------------------------------------------------------------*/
13593 /* genSystemThreadSleep - */
13594 /*-----------------------------------------------------------------*/
13595 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
13600 assert (nparms==1);
13601 /* save registers that need to be saved */
13602 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13603 ds390_rUmaskForOp (IC_RESULT(ic))));
13606 aopOp(to,ic,FALSE,FALSE);
13607 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
13608 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
13609 emitcode ("push","%s",
13610 aopGet(to,0,FALSE,TRUE,DP2_RESULT_REG));
13611 emitcode ("push","%s",
13612 aopGet(to,1,FALSE,TRUE,DP2_RESULT_REG));
13613 emitcode ("push","%s",
13614 aopGet(to,2,FALSE,TRUE,DP2_RESULT_REG));
13615 emitcode ("push","%s",
13616 aopGet(to,3,FALSE,TRUE,DP2_RESULT_REG));
13617 emitcode ("pop","ar3");
13618 emitcode ("pop","ar2");
13619 emitcode ("pop","ar1");
13620 emitcode ("pop","ar0");
13622 emitcode ("mov","r0,%s",
13623 aopGet(to,0,FALSE,TRUE,DP2_RESULT_REG));
13624 emitcode ("mov","r1,%s",
13625 aopGet(to,1,FALSE,TRUE,DP2_RESULT_REG));
13626 emitcode ("mov","r2,%s",
13627 aopGet(to,2,FALSE,TRUE,DP2_RESULT_REG));
13628 emitcode ("mov","r3,%s",
13629 aopGet(to,3,FALSE,TRUE,DP2_RESULT_REG));
13631 freeAsmop (to, NULL, ic, FALSE);
13633 /* suspend in acc */
13635 aopOp(s,ic,FALSE,FALSE);
13636 emitcode ("mov","a,%s",
13637 aopGet(s,0,FALSE,TRUE,NULL));
13638 freeAsmop (s, NULL, ic, FALSE);
13640 /* make the call */
13641 emitcode ("lcall","System_%s",name);
13643 unsavermask(rsave);
13646 /*-----------------------------------------------------------------*/
13647 /* genSystemThreadResume - */
13648 /*-----------------------------------------------------------------*/
13649 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
13654 assert (nparms==2);
13655 /* save registers that need to be saved */
13656 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13657 ds390_rUmaskForOp (IC_RESULT(ic))));
13663 aopOp(pid,ic,FALSE,FALSE);
13664 emitcode ("mov","r0,%s",
13665 aopGet(pid,0,FALSE,TRUE,DP2_RESULT_REG));
13666 freeAsmop (pid, NULL, ic, FALSE);
13669 aopOp(tid,ic,FALSE,FALSE);
13670 emitcode ("mov","a,%s",
13671 aopGet(tid,0,FALSE,TRUE,DP2_RESULT_REG));
13672 freeAsmop (tid, NULL, ic, FALSE);
13674 emitcode ("lcall","System_ThreadResume");
13676 /* put result into place */
13678 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13679 if (rsym->liveFrom != rsym->liveTo) {
13680 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13681 aopPut(IC_RESULT(ic),"a",0);
13682 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13685 unsavermask(rsave);
13688 /*-----------------------------------------------------------------*/
13689 /* genSystemProcessResume - */
13690 /*-----------------------------------------------------------------*/
13691 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
13696 assert (nparms==1);
13697 /* save registers that need to be saved */
13698 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13699 ds390_rUmaskForOp (IC_RESULT(ic))));
13704 aopOp(pid,ic,FALSE,FALSE);
13705 emitcode ("mov","a,%s",
13706 aopGet(pid,0,FALSE,TRUE,DP2_RESULT_REG));
13707 freeAsmop (pid, NULL, ic, FALSE);
13709 emitcode ("lcall","System_ProcessResume");
13711 unsavermask(rsave);
13714 /*-----------------------------------------------------------------*/
13716 /*-----------------------------------------------------------------*/
13717 static void genSystem (iCode *ic,int nparms,char *name)
13719 assert(nparms == 0);
13721 emitcode ("lcall","System_%s",name);
13724 /*-----------------------------------------------------------------*/
13725 /* genSystemPoll - */
13726 /*-----------------------------------------------------------------*/
13727 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
13732 assert (nparms==1);
13733 /* save registers that need to be saved */
13734 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13735 ds390_rUmaskForOp (IC_RESULT(ic))));
13738 aopOp (fp,ic,FALSE,FALSE);
13739 if (AOP_TYPE (fp) == AOP_IMMD) {
13740 emitcode ("mov", "dptr,%s",
13741 aopGet (fp, 0, TRUE, FALSE, DP2_RESULT_REG));
13742 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
13743 emitcode ("mov","dpl,%s",
13744 aopGet(fp,0,FALSE,FALSE,DP2_RESULT_REG));
13745 emitcode ("mov","dph,%s",
13746 aopGet(fp,1,FALSE,FALSE,DP2_RESULT_REG));
13747 emitcode ("mov","dpx,%s",
13748 aopGet(fp,2,FALSE,FALSE,DP2_RESULT_REG));
13750 freeAsmop (fp, NULL, ic, FALSE);
13752 emitcode ("lcall","System_%sPoll",name);
13754 /* put result into place */
13756 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13757 if (rsym->liveFrom != rsym->liveTo) {
13758 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13759 aopPut(IC_RESULT(ic),"a",0);
13760 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13763 unsavermask(rsave);
13766 /*-----------------------------------------------------------------*/
13767 /* genSystemGetCurrentID - */
13768 /*-----------------------------------------------------------------*/
13769 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
13771 assert (nparms==0);
13773 emitcode ("lcall","System_GetCurrent%sId",name);
13774 /* put result into place */
13776 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13777 if (rsym->liveFrom != rsym->liveTo) {
13778 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13779 aopPut(IC_RESULT(ic),"a",0);
13780 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13785 /*-----------------------------------------------------------------*/
13786 /* genDummyRead - generate code for dummy read of volatiles */
13787 /*-----------------------------------------------------------------*/
13789 genDummyRead (iCode * ic)
13794 D (emitcode(";", "genDummyRead"));
13796 op = IC_RIGHT (ic);
13797 if (op && IS_SYMOP (op))
13799 aopOp (op, ic, FALSE, FALSE);
13801 /* if the result is a bit */
13802 if (AOP_TYPE (op) == AOP_CRY)
13803 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13806 /* bit variables done */
13808 size = AOP_SIZE (op);
13812 MOVA (aopGet (op, offset, FALSE, FALSE, FALSE));
13817 freeAsmop (op, NULL, ic, TRUE);
13821 if (op && IS_SYMOP (op))
13823 aopOp (op, ic, FALSE, FALSE);
13825 /* if the result is a bit */
13826 if (AOP_TYPE (op) == AOP_CRY)
13827 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13830 /* bit variables done */
13832 size = AOP_SIZE (op);
13836 MOVA (aopGet (op, offset, FALSE, FALSE, FALSE));
13841 freeAsmop (op, NULL, ic, TRUE);
13845 /*-----------------------------------------------------------------*/
13846 /* genCritical - generate code for start of a critical sequence */
13847 /*-----------------------------------------------------------------*/
13849 genCritical (iCode *ic)
13851 symbol *tlbl = newiTempLabel (NULL);
13853 D (emitcode(";", "genCritical"));
13855 if (IC_RESULT (ic))
13856 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
13858 emitcode ("setb", "c");
13859 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
13860 emitcode ("clr", "c");
13861 emitcode ("", "%05d$:", (tlbl->key + 100));
13863 if (IC_RESULT (ic))
13864 outBitC (IC_RESULT (ic)); /* save old ea in an operand */
13866 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
13868 if (IC_RESULT (ic))
13869 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13872 /*-----------------------------------------------------------------*/
13873 /* genEndCritical - generate code for end of a critical sequence */
13874 /*-----------------------------------------------------------------*/
13876 genEndCritical (iCode *ic)
13878 D(emitcode("; genEndCritical",""));
13882 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
13883 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
13885 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
13886 emitcode ("mov", "ea,c");
13890 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE, FALSE));
13891 emitcode ("rrc", "a");
13892 emitcode ("mov", "ea,c");
13894 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
13898 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
13899 emitcode ("mov", "ea,c");
13905 /*-----------------------------------------------------------------*/
13906 /* genBuiltIn - calls the appropriate function to generating code */
13907 /* for a built in function */
13908 /*-----------------------------------------------------------------*/
13909 static void genBuiltIn (iCode *ic)
13911 operand *bi_parms[MAX_BUILTIN_ARGS];
13916 /* get all the arguments for a built in function */
13917 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
13919 /* which function is it */
13920 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
13921 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
13922 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
13923 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
13924 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
13925 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
13926 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
13927 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
13928 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
13929 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
13930 genMemsetX(bi_iCode,nbi_parms,bi_parms);
13931 } else if (strcmp(bif->name,"__builtin_inp")==0) {
13932 genInp(bi_iCode,nbi_parms,bi_parms);
13933 } else if (strcmp(bif->name,"__builtin_outp")==0) {
13934 genOutp(bi_iCode,nbi_parms,bi_parms);
13935 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
13936 genSwapW(bi_iCode,nbi_parms,bi_parms);
13937 /* JavaNative builtIns */
13938 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
13939 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
13940 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
13941 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
13942 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
13943 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
13944 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
13945 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
13946 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
13947 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13948 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
13949 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13950 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
13951 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
13952 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
13953 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
13954 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
13955 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13956 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
13957 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13958 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
13959 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
13960 } else if (strcmp(bif->name,"MM_Malloc")==0) {
13961 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
13962 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
13963 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
13964 } else if (strcmp(bif->name,"MM_Free")==0) {
13965 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
13966 } else if (strcmp(bif->name,"MM_Deref")==0) {
13967 genMMDeref(bi_iCode,nbi_parms,bi_parms);
13968 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
13969 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
13970 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
13971 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
13972 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
13973 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
13974 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
13975 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
13976 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
13977 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
13978 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
13979 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
13980 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
13981 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
13982 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
13983 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
13984 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13985 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13986 } else if (strcmp(bif->name,"System_SaveThread")==0) {
13987 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13988 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13989 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13990 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
13991 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
13992 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
13993 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
13994 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
13995 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
13996 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
13997 genSystem(bi_iCode,nbi_parms,"ProcessYield");
13998 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
13999 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
14000 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
14001 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
14002 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
14003 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
14004 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
14005 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
14006 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
14007 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
14009 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
14015 /*-----------------------------------------------------------------*/
14016 /* gen390Code - generate code for Dallas 390 based controllers */
14017 /*-----------------------------------------------------------------*/
14019 gen390Code (iCode * lic)
14024 _G.currentFunc = NULL;
14025 lineHead = lineCurr = NULL;
14026 dptrn[1][0] = "dpl1";
14027 dptrn[1][1] = "dph1";
14028 dptrn[1][2] = "dpx1";
14030 if (options.model == MODEL_FLAT24) {
14031 fReturnSizeDS390 = 5;
14032 fReturn = fReturn24;
14034 fReturnSizeDS390 = 4;
14035 fReturn = fReturn16;
14036 options.stack10bit=0;
14039 /* print the allocation information */
14040 if (allocInfo && currFunc)
14041 printAllocInfo (currFunc, codeOutFile);
14043 /* if debug information required */
14044 if (options.debug && currFunc)
14046 debugFile->writeFunction (currFunc, lic);
14048 /* stack pointer name */
14049 if (options.useXstack)
14055 for (ic = lic; ic; ic = ic->next)
14057 _G.current_iCode = ic;
14059 if (ic->lineno && cln != ic->lineno)
14063 debugFile->writeCLine (ic);
14065 if (!options.noCcodeInAsm) {
14066 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
14067 printCLine(ic->filename, ic->lineno));
14071 if (options.iCodeInAsm) {
14072 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
14074 /* if the result is marked as
14075 spilt and rematerializable or code for
14076 this has already been generated then
14078 if (resultRemat (ic) || ic->generated)
14081 /* depending on the operation */
14101 /* IPOP happens only when trying to restore a
14102 spilt live range, if there is an ifx statement
14103 following this pop then the if statement might
14104 be using some of the registers being popped which
14105 would destory the contents of the register so
14106 we need to check for this condition and handle it */
14108 ic->next->op == IFX &&
14109 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
14110 genIfx (ic->next, ic);
14128 genEndFunction (ic);
14148 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
14165 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
14169 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
14176 /* note these two are xlated by algebraic equivalence
14177 during parsing SDCC.y */
14178 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
14179 "got '>=' or '<=' shouldn't have come here");
14183 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
14195 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
14199 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
14203 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
14227 genRightShift (ic);
14230 case GET_VALUE_AT_ADDRESS:
14231 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
14235 if (POINTER_SET (ic))
14236 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
14262 if (ic->builtinSEND)
14265 addSet (&_G.sendSet, ic);
14268 case DUMMY_READ_VOLATILE:
14277 genEndCritical (ic);
14284 #if 0 // obsolete, and buggy for != xdata
14296 /* now we are ready to call the
14297 peep hole optimizer */
14298 if (!options.nopeep)
14299 peepHole (&lineHead);
14301 /* now do the actual printing */
14302 printLine (lineHead, codeOutFile);