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"); \
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);
250 lineCurr->isComment = (*lbp == ';');
255 emitLabel (symbol *tlbl)
257 emitcode ("", "!tlabeldef", tlbl->key + 100);
258 lineCurr->isLabel = 1;
261 /*-----------------------------------------------------------------*/
262 /* ds390_emitDebuggerSymbol - associate the current code location */
263 /* with a debugger symbol */
264 /*-----------------------------------------------------------------*/
266 ds390_emitDebuggerSymbol (char * debugSym)
269 emitcode ("", "%s ==.", debugSym);
273 /*-----------------------------------------------------------------*/
274 /* mova - moves specified value into accumulator */
275 /*-----------------------------------------------------------------*/
279 /* do some early peephole optimization */
280 if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
283 emitcode("mov", "a,%s", x);
286 /*-----------------------------------------------------------------*/
287 /* movb - moves specified value into register b */
288 /*-----------------------------------------------------------------*/
292 /* do some early peephole optimization */
293 if (!strncmp(x, "b", 2))
296 emitcode("mov","b,%s", x);
299 /*-----------------------------------------------------------------*/
300 /* movc - moves specified value into the carry */
301 /*-----------------------------------------------------------------*/
309 else if (strcmp (s, "c"))
310 {/* it's not in carry already */
312 /* set C, if a >= 1 */
313 emitcode ("add", "a,#0xff");
317 /*-----------------------------------------------------------------*/
318 /* pushB - saves register B if necessary */
319 /*-----------------------------------------------------------------*/
323 bool pushedB = FALSE;
327 emitcode ("push", "b");
328 // printf("B was in use !\n");
338 /*-----------------------------------------------------------------*/
339 /* popB - restores value of register B if necessary */
340 /*-----------------------------------------------------------------*/
346 emitcode ("pop", "b");
354 /*-----------------------------------------------------------------*/
355 /* pushReg - saves register */
356 /*-----------------------------------------------------------------*/
358 pushReg (int index, bool bits_pushed)
360 regs * reg = REG_WITH_INDEX (index);
361 if (reg->type == REG_BIT)
364 emitcode ("push", "%s", reg->base);
368 emitcode ("push", "%s", reg->dname);
372 /*-----------------------------------------------------------------*/
373 /* popReg - restores register */
374 /*-----------------------------------------------------------------*/
376 popReg (int index, bool bits_popped)
378 regs * reg = REG_WITH_INDEX (index);
379 if (reg->type == REG_BIT)
382 emitcode ("pop", "%s", reg->base);
386 emitcode ("pop", "%s", reg->dname);
390 /*-----------------------------------------------------------------*/
391 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
392 /*-----------------------------------------------------------------*/
394 getFreePtr (iCode * ic, asmop ** aopp, bool result)
399 /* the logic: if r0 & r1 used in the instruction
400 then we are in trouble otherwise */
402 /* first check if r0 & r1 are used by this
403 instruction, in which case we are in trouble */
404 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
405 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
410 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
411 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
413 /* if no usage of r0 then return it */
416 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
417 (*aopp)->type = AOP_R0;
419 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
422 /* if no usage of r1 then return it */
425 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
426 (*aopp)->type = AOP_R1;
428 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R1_IDX);
431 /* now we know they both have usage */
432 /* if r0 not used in this instruction */
435 /* push it if not already pushed */
438 emitcode ("push", "%s",
439 REG_WITH_INDEX (R0_IDX)->dname);
443 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
444 (*aopp)->type = AOP_R0;
446 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
449 /* if r1 not used then */
453 /* push it if not already pushed */
456 emitcode ("push", "%s",
457 REG_WITH_INDEX (R1_IDX)->dname);
461 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
462 (*aopp)->type = AOP_R1;
463 return REG_WITH_INDEX (R1_IDX);
467 /* I said end of world, but not quite end of world yet */
468 /* if this is a result then we can push it on the stack */
471 (*aopp)->type = AOP_STK;
475 /* now this is REALLY the end of the world */
476 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
477 "getFreePtr should never reach here");
480 return NULL; // notreached, but makes compiler happy.
484 /*-----------------------------------------------------------------*/
485 /* genSetDPTR: generate code to select which DPTR is in use (zero */
486 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
487 /* alternate DPTR (DPL1/DPH1/DPX1). */
488 /*-----------------------------------------------------------------*/
493 /* If we are doing lazy evaluation, simply note the desired
494 * change, but don't emit any code yet.
504 emitcode ("mov", "dps,#0");
509 emitcode ("mov", "dps,#1");
513 /*------------------------------------------------------------------*/
514 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
516 /* Any code that operates on DPTR (NB: not on the individual */
517 /* components, like DPH) *must* call _flushLazyDPS() before using */
518 /* DPTR within a lazy DPS evaluation block. */
520 /* Note that aopPut and aopGet already contain the proper calls to */
521 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
522 /* DPS evaluation block. */
524 /* Also, _flushLazyDPS must be called before any flow control */
525 /* operations that could potentially branch out of the block. */
527 /* Lazy DPS evaluation is simply an optimization (though an */
528 /* important one), so if in doubt, leave it out. */
529 /*------------------------------------------------------------------*/
531 _startLazyDPSEvaluation (void)
535 #ifdef BETTER_LITERAL_SHIFT
542 /*------------------------------------------------------------------*/
543 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
544 /* desired one. Call before using DPTR within a lazy DPS evaluation */
546 /*------------------------------------------------------------------*/
556 if (_desiredDPS != _currentDPS)
560 emitcode ("inc", "dps");
564 emitcode ("dec", "dps");
566 _currentDPS = _desiredDPS;
570 /*-----------------------------------------------------------------*/
571 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
573 /* Forces us back to the safe state (standard DPTR selected). */
574 /*-----------------------------------------------------------------*/
576 _endLazyDPSEvaluation (void)
578 #ifdef BETTER_LITERAL_SHIFT
596 /*-----------------------------------------------------------------*/
597 /* newAsmop - creates a new asmOp */
598 /*-----------------------------------------------------------------*/
600 newAsmop (short type)
604 aop = Safe_calloc (1, sizeof (asmop));
610 /*-----------------------------------------------------------------*/
611 /* pointerCode - returns the code for a pointer type */
612 /*-----------------------------------------------------------------*/
614 pointerCode (sym_link * etype)
617 return PTR_TYPE (SPEC_OCLS (etype));
621 /*-----------------------------------------------------------------*/
622 /* leftRightUseAcc - returns size of accumulator use by operands */
623 /*-----------------------------------------------------------------*/
625 leftRightUseAcc(iCode *ic)
634 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
635 "null iCode pointer");
642 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
645 size = getSize (OP_SYMBOL (op)->type);
650 else if (ic->op == JUMPTABLE)
653 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
656 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);
672 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
675 size = getSize (OP_SYMBOL (op)->type);
687 /*-----------------------------------------------------------------*/
688 /* aopForSym - for a true symbol */
689 /*-----------------------------------------------------------------*/
691 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
695 bool accuse = leftRightUseAcc (ic) || _G.accInUse;
696 char *dpl = useDP2 ? "dpl1" : "dpl";
697 char *dph = useDP2 ? "dph1" : "dph";
698 char *dpx = useDP2 ? "dpx1" : "dpx";
700 wassertl (ic != NULL, "Got a null iCode");
701 wassertl (sym != NULL, "Got a null symbol");
703 space = SPEC_OCLS (sym->etype);
705 /* if already has one */
708 if ((sym->aop->type == AOP_DPTR && useDP2)
709 || (sym->aop->type == AOP_DPTR2 && !useDP2))
713 sym->aop->allocated++;
718 /* assign depending on the storage class */
719 /* if it is on the stack or indirectly addressable */
720 /* space we need to assign either r0 or r1 to it */
721 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
723 sym->aop = aop = newAsmop (0);
724 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
725 aop->size = getSize (sym->type);
727 /* now assign the address of the variable to
728 the pointer register */
729 if (aop->type != AOP_STK)
733 signed char offset = ((sym->stack < 0) ?
734 ((signed char) (sym->stack - _G.nRegsSaved)) :
735 ((signed char) sym->stack)) & 0xff;
737 if ((abs(offset) <= 3) ||
738 (accuse && (abs(offset) <= 7)))
740 emitcode ("mov", "%s,_bp",
741 aop->aopu.aop_ptr->name);
744 emitcode ("dec", aop->aopu.aop_ptr->name);
749 emitcode ("inc", aop->aopu.aop_ptr->name);
756 emitcode ("push", "acc");
757 emitcode ("mov", "a,_bp");
758 emitcode ("add", "a,#!constbyte", offset);
759 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
761 emitcode ("pop", "acc");
766 emitcode ("mov", "%s,#%s",
767 aop->aopu.aop_ptr->name,
770 aop->paged = space->paged;
773 aop->aopu.aop_stk = sym->stack;
777 if (sym->onStack && options.stack10bit)
779 short stack_val = -((sym->stack < 0) ?
780 ((short) (sym->stack - _G.nRegsSaved)) :
781 ((short) sym->stack)) ;
783 emitcode ("push",dpl);
784 emitcode ("push",dph);
785 emitcode ("push",dpx);
787 /* It's on the 10 bit stack, which is located in
790 if (stack_val < 0 && stack_val > -5)
791 { /* between -5 & -1 */
792 if (options.model == MODEL_FLAT24)
794 emitcode ("mov", "%s,#!constbyte", dpx,
795 (options.stack_loc >> 16) & 0xff);
797 emitcode ("mov", "%s,_bpx+1", dph);
798 emitcode ("mov", "%s,_bpx", dpl);
800 emitcode ("mov","dps,#1");
802 stack_val = -stack_val;
803 while (stack_val--) {
804 emitcode ("inc","dptr");
807 emitcode("mov","dps,#0");
813 emitcode ("push", "acc");
815 emitcode ("mov", "a,_bpx");
816 emitcode ("clr","c");
817 emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
818 emitcode ("mov","%s,a", dpl);
819 emitcode ("mov","a,_bpx+1");
820 emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
821 emitcode ("mov", "%s,a", dph);
822 if (options.model == MODEL_FLAT24)
824 emitcode ("mov", "%s,#!constbyte", dpx,
825 (options.stack_loc >> 16) & 0xff);
829 emitcode ("pop", "acc");
831 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
832 aop->size = getSize (sym->type);
836 /* if in bit space */
837 if (IN_BITSPACE (space))
839 sym->aop = aop = newAsmop (AOP_CRY);
840 aop->aopu.aop_dir = sym->rname;
841 aop->size = getSize (sym->type);
844 /* if it is in direct space */
845 if (IN_DIRSPACE (space))
847 sym->aop = aop = newAsmop (AOP_DIR);
848 aop->aopu.aop_dir = sym->rname;
849 aop->size = getSize (sym->type);
853 /* special case for a function */
854 if (IS_FUNC (sym->type) && !(sym->isitmp))
856 sym->aop = aop = newAsmop (AOP_IMMD);
857 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
858 aop->size = FPTRSIZE;
862 /* only remaining is far space */
863 /* in which case DPTR gets the address */
864 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
869 emitcode ("mov", "dptr,#%s", sym->rname);
874 emitcode ("mov", "dptr,#%s", sym->rname);
876 aop->size = getSize (sym->type);
878 /* if it is in code space */
879 if (IN_CODESPACE (space))
885 /*-----------------------------------------------------------------*/
886 /* aopForRemat - rematerialzes an object */
887 /*-----------------------------------------------------------------*/
889 aopForRemat (symbol * sym)
891 iCode *ic = sym->rematiCode;
892 asmop *aop = newAsmop (AOP_IMMD);
899 val += (int) operandLitValue (IC_RIGHT (ic));
900 else if (ic->op == '-')
901 val -= (int) operandLitValue (IC_RIGHT (ic));
902 else if (IS_CAST_ICODE(ic)) {
903 sym_link *from_type = operandType(IC_RIGHT(ic));
904 aop->aopu.aop_immd.from_cast_remat = 1;
905 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
906 ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
910 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
915 SNPRINTF (buffer, sizeof(buffer),
917 OP_SYMBOL (IC_LEFT (ic))->rname,
918 val >= 0 ? '+' : '-',
919 abs (val) & 0xffffff);
923 if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
925 SNPRINTF(buffer, sizeof(buffer),
926 "0x%x",(int) operandLitValue (IC_RIGHT (ic)));
930 strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
934 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
935 /* set immd2 field if required */
936 if (aop->aopu.aop_immd.from_cast_remat)
938 tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
939 aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
945 /*-----------------------------------------------------------------*/
946 /* aopHasRegs - returns true if aop has regs between from-to */
947 /*-----------------------------------------------------------------*/
948 static int aopHasRegs(asmop *aop, int from, int to)
952 if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
954 for (; size < aop->size ; size++) {
956 for (reg = from ; reg <= to ; reg++)
957 if (aop->aopu.aop_reg[size] == REG_WITH_INDEX(reg)) return 1;
962 /*-----------------------------------------------------------------*/
963 /* regsInCommon - two operands have some registers in common */
964 /*-----------------------------------------------------------------*/
966 regsInCommon (operand * op1, operand * op2)
971 /* if they have registers in common */
972 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
975 sym1 = OP_SYMBOL (op1);
976 sym2 = OP_SYMBOL (op2);
978 if (sym1->nRegs == 0 || sym2->nRegs == 0)
981 for (i = 0; i < sym1->nRegs; i++)
987 for (j = 0; j < sym2->nRegs; j++)
992 if (sym2->regs[j] == sym1->regs[i])
1000 /*-----------------------------------------------------------------*/
1001 /* operandsEqu - equivalent */
1002 /*-----------------------------------------------------------------*/
1004 operandsEqu (operand * op1, operand * op2)
1006 symbol *sym1, *sym2;
1008 /* if they're not symbols */
1009 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1012 sym1 = OP_SYMBOL (op1);
1013 sym2 = OP_SYMBOL (op2);
1015 /* if both are itemps & one is spilt
1016 and the other is not then false */
1017 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
1018 sym1->isspilt != sym2->isspilt)
1021 /* if they are the same */
1025 /* if they have the same rname */
1026 if (sym1->rname[0] && sym2->rname[0] &&
1027 strcmp (sym1->rname, sym2->rname) == 0 &&
1028 !(IS_PARM (op2) && IS_ITEMP (op1)))
1031 /* if left is a tmp & right is not */
1032 if (IS_ITEMP (op1) &&
1035 (sym1->usl.spillLoc == sym2))
1038 if (IS_ITEMP (op2) &&
1042 (sym2->usl.spillLoc == sym1))
1045 /* are they spilt to the same location */
1046 if (IS_ITEMP (op2) &&
1050 (sym1->usl.spillLoc == sym2->usl.spillLoc))
1056 /*-----------------------------------------------------------------*/
1057 /* sameRegs - two asmops have the same registers */
1058 /*-----------------------------------------------------------------*/
1060 sameRegs (asmop * aop1, asmop * aop2)
1066 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
1073 if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
1076 if (aop1->type != aop2->type)
1079 if (aop1->size != aop2->size)
1082 for (i = 0; i < aop1->size; i++)
1083 if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
1089 /*-----------------------------------------------------------------*/
1090 /* aopOp - allocates an asmop for an operand : */
1091 /*-----------------------------------------------------------------*/
1093 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
1102 /* if this a literal */
1103 if (IS_OP_LITERAL (op))
1105 op->aop = aop = newAsmop (AOP_LIT);
1106 aop->aopu.aop_lit = op->operand.valOperand;
1107 aop->size = getSize (operandType (op));
1111 /* if already has a asmop then continue */
1114 if ((op->aop->type == AOP_DPTR && useDP2)
1115 || (op->aop->type == AOP_DPTR2 && !useDP2))
1119 op->aop->allocated++;
1124 /* if the underlying symbol has a aop */
1125 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
1127 op->aop = OP_SYMBOL (op)->aop;
1128 if ((op->aop->type == AOP_DPTR && useDP2)
1129 || (op->aop->type == AOP_DPTR2 && !useDP2))
1133 op->aop->allocated++;
1138 /* if this is a true symbol */
1139 if (IS_TRUE_SYMOP (op))
1141 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
1145 /* this is a temporary : this has
1151 e) can be a return use only */
1153 sym = OP_SYMBOL (op);
1155 /* if the type is a conditional */
1156 if (sym->regType == REG_CND)
1158 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
1163 /* if it is spilt then two situations
1165 b) has a spill location */
1166 if (sym->isspilt || sym->nRegs == 0)
1169 /* rematerialize it NOW */
1172 sym->aop = op->aop = aop =
1174 aop->size = getSize (sym->type);
1181 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
1182 aop->size = getSize (sym->type);
1183 for (i = 0; i < 2; i++)
1184 aop->aopu.aop_str[i] = accUse[i];
1194 /* a AOP_STR uses DPTR, but DPTR is already in use;
1197 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
1200 aop = op->aop = sym->aop = newAsmop (AOP_STR);
1201 aop->size = getSize (sym->type);
1202 for (i = 0; i < fReturnSizeDS390; i++)
1203 aop->aopu.aop_str[i] = fReturn[i];
1207 if (sym->dptr) { /* has been allocated to a DPTRn */
1208 aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
1209 aop->size = getSize (sym->type);
1210 aop->aopu.dptr = sym->dptr;
1214 if (sym->usl.spillLoc)
1216 asmop *oldAsmOp = NULL;
1218 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1220 /* force a new aop if sizes differ */
1221 oldAsmOp = sym->usl.spillLoc->aop;
1222 sym->usl.spillLoc->aop = NULL;
1224 sym->aop = op->aop = aop =
1225 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
1226 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1228 /* Don't reuse the new aop, go with the last one */
1229 sym->usl.spillLoc->aop = oldAsmOp;
1231 aop->size = getSize (sym->type);
1235 /* else must be a dummy iTemp */
1236 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1237 aop->size = getSize (sym->type);
1241 /* if the type is a bit register */
1242 if (sym->regType == REG_BIT)
1244 sym->aop = op->aop = aop = newAsmop (AOP_CRY);
1245 aop->size = sym->nRegs;//1???
1246 aop->aopu.aop_reg[0] = sym->regs[0];
1247 aop->aopu.aop_dir = sym->regs[0]->name;
1251 /* must be in a register */
1252 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1253 aop->size = sym->nRegs;
1254 for (i = 0; i < sym->nRegs; i++)
1255 aop->aopu.aop_reg[i] = sym->regs[i];
1258 /*-----------------------------------------------------------------*/
1259 /* freeAsmop - free up the asmop given to an operand */
1260 /*----------------------------------------------------------------*/
1262 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1279 /* depending on the asmop type only three cases need work
1280 AOP_R0, AOP_R1 & AOP_STK */
1288 emitcode ("pop", "ar0");
1292 bitVectUnSetBit (ic->rUsed, R0_IDX);
1300 emitcode ("pop", "ar1");
1304 bitVectUnSetBit (ic->rUsed, R1_IDX);
1310 int stk = aop->aopu.aop_stk + aop->size;
1311 bitVectUnSetBit (ic->rUsed, R0_IDX);
1312 bitVectUnSetBit (ic->rUsed, R1_IDX);
1314 getFreePtr (ic, &aop, FALSE);
1316 if (options.stack10bit)
1318 /* I'm not sure what to do here yet... */
1321 "*** Warning: probably generating bad code for "
1322 "10 bit stack mode.\n");
1327 emitcode ("mov", "a,_bp");
1328 emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1329 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1333 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1338 emitcode ("pop", "acc");
1339 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1342 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1345 freeAsmop (op, NULL, ic, TRUE);
1348 emitcode ("pop", "ar1");
1353 emitcode ("pop", "ar0");
1358 if (_G.dptr1InUse) {
1359 emitcode ("pop","dpx1");
1360 emitcode ("pop","dph1");
1361 emitcode ("pop","dpl1");
1366 emitcode ("pop","dpx");
1367 emitcode ("pop","dph");
1368 emitcode ("pop","dpl");
1374 /* all other cases just dealloc */
1380 OP_SYMBOL (op)->aop = NULL;
1381 /* if the symbol has a spill */
1383 SPIL_LOC (op)->aop = NULL;
1388 #define DEFAULT_ACC_WARNING 0
1389 static int saveAccWarn = DEFAULT_ACC_WARNING;
1392 /*-----------------------------------------------------------------*/
1393 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
1394 /* clobber the accumulator */
1395 /*-----------------------------------------------------------------*/
1397 aopGetUsesAcc (operand * oper, int offset)
1399 asmop * aop = AOP (oper);
1401 if (offset > (aop->size - 1))
1421 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1432 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1438 /* Error case --- will have been caught already */
1444 /*-------------------------------------------------------------------*/
1445 /* aopGet - for fetching value of the aop */
1447 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1448 /* in the accumulator. Set it to the name of a free register */
1449 /* if acc must be preserved; the register will be used to preserve */
1450 /* acc temporarily and to return the result byte. */
1451 /*-------------------------------------------------------------------*/
1453 aopGet (operand * oper,
1459 asmop * aop = AOP (oper);
1461 /* offset is greater than
1463 if (offset > (aop->size - 1) &&
1464 aop->type != AOP_LIT)
1467 /* depending on type */
1475 /* if we need to increment it */
1476 while (offset > aop->coff)
1478 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1482 while (offset < aop->coff)
1484 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1491 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1492 return (dname ? "acc" : "a");
1494 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1495 return Safe_strdup(buffer);
1498 assert(offset <= 3);
1499 return dptrn[aop->aopu.dptr][offset];
1504 if (aop->type == AOP_DPTR2)
1512 // if (aop->type != AOP_DPTR2)
1514 // if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1515 // emitcode(";", "spanky: saveAcc for DPTR");
1518 emitcode ("xch", "a, %s", saveAcc);
1523 while (offset > aop->coff)
1525 emitcode ("inc", "dptr");
1529 while (offset < aop->coff)
1531 emitcode ("lcall", "__decdptr");
1538 emitcode ("clr", "a");
1539 emitcode ("movc", "a,@a+dptr");
1543 emitcode ("movx", "a,@dptr");
1546 if (aop->type == AOP_DPTR2)
1554 emitcode ("xch", "a, %s", saveAcc);
1555 // if (strcmp(saveAcc, "_ap"))
1557 // emitcode(";", "spiffy: non _ap return from aopGet.");
1562 return (dname ? "acc" : "a");
1565 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1567 SNPRINTF(buffer, sizeof(buffer),
1568 "%s",aop->aopu.aop_immd.aop_immd2);
1572 SNPRINTF(buffer, sizeof(buffer),
1573 "#%s", aop->aopu.aop_immd.aop_immd1);
1579 tsprintf(buffer, sizeof(buffer),
1580 "#!his",aop->aopu.aop_immd.aop_immd1);
1583 tsprintf(buffer, sizeof(buffer),
1584 "#!hihis",aop->aopu.aop_immd.aop_immd1);
1587 tsprintf(buffer, sizeof(buffer),
1588 "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1590 default: /* should not need this (just in case) */
1591 SNPRINTF (buffer, sizeof(buffer),
1593 aop->aopu.aop_immd.aop_immd1,
1599 SNPRINTF (buffer, sizeof(buffer),
1601 aop->aopu.aop_immd.aop_immd1);
1603 return Safe_strdup(buffer);
1606 if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1608 SNPRINTF (buffer, sizeof(buffer),
1610 aop->aopu.aop_dir, offset * 8);
1614 SNPRINTF (buffer, sizeof(buffer),
1621 SNPRINTF (buffer, sizeof(buffer),
1626 return Safe_strdup(buffer);
1630 return aop->aopu.aop_reg[offset]->dname;
1632 return aop->aopu.aop_reg[offset]->name;
1635 emitcode ("clr", "a");
1636 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1637 emitcode ("rlc", "a");
1638 return (dname ? "acc" : "a");
1641 if (!offset && dname)
1643 return aop->aopu.aop_str[offset];
1646 return aopLiteral (aop->aopu.aop_lit, offset);
1650 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1654 return aop->aopu.aop_str[offset];
1658 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1659 "aopget got unsupported aop->type");
1662 return NULL; // not reached, but makes compiler happy.
1665 /*-----------------------------------------------------------------*/
1666 /* aopPut - puts a string for a aop and indicates if acc is in use */
1667 /*-----------------------------------------------------------------*/
1669 aopPut (operand * result, const char *s, int offset)
1671 bool bvolatile = isOperandVolatile (result, FALSE);
1672 bool accuse = FALSE;
1673 asmop * aop = AOP (result);
1675 if (aop->size && offset > (aop->size - 1))
1677 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1678 "aopPut got offset > aop->size");
1682 /* will assign value to value */
1683 /* depending on where it is ofcourse */
1687 MOVA (s); /* read s in case it was volatile */
1692 if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1694 SNPRINTF (buffer, sizeof(buffer),
1696 aop->aopu.aop_dir, offset * 8);
1700 SNPRINTF (buffer, sizeof(buffer),
1702 aop->aopu.aop_dir, offset);
1706 SNPRINTF (buffer, sizeof(buffer),
1711 if (strcmp (buffer, s) || bvolatile)
1713 emitcode ("mov", "%s,%s", buffer, s);
1715 if (!strcmp (buffer, "acc"))
1722 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1723 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1726 strcmp (s, "r0") == 0 ||
1727 strcmp (s, "r1") == 0 ||
1728 strcmp (s, "r2") == 0 ||
1729 strcmp (s, "r3") == 0 ||
1730 strcmp (s, "r4") == 0 ||
1731 strcmp (s, "r5") == 0 ||
1732 strcmp (s, "r6") == 0 ||
1733 strcmp (s, "r7") == 0)
1735 emitcode ("mov", "%s,%s",
1736 aop->aopu.aop_reg[offset]->dname, s);
1740 emitcode ("mov", "%s,%s",
1741 aop->aopu.aop_reg[offset]->name, s);
1747 emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1753 if (aop->type == AOP_DPTR2)
1761 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1762 "aopPut writing to code space");
1766 while (offset > aop->coff)
1769 emitcode ("inc", "dptr");
1772 while (offset < aop->coff)
1775 emitcode ("lcall", "__decdptr");
1780 /* if not in accumulator */
1783 emitcode ("movx", "@dptr,a");
1785 if (aop->type == AOP_DPTR2)
1793 while (offset > aop->coff)
1796 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1798 while (offset < aop->coff)
1801 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1808 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1813 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1815 else if (strcmp (s, "r0") == 0 ||
1816 strcmp (s, "r1") == 0 ||
1817 strcmp (s, "r2") == 0 ||
1818 strcmp (s, "r3") == 0 ||
1819 strcmp (s, "r4") == 0 ||
1820 strcmp (s, "r5") == 0 ||
1821 strcmp (s, "r6") == 0 ||
1822 strcmp (s, "r7") == 0)
1825 SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1826 emitcode ("mov", "@%s,%s",
1827 aop->aopu.aop_ptr->name, buffer);
1831 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1836 if (strcmp (s, "a") == 0)
1837 emitcode ("push", "acc");
1841 emitcode ("push", "acc");
1843 emitcode ("push", s);
1849 /* if not bit variable */
1850 if (!aop->aopu.aop_dir)
1852 /* inefficient: move carry into A and use jz/jnz */
1853 emitcode ("clr", "a");
1854 emitcode ("rlc", "a");
1860 emitcode ("clr", "%s", aop->aopu.aop_dir);
1862 emitcode ("setb", "%s", aop->aopu.aop_dir);
1863 else if (!strcmp (s, "c"))
1864 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1865 else if (strcmp (s, aop->aopu.aop_dir))
1868 /* set C, if a >= 1 */
1869 emitcode ("add", "a,#!constbyte",0xff);
1870 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1877 if (strcmp (aop->aopu.aop_str[offset], s) || bvolatile)
1878 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1884 if (!offset && (strcmp (s, "acc") == 0) && !bvolatile)
1887 if (strcmp (aop->aopu.aop_str[offset], s) && !bvolatile)
1888 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1892 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1893 "aopPut got unsupported aop->type");
1901 /*--------------------------------------------------------------------*/
1902 /* reAdjustPreg - points a register back to where it should (coff==0) */
1903 /*--------------------------------------------------------------------*/
1905 reAdjustPreg (asmop * aop)
1907 if ((aop->coff==0) || (aop->size <= 1))
1915 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1919 if (aop->type == AOP_DPTR2)
1926 emitcode ("lcall", "__decdptr");
1929 if (aop->type == AOP_DPTR2)
1938 /*-----------------------------------------------------------------*/
1939 /* opIsGptr: returns non-zero if the passed operand is */
1940 /* a generic pointer type. */
1941 /*-----------------------------------------------------------------*/
1943 opIsGptr (operand * op)
1945 sym_link *type = operandType (op);
1947 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1954 /*-----------------------------------------------------------------*/
1955 /* getDataSize - get the operand data size */
1956 /*-----------------------------------------------------------------*/
1958 getDataSize (operand * op)
1961 size = AOP_SIZE (op);
1962 if (size == GPTRSIZE)
1964 sym_link *type = operandType (op);
1965 if (IS_GENPTR (type))
1967 /* generic pointer; arithmetic operations
1968 * should ignore the high byte (pointer type).
1976 /*-----------------------------------------------------------------*/
1977 /* outAcc - output Acc */
1978 /*-----------------------------------------------------------------*/
1980 outAcc (operand * result)
1983 size = getDataSize (result);
1986 aopPut (result, "a", 0);
1989 /* unsigned or positive */
1992 aopPut (result, zero, offset++);
1997 /*-----------------------------------------------------------------*/
1998 /* outBitC - output a bit C */
1999 /*-----------------------------------------------------------------*/
2001 outBitC (operand * result)
2003 /* if the result is bit */
2004 if (AOP_TYPE (result) == AOP_CRY)
2006 aopPut (result, "c", 0);
2010 emitcode ("clr", "a");
2011 emitcode ("rlc", "a");
2016 /*-----------------------------------------------------------------*/
2017 /* toBoolean - emit code for orl a,operator(sizeop) */
2018 /*-----------------------------------------------------------------*/
2020 toBoolean (operand * oper)
2022 int size = AOP_SIZE (oper) - 1;
2026 /* The generic part of a generic pointer should
2027 * not participate in it's truth value.
2029 * i.e. 0x10000000 is zero.
2031 if (opIsGptr (oper))
2033 D (emitcode (";", "toBoolean: generic ptr special case."));
2037 _startLazyDPSEvaluation ();
2038 MOVA (aopGet (oper, 0, FALSE, FALSE, NULL));
2039 if (AOP_NEEDSACC (oper) && size && (AOP (oper)->type != AOP_ACC))
2042 emitcode("mov", "b,a");
2045 MOVA (aopGet (oper, offset++, FALSE, FALSE, NULL));
2046 emitcode ("orl", "b,a");
2048 MOVA (aopGet (oper, offset++, FALSE, FALSE, NULL));
2049 emitcode ("orl", "a,b");
2056 emitcode ("orl", "a,%s",
2057 aopGet (oper, offset++, FALSE, FALSE, NULL));
2060 _endLazyDPSEvaluation ();
2064 /*-----------------------------------------------------------------*/
2065 /* genNot - generate code for ! operation */
2066 /*-----------------------------------------------------------------*/
2072 D (emitcode (";", "genNot"));
2074 /* assign asmOps to operand & result */
2075 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2076 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
2078 /* if in bit space then a special case */
2079 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2081 /* if left==result then cpl bit */
2082 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2084 emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2088 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2089 emitcode ("cpl", "c");
2090 outBitC (IC_RESULT (ic));
2095 toBoolean (IC_LEFT (ic));
2097 /* set C, if a == 0 */
2098 tlbl = newiTempLabel (NULL);
2099 emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
2101 outBitC (IC_RESULT (ic));
2104 /* release the aops */
2105 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2106 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2110 /*-----------------------------------------------------------------*/
2111 /* genCpl - generate code for complement */
2112 /*-----------------------------------------------------------------*/
2119 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
2121 D(emitcode (";", "genCpl"));
2123 /* assign asmOps to operand & result */
2124 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2125 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
2127 /* special case if in bit space */
2128 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2132 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
2133 (SPEC_USIGN (letype) && IS_CHAR (letype)))
2135 /* promotion rules are responsible for this strange result:
2136 bit -> int -> ~int -> bit
2137 uchar -> int -> ~int -> bit
2139 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
2143 tlbl=newiTempLabel(NULL);
2144 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE, NULL);
2145 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
2146 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
2147 IS_AOP_PREG (IC_LEFT (ic)))
2149 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
2154 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
2157 outBitC (IC_RESULT(ic));
2161 size = AOP_SIZE (IC_RESULT (ic));
2162 _startLazyDPSEvaluation ();
2165 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL);
2167 emitcode ("cpl", "a");
2168 aopPut (IC_RESULT (ic), "a", offset++);
2170 _endLazyDPSEvaluation ();
2174 /* release the aops */
2175 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2176 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2179 /*-----------------------------------------------------------------*/
2180 /* genUminusFloat - unary minus for floating points */
2181 /*-----------------------------------------------------------------*/
2183 genUminusFloat (operand * op, operand * result)
2185 int size, offset = 0;
2188 D (emitcode (";", "genUminusFloat"));
2190 /* for this we just copy and then flip the bit */
2192 _startLazyDPSEvaluation ();
2193 size = AOP_SIZE (op) - 1;
2198 aopGet (op, offset, FALSE, FALSE, NULL),
2203 l = aopGet (op, offset, FALSE, FALSE, NULL);
2206 emitcode ("cpl", "acc.7");
2207 aopPut (result, "a", offset);
2208 _endLazyDPSEvaluation ();
2211 /*-----------------------------------------------------------------*/
2212 /* genUminus - unary minus code generation */
2213 /*-----------------------------------------------------------------*/
2215 genUminus (iCode * ic)
2220 D (emitcode (";", "genUminus"));
2223 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2224 aopOp (IC_RESULT (ic), ic, TRUE, (AOP_TYPE(IC_LEFT (ic)) == AOP_DPTR));
2226 /* if both in bit space then special
2228 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2229 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2232 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2233 emitcode ("cpl", "c");
2234 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2238 optype = operandType (IC_LEFT (ic));
2240 /* if float then do float stuff */
2241 if (IS_FLOAT (optype))
2243 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2247 /* otherwise subtract from zero */
2248 size = AOP_SIZE (IC_LEFT (ic));
2250 _startLazyDPSEvaluation ();
2253 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL);
2254 if (!strcmp (l, "a"))
2258 emitcode ("cpl", "a");
2259 emitcode ("addc", "a,#0");
2265 emitcode ("clr", "a");
2266 emitcode ("subb", "a,%s", l);
2268 aopPut (IC_RESULT (ic), "a", offset++);
2270 _endLazyDPSEvaluation ();
2272 /* if any remaining bytes in the result */
2273 /* we just need to propagate the sign */
2274 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2276 emitcode ("rlc", "a");
2277 emitcode ("subb", "a,acc");
2279 aopPut (IC_RESULT (ic), "a", offset++);
2283 /* release the aops */
2284 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2285 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2288 /*-----------------------------------------------------------------*/
2289 /* savermask - saves registers in the mask */
2290 /*-----------------------------------------------------------------*/
2291 static void savermask(bitVect *rs_mask)
2295 if (options.useXstack)
2297 if (bitVectBitValue (rs_mask, R0_IDX))
2298 emitcode ("mov", "b,r0");
2299 emitcode ("mov", "r0,%s", spname);
2300 for (i = 0; i < ds390_nRegs; i++)
2302 if (bitVectBitValue (rs_mask, i))
2305 emitcode ("mov", "a,b");
2307 emitcode ("mov", "a,%s", REG_WITH_INDEX (i)->name);
2308 emitcode ("movx", "@r0,a");
2309 emitcode ("inc", "r0");
2312 emitcode ("mov", "%s,r0", spname);
2313 if (bitVectBitValue (rs_mask, R0_IDX))
2314 emitcode ("mov", "r0,b");
2318 bool bits_pushed = FALSE;
2319 for (i = 0; i < ds390_nRegs; i++)
2321 if (bitVectBitValue (rs_mask, i))
2323 bits_pushed = pushReg (i, bits_pushed);
2329 /*-----------------------------------------------------------------*/
2330 /* saveRegisters - will look for a call and save the registers */
2331 /*-----------------------------------------------------------------*/
2333 saveRegisters (iCode * lic)
2339 for (ic = lic; ic; ic = ic->next)
2340 if (ic->op == CALL || ic->op == PCALL)
2345 fprintf (stderr, "found parameter push with no function call\n");
2349 /* if the registers have been saved already or don't need to be then
2352 || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2355 /* special case if DPTR alive across a function call then must save it
2356 even though callee saves */
2357 if (IS_SYMOP(IC_LEFT(ic)) &&
2358 IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type))
2361 rsave = newBitVect(ic->rMask->size);
2362 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2363 if (bitVectBitValue(ic->rMask,i))
2364 rsave = bitVectSetBit(rsave,i);
2366 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2370 /* save the registers in use at this time but skip the
2371 ones for the result */
2372 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2373 ds390_rUmaskForOp (IC_RESULT(ic)));
2379 /*-----------------------------------------------------------------*/
2380 /* usavermask - restore registers with mask */
2381 /*-----------------------------------------------------------------*/
2382 static void unsavermask(bitVect *rs_mask)
2386 if (options.useXstack)
2388 emitcode ("mov", "r0,%s", spname);
2389 for (i = ds390_nRegs; i >= 0; i--)
2391 if (bitVectBitValue (rs_mask, i))
2393 regs * reg = REG_WITH_INDEX (i);
2394 emitcode ("dec", "r0");
2395 emitcode ("movx", "a,@r0");
2398 emitcode ("push", "acc");
2402 emitcode ("mov", "%s,a", reg->name);
2406 emitcode ("mov", "%s,r0", spname);
2407 if (bitVectBitValue (rs_mask, R0_IDX))
2409 emitcode ("pop", "ar0");
2414 bool bits_popped = FALSE;
2415 for (i = ds390_nRegs; i >= 0; i--)
2417 if (bitVectBitValue (rs_mask, i))
2419 bits_popped = popReg (i, bits_popped);
2425 /*-----------------------------------------------------------------*/
2426 /* unsaveRegisters - pop the pushed registers */
2427 /*-----------------------------------------------------------------*/
2429 unsaveRegisters (iCode * ic)
2433 if (IS_SYMOP(IC_LEFT (ic)) &&
2434 IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2436 rsave = newBitVect(ic->rMask->size);
2437 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2438 if (bitVectBitValue(ic->rMask,i))
2439 rsave = bitVectSetBit(rsave,i);
2441 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2443 /* restore the registers in use at this time but skip the
2444 ones for the result */
2445 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2446 ds390_rUmaskForOp (IC_RESULT(ic)));
2452 /*-----------------------------------------------------------------*/
2454 /*-----------------------------------------------------------------*/
2456 pushSide (operand * oper, int size)
2459 _startLazyDPSEvaluation ();
2462 char *l = aopGet (oper, offset++, FALSE, TRUE, NULL);
2463 if (AOP_TYPE (oper) != AOP_REG &&
2464 AOP_TYPE (oper) != AOP_DIR &&
2468 emitcode ("push", "acc");
2472 emitcode ("push", "%s", l);
2475 _endLazyDPSEvaluation ();
2478 /*-----------------------------------------------------------------*/
2479 /* assignResultValue - also indicates if acc is in use afterwards */
2480 /*-----------------------------------------------------------------*/
2482 assignResultValue (operand * oper, operand * func)
2485 unsigned size = AOP_SIZE (oper);
2486 bool accuse = FALSE;
2487 bool pushedA = FALSE;
2489 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2495 if (size == fReturnSizeDS390)
2497 /* I don't think this case can ever happen... */
2498 /* ACC is the last part of this. If writing the result
2499 * uses ACC, we must preserve it.
2501 if (AOP_NEEDSACC(oper))
2503 emitcode(";", "assignResultValue special case for ACC.");
2504 emitcode("push", "acc");
2510 _startLazyDPSEvaluation ();
2513 accuse |= aopPut (oper, fReturn[offset], offset);
2516 _endLazyDPSEvaluation ();
2520 emitcode ("pop", "acc");
2521 accuse |= aopPut (oper, "a", offset);
2527 /*-----------------------------------------------------------------*/
2528 /* genXpush - pushes onto the external stack */
2529 /*-----------------------------------------------------------------*/
2531 genXpush (iCode * ic)
2533 asmop *aop = newAsmop (0);
2535 int size, offset = 0;
2537 D (emitcode (";", "genXpush"));
2539 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2540 r = getFreePtr (ic, &aop, FALSE);
2542 size = AOP_SIZE (IC_LEFT (ic));
2546 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
2547 emitcode ("mov", "%s,_spx", r->name);
2548 emitcode ("inc", "_spx"); // allocate space first
2549 emitcode ("movx", "@%s,a", r->name);
2553 // allocate space first
2554 emitcode ("mov", "%s,_spx", r->name);
2556 emitcode ("add", "a,#%d", size);
2557 emitcode ("mov", "_spx,a");
2559 _startLazyDPSEvaluation ();
2562 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE, NULL));
2563 emitcode ("movx", "@%s,a", r->name);
2564 emitcode ("inc", "%s", r->name);
2566 _endLazyDPSEvaluation ();
2569 freeAsmop (NULL, aop, ic, TRUE);
2570 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2573 /*-----------------------------------------------------------------*/
2574 /* genIpush - generate code for pushing this gets a little complex */
2575 /*-----------------------------------------------------------------*/
2577 genIpush (iCode * ic)
2579 int size, offset = 0;
2583 D (emitcode (";", "genIpush"));
2585 /* if this is not a parm push : ie. it is spill push
2586 and spill push is always done on the local stack */
2590 /* and the item is spilt then do nothing */
2591 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2594 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2595 size = AOP_SIZE (IC_LEFT (ic));
2596 /* push it on the stack */
2597 _startLazyDPSEvaluation ();
2600 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE, NULL);
2606 emitcode ("push", "%s", l);
2608 _endLazyDPSEvaluation ();
2612 /* this is a parameter push: in this case we call
2613 the routine to find the call and save those
2614 registers that need to be saved */
2617 /* if use external stack then call the external
2618 stack pushing routine */
2619 if (options.useXstack)
2625 /* then do the push */
2626 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2628 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2629 size = AOP_SIZE (IC_LEFT (ic));
2631 _startLazyDPSEvaluation ();
2634 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE, NULL);
2635 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2636 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2639 if (strcmp (l, prev) || *l == '@')
2641 emitcode ("push", "acc");
2645 emitcode ("push", "%s", l);
2649 _endLazyDPSEvaluation ();
2651 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2654 /*-----------------------------------------------------------------*/
2655 /* genIpop - recover the registers: can happen only for spilling */
2656 /*-----------------------------------------------------------------*/
2658 genIpop (iCode * ic)
2662 D (emitcode (";", "genIpop"));
2664 /* if the temp was not pushed then */
2665 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2668 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2669 size = AOP_SIZE (IC_LEFT (ic));
2670 offset = (size - 1);
2671 _startLazyDPSEvaluation ();
2674 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2675 FALSE, TRUE, NULL));
2677 _endLazyDPSEvaluation ();
2679 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2682 /*-----------------------------------------------------------------*/
2683 /* saveRBank - saves an entire register bank on the stack */
2684 /*-----------------------------------------------------------------*/
2686 saveRBank (int bank, iCode * ic, bool pushPsw)
2689 int count = 8 + (ds390_nBitRegs/8) + (pushPsw ? 1 : 0);
2693 if (options.useXstack)
2697 /* Assume r0 is available for use. */
2698 r = REG_WITH_INDEX (R0_IDX);;
2703 r = getFreePtr (ic, &aop, FALSE);
2705 // allocate space first
2706 emitcode ("mov", "%s,_spx", r->name);
2708 emitcode ("add", "a,#%d", count);
2709 emitcode ("mov", "_spx,a");
2712 for (i = 0; i < 8; i++) /* only R0-R7 needs saving */
2714 if (options.useXstack)
2716 emitcode ("mov", "a,(%s+%d)",
2717 regs390[i].base, 8 * bank + regs390[i].offset);
2718 emitcode ("movx", "@%s,a", r->name);
2720 emitcode ("inc", "%s", r->name);
2723 emitcode ("push", "(%s+%d)",
2724 regs390[i].base, 8 * bank + regs390[i].offset);
2727 if (ds390_nBitRegs > 0)
2729 if (options.useXstack)
2731 emitcode ("mov", "a,bits");
2732 emitcode ("movx", "@%s,a", r->name);
2734 emitcode ("inc", "%s", r->name);
2738 emitcode ("push", "bits");
2745 if (options.useXstack)
2747 emitcode ("mov", "a,psw");
2748 emitcode ("movx", "@%s,a", r->name);
2752 emitcode ("push", "psw");
2755 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2760 freeAsmop (NULL, aop, ic, TRUE);
2769 /*-----------------------------------------------------------------*/
2770 /* unsaveRBank - restores the register bank from stack */
2771 /*-----------------------------------------------------------------*/
2773 unsaveRBank (int bank, iCode * ic, bool popPsw)
2779 if (options.useXstack)
2783 /* Assume r0 is available for use. */
2784 r = REG_WITH_INDEX (R0_IDX);;
2789 r = getFreePtr (ic, &aop, FALSE);
2791 emitcode ("mov", "%s,_spx", r->name);
2796 if (options.useXstack)
2798 emitcode ("dec", "%s", r->name);
2799 emitcode ("movx", "a,@%s", r->name);
2800 emitcode ("mov", "psw,a");
2804 emitcode ("pop", "psw");
2808 if (ds390_nBitRegs > 0)
2810 if (options.useXstack)
2812 emitcode ("dec", "%s", r->name);
2813 emitcode ("movx", "a,@%s", r->name);
2814 emitcode ("mov", "bits,a");
2818 emitcode ("pop", "bits");
2822 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2824 if (options.useXstack)
2826 emitcode ("dec", "%s", r->name);
2827 emitcode ("movx", "a,@%s", r->name);
2828 emitcode ("mov", "(%s+%d),a",
2829 regs390[i].base, 8 * bank + regs390[i].offset);
2833 emitcode ("pop", "(%s+%d)",
2834 regs390[i].base, 8 * bank + regs390[i].offset);
2838 if (options.useXstack)
2840 emitcode ("mov", "_spx,%s", r->name);
2845 freeAsmop (NULL, aop, ic, TRUE);
2849 /*-----------------------------------------------------------------*/
2850 /* genSend - gen code for SEND */
2851 /*-----------------------------------------------------------------*/
2852 static void genSend(set *sendSet)
2857 static int rb1_count = 0;
2859 /* first we do all bit parameters */
2860 for (sic = setFirstItem (sendSet); sic;
2861 sic = setNextItem (sendSet))
2863 if (sic->argreg > 12)
2865 int bit = sic->argreg-13;
2867 aopOp (IC_LEFT (sic), sic, FALSE,
2868 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2870 /* if left is a literal then
2871 we know what the value is */
2872 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2874 if (((int) operandLitValue (IC_LEFT (sic))))
2875 emitcode ("setb", "b[%d]", bit);
2877 emitcode ("clr", "b[%d]", bit);
2879 else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2881 char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2882 if (strcmp (l, "c"))
2883 emitcode ("mov", "c,%s", l);
2884 emitcode ("mov", "b[%d],c", bit);
2889 toBoolean (IC_LEFT (sic));
2890 /* set C, if a >= 1 */
2891 emitcode ("add", "a,#0xff");
2892 emitcode ("mov", "b[%d],c", bit);
2897 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2903 saveRegisters (setFirstItem (sendSet));
2904 emitcode ("mov", "bits,b");
2907 /* then we do all other parameters */
2908 for (sic = setFirstItem (sendSet); sic;
2909 sic = setNextItem (sendSet))
2911 if (sic->argreg <= 12)
2913 int size, offset = 0;
2915 size = getSize (operandType (IC_LEFT (sic)));
2916 D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2917 if (sendCount == 0) { /* first parameter */
2918 // we know that dpl(hxb) is the result, so
2920 _startLazyDPSEvaluation ();
2922 aopOp (IC_LEFT (sic), sic, FALSE,
2923 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2925 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2929 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE, NULL);
2930 if (strcmp (l, fReturn[offset]))
2932 emitcode ("mov", "%s,%s", fReturn[offset], l);
2936 _endLazyDPSEvaluation ();
2937 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2939 } else { /* if more parameter in registers */
2940 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2942 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (IC_LEFT (sic), offset++,
2943 FALSE, FALSE, NULL));
2945 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2953 adjustEsp(const char *reg)
2955 emitcode ("anl","%s,#3", reg);
2956 if (TARGET_IS_DS400)
2958 emitcode ("orl","%s,#!constbyte",
2960 (options.stack_loc >> 8) & 0xff);
2964 /*-----------------------------------------------------------------*/
2965 /* selectRegBank - emit code to select the register bank */
2966 /*-----------------------------------------------------------------*/
2968 selectRegBank (short bank, bool keepFlags)
2970 /* if f.e. result is in carry */
2973 emitcode ("anl", "psw,#0xE7");
2975 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2979 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2983 /*-----------------------------------------------------------------*/
2984 /* genCall - generates a call statement */
2985 /*-----------------------------------------------------------------*/
2987 genCall (iCode * ic)
2991 bool restoreBank = FALSE;
2992 bool swapBanks = FALSE;
2993 bool accuse = FALSE;
2994 bool accPushed = FALSE;
2995 bool resultInF0 = FALSE;
2996 bool assignResultGenerated = FALSE;
2998 D (emitcode (";", "genCall"));
3000 /* if we are calling a not _naked function that is not using
3001 the same register bank then we need to save the
3002 destination registers on the stack */
3003 dtype = operandType (IC_LEFT (ic));
3004 etype = getSpec(dtype);
3005 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
3006 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3007 IFFUNC_ISISR (currFunc->type))
3011 /* This is unexpected; the bank should have been saved in
3014 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
3020 /* if caller saves & we have not saved then */
3024 /* if send set is not empty then assign */
3025 /* We've saved all the registers we care about;
3026 * therefore, we may clobber any register not used
3027 * in the calling convention (i.e. anything not in
3032 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
3033 genSend(reverseSet(_G.sendSet));
3035 genSend(_G.sendSet);
3042 emitcode ("mov", "psw,#!constbyte",
3043 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3047 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
3048 OP_SYMBOL (IC_LEFT (ic))->rname :
3049 OP_SYMBOL (IC_LEFT (ic))->name));
3053 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
3056 /* if we need assign a result value */
3057 if ((IS_ITEMP (IC_RESULT (ic)) &&
3058 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3059 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3060 OP_SYMBOL (IC_RESULT (ic))->accuse ||
3061 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3062 IS_TRUE_SYMOP (IC_RESULT (ic)))
3064 if (isOperandInFarSpace (IC_RESULT (ic))
3065 && getSize (operandType (IC_RESULT (ic))) <= 2)
3067 int size = getSize (operandType (IC_RESULT (ic)));
3068 bool pushedB = FALSE;
3070 /* Special case for 1 or 2 byte return in far space. */
3075 emitcode ("mov", "b,%s", fReturn[1]);
3079 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
3084 aopPut (IC_RESULT (ic), "a", 0);
3088 aopPut (IC_RESULT (ic), "b", 1);
3090 assignResultGenerated = TRUE;
3091 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3095 bool pushedB = pushB ();
3096 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
3099 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3100 assignResultGenerated = TRUE;
3101 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3105 /* adjust the stack for parameters if required */
3109 if (options.stack10bit) {
3110 if (ic->parmBytes <= 10) {
3111 emitcode(";","stack adjustment for parms");
3112 for (i=0; i < ic->parmBytes ; i++) {
3113 emitcode("pop","acc");
3117 emitcode ("clr","c");
3118 emitcode ("mov","a,sp");
3119 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
3120 emitcode ("mov","sp,a");
3121 emitcode ("mov","a,esp");
3123 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
3124 emitcode ("mov","esp,a");
3128 if (ic->parmBytes > 3)
3132 emitcode ("push", "acc");
3135 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3136 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3137 !assignResultGenerated)
3139 emitcode ("mov", "F0,c");
3143 emitcode ("mov", "a,%s", spname);
3144 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
3145 emitcode ("mov", "%s,a", spname);
3147 /* unsaveRegisters from xstack needs acc, but */
3148 /* unsaveRegisters from stack needs this popped */
3149 if (accPushed && !options.useXstack)
3151 emitcode ("pop", "acc");
3156 for (i = 0; i < ic->parmBytes; i++)
3157 emitcode ("dec", "%s", spname);
3161 /* if we had saved some registers then unsave them */
3162 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3164 if (accuse && !accPushed && options.useXstack)
3166 /* xstack needs acc, but doesn't touch normal stack */
3167 emitcode ("push", "acc");
3170 unsaveRegisters (ic);
3173 /* if register bank was saved then pop them */
3175 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
3177 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
3180 emitcode ("mov", "c,F0");
3182 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
3183 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3184 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3188 emitcode ("pop", "acc");
3191 /*-----------------------------------------------------------------*/
3192 /* genPcall - generates a call by pointer statement */
3193 /*-----------------------------------------------------------------*/
3195 genPcall (iCode * ic)
3199 symbol *rlbl = newiTempLabel (NULL);
3200 bool restoreBank=FALSE;
3201 bool resultInF0 = FALSE;
3203 D (emitcode (";", "genPcall"));
3205 dtype = operandType (IC_LEFT (ic))->next;
3206 etype = getSpec(dtype);
3207 /* if caller saves & we have not saved then */
3211 /* if we are calling a not _naked function that is not using
3212 the same register bank then we need to save the
3213 destination registers on the stack */
3214 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
3215 IFFUNC_ISISR (currFunc->type) &&
3216 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
3217 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3221 /* push the return address on to the stack */
3222 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
3223 emitcode ("push", "acc");
3224 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
3225 emitcode ("push", "acc");
3227 if (options.model == MODEL_FLAT24)
3229 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
3230 emitcode ("push", "acc");
3233 /* now push the calling address */
3234 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3236 pushSide (IC_LEFT (ic), FPTRSIZE);
3238 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3240 /* if send set is not empty the assign */
3243 genSend(reverseSet(_G.sendSet));
3248 emitcode ("ret", "");
3252 /* if we need assign a result value */
3253 if ((IS_ITEMP (IC_RESULT (ic)) &&
3254 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3255 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3256 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3257 IS_TRUE_SYMOP (IC_RESULT (ic)))
3261 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
3264 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3266 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3269 /* adjust the stack for parameters if required */
3273 if (options.stack10bit) {
3274 if (ic->parmBytes <= 10) {
3275 emitcode(";","stack adjustment for parms");
3276 for (i=0; i < ic->parmBytes ; i++) {
3277 emitcode("pop","acc");
3280 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3281 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3283 emitcode ("mov", "F0,c");
3288 emitcode ("clr","c");
3289 emitcode ("mov","a,sp");
3290 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
3291 emitcode ("mov","sp,a");
3292 emitcode ("mov","a,esp");
3294 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
3295 emitcode ("mov","esp,a");
3299 if (ic->parmBytes > 3) {
3300 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3301 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3303 emitcode ("mov", "F0,c");
3307 emitcode ("mov", "a,%s", spname);
3308 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
3309 emitcode ("mov", "%s,a", spname);
3312 for (i = 0; i < ic->parmBytes; i++)
3313 emitcode ("dec", "%s", spname);
3316 /* if register bank was saved then unsave them */
3318 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3320 /* if we had saved some registers then unsave them */
3322 unsaveRegisters (ic);
3324 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3327 emitcode ("mov", "c,F0");
3329 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
3330 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3331 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3335 /*-----------------------------------------------------------------*/
3336 /* resultRemat - result is rematerializable */
3337 /*-----------------------------------------------------------------*/
3339 resultRemat (iCode * ic)
3341 if (SKIP_IC (ic) || ic->op == IFX)
3344 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3346 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3347 if (sym->remat && !POINTER_SET (ic))
3354 #if defined(__BORLANDC__) || defined(_MSC_VER)
3355 #define STRCASECMP stricmp
3357 #define STRCASECMP strcasecmp
3360 /*-----------------------------------------------------------------*/
3361 /* inExcludeList - return 1 if the string is in exclude Reg list */
3362 /*-----------------------------------------------------------------*/
3364 regsCmp(void *p1, void *p2)
3366 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3370 inExcludeList (char *s)
3372 const char *p = setFirstItem(options.excludeRegsSet);
3374 if (p == NULL || STRCASECMP(p, "none") == 0)
3378 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3381 /*-----------------------------------------------------------------*/
3382 /* genFunction - generated code for function entry */
3383 /*-----------------------------------------------------------------*/
3385 genFunction (iCode * ic)
3387 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3389 bool switchedPSW = FALSE;
3390 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3392 D (emitcode (";", "genFunction"));
3395 /* create the function header */
3396 emitcode (";", "-----------------------------------------");
3397 emitcode (";", " function %s", sym->name);
3398 emitcode (";", "-----------------------------------------");
3400 emitcode ("", "%s:", sym->rname);
3401 lineCurr->isLabel = 1;
3402 ftype = operandType (IC_LEFT (ic));
3403 _G.currentFunc = sym;
3405 if (IFFUNC_ISNAKED(ftype))
3407 emitcode(";", "naked function: no prologue.");
3411 if (options.stack_probe)
3412 emitcode ("lcall","__stack_probe");
3414 /* here we need to generate the equates for the
3415 register bank if required */
3416 if (FUNC_REGBANK (ftype) != rbank)
3420 rbank = FUNC_REGBANK (ftype);
3421 for (i = 0; i < ds390_nRegs; i++)
3423 if (regs390[i].print) {
3424 if (strcmp (regs390[i].base, "0") == 0)
3425 emitcode ("", "%s !equ !constbyte",
3427 8 * rbank + regs390[i].offset);
3429 emitcode ("", "%s !equ %s + !constbyte",
3432 8 * rbank + regs390[i].offset);
3437 /* if this is an interrupt service routine then
3438 save acc, b, dpl, dph */
3439 if (IFFUNC_ISISR (sym->type))
3441 if (!inExcludeList ("acc"))
3442 emitcode ("push", "acc");
3443 if (!inExcludeList ("b"))
3444 emitcode ("push", "b");
3445 if (!inExcludeList ("dpl"))
3446 emitcode ("push", "dpl");
3447 if (!inExcludeList ("dph"))
3448 emitcode ("push", "dph");
3449 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3451 emitcode ("push", "dpx");
3452 /* Make sure we're using standard DPTR */
3453 emitcode ("push", "dps");
3454 emitcode ("mov", "dps,#0");
3455 if (options.stack10bit)
3457 /* This ISR could conceivably use DPTR2. Better save it. */
3458 emitcode ("push", "dpl1");
3459 emitcode ("push", "dph1");
3460 emitcode ("push", "dpx1");
3461 emitcode ("push", DP2_RESULT_REG);
3464 /* if this isr has no bank i.e. is going to
3465 run with bank 0 , then we need to save more
3467 if (!FUNC_REGBANK (sym->type))
3471 /* if this function does not call any other
3472 function then we can be economical and
3473 save only those registers that are used */
3474 if (!IFFUNC_HASFCALL(sym->type))
3476 /* if any registers used */
3479 bool bits_pushed = FALSE;
3480 /* save the registers used */
3481 for (i = 0; i < sym->regsUsed->size; i++)
3483 if (bitVectBitValue (sym->regsUsed, i))
3484 bits_pushed = pushReg (i, bits_pushed);
3490 /* this function has a function call. We cannot
3491 determine register usage so we will have to push the
3493 saveRBank (0, ic, FALSE);
3494 if (options.parms_in_bank1) {
3495 for (i=0; i < 8 ; i++ ) {
3496 emitcode ("push","%s",rb1regs[i]);
3503 /* This ISR uses a non-zero bank.
3505 * We assume that the bank is available for our
3508 * However, if this ISR calls a function which uses some
3509 * other bank, we must save that bank entirely.
3511 unsigned long banksToSave = 0;
3513 if (IFFUNC_HASFCALL(sym->type))
3516 #define MAX_REGISTER_BANKS 4
3521 for (i = ic; i; i = i->next)
3523 if (i->op == ENDFUNCTION)
3525 /* we got to the end OK. */
3533 dtype = operandType (IC_LEFT(i));
3535 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3537 /* Mark this bank for saving. */
3538 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3540 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3544 banksToSave |= (1 << FUNC_REGBANK(dtype));
3547 /* And note that we don't need to do it in
3555 /* This is a mess; we have no idea what
3556 * register bank the called function might
3559 * The only thing I can think of to do is
3560 * throw a warning and hope.
3562 werror(W_FUNCPTR_IN_USING_ISR);
3566 if (banksToSave && options.useXstack)
3568 /* Since we aren't passing it an ic,
3569 * saveRBank will assume r0 is available to abuse.
3571 * So switch to our (trashable) bank now, so
3572 * the caller's R0 isn't trashed.
3574 emitcode ("push", "psw");
3575 emitcode ("mov", "psw,#!constbyte",
3576 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3580 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3582 if (banksToSave & (1 << ix))
3584 saveRBank(ix, NULL, FALSE);
3588 // TODO: this needs a closer look
3589 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3594 /* if callee-save to be used for this function
3595 then save the registers being used in this function */
3596 if (IFFUNC_CALLEESAVES(sym->type))
3600 /* if any registers used */
3603 bool bits_pushed = FALSE;
3604 /* save the registers used */
3605 for (i = 0; i < sym->regsUsed->size; i++)
3607 if (bitVectBitValue (sym->regsUsed, i))
3609 bits_pushed = pushReg (i, bits_pushed);
3617 /* set the register bank to the desired value */
3618 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3621 emitcode ("push", "psw");
3622 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3626 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3627 if (options.stack10bit) {
3628 emitcode ("push","_bpx");
3629 emitcode ("push","_bpx+1");
3630 emitcode ("mov","_bpx,%s",spname);
3631 emitcode ("mov","_bpx+1,esp");
3632 adjustEsp("_bpx+1");
3634 if (options.useXstack)
3636 emitcode ("mov", "r0,%s", spname);
3637 emitcode ("mov", "a,_bp");
3638 emitcode ("movx", "@r0,a");
3639 emitcode ("inc", "%s", spname);
3641 /* set up the stack */
3642 emitcode ("push", "_bp"); /* save the callers stack */
3644 emitcode ("mov", "_bp,%s", spname);
3648 /* adjust the stack for the function */
3651 if (options.stack10bit) {
3652 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
3653 assert (sym->recvSize <= 4);
3654 if (sym->stack <= 8) {
3655 while (i--) emitcode ("push","acc");
3658 emitcode ("mov","a,sp");
3659 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3660 emitcode ("mov","sp,a");
3661 emitcode ("mov","a,esp");
3663 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3664 emitcode ("mov","esp,a");
3669 werror (W_STACK_OVERFLOW, sym->name);
3671 if (i > 3 && sym->recvSize < 4) {
3673 emitcode ("mov", "a,sp");
3674 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3675 emitcode ("mov", "sp,a");
3679 emitcode ("inc", "sp");
3686 emitcode ("mov", "a,_spx");
3687 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3688 emitcode ("mov", "_spx,a");
3691 /* if critical function then turn interrupts off */
3692 if (IFFUNC_ISCRITICAL (ftype))
3694 symbol *tlbl = newiTempLabel (NULL);
3695 emitcode ("setb", "c");
3696 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3697 emitcode ("clr", "c");
3699 emitcode ("push", "psw"); /* save old ea via c in psw */
3703 /*-----------------------------------------------------------------*/
3704 /* genEndFunction - generates epilogue for functions */
3705 /*-----------------------------------------------------------------*/
3707 genEndFunction (iCode * ic)
3709 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3710 lineNode *lnp = lineCurr;
3712 bitVect *regsUsedPrologue;
3713 bitVect *regsUnneeded;
3716 D (emitcode (";", "genEndFunction"));
3718 _G.currentFunc = NULL;
3719 if (IFFUNC_ISNAKED(sym->type))
3721 emitcode(";", "naked function: no epilogue.");
3722 if (options.debug && currFunc)
3723 debugFile->writeEndFunction (currFunc, ic, 0);
3727 if (IFFUNC_ISCRITICAL (sym->type))
3729 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3731 emitcode ("rlc", "a"); /* save c in a */
3732 emitcode ("pop", "psw"); /* restore ea via c in psw */
3733 emitcode ("mov", "ea,c");
3734 emitcode ("rrc", "a"); /* restore c from a */
3738 emitcode ("pop", "psw"); /* restore ea via c in psw */
3739 emitcode ("mov", "ea,c");
3743 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3744 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3746 if (options.stack10bit) {
3748 emitcode ("mov", "sp,_bpx", spname);
3749 emitcode ("mov", "esp,_bpx+1", spname);
3752 emitcode ("mov", "%s,_bp", spname);
3756 /* if use external stack but some variables were
3757 added to the local stack then decrement the
3759 if (options.useXstack && sym->stack) {
3760 emitcode ("mov", "a,sp");
3761 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3762 emitcode ("mov", "sp,a");
3766 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3767 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3769 if (options.useXstack) {
3770 emitcode ("mov", "r0,%s", spname);
3771 emitcode ("movx", "a,@r0");
3772 emitcode ("mov", "_bp,a");
3773 emitcode ("dec", "%s", spname);
3775 if (options.stack10bit) {
3776 emitcode ("pop", "_bpx+1");
3777 emitcode ("pop", "_bpx");
3779 emitcode ("pop", "_bp");
3784 /* restore the register bank */
3785 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3787 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3788 || !options.useXstack)
3790 /* Special case of ISR using non-zero bank with useXstack
3793 emitcode ("pop", "psw");
3797 if (IFFUNC_ISISR (sym->type))
3800 /* now we need to restore the registers */
3801 /* if this isr has no bank i.e. is going to
3802 run with bank 0 , then we need to save more
3804 if (!FUNC_REGBANK (sym->type))
3807 /* if this function does not call any other
3808 function then we can be economical and
3809 save only those registers that are used */
3810 if (!IFFUNC_HASFCALL(sym->type))
3812 /* if any registers used */
3815 bool bits_popped = FALSE;
3816 /* save the registers used */
3817 for (i = sym->regsUsed->size; i >= 0; i--)
3819 if (bitVectBitValue (sym->regsUsed, i))
3820 bits_popped = popReg (i, bits_popped);
3826 /* this function has a function call. We cannot
3827 determine register usage so we will have to pop the
3829 if (options.parms_in_bank1) {
3830 for (i = 7 ; i >= 0 ; i-- ) {
3831 emitcode ("pop","%s",rb1regs[i]);
3834 unsaveRBank (0, ic, FALSE);
3839 /* This ISR uses a non-zero bank.
3841 * Restore any register banks saved by genFunction
3844 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3847 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3849 if (savedBanks & (1 << ix))
3851 unsaveRBank(ix, NULL, FALSE);
3855 if (options.useXstack)
3857 /* Restore bank AFTER calling unsaveRBank,
3858 * since it can trash r0.
3860 emitcode ("pop", "psw");
3864 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3866 if (options.stack10bit)
3868 emitcode ("pop", DP2_RESULT_REG);
3869 emitcode ("pop", "dpx1");
3870 emitcode ("pop", "dph1");
3871 emitcode ("pop", "dpl1");
3873 emitcode ("pop", "dps");
3874 emitcode ("pop", "dpx");
3876 if (!inExcludeList ("dph"))
3877 emitcode ("pop", "dph");
3878 if (!inExcludeList ("dpl"))
3879 emitcode ("pop", "dpl");
3880 if (!inExcludeList ("b"))
3881 emitcode ("pop", "b");
3882 if (!inExcludeList ("acc"))
3883 emitcode ("pop", "acc");
3885 /* if debug then send end of function */
3886 if (options.debug && currFunc)
3888 debugFile->writeEndFunction (currFunc, ic, 1);
3891 emitcode ("reti", "");
3895 if (IFFUNC_CALLEESAVES(sym->type))
3899 /* if any registers used */
3902 /* save the registers used */
3903 for (i = sym->regsUsed->size; i >= 0; i--)
3905 if (bitVectBitValue (sym->regsUsed, i))
3906 emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3911 /* if debug then send end of function */
3912 if (options.debug && currFunc)
3914 debugFile->writeEndFunction (currFunc, ic, 1);
3917 emitcode ("ret", "");
3920 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3923 /* If this was an interrupt handler using bank 0 that called another */
3924 /* function, then all registers must be saved; nothing to optimized. */
3925 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3926 && !FUNC_REGBANK(sym->type))
3929 /* There are no push/pops to optimize if not callee-saves or ISR */
3930 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3933 /* If there were stack parameters, we cannot optimize without also */
3934 /* fixing all of the stack offsets; this is too dificult to consider. */
3935 if (FUNC_HASSTACKPARM(sym->type))
3938 /* Compute the registers actually used */
3939 regsUsed = newBitVect (ds390_nRegs);
3940 regsUsedPrologue = newBitVect (ds390_nRegs);
3943 if (lnp->ic && lnp->ic->op == FUNCTION)
3944 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3946 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3948 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3949 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3956 if (bitVectBitValue (regsUsedPrologue, DPS_IDX)
3957 && !bitVectBitValue (regsUsed, DPS_IDX))
3959 bitVectUnSetBit (regsUsedPrologue, DPS_IDX);
3962 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3963 && !bitVectBitValue (regsUsed, CND_IDX))
3965 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3966 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3967 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3968 bitVectUnSetBit (regsUsed, CND_IDX);
3971 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3973 /* If this was an interrupt handler that called another function */
3974 /* function, then assume working registers may be modified by it. */
3975 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3977 regsUsed = bitVectSetBit (regsUsed, AP_IDX);
3978 regsUsed = bitVectSetBit (regsUsed, DPX1_IDX);
3979 regsUsed = bitVectSetBit (regsUsed, DPL1_IDX);
3980 regsUsed = bitVectSetBit (regsUsed, DPH1_IDX);
3981 regsUsed = bitVectSetBit (regsUsed, DPX_IDX);
3982 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3983 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3984 regsUsed = bitVectSetBit (regsUsed, DPS_IDX);
3985 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3986 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3987 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3990 /* Remove the unneeded push/pops */
3991 regsUnneeded = newBitVect (ds390_nRegs);
3994 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3996 if (!strncmp(lnp->line, "push", 4))
3998 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3999 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4001 connectLine (lnp->prev, lnp->next);
4002 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4005 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
4007 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
4008 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4010 connectLine (lnp->prev, lnp->next);
4011 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4018 for (idx = 0; idx < regsUnneeded->size; idx++)
4019 if (bitVectBitValue (regsUnneeded, idx))
4020 emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
4022 freeBitVect (regsUnneeded);
4023 freeBitVect (regsUsed);
4024 freeBitVect (regsUsedPrologue);
4027 /*-----------------------------------------------------------------*/
4028 /* genJavaNativeRet - generate code for return JavaNative */
4029 /*-----------------------------------------------------------------*/
4030 static void genJavaNativeRet(iCode *ic)
4034 aopOp (IC_LEFT (ic), ic, FALSE,
4035 AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
4036 size = AOP_SIZE (IC_LEFT (ic));
4040 /* it is assigned to GPR0-R3 then push them */
4041 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
4042 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
4043 for (i = 0 ; i < size ; i++ ) {
4044 emitcode ("push","%s",
4045 aopGet(IC_LEFT(ic),i,FALSE,TRUE,DP2_RESULT_REG));
4047 for (i = (size-1) ; i >= 0 ; i--) {
4048 emitcode ("pop","a%s",javaRet[i]);
4051 for (i = 0 ; i < size ; i++)
4052 emitcode ("mov","%s,%s",javaRet[i],
4053 aopGet(IC_LEFT(ic),i,FALSE,TRUE,DP2_RESULT_REG));
4055 for (i = size ; i < 4 ; i++ )
4056 emitcode ("mov","%s,#0",javaRet[i]);
4060 /*-----------------------------------------------------------------*/
4061 /* genRet - generate code for return statement */
4062 /*-----------------------------------------------------------------*/
4066 int size, offset = 0, pushed = 0;
4068 D (emitcode (";", "genRet"));
4070 /* if we have no return value then
4071 just generate the "ret" */
4075 /* if this is a JavaNative function then return
4076 value in different register */
4077 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
4078 genJavaNativeRet(ic);
4081 /* we have something to return then
4082 move the return value into place */
4083 aopOp (IC_LEFT (ic), ic, FALSE,
4084 (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
4085 size = AOP_SIZE (IC_LEFT (ic));
4087 _startLazyDPSEvaluation ();
4089 if (IS_BIT(_G.currentFunc->etype))
4091 movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4098 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
4100 l = aopGet (IC_LEFT (ic), offset++,
4102 emitcode ("push", "%s", l);
4107 /* Since A is the last element of fReturn,
4108 * it is OK to clobber it in the aopGet.
4110 l = aopGet (IC_LEFT (ic), offset,
4111 FALSE, FALSE, NULL);
4112 if (strcmp (fReturn[offset], l))
4113 emitcode ("mov", "%s,%s", fReturn[offset++], l);
4116 _endLazyDPSEvaluation ();
4121 if (strcmp (fReturn[pushed], "a"))
4122 emitcode ("pop", fReturn[pushed]);
4124 emitcode ("pop", "acc");
4126 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4129 /* generate a jump to the return label
4130 if the next is not the return statement */
4131 if (!(ic->next && ic->next->op == LABEL &&
4132 IC_LABEL (ic->next) == returnLabel))
4134 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
4138 /*-----------------------------------------------------------------*/
4139 /* genLabel - generates a label */
4140 /*-----------------------------------------------------------------*/
4142 genLabel (iCode * ic)
4144 /* special case never generate */
4145 if (IC_LABEL (ic) == entryLabel)
4148 D (emitcode (";", "genLabel"));
4150 emitLabel (IC_LABEL (ic));
4153 /*-----------------------------------------------------------------*/
4154 /* genGoto - generates a ljmp */
4155 /*-----------------------------------------------------------------*/
4157 genGoto (iCode * ic)
4159 D (emitcode (";", "genGoto"));
4161 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
4164 /*-----------------------------------------------------------------*/
4165 /* findLabelBackwards: walks back through the iCode chain looking */
4166 /* for the given label. Returns number of iCode instructions */
4167 /* between that label and given ic. */
4168 /* Returns zero if label not found. */
4169 /*-----------------------------------------------------------------*/
4171 findLabelBackwards (iCode * ic, int key)
4180 /* If we have any pushes or pops, we cannot predict the distance.
4181 I don't like this at all, this should be dealt with in the
4183 if (ic->op == IPUSH || ic->op == IPOP) {
4187 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4189 /* printf("findLabelBackwards = %d\n", count); */
4197 /*-----------------------------------------------------------------*/
4198 /* genPlusIncr :- does addition with increment if possible */
4199 /*-----------------------------------------------------------------*/
4201 genPlusIncr (iCode * ic)
4203 unsigned int icount;
4204 unsigned int size = getDataSize (IC_RESULT (ic));
4206 /* will try to generate an increment */
4207 /* if the right side is not a literal
4209 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4212 /* if the literal value of the right hand side
4213 is greater than 4 then it is not worth it */
4214 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4217 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4218 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4220 emitcode("inc","%s",aopGet(IC_RESULT(ic),0,FALSE,FALSE,NULL));
4224 /* if increment 16 bits in register */
4226 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4227 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4228 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4237 /* If the next instruction is a goto and the goto target
4238 * is <= 5 instructions previous to this, we can generate
4239 * jumps straight to that target.
4241 if (ic->next && ic->next->op == GOTO
4242 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4245 D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4246 tlbl = IC_LABEL (ic->next);
4251 tlbl = newiTempLabel (NULL);
4254 l = aopGet (IC_RESULT (ic), LSB, FALSE, FALSE, NULL);
4255 emitcode ("inc", "%s", l);
4257 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4258 IS_AOP_PREG (IC_RESULT (ic)))
4260 emitcode ("cjne", "%s,%s,!tlabel", l, zero, tlbl->key + 100);
4264 emitcode ("clr", "a");
4265 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4268 l = aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE, NULL);
4269 emitcode ("inc", "%s", l);
4272 if (!strcmp(l, "acc"))
4274 emitcode("jnz", "!tlabel", tlbl->key + 100);
4276 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4277 IS_AOP_PREG (IC_RESULT (ic)))
4279 emitcode ("cjne", "%s,%s,!tlabel", l, zero, tlbl->key + 100);
4283 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4286 l = aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE, NULL);
4287 emitcode ("inc", "%s", l);
4291 if (!strcmp(l, "acc"))
4293 emitcode("jnz", "!tlabel", tlbl->key + 100);
4295 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4296 IS_AOP_PREG (IC_RESULT (ic)))
4298 emitcode ("cjne", "%s,%s,!tlabel", l, zero, tlbl->key + 100);
4302 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4305 l = aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE, NULL);
4306 emitcode ("inc", "%s", l);
4316 if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
4317 !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
4318 options.model == MODEL_FLAT24 )
4320 if (IC_RESULT(ic)->isGptr)
4322 emitcode ("mov", "b,%s", aopGet(IC_LEFT (ic), 3, FALSE, FALSE, NULL));
4326 emitcode ("mov", "dpx,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE, NULL));
4328 emitcode ("mov", "dph,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE, NULL));
4330 emitcode ("mov", "dpl,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4334 emitcode ("inc", "dptr");
4338 if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
4339 AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
4341 emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
4343 emitcode ("inc", "dptr");
4344 emitcode ("mov", "dps,#0");
4348 /* if the sizes are greater than 1 then we cannot */
4349 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4350 AOP_SIZE (IC_LEFT (ic)) > 1)
4353 /* we can if the aops of the left & result match or
4354 if they are in registers and the registers are the
4357 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4358 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4359 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4363 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4364 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
4365 aopPut (IC_RESULT (ic), "a", 0);
4369 _startLazyDPSEvaluation ();
4372 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4374 _endLazyDPSEvaluation ();
4383 /*-----------------------------------------------------------------*/
4384 /* outBitAcc - output a bit in acc */
4385 /*-----------------------------------------------------------------*/
4387 outBitAcc (operand * result)
4389 symbol *tlbl = newiTempLabel (NULL);
4390 /* if the result is a bit */
4391 if (AOP_TYPE (result) == AOP_CRY)
4393 aopPut (result, "a", 0);
4397 emitcode ("jz", "!tlabel", tlbl->key + 100);
4398 emitcode ("mov", "a,%s", one);
4404 /*-----------------------------------------------------------------*/
4405 /* genPlusBits - generates code for addition of two bits */
4406 /*-----------------------------------------------------------------*/
4408 genPlusBits (iCode * ic)
4410 D (emitcode (";", "genPlusBits"));
4412 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4414 symbol *lbl = newiTempLabel (NULL);
4415 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4416 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4417 emitcode ("cpl", "c");
4419 outBitC (IC_RESULT (ic));
4423 emitcode ("clr", "a");
4424 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4425 emitcode ("rlc", "a");
4426 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4427 emitcode ("addc", "a,%s", zero);
4428 outAcc (IC_RESULT (ic));
4433 adjustArithmeticResult (iCode * ic)
4435 if (opIsGptr (IC_RESULT (ic)) &&
4436 opIsGptr (IC_LEFT (ic)) &&
4437 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4439 aopPut (IC_RESULT (ic),
4440 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE, NULL),
4444 if (opIsGptr (IC_RESULT (ic)) &&
4445 opIsGptr (IC_RIGHT (ic)) &&
4446 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4448 aopPut (IC_RESULT (ic),
4449 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE, NULL),
4453 if (opIsGptr (IC_RESULT (ic)) &&
4454 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4455 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4456 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4457 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4460 SNPRINTF (buffer, sizeof(buffer),
4461 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4462 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4466 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
4467 // generates the result if possible. If result is generated, returns TRUE; otherwise
4468 // returns false and caller must deal with fact that result isn't aopOp'd.
4469 bool aopOp3(iCode * ic)
4471 bool dp1InUse, dp2InUse;
4474 // First, generate the right opcode. DPTR may be used if neither left nor result are
4477 // D (emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
4478 // AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
4479 // AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
4480 // AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
4482 // D (emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
4483 // AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
4484 // AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
4485 // AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
4488 // Right uses DPTR unless left or result is an AOP_STR; however,
4489 // if right is an AOP_STR, it must use DPTR regardless.
4490 if ((AOP_IS_STR (IC_LEFT (ic)) || AOP_IS_STR (IC_RESULT (ic)))
4491 && !AOP_IS_STR (IC_RIGHT (ic)))
4500 aopOp (IC_RIGHT(ic), ic, FALSE, useDp2);
4502 // if the right used DPTR, left MUST use DPTR2.
4503 // if the right used DPTR2, left MUST use DPTR.
4504 // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
4505 // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
4506 // enabling us to assign DPTR to result.
4508 if (AOP_USESDPTR (IC_RIGHT (ic)))
4512 else if (AOP_USESDPTR2 (IC_RIGHT (ic)))
4518 if (AOP_IS_STR (IC_RESULT (ic)) && !AOP_IS_STR (IC_LEFT (ic)))
4528 aopOp (IC_LEFT (ic), ic, FALSE, useDp2);
4531 // We've op'd the left & right. So, if left or right are the same operand as result,
4532 // we know aopOp will succeed, and we can just do it & bail.
4533 if (isOperandEqual (IC_LEFT (ic), IC_RESULT (ic)))
4535 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4538 if (isOperandEqual (IC_RIGHT (ic), IC_RESULT (ic)))
4540 // D (emitcode(";", "aopOp3: (left | right) & result equal"));
4541 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4545 // Operands may be equivalent (but not equal) if they share a spill location. If
4546 // so, use the same DPTR or DPTR2.
4547 if (operandsEqu (IC_LEFT (ic), IC_RESULT (ic)))
4549 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4552 if (operandsEqu (IC_RIGHT (ic), IC_RESULT (ic)))
4554 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4558 // Note which dptrs are currently in use.
4559 dp1InUse = AOP_USESDPTR (IC_LEFT (ic)) || AOP_USESDPTR (IC_RIGHT (ic));
4560 dp2InUse = AOP_USESDPTR2 (IC_LEFT (ic)) || AOP_USESDPTR2 (IC_RIGHT (ic));
4562 // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
4564 if (dp1InUse && AOP_IS_STR (IC_RESULT (ic)))
4569 // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
4570 if (dp2InUse && AOP_IS_DPTRn (IC_RESULT (ic)))
4575 // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
4576 if (dp1InUse && dp2InUse && isOperandInFarSpace (IC_RESULT (ic)))
4581 aopOp (IC_RESULT (ic), ic, TRUE, dp1InUse);
4583 // Some sanity checking...
4584 if (dp1InUse && AOP_USESDPTR (IC_RESULT (ic)))
4587 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
4588 __FILE__, __LINE__, ic->filename, ic->lineno);
4589 emitcode(";", ">>> unexpected DPTR here.");
4592 if (dp2InUse && AOP_USESDPTR2 (IC_RESULT (ic)))
4595 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
4596 __FILE__, __LINE__, ic->filename, ic->lineno);
4597 emitcode(";", ">>> unexpected DPTR2 here.");
4603 // Macro to aopOp all three operands of an ic. If this cannot be done,
4604 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
4605 // will be set TRUE. The caller must then handle the case specially, noting
4606 // that the IC_RESULT operand is not aopOp'd.
4608 #define AOP_OP_3_NOFATAL(ic, rc) \
4609 do { rc = !aopOp3(ic); } while (0)
4611 // aopOp the left & right operands of an ic.
4612 #define AOP_OP_2(ic) \
4613 aopOp (IC_RIGHT (ic), ic, FALSE, AOP_IS_STR (IC_LEFT (ic))); \
4614 aopOp (IC_LEFT (ic), ic, FALSE, AOP_USESDPTR (IC_RIGHT (ic)));
4616 // convienience macro.
4617 #define AOP_SET_LOCALS(ic) \
4618 left = IC_LEFT(ic); \
4619 right = IC_RIGHT(ic); \
4620 result = IC_RESULT(ic);
4623 // Given an integer value of pushedSize bytes on the stack,
4624 // adjust it to be resultSize bytes, either by discarding
4625 // the most significant bytes or by zero-padding.
4627 // On exit from this macro, pushedSize will have been adjusted to
4628 // equal resultSize, and ACC may be trashed.
4629 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
4630 /* If the pushed data is bigger than the result, \
4631 * simply discard unused bytes. Icky, but works. \
4633 while (pushedSize > resultSize) \
4635 D (emitcode (";", "discarding unused result byte.")); \
4636 emitcode ("pop", "acc"); \
4639 if (pushedSize < resultSize) \
4641 emitcode ("clr", "a"); \
4642 /* Conversly, we haven't pushed enough here. \
4643 * just zero-pad, and all is well. \
4645 while (pushedSize < resultSize) \
4647 emitcode("push", "acc"); \
4651 assert(pushedSize == resultSize);
4653 /*-----------------------------------------------------------------*/
4654 /* genPlus - generates code for addition */
4655 /*-----------------------------------------------------------------*/
4657 genPlus (iCode * ic)
4659 int size, offset = 0;
4662 bool swappedLR = FALSE;
4664 D (emitcode (";", "genPlus"));
4666 /* special cases :- */
4667 if ( AOP_IS_STR (IC_LEFT (ic)) &&
4668 isOperandLiteral (IC_RIGHT (ic)) && OP_SYMBOL (IC_RESULT (ic))->ruonly) {
4669 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4670 size = (int)floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4672 while (size--) emitcode ("inc","dptr");
4674 emitcode ("mov", "a,dpl");
4675 emitcode ("add", "a,#!constbyte", size & 0xff);
4676 emitcode ("mov", "dpl,a");
4677 emitcode ("mov", "a,dph");
4678 emitcode ("addc", "a,#!constbyte", (size >> 8) & 0xff);
4679 emitcode ("mov", "dph,a");
4680 emitcode ("mov", "a,dpx");
4681 emitcode ("addc", "a,#!constbyte", (size >> 16) & 0xff);
4682 emitcode ("mov", "dpx,a");
4684 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4687 if ( IS_SYMOP (IC_LEFT (ic)) &&
4688 OP_SYMBOL (IC_LEFT (ic))->remat &&
4689 isOperandInFarSpace (IC_RIGHT (ic))) {
4690 operand *op = IC_RIGHT(ic);
4691 IC_RIGHT(ic) = IC_LEFT(ic);
4695 AOP_OP_3_NOFATAL (ic, pushResult);
4699 D (emitcode (";", "genPlus: must push result: 3 ops in far space"));
4704 /* if literal, literal on the right or
4705 if left requires ACC or right is already
4707 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4708 ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic)))) ||
4709 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4711 operand *t = IC_RIGHT (ic);
4712 IC_RIGHT (ic) = IC_LEFT (ic);
4715 D (emitcode (";", "Swapped plus args."));
4718 /* if both left & right are in bit
4720 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4721 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4727 /* if left in bit space & right literal */
4728 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4729 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4731 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4732 /* if result in bit space */
4733 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4735 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4736 emitcode ("cpl", "c");
4737 outBitC (IC_RESULT (ic));
4741 size = getDataSize (IC_RESULT (ic));
4742 _startLazyDPSEvaluation ();
4745 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4746 emitcode ("addc", "a,%s", zero);
4747 aopPut (IC_RESULT (ic), "a", offset++);
4749 _endLazyDPSEvaluation ();
4754 /* if I can do an increment instead
4755 of add then GOOD for ME */
4756 if (genPlusIncr (ic) == TRUE)
4758 D (emitcode (";", "did genPlusIncr"));
4763 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4765 _startLazyDPSEvaluation ();
4768 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4770 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
4772 emitcode ("add", "a,%s",
4773 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4775 emitcode ("addc", "a,%s",
4776 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4780 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4782 /* right is going to use ACC or we would have taken the
4785 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4787 D(emitcode(";", "+ AOP_ACC special case."););
4788 emitcode("xch", "a, %s", DP2_RESULT_REG);
4790 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4793 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4796 emitcode("add", "a, %s", DP2_RESULT_REG);
4800 emitcode ("add", "a,%s",
4801 aopGet (IC_LEFT(ic), offset, FALSE, FALSE,
4807 emitcode ("addc", "a,%s",
4808 aopGet (IC_LEFT (ic), offset, FALSE, FALSE,
4814 aopPut (IC_RESULT (ic), "a", offset);
4818 emitcode ("push", "acc");
4822 _endLazyDPSEvaluation ();
4826 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4828 size = getDataSize (IC_LEFT (ic));
4829 rSize = getDataSize (IC_RESULT (ic));
4831 ADJUST_PUSHED_RESULT(size, rSize);
4833 _startLazyDPSEvaluation ();
4836 emitcode ("pop", "acc");
4837 aopPut (IC_RESULT (ic), "a", size);
4839 _endLazyDPSEvaluation ();
4842 adjustArithmeticResult (ic);
4845 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4848 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4849 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4853 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4854 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4858 /*-----------------------------------------------------------------*/
4859 /* genMinusDec :- does subtraction with decrement if possible */
4860 /*-----------------------------------------------------------------*/
4862 genMinusDec (iCode * ic)
4864 unsigned int icount;
4865 unsigned int size = getDataSize (IC_RESULT (ic));
4867 /* will try to generate an increment */
4868 /* if the right side is not a literal
4870 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4873 /* if the literal value of the right hand side
4874 is greater than 4 then it is not worth it */
4875 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4878 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4879 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4881 emitcode("dec","%s",aopGet(IC_RESULT(ic),0,FALSE,FALSE,NULL));
4885 /* if decrement 16 bits in register */
4886 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4887 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4888 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4897 /* If the next instruction is a goto and the goto target
4898 * is <= 5 instructions previous to this, we can generate
4899 * jumps straight to that target.
4901 if (ic->next && ic->next->op == GOTO
4902 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4905 D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4906 tlbl = IC_LABEL (ic->next);
4911 tlbl = newiTempLabel (NULL);
4915 l = aopGet (IC_RESULT (ic), LSB, FALSE, FALSE, NULL);
4916 emitcode ("dec", "%s", l);
4918 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4919 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4920 IS_AOP_PREG (IC_RESULT (ic)))
4922 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4926 emitcode ("mov", "a,#!constbyte",0xff);
4927 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4929 l = aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE, NULL);
4930 emitcode ("dec", "%s", l);
4933 if (!strcmp(l, "acc"))
4935 emitcode("jnz", "!tlabel", tlbl->key + 100);
4937 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4938 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4939 IS_AOP_PREG (IC_RESULT (ic)))
4941 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4945 emitcode ("mov", "a,#!constbyte",0xff);
4946 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4948 l = aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE, NULL);
4949 emitcode ("dec", "%s", l);
4953 if (!strcmp(l, "acc"))
4955 emitcode("jnz", "!tlabel", tlbl->key + 100);
4957 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4958 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4959 IS_AOP_PREG (IC_RESULT (ic)))
4961 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4965 emitcode ("mov", "a,#!constbyte",0xff);
4966 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4968 l = aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE, NULL);
4969 emitcode ("dec", "%s", l);
4978 /* if the sizes are greater than 1 then we cannot */
4979 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4980 AOP_SIZE (IC_LEFT (ic)) > 1)
4983 /* we can if the aops of the left & result match or
4984 if they are in registers and the registers are the
4987 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4988 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4989 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4993 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4995 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL));
5000 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL);
5003 _startLazyDPSEvaluation ();
5006 emitcode ("dec", "%s", l);
5008 _endLazyDPSEvaluation ();
5010 if (AOP_NEEDSACC (IC_RESULT (ic)))
5011 aopPut (IC_RESULT (ic), "a", 0);
5019 /*-----------------------------------------------------------------*/
5020 /* addSign - complete with sign */
5021 /*-----------------------------------------------------------------*/
5023 addSign (operand * result, int offset, int sign)
5025 int size = (getDataSize (result) - offset);
5028 _startLazyDPSEvaluation();
5031 emitcode ("rlc", "a");
5032 emitcode ("subb", "a,acc");
5035 aopPut (result, "a", offset++);
5042 aopPut (result, zero, offset++);
5045 _endLazyDPSEvaluation();
5049 /*-----------------------------------------------------------------*/
5050 /* genMinusBits - generates code for subtraction of two bits */
5051 /*-----------------------------------------------------------------*/
5053 genMinusBits (iCode * ic)
5055 symbol *lbl = newiTempLabel (NULL);
5057 D (emitcode (";", "genMinusBits"));
5059 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
5061 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
5062 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
5063 emitcode ("cpl", "c");
5065 outBitC (IC_RESULT (ic));
5069 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
5070 emitcode ("subb", "a,acc");
5071 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
5072 emitcode ("inc", "a");
5074 aopPut (IC_RESULT (ic), "a", 0);
5075 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
5079 /*-----------------------------------------------------------------*/
5080 /* genMinus - generates code for subtraction */
5081 /*-----------------------------------------------------------------*/
5083 genMinus (iCode * ic)
5085 int size, offset = 0;
5090 D (emitcode (";", "genMinus"));
5092 AOP_OP_3_NOFATAL(ic, pushResult);
5096 /* special cases :- */
5097 /* if both left & right are in bit space */
5098 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
5099 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
5105 /* if I can do an decrement instead
5106 of subtract then GOOD for ME */
5107 if (genMinusDec (ic) == TRUE)
5112 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
5114 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
5120 lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5125 /* if literal, add a,#-lit, else normal subb */
5126 _startLazyDPSEvaluation ();
5128 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
5129 if (AOP_USESDPTR(IC_RIGHT(ic))) {
5130 emitcode ("mov","b,%s",
5131 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
5132 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
5133 emitcode ("subb","a,b");
5135 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
5136 emitcode ("subb", "a,%s",
5137 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE,
5141 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
5142 /* first add without previous c */
5144 if (!size && lit==-1) {
5145 emitcode ("dec", "a");
5147 emitcode ("add", "a,#!constbyte",
5148 (unsigned int) (lit & 0x0FFL));
5151 emitcode ("addc", "a,#!constbyte",
5152 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5157 emitcode ("push", "acc");
5159 aopPut (IC_RESULT (ic), "a", offset);
5163 _endLazyDPSEvaluation ();
5167 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
5169 size = getDataSize (IC_LEFT (ic));
5170 rSize = getDataSize (IC_RESULT (ic));
5172 ADJUST_PUSHED_RESULT(size, rSize);
5174 _startLazyDPSEvaluation ();
5177 emitcode ("pop", "acc");
5178 aopPut (IC_RESULT (ic), "a", size);
5180 _endLazyDPSEvaluation ();
5183 adjustArithmeticResult (ic);
5186 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5187 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5188 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5192 /*-----------------------------------------------------------------*/
5193 /* genMultbits :- multiplication of bits */
5194 /*-----------------------------------------------------------------*/
5196 genMultbits (operand * left,
5201 D (emitcode (";", "genMultbits"));
5203 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5204 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5205 aopOp(result, ic, TRUE, FALSE);
5209 /*-----------------------------------------------------------------*/
5210 /* genMultOneByte : 8*8=8/16 bit multiplication */
5211 /*-----------------------------------------------------------------*/
5213 genMultOneByte (operand * left,
5220 bool runtimeSign, compiletimeSign;
5221 bool lUnsigned, rUnsigned, pushedB;
5223 /* (if two literals: the value is computed before) */
5224 /* if one literal, literal on the right */
5225 if (AOP_TYPE (left) == AOP_LIT)
5230 /* emitcode (";", "swapped left and right"); */
5232 /* if no literal, unsigned on the right: shorter code */
5233 if ( AOP_TYPE (right) != AOP_LIT
5234 && SPEC_USIGN (getSpec (operandType (left))))
5241 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5242 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5246 if ((lUnsigned && rUnsigned)
5247 /* sorry, I don't know how to get size
5248 without calling aopOp (result,...);
5249 see Feature Request */
5250 /* || size == 1 */ ) /* no, this is not a bug; with a 1 byte result there's
5251 no need to take care about the signedness! */
5253 /* just an unsigned 8 * 8 = 8 multiply
5255 /* emitcode (";","unsigned"); */
5256 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
5257 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
5258 emitcode ("mul", "ab");
5261 aopOp (result, ic, TRUE, FALSE);
5262 size = AOP_SIZE (result);
5264 if (size < 1 || size > 2)
5266 /* this should never happen */
5267 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
5268 size, __FILE__, lineno);
5272 aopPut (result, "a", 0);
5275 aopPut (result, "b", 1);
5281 /* we have to do a signed multiply */
5282 /* emitcode (";", "signed"); */
5284 /* now sign adjust for both left & right */
5286 /* let's see what's needed: */
5287 /* apply negative sign during runtime */
5288 runtimeSign = FALSE;
5289 /* negative sign from literals */
5290 compiletimeSign = FALSE;
5294 if (AOP_TYPE(left) == AOP_LIT)
5296 /* signed literal */
5297 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5299 compiletimeSign = TRUE;
5302 /* signed but not literal */
5308 if (AOP_TYPE(right) == AOP_LIT)
5310 /* signed literal */
5311 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5313 compiletimeSign ^= TRUE;
5316 /* signed but not literal */
5320 /* initialize F0, which stores the runtime sign */
5323 if (compiletimeSign)
5324 emitcode ("setb", "F0"); /* set sign flag */
5326 emitcode ("clr", "F0"); /* reset sign flag */
5329 /* save the signs of the operands */
5330 if (AOP_TYPE(right) == AOP_LIT)
5332 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5334 if (!rUnsigned && val < 0)
5335 emitcode ("mov", "b,#!constbyte", -val);
5337 emitcode ("mov", "b,#!constbyte", (unsigned char) val);
5339 else /* ! literal */
5341 if (rUnsigned) /* emitcode (";", "signed"); */
5342 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
5345 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
5346 lbl = newiTempLabel (NULL);
5347 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5348 emitcode ("cpl", "F0"); /* complement sign flag */
5349 emitcode ("cpl", "a"); /* 2's complement */
5350 emitcode ("inc", "a");
5352 emitcode ("mov", "b,a");
5356 if (AOP_TYPE(left) == AOP_LIT)
5358 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5360 if (!lUnsigned && val < 0)
5361 emitcode ("mov", "a,#!constbyte", -val);
5363 emitcode ("mov", "a,#!constbyte", (unsigned char) val);
5365 else /* ! literal */
5367 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
5369 if (!lUnsigned) /* emitcode (";", "signed"); */
5371 lbl = newiTempLabel (NULL);
5372 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5373 emitcode ("cpl", "F0"); /* complement sign flag */
5374 emitcode ("cpl", "a"); /* 2's complement */
5375 emitcode ("inc", "a");
5380 /* now the multiplication */
5381 emitcode ("mul", "ab");
5383 aopOp(result, ic, TRUE, FALSE);
5384 size = AOP_SIZE (result);
5386 if (size < 1 || size > 2)
5388 /* this should never happen */
5389 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
5390 size, __FILE__, lineno);
5394 if (runtimeSign || compiletimeSign)
5396 lbl = newiTempLabel (NULL);
5398 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5399 emitcode ("cpl", "a"); /* lsb 2's complement */
5401 emitcode ("inc", "a"); /* inc doesn't set carry flag */
5404 emitcode ("add", "a,#1"); /* this sets carry flag */
5405 emitcode ("xch", "a,b");
5406 emitcode ("cpl", "a"); /* msb 2's complement */
5407 emitcode ("addc", "a,#0");
5408 emitcode ("xch", "a,b");
5412 aopPut (result, "a", 0);
5415 aopPut (result, "b", 1);
5420 /*-----------------------------------------------------------------*/
5421 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
5422 /*-----------------------------------------------------------------*/
5423 static void genMultTwoByte (operand *left, operand *right,
5424 operand *result, iCode *ic)
5426 sym_link *retype = getSpec(operandType(right));
5427 sym_link *letype = getSpec(operandType(left));
5428 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5431 if (AOP_TYPE (left) == AOP_LIT) {
5436 /* save EA bit in F1 */
5437 lbl = newiTempLabel(NULL);
5438 emitcode ("setb","F1");
5439 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5440 emitcode ("clr","F1");
5443 /* load up MB with right */
5445 emitcode("clr","F0");
5446 if (AOP_TYPE(right) == AOP_LIT) {
5447 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5449 emitcode("setb","F0");
5452 emitcode ("mov","mb,#!constbyte",val & 0xff);
5453 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5455 lbl = newiTempLabel(NULL);
5456 emitcode ("mov","b,%s",aopGet(right,0,FALSE,FALSE,NULL));
5457 emitcode ("mov","a,%s",aopGet(right,1,FALSE,FALSE,NULL));
5458 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5459 emitcode ("xch", "a,b");
5460 emitcode ("cpl","a");
5461 emitcode ("add", "a,#1");
5462 emitcode ("xch", "a,b");
5463 emitcode ("cpl", "a"); // msb
5464 emitcode ("addc", "a,#0");
5465 emitcode ("setb","F0");
5467 emitcode ("mov","mb,b");
5468 emitcode ("mov","mb,a");
5471 emitcode ("mov","mb,%s",aopGet(right,0,FALSE,FALSE,NULL));
5472 emitcode ("mov","mb,%s",aopGet(right,1,FALSE,FALSE,NULL));
5474 /* load up MA with left */
5476 lbl = newiTempLabel(NULL);
5477 emitcode ("mov","b,%s",aopGet(left,0,FALSE,FALSE,NULL));
5478 emitcode ("mov","a,%s",aopGet(left,1,FALSE,FALSE,NULL));
5479 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5480 emitcode ("xch", "a,b");
5481 emitcode ("cpl","a");
5482 emitcode ("add", "a,#1");
5483 emitcode ("xch", "a,b");
5484 emitcode ("cpl", "a"); // msb
5485 emitcode ("addc","a,#0");
5486 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5487 emitcode ("setb","F0");
5489 emitcode ("mov","ma,b");
5490 emitcode ("mov","ma,a");
5492 emitcode ("mov","ma,%s",aopGet(left,0,FALSE,FALSE,NULL));
5493 emitcode ("mov","ma,%s",aopGet(left,1,FALSE,FALSE,NULL));
5495 /* wait for multiplication to finish */
5496 lbl = newiTempLabel(NULL);
5498 emitcode("mov","a,mcnt1");
5499 emitcode("anl","a,#!constbyte",0x80);
5500 emitcode("jnz","!tlabel",lbl->key+100);
5502 freeAsmop (left, NULL, ic, TRUE);
5503 freeAsmop (right, NULL, ic,TRUE);
5504 aopOp(result, ic, TRUE, FALSE);
5506 /* if unsigned then simple */
5508 emitcode ("mov","a,ma");
5509 if (AOP_SIZE(result) >= 4) aopPut(result,"a",3);
5510 emitcode ("mov","a,ma");
5511 if (AOP_SIZE(result) >= 3) aopPut(result,"a",2);
5512 aopPut(result,"ma",1);
5513 aopPut(result,"ma",0);
5515 emitcode("push","ma");
5516 emitcode("push","ma");
5517 emitcode("push","ma");
5519 /* negate result if needed */
5520 lbl = newiTempLabel(NULL);
5521 emitcode("jnb","F0,!tlabel",lbl->key+100);
5522 emitcode("cpl","a");
5523 emitcode("add","a,#1");
5525 if (AOP_TYPE(result) == AOP_ACC)
5527 D (emitcode(";", "ACC special case."));
5528 /* We know result is the only live aop, and
5529 * it's obviously not a DPTR2, so AP is available.
5531 emitcode("mov", "%s,acc", DP2_RESULT_REG);
5535 aopPut(result,"a",0);
5538 emitcode("pop","acc");
5539 lbl = newiTempLabel(NULL);
5540 emitcode("jnb","F0,!tlabel",lbl->key+100);
5541 emitcode("cpl","a");
5542 emitcode("addc","a,#0");
5544 aopPut(result,"a",1);
5545 emitcode("pop","acc");
5546 if (AOP_SIZE(result) >= 3) {
5547 lbl = newiTempLabel(NULL);
5548 emitcode("jnb","F0,!tlabel",lbl->key+100);
5549 emitcode("cpl","a");
5550 emitcode("addc","a,#0");
5552 aopPut(result,"a",2);
5554 emitcode("pop","acc");
5555 if (AOP_SIZE(result) >= 4) {
5556 lbl = newiTempLabel(NULL);
5557 emitcode("jnb","F0,!tlabel",lbl->key+100);
5558 emitcode("cpl","a");
5559 emitcode("addc","a,#0");
5561 aopPut(result,"a",3);
5563 if (AOP_TYPE(result) == AOP_ACC)
5565 /* We stashed the result away above. */
5566 emitcode("mov", "acc,%s", DP2_RESULT_REG);
5570 freeAsmop (result, NULL, ic, TRUE);
5572 /* restore EA bit in F1 */
5573 lbl = newiTempLabel(NULL);
5574 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5575 emitcode ("setb","EA");
5580 /*-----------------------------------------------------------------*/
5581 /* genMult - generates code for multiplication */
5582 /*-----------------------------------------------------------------*/
5584 genMult (iCode * ic)
5586 operand *left = IC_LEFT (ic);
5587 operand *right = IC_RIGHT (ic);
5588 operand *result = IC_RESULT (ic);
5590 D (emitcode (";", "genMult"));
5592 /* assign the asmops */
5595 /* special cases first */
5597 if (AOP_TYPE (left) == AOP_CRY &&
5598 AOP_TYPE (right) == AOP_CRY)
5600 genMultbits (left, right, result, ic);
5604 /* if both are of size == 1 */
5605 if (AOP_SIZE (left) == 1 &&
5606 AOP_SIZE (right) == 1)
5608 genMultOneByte (left, right, result, ic);
5612 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5613 /* use the ds390 ARITHMETIC accel UNIT */
5614 genMultTwoByte (left, right, result, ic);
5617 /* should have been converted to function call */
5621 freeAsmop (result, NULL, ic, TRUE);
5622 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5623 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5626 /*-----------------------------------------------------------------*/
5627 /* genDivbits :- division of bits */
5628 /*-----------------------------------------------------------------*/
5630 genDivbits (operand * left,
5638 D(emitcode ("; genDivbits",""));
5642 /* the result must be bit */
5643 LOAD_AB_FOR_DIV (left, right, l);
5644 emitcode ("div", "ab");
5645 emitcode ("rrc", "a");
5646 aopOp(result, ic, TRUE, FALSE);
5650 aopPut (result, "c", 0);
5653 /*-----------------------------------------------------------------*/
5654 /* genDivOneByte : 8 bit division */
5655 /*-----------------------------------------------------------------*/
5657 genDivOneByte (operand * left,
5662 bool lUnsigned, rUnsigned, pushedB;
5663 bool runtimeSign, compiletimeSign;
5668 D(emitcode ("; genDivOneByte",""));
5671 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5672 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5676 /* signed or unsigned */
5677 if (lUnsigned && rUnsigned)
5679 /* unsigned is easy */
5680 LOAD_AB_FOR_DIV (left, right, l);
5681 emitcode ("div", "ab");
5684 aopOp (result, ic, TRUE, FALSE);
5685 aopPut (result, "a", 0);
5688 size = AOP_SIZE (result) - 1;
5691 aopPut (result, zero, offset++);
5697 /* signed is a little bit more difficult */
5699 /* now sign adjust for both left & right */
5701 /* let's see what's needed: */
5702 /* apply negative sign during runtime */
5703 runtimeSign = FALSE;
5704 /* negative sign from literals */
5705 compiletimeSign = FALSE;
5709 if (AOP_TYPE(left) == AOP_LIT)
5711 /* signed literal */
5712 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5714 compiletimeSign = TRUE;
5717 /* signed but not literal */
5723 if (AOP_TYPE(right) == AOP_LIT)
5725 /* signed literal */
5726 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5728 compiletimeSign ^= TRUE;
5731 /* signed but not literal */
5735 /* initialize F0, which stores the runtime sign */
5738 if (compiletimeSign)
5739 emitcode ("setb", "F0"); /* set sign flag */
5741 emitcode ("clr", "F0"); /* reset sign flag */
5744 /* save the signs of the operands */
5745 if (AOP_TYPE(right) == AOP_LIT)
5747 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5749 if (!rUnsigned && val < 0)
5750 emitcode ("mov", "b,#0x%02x", -val);
5752 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5754 else /* ! literal */
5757 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
5760 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
5761 lbl = newiTempLabel (NULL);
5762 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5763 emitcode ("cpl", "F0"); /* complement sign flag */
5764 emitcode ("cpl", "a"); /* 2's complement */
5765 emitcode ("inc", "a");
5767 emitcode ("mov", "b,a");
5771 if (AOP_TYPE(left) == AOP_LIT)
5773 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5775 if (!lUnsigned && val < 0)
5776 emitcode ("mov", "a,#0x%02x", -val);
5778 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5780 else /* ! literal */
5782 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
5786 lbl = newiTempLabel (NULL);
5787 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5788 emitcode ("cpl", "F0"); /* complement sign flag */
5789 emitcode ("cpl", "a"); /* 2's complement */
5790 emitcode ("inc", "a");
5795 /* now the division */
5796 emitcode ("nop", "; workaround for DS80C390 div bug.");
5797 emitcode ("div", "ab");
5799 if (runtimeSign || compiletimeSign)
5801 lbl = newiTempLabel (NULL);
5803 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5804 emitcode ("cpl", "a"); /* lsb 2's complement */
5805 emitcode ("inc", "a");
5809 aopOp (result, ic, TRUE, FALSE);
5810 size = AOP_SIZE (result) - 1;
5814 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5815 then the result will be in b, a */
5816 emitcode ("mov", "b,a"); /* 1 */
5817 /* msb is 0x00 or 0xff depending on the sign */
5820 emitcode ("mov", "c,F0");
5821 emitcode ("subb", "a,acc");
5822 emitcode ("xch", "a,b"); /* 2 */
5824 aopPut (result, "b", offset++); /* write msb's */
5826 else /* compiletimeSign */
5828 aopPut (result, "#0xff", offset++); /* write msb's */
5830 aopPut (result, "a", 0); /* 3: write lsb */
5835 aopOp(result, ic, TRUE, FALSE);
5836 size = AOP_SIZE (result) - 1;
5838 aopPut (result, "a", 0);
5840 aopPut (result, zero, offset++);
5846 /*-----------------------------------------------------------------*/
5847 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
5848 /*-----------------------------------------------------------------*/
5849 static void genDivTwoByte (operand *left, operand *right,
5850 operand *result, iCode *ic)
5852 sym_link *retype = getSpec(operandType(right));
5853 sym_link *letype = getSpec(operandType(left));
5854 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5857 /* save EA bit in F1 */
5858 lbl = newiTempLabel(NULL);
5859 emitcode ("setb","F1");
5860 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5861 emitcode ("clr","F1");
5864 /* load up MA with left */
5866 emitcode("clr","F0");
5867 lbl = newiTempLabel(NULL);
5868 emitcode ("mov","b,%s",aopGet(left,0,FALSE,FALSE,NULL));
5869 emitcode ("mov","a,%s",aopGet(left,1,FALSE,FALSE,NULL));
5870 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5871 emitcode ("xch", "a,b");
5872 emitcode ("cpl","a");
5873 emitcode ("add", "a,#1");
5874 emitcode ("xch", "a,b");
5875 emitcode ("cpl", "a"); // msb
5876 emitcode ("addc","a,#0");
5877 emitcode ("setb","F0");
5879 emitcode ("mov","ma,b");
5880 emitcode ("mov","ma,a");
5882 emitcode ("mov","ma,%s",aopGet(left,0,FALSE,FALSE,NULL));
5883 emitcode ("mov","ma,%s",aopGet(left,1,FALSE,FALSE,NULL));
5886 /* load up MB with right */
5888 if (AOP_TYPE(right) == AOP_LIT) {
5889 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5891 lbl = newiTempLabel(NULL);
5892 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5893 emitcode("setb","F0");
5897 emitcode ("mov","mb,#!constbyte",val & 0xff);
5898 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5900 lbl = newiTempLabel(NULL);
5901 emitcode ("mov","b,%s",aopGet(right,0,FALSE,FALSE,NULL));
5902 emitcode ("mov","a,%s",aopGet(right,1,FALSE,FALSE,NULL));
5903 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5904 emitcode ("xch", "a,b");
5905 emitcode ("cpl","a");
5906 emitcode ("add", "a,#1");
5907 emitcode ("xch", "a,b");
5908 emitcode ("cpl", "a"); // msb
5909 emitcode ("addc", "a,#0");
5910 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5911 emitcode ("setb","F0");
5913 emitcode ("mov","mb,b");
5914 emitcode ("mov","mb,a");
5917 emitcode ("mov","mb,%s",aopGet(right,0,FALSE,FALSE,NULL));
5918 emitcode ("mov","mb,%s",aopGet(right,1,FALSE,FALSE,NULL));
5921 /* wait for multiplication to finish */
5922 lbl = newiTempLabel(NULL);
5924 emitcode("mov","a,mcnt1");
5925 emitcode("anl","a,#!constbyte",0x80);
5926 emitcode("jnz","!tlabel",lbl->key+100);
5928 freeAsmop (left, NULL, ic, TRUE);
5929 freeAsmop (right, NULL, ic,TRUE);
5930 aopOp(result, ic, TRUE, FALSE);
5932 /* if unsigned then simple */
5934 aopPut(result,"ma",1);
5935 aopPut(result,"ma",0);
5937 emitcode("push","ma");
5939 /* negate result if needed */
5940 lbl = newiTempLabel(NULL);
5941 emitcode("jnb","F0,!tlabel",lbl->key+100);
5942 emitcode("cpl","a");
5943 emitcode("add","a,#1");
5945 aopPut(result,"a",0);
5946 emitcode("pop","acc");
5947 lbl = newiTempLabel(NULL);
5948 emitcode("jnb","F0,!tlabel",lbl->key+100);
5949 emitcode("cpl","a");
5950 emitcode("addc","a,#0");
5952 aopPut(result,"a",1);
5954 freeAsmop (result, NULL, ic, TRUE);
5955 /* restore EA bit in F1 */
5956 lbl = newiTempLabel(NULL);
5957 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5958 emitcode ("setb","EA");
5963 /*-----------------------------------------------------------------*/
5964 /* genDiv - generates code for division */
5965 /*-----------------------------------------------------------------*/
5969 operand *left = IC_LEFT (ic);
5970 operand *right = IC_RIGHT (ic);
5971 operand *result = IC_RESULT (ic);
5973 D (emitcode (";", "genDiv"));
5975 /* assign the amsops */
5978 /* special cases first */
5980 if (AOP_TYPE (left) == AOP_CRY &&
5981 AOP_TYPE (right) == AOP_CRY)
5983 genDivbits (left, right, result, ic);
5987 /* if both are of size == 1 */
5988 if (AOP_SIZE (left) == 1 &&
5989 AOP_SIZE (right) == 1)
5991 genDivOneByte (left, right, result, ic);
5995 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5996 /* use the ds390 ARITHMETIC accel UNIT */
5997 genDivTwoByte (left, right, result, ic);
6000 /* should have been converted to function call */
6003 freeAsmop (result, NULL, ic, TRUE);
6004 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6005 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6008 /*-----------------------------------------------------------------*/
6009 /* genModbits :- modulus of bits */
6010 /*-----------------------------------------------------------------*/
6012 genModbits (operand * left,
6020 D (emitcode (";", "genModbits"));
6024 /* the result must be bit */
6025 LOAD_AB_FOR_DIV (left, right, l);
6026 emitcode ("div", "ab");
6027 emitcode ("mov", "a,b");
6028 emitcode ("rrc", "a");
6029 aopOp(result, ic, TRUE, FALSE);
6033 aopPut (result, "c", 0);
6036 /*-----------------------------------------------------------------*/
6037 /* genModOneByte : 8 bit modulus */
6038 /*-----------------------------------------------------------------*/
6040 genModOneByte (operand * left,
6045 bool lUnsigned, rUnsigned, pushedB;
6046 bool runtimeSign, compiletimeSign;
6051 D (emitcode (";", "genModOneByte"));
6054 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
6055 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
6059 /* signed or unsigned */
6060 if (lUnsigned && rUnsigned)
6062 /* unsigned is easy */
6063 LOAD_AB_FOR_DIV (left, right, l);
6064 emitcode ("div", "ab");
6065 aopOp (result, ic, TRUE, FALSE);
6066 aopPut (result, "b", 0);
6068 for (size = AOP_SIZE (result) - 1; size--;)
6069 aopPut (result, zero, offset++);
6075 /* signed is a little bit more difficult */
6077 /* now sign adjust for both left & right */
6079 /* modulus: sign of the right operand has no influence on the result! */
6080 if (AOP_TYPE(right) == AOP_LIT)
6082 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
6084 if (!rUnsigned && val < 0)
6085 emitcode ("mov", "b,#0x%02x", -val);
6087 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
6089 else /* not literal */
6092 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
6095 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
6096 lbl = newiTempLabel (NULL);
6097 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
6098 emitcode ("cpl", "a"); /* 2's complement */
6099 emitcode ("inc", "a");
6101 emitcode ("mov", "b,a");
6105 /* let's see what's needed: */
6106 /* apply negative sign during runtime */
6107 runtimeSign = FALSE;
6108 /* negative sign from literals */
6109 compiletimeSign = FALSE;
6111 /* sign adjust left side */
6112 if (AOP_TYPE(left) == AOP_LIT)
6114 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
6116 if (!lUnsigned && val < 0)
6118 compiletimeSign = TRUE; /* set sign flag */
6119 emitcode ("mov", "a,#0x%02x", -val);
6122 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
6124 else /* ! literal */
6126 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
6131 emitcode ("clr", "F0"); /* clear sign flag */
6133 lbl = newiTempLabel (NULL);
6134 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
6135 emitcode ("setb", "F0"); /* set sign flag */
6136 emitcode ("cpl", "a"); /* 2's complement */
6137 emitcode ("inc", "a");
6142 /* now the modulus */
6143 emitcode ("nop", "; workaround for DS80C390 div bug.");
6144 emitcode ("div", "ab");
6146 if (runtimeSign || compiletimeSign)
6148 emitcode ("mov", "a,b");
6149 lbl = newiTempLabel (NULL);
6151 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
6152 emitcode ("cpl", "a"); /* lsb 2's complement */
6153 emitcode ("inc", "a");
6157 aopOp (result, ic, TRUE, FALSE);
6158 size = AOP_SIZE (result) - 1;
6162 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
6163 then the result will be in b, a */
6164 emitcode ("mov", "b,a"); /* 1 */
6165 /* msb is 0x00 or 0xff depending on the sign */
6168 emitcode ("mov", "c,F0");
6169 emitcode ("subb", "a,acc");
6170 emitcode ("xch", "a,b"); /* 2 */
6172 aopPut (result, "b", offset++); /* write msb's */
6174 else /* compiletimeSign */
6176 aopPut (result, "#0xff", offset++); /* write msb's */
6178 aopPut (result, "a", 0); /* 3: write lsb */
6183 aopOp(result, ic, TRUE, FALSE);
6184 size = AOP_SIZE (result) - 1;
6186 aopPut (result, "b", 0);
6188 aopPut (result, zero, offset++);
6194 /*-----------------------------------------------------------------*/
6195 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
6196 /*-----------------------------------------------------------------*/
6197 static void genModTwoByte (operand *left, operand *right,
6198 operand *result, iCode *ic)
6200 sym_link *retype = getSpec(operandType(right));
6201 sym_link *letype = getSpec(operandType(left));
6202 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
6205 /* load up MA with left */
6206 /* save EA bit in F1 */
6207 lbl = newiTempLabel(NULL);
6208 emitcode ("setb","F1");
6209 emitcode ("jbc","EA,!tlabel",lbl->key+100);
6210 emitcode ("clr","F1");
6214 lbl = newiTempLabel(NULL);
6215 emitcode ("mov","b,%s",aopGet(left,0,FALSE,FALSE,NULL));
6216 emitcode ("mov","a,%s",aopGet(left,1,FALSE,FALSE,NULL));
6217 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
6218 emitcode ("xch", "a,b");
6219 emitcode ("cpl","a");
6220 emitcode ("add", "a,#1");
6221 emitcode ("xch", "a,b");
6222 emitcode ("cpl", "a"); // msb
6223 emitcode ("addc","a,#0");
6225 emitcode ("mov","ma,b");
6226 emitcode ("mov","ma,a");
6228 emitcode ("mov","ma,%s",aopGet(left,0,FALSE,FALSE,NULL));
6229 emitcode ("mov","ma,%s",aopGet(left,1,FALSE,FALSE,NULL));
6232 /* load up MB with right */
6234 if (AOP_TYPE(right) == AOP_LIT) {
6235 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
6239 emitcode ("mov","mb,#!constbyte",val & 0xff);
6240 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
6242 lbl = newiTempLabel(NULL);
6243 emitcode ("mov","b,%s",aopGet(right,0,FALSE,FALSE,NULL));
6244 emitcode ("mov","a,%s",aopGet(right,1,FALSE,FALSE,NULL));
6245 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
6246 emitcode ("xch", "a,b");
6247 emitcode ("cpl","a");
6248 emitcode ("add", "a,#1");
6249 emitcode ("xch", "a,b");
6250 emitcode ("cpl", "a"); // msb
6251 emitcode ("addc", "a,#0");
6253 emitcode ("mov","mb,b");
6254 emitcode ("mov","mb,a");
6257 emitcode ("mov","mb,%s",aopGet(right,0,FALSE,FALSE,NULL));
6258 emitcode ("mov","mb,%s",aopGet(right,1,FALSE,FALSE,NULL));
6261 /* wait for multiplication to finish */
6262 lbl = newiTempLabel(NULL);
6264 emitcode("mov","a,mcnt1");
6265 emitcode("anl","a,#!constbyte",0x80);
6266 emitcode("jnz","!tlabel",lbl->key+100);
6268 freeAsmop (left, NULL, ic, TRUE);
6269 freeAsmop (right, NULL, ic,TRUE);
6270 aopOp(result, ic, TRUE, FALSE);
6272 aopPut(result,"mb",1);
6273 aopPut(result,"mb",0);
6274 freeAsmop (result, NULL, ic, TRUE);
6276 /* restore EA bit in F1 */
6277 lbl = newiTempLabel(NULL);
6278 emitcode ("jnb","F1,!tlabel",lbl->key+100);
6279 emitcode ("setb","EA");
6283 /*-----------------------------------------------------------------*/
6284 /* genMod - generates code for division */
6285 /*-----------------------------------------------------------------*/
6289 operand *left = IC_LEFT (ic);
6290 operand *right = IC_RIGHT (ic);
6291 operand *result = IC_RESULT (ic);
6293 D (emitcode (";", "genMod"));
6295 /* assign the asmops */
6298 /* special cases first */
6300 if (AOP_TYPE (left) == AOP_CRY &&
6301 AOP_TYPE (right) == AOP_CRY)
6303 genModbits (left, right, result, ic);
6307 /* if both are of size == 1 */
6308 if (AOP_SIZE (left) == 1 &&
6309 AOP_SIZE (right) == 1)
6311 genModOneByte (left, right, result, ic);
6315 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
6316 /* use the ds390 ARITHMETIC accel UNIT */
6317 genModTwoByte (left, right, result, ic);
6321 /* should have been converted to function call */
6325 freeAsmop (result, NULL, ic, TRUE);
6326 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6327 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6330 /*-----------------------------------------------------------------*/
6331 /* genIfxJump :- will create a jump depending on the ifx */
6332 /*-----------------------------------------------------------------*/
6334 genIfxJump (iCode * ic, char *jval)
6337 symbol *tlbl = newiTempLabel (NULL);
6340 D (emitcode (";", "genIfxJump"));
6342 /* if true label then we jump if condition
6346 jlbl = IC_TRUE (ic);
6347 inst = ((strcmp (jval, "a") == 0 ? "jz" :
6348 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
6352 /* false label is present */
6353 jlbl = IC_FALSE (ic);
6354 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
6355 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
6357 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
6358 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
6360 emitcode (inst, "!tlabel", tlbl->key + 100);
6361 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
6364 /* mark the icode as generated */
6368 /*-----------------------------------------------------------------*/
6369 /* genCmp :- greater or less than comparison */
6370 /*-----------------------------------------------------------------*/
6372 genCmp (operand * left, operand * right,
6373 iCode * ic, iCode * ifx, int sign)
6375 int size, offset = 0;
6376 unsigned long lit = 0L;
6379 D (emitcode (";", "genCmp"));
6381 result = IC_RESULT (ic);
6383 /* if left & right are bit variables */
6384 if (AOP_TYPE (left) == AOP_CRY &&
6385 AOP_TYPE (right) == AOP_CRY)
6387 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6388 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6392 /* subtract right from left if at the
6393 end the carry flag is set then we know that
6394 left is greater than right */
6395 size = max (AOP_SIZE (left), AOP_SIZE (right));
6397 /* if unsigned char cmp with lit, do cjne left,#right,zz */
6398 if ((size == 1) && !sign &&
6399 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
6401 symbol *lbl = newiTempLabel (NULL);
6402 emitcode ("cjne", "%s,%s,!tlabel",
6403 aopGet (left, offset, FALSE, FALSE, NULL),
6404 aopGet (right, offset, FALSE, FALSE, NULL),
6410 if (AOP_TYPE (right) == AOP_LIT)
6412 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6413 /* optimize if(x < 0) or if(x >= 0) */
6422 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
6424 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6425 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6427 aopOp (result, ic, FALSE, FALSE);
6429 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
6431 freeAsmop (result, NULL, ic, TRUE);
6432 genIfxJump (ifx, "acc.7");
6437 emitcode ("rlc", "a");
6439 goto release_freedLR;
6447 // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
6448 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
6449 // emitcode (";", "genCmp #2");
6450 if (sign && (size == 0))
6452 // emitcode (";", "genCmp #3");
6453 emitcode ("xrl", "a,#!constbyte",0x80);
6454 if (AOP_TYPE (right) == AOP_LIT)
6456 unsigned long lit = (unsigned long)
6457 floatFromVal (AOP (right)->aopu.aop_lit);
6458 // emitcode (";", "genCmp #3.1");
6459 emitcode ("subb", "a,#!constbyte",
6460 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
6464 // emitcode (";", "genCmp #3.2");
6466 MOVB (aopGet (right, offset++, FALSE, FALSE, "b"));
6467 saveAccWarn = DEFAULT_ACC_WARNING;
6468 emitcode ("xrl", "b,#!constbyte",0x80);
6469 emitcode ("subb", "a,b");
6476 // emitcode (";", "genCmp #4");
6478 s = aopGet (right, offset++, FALSE, FALSE, "b");
6479 saveAccWarn = DEFAULT_ACC_WARNING;
6481 emitcode ("subb", "a,%s", s);
6488 /* Don't need the left & right operands any more; do need the result. */
6489 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6490 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6492 aopOp (result, ic, FALSE, FALSE);
6496 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6502 /* if the result is used in the next
6503 ifx conditional branch then generate
6504 code a little differently */
6507 genIfxJump (ifx, "c");
6513 /* leave the result in acc */
6515 freeAsmop (result, NULL, ic, TRUE);
6518 /*-----------------------------------------------------------------*/
6519 /* genCmpGt :- greater than comparison */
6520 /*-----------------------------------------------------------------*/
6522 genCmpGt (iCode * ic, iCode * ifx)
6524 operand *left, *right;
6525 sym_link *letype, *retype;
6528 D (emitcode (";", "genCmpGt"));
6530 left = IC_LEFT (ic);
6531 right = IC_RIGHT (ic);
6533 letype = getSpec (operandType (left));
6534 retype = getSpec (operandType (right));
6535 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6537 /* assign the left & right amsops */
6540 genCmp (right, left, ic, ifx, sign);
6543 /*-----------------------------------------------------------------*/
6544 /* genCmpLt - less than comparisons */
6545 /*-----------------------------------------------------------------*/
6547 genCmpLt (iCode * ic, iCode * ifx)
6549 operand *left, *right;
6550 sym_link *letype, *retype;
6553 D (emitcode (";", "genCmpLt"));
6555 left = IC_LEFT (ic);
6556 right = IC_RIGHT (ic);
6558 letype = getSpec (operandType (left));
6559 retype = getSpec (operandType (right));
6560 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6562 /* assign the left & right amsops */
6565 genCmp (left, right, ic, ifx, sign);
6568 /*-----------------------------------------------------------------*/
6569 /* gencjneshort - compare and jump if not equal */
6570 /*-----------------------------------------------------------------*/
6572 gencjneshort (operand * left, operand * right, symbol * lbl)
6574 int size = max (AOP_SIZE (left), AOP_SIZE (right));
6576 unsigned long lit = 0L;
6578 D (emitcode (";", "gencjneshort"));
6580 /* if the left side is a literal or
6581 if the right is in a pointer register and left
6583 if ((AOP_TYPE (left) == AOP_LIT) ||
6584 (AOP_TYPE (left) == AOP_IMMD) ||
6585 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6592 if (AOP_TYPE (right) == AOP_LIT)
6593 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6595 if (opIsGptr (left) || opIsGptr (right))
6597 /* We are comparing a generic pointer to something.
6598 * Exclude the generic type byte from the comparison.
6601 D (emitcode (";", "cjneshort: generic ptr special case."););
6605 /* if the right side is a literal then anything goes */
6606 if (AOP_TYPE (right) == AOP_LIT &&
6607 AOP_TYPE (left) != AOP_DIR)
6611 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
6612 emitcode ("cjne", "a,%s,!tlabel",
6613 aopGet (right, offset, FALSE, FALSE, NULL),
6619 /* if the right side is in a register or in direct space or
6620 if the left is a pointer register & right is not */
6621 else if (AOP_TYPE (right) == AOP_REG ||
6622 AOP_TYPE (right) == AOP_DIR ||
6623 AOP_TYPE (right) == AOP_LIT ||
6624 AOP_TYPE (right) == AOP_IMMD ||
6625 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6626 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6630 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
6631 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6632 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6633 emitcode ("jnz", "!tlabel", lbl->key + 100);
6635 emitcode ("cjne", "a,%s,!tlabel",
6636 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG),
6643 /* right is a pointer reg need both a & b */
6646 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
6647 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
6648 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
6654 /*-----------------------------------------------------------------*/
6655 /* gencjne - compare and jump if not equal */
6656 /*-----------------------------------------------------------------*/
6658 gencjne (operand * left, operand * right, symbol * lbl)
6660 symbol *tlbl = newiTempLabel (NULL);
6662 D (emitcode (";", "gencjne"));
6664 gencjneshort (left, right, lbl);
6666 emitcode ("mov", "a,%s", one);
6667 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
6669 emitcode ("clr", "a");
6673 /*-----------------------------------------------------------------*/
6674 /* genCmpEq - generates code for equal to */
6675 /*-----------------------------------------------------------------*/
6677 genCmpEq (iCode * ic, iCode * ifx)
6679 operand *left, *right, *result;
6681 D (emitcode (";", "genCmpEq"));
6684 AOP_SET_LOCALS (ic);
6686 /* if literal, literal on the right or
6687 if the right is in a pointer register and left
6689 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6690 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6692 operand *t = IC_RIGHT (ic);
6693 IC_RIGHT (ic) = IC_LEFT (ic);
6697 if (ifx && /* !AOP_SIZE(result) */
6698 OP_SYMBOL (result) &&
6699 OP_SYMBOL (result)->regType == REG_CND)
6702 /* if they are both bit variables */
6703 if (AOP_TYPE (left) == AOP_CRY &&
6704 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6706 if (AOP_TYPE (right) == AOP_LIT)
6708 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6711 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6712 emitcode ("cpl", "c");
6716 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6720 emitcode ("clr", "c");
6722 /* AOP_TYPE(right) == AOP_CRY */
6726 symbol *lbl = newiTempLabel (NULL);
6727 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6728 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6729 emitcode ("cpl", "c");
6732 /* if true label then we jump if condition
6734 tlbl = newiTempLabel (NULL);
6737 emitcode ("jnc", "!tlabel", tlbl->key + 100);
6738 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6742 emitcode ("jc", "!tlabel", tlbl->key + 100);
6743 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6749 tlbl = newiTempLabel (NULL);
6750 gencjneshort (left, right, tlbl);
6753 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6758 symbol *lbl = newiTempLabel (NULL);
6759 emitcode ("sjmp", "!tlabel", lbl->key + 100);
6761 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6765 /* mark the icode as generated */
6768 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6769 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6773 /* if they are both bit variables */
6774 if (AOP_TYPE (left) == AOP_CRY &&
6775 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6777 if (AOP_TYPE (right) == AOP_LIT)
6779 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6782 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6783 emitcode ("cpl", "c");
6787 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6791 emitcode ("clr", "c");
6793 /* AOP_TYPE(right) == AOP_CRY */
6797 symbol *lbl = newiTempLabel (NULL);
6798 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6799 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6800 emitcode ("cpl", "c");
6804 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6805 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6807 aopOp (result, ic, TRUE, FALSE);
6810 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6817 genIfxJump (ifx, "c");
6820 /* if the result is used in an arithmetic operation
6821 then put the result in place */
6826 gencjne (left, right, newiTempLabel (NULL));
6828 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6829 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6831 aopOp (result, ic, TRUE, FALSE);
6833 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6835 aopPut (result, "a", 0);
6840 genIfxJump (ifx, "a");
6843 /* if the result is used in an arithmetic operation
6844 then put the result in place */
6845 if (AOP_TYPE (result) != AOP_CRY)
6847 /* leave the result in acc */
6851 freeAsmop (result, NULL, ic, TRUE);
6854 /*-----------------------------------------------------------------*/
6855 /* ifxForOp - returns the icode containing the ifx for operand */
6856 /*-----------------------------------------------------------------*/
6858 ifxForOp (operand * op, iCode * ic)
6860 /* if true symbol then needs to be assigned */
6861 if (IS_TRUE_SYMOP (op))
6864 /* if this has register type condition and
6865 the next instruction is ifx with the same operand
6866 and live to of the operand is upto the ifx only then */
6868 ic->next->op == IFX &&
6869 IC_COND (ic->next)->key == op->key &&
6870 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6876 /*-----------------------------------------------------------------*/
6877 /* hasInc - operand is incremented before any other use */
6878 /*-----------------------------------------------------------------*/
6880 hasInc (operand *op, iCode *ic, int osize)
6882 sym_link *type = operandType(op);
6883 sym_link *retype = getSpec (type);
6884 iCode *lic = ic->next;
6887 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6888 if (!IS_SYMOP(op)) return NULL;
6890 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6891 if (IS_AGGREGATE(type->next)) return NULL;
6892 if (osize != (isize = getSize(type->next))) return NULL;
6895 /* if operand of the form op = op + <sizeof *op> */
6896 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6897 isOperandEqual(IC_RESULT(lic),op) &&
6898 isOperandLiteral(IC_RIGHT(lic)) &&
6899 operandLitValue(IC_RIGHT(lic)) == isize) {
6902 /* if the operand used or deffed */
6903 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6906 /* if GOTO or IFX */
6907 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6913 /*-----------------------------------------------------------------*/
6914 /* genAndOp - for && operation */
6915 /*-----------------------------------------------------------------*/
6917 genAndOp (iCode * ic)
6919 operand *left, *right, *result;
6922 D (emitcode (";", "genAndOp"));
6924 /* note here that && operations that are in an
6925 if statement are taken away by backPatchLabels
6926 only those used in arthmetic operations remain */
6928 AOP_SET_LOCALS (ic);
6930 /* if both are bit variables */
6931 if (AOP_TYPE (left) == AOP_CRY &&
6932 AOP_TYPE (right) == AOP_CRY)
6934 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6935 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6936 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6937 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6939 aopOp (result,ic,FALSE, FALSE);
6944 tlbl = newiTempLabel (NULL);
6946 emitcode ("jz", "!tlabel", tlbl->key + 100);
6949 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6950 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6952 aopOp (result,ic,FALSE, FALSE);
6956 freeAsmop (result, NULL, ic, TRUE);
6960 /*-----------------------------------------------------------------*/
6961 /* genOrOp - for || operation */
6962 /*-----------------------------------------------------------------*/
6964 genOrOp (iCode * ic)
6966 operand *left, *right, *result;
6969 D (emitcode (";", "genOrOp"));
6971 /* note here that || operations that are in an
6972 if statement are taken away by backPatchLabels
6973 only those used in arthmetic operations remain */
6975 AOP_SET_LOCALS (ic);
6977 /* if both are bit variables */
6978 if (AOP_TYPE (left) == AOP_CRY &&
6979 AOP_TYPE (right) == AOP_CRY)
6981 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6982 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6983 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6984 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6986 aopOp (result,ic,FALSE, FALSE);
6992 tlbl = newiTempLabel (NULL);
6994 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6997 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6998 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7000 aopOp (result,ic,FALSE, FALSE);
7005 freeAsmop (result, NULL, ic, TRUE);
7008 /*-----------------------------------------------------------------*/
7009 /* isLiteralBit - test if lit == 2^n */
7010 /*-----------------------------------------------------------------*/
7012 isLiteralBit (unsigned long lit)
7014 unsigned long pw[32] =
7015 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
7016 0x100L, 0x200L, 0x400L, 0x800L,
7017 0x1000L, 0x2000L, 0x4000L, 0x8000L,
7018 0x10000L, 0x20000L, 0x40000L, 0x80000L,
7019 0x100000L, 0x200000L, 0x400000L, 0x800000L,
7020 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
7021 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
7024 for (idx = 0; idx < 32; idx++)
7030 /*-----------------------------------------------------------------*/
7031 /* continueIfTrue - */
7032 /*-----------------------------------------------------------------*/
7034 continueIfTrue (iCode * ic)
7037 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
7041 /*-----------------------------------------------------------------*/
7043 /*-----------------------------------------------------------------*/
7045 jumpIfTrue (iCode * ic)
7048 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
7052 /*-----------------------------------------------------------------*/
7053 /* jmpTrueOrFalse - */
7054 /*-----------------------------------------------------------------*/
7056 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
7058 // ugly but optimized by peephole
7061 symbol *nlbl = newiTempLabel (NULL);
7062 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
7064 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
7069 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
7075 // Generate code to perform a bit-wise logic operation
7076 // on two operands in far space (assumed to already have been
7077 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
7078 // in far space. This requires pushing the result on the stack
7079 // then popping it into the result.
7081 genFarFarLogicOp(iCode *ic, char *logicOp)
7083 int size, resultSize, compSize;
7087 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
7088 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
7089 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
7091 _startLazyDPSEvaluation();
7092 for (size = compSize; (size--); offset++)
7094 MOVA (aopGet (IC_LEFT(ic), offset, FALSE, FALSE, NULL));
7095 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
7096 MOVA (aopGet (IC_RIGHT(ic), offset, FALSE, FALSE, NULL));
7098 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
7099 emitcode ("push", "acc");
7101 _endLazyDPSEvaluation();
7103 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7104 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7105 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
7107 resultSize = AOP_SIZE(IC_RESULT(ic));
7109 ADJUST_PUSHED_RESULT(compSize, resultSize);
7111 _startLazyDPSEvaluation();
7114 emitcode ("pop", "acc");
7115 aopPut (IC_RESULT (ic), "a", compSize);
7117 _endLazyDPSEvaluation();
7118 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
7122 /*-----------------------------------------------------------------*/
7123 /* genAnd - code for and */
7124 /*-----------------------------------------------------------------*/
7126 genAnd (iCode * ic, iCode * ifx)
7128 operand *left, *right, *result;
7129 int size, offset = 0;
7130 unsigned long lit = 0L;
7135 D (emitcode (";", "genAnd"));
7137 AOP_OP_3_NOFATAL (ic, pushResult);
7138 AOP_SET_LOCALS (ic);
7142 genFarFarLogicOp(ic, "anl");
7147 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7149 AOP_TYPE (left), AOP_TYPE (right));
7150 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7152 AOP_SIZE (left), AOP_SIZE (right));
7155 /* if left is a literal & right is not then exchange them */
7156 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7157 #ifdef LOGIC_OPS_BROKEN
7158 || AOP_NEEDSACC (left)
7162 operand *tmp = right;
7167 /* if result = right then exchange left and right */
7168 if (sameRegs (AOP (result), AOP (right)))
7170 operand *tmp = right;
7175 /* if right is bit then exchange them */
7176 if (AOP_TYPE (right) == AOP_CRY &&
7177 AOP_TYPE (left) != AOP_CRY)
7179 operand *tmp = right;
7183 if (AOP_TYPE (right) == AOP_LIT)
7184 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7186 size = AOP_SIZE (result);
7189 // result = bit & yy;
7190 if (AOP_TYPE (left) == AOP_CRY)
7192 // c = bit & literal;
7193 if (AOP_TYPE (right) == AOP_LIT)
7197 if (size && sameRegs (AOP (result), AOP (left)))
7200 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7205 if (size && (AOP_TYPE (result) == AOP_CRY))
7207 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
7210 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7215 emitcode ("clr", "c");
7220 if (AOP_TYPE (right) == AOP_CRY)
7223 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7224 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
7229 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
7231 emitcode ("rrc", "a");
7232 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
7240 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7241 genIfxJump (ifx, "c");
7245 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7246 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7247 if ((AOP_TYPE (right) == AOP_LIT) &&
7248 (AOP_TYPE (result) == AOP_CRY) &&
7249 (AOP_TYPE (left) != AOP_CRY))
7251 int posbit = isLiteralBit (lit);
7256 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE, NULL));
7260 switch (posbit & 0x07)
7262 case 0: emitcode ("rrc", "a");
7264 case 7: emitcode ("rlc", "a");
7266 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
7275 SNPRINTF (buffer, sizeof(buffer),
7276 "acc.%d", posbit & 0x07);
7277 genIfxJump (ifx, buffer);
7281 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
7288 symbol *tlbl = newiTempLabel (NULL);
7289 int sizel = AOP_SIZE (left);
7291 emitcode ("setb", "c");
7294 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
7296 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7298 if ((posbit = isLiteralBit (bytelit)) != 0)
7299 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
7302 if (bytelit != 0x0FFL)
7303 emitcode ("anl", "a,%s",
7304 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG));
7305 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7310 // bit = left & literal
7313 emitcode ("clr", "c");
7316 // if(left & literal)
7320 jmpTrueOrFalse (ifx, tlbl);
7330 /* if left is same as result */
7331 if (sameRegs (AOP (result), AOP (left)))
7333 for (; size--; offset++)
7335 if (AOP_TYPE (right) == AOP_LIT)
7337 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7338 if (bytelit == 0x0FF)
7340 /* dummy read of volatile operand */
7341 if (isOperandVolatile (left, FALSE))
7342 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7346 else if (bytelit == 0)
7348 aopPut (result, zero, offset);
7350 else if (IS_AOP_PREG (result))
7352 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7353 emitcode ("anl", "a,%s",
7354 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG));
7355 aopPut (result, "a", offset);
7358 emitcode ("anl", "%s,%s",
7359 aopGet (left, offset, FALSE, TRUE, NULL),
7360 aopGet (right, offset, FALSE, FALSE, NULL));
7364 if (AOP_TYPE (left) == AOP_ACC)
7367 emitcode("mov", "a,b");
7368 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7370 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7372 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
7373 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7374 emitcode ("anl", "a,b");
7375 aopPut (result, "a", offset);
7377 else if (aopGetUsesAcc (left, offset))
7379 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7380 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7381 aopPut (result, "a", offset);
7385 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7386 if (IS_AOP_PREG (result))
7388 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7389 aopPut (result, "a", offset);
7392 emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7399 // left & result in different registers
7400 if (AOP_TYPE (result) == AOP_CRY)
7403 // if(size), result in bit
7404 // if(!size && ifx), conditional oper: if(left & right)
7405 symbol *tlbl = newiTempLabel (NULL);
7406 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
7408 emitcode ("setb", "c");
7411 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7412 && AOP_TYPE(left)==AOP_ACC)
7415 emitcode("mov", "a,b");
7416 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, NULL));
7418 else if (AOP_TYPE(left)==AOP_ACC)
7422 bool pushedB = pushB ();
7423 emitcode("mov", "b,a");
7424 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7425 emitcode("anl", "a,b");
7430 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7431 emitcode("anl", "a,b");
7434 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7436 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE, NULL));
7437 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7438 emitcode ("anl", "a,b");
7440 else if (aopGetUsesAcc (left, offset))
7442 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7443 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7447 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7448 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7451 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7461 jmpTrueOrFalse (ifx, tlbl);
7467 for (; (size--); offset++)
7470 // result = left & right
7471 if (AOP_TYPE (right) == AOP_LIT)
7473 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7474 if (bytelit == 0x0FF)
7477 aopGet (left, offset, FALSE, FALSE, NULL),
7481 else if (bytelit == 0)
7483 /* dummy read of volatile operand */
7484 if (isOperandVolatile (left, FALSE))
7485 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7486 aopPut (result, zero, offset);
7489 else if (AOP_TYPE (left) == AOP_ACC)
7493 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, NULL));
7494 aopPut (result, "a", offset);
7499 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE, NULL));
7500 aopPut (result, "b", offset);
7505 // faster than result <- left, anl result,right
7506 // and better if result is SFR
7507 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7508 && AOP_TYPE(left)==AOP_ACC)
7511 emitcode("mov", "a,b");
7512 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, NULL));
7514 else if (AOP_TYPE(left)==AOP_ACC)
7518 bool pushedB = pushB ();
7519 emitcode("mov", "b,a");
7520 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7521 emitcode("anl", "a,b");
7526 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7527 emitcode("anl", "a,b");
7530 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7532 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
7533 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7534 emitcode ("anl", "a,b");
7536 else if (aopGetUsesAcc (left, offset))
7538 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7539 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7543 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7544 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7546 aopPut (result, "a", offset);
7552 freeAsmop (result, NULL, ic, TRUE);
7553 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7554 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7557 /*-----------------------------------------------------------------*/
7558 /* genOr - code for or */
7559 /*-----------------------------------------------------------------*/
7561 genOr (iCode * ic, iCode * ifx)
7563 operand *left, *right, *result;
7564 int size, offset = 0;
7565 unsigned long lit = 0L;
7569 D (emitcode (";", "genOr"));
7571 AOP_OP_3_NOFATAL (ic, pushResult);
7572 AOP_SET_LOCALS (ic);
7576 genFarFarLogicOp(ic, "orl");
7582 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7584 AOP_TYPE (left), AOP_TYPE (right));
7585 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7587 AOP_SIZE (left), AOP_SIZE (right));
7590 /* if left is a literal & right is not then exchange them */
7591 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7592 #ifdef LOGIC_OPS_BROKEN
7593 || AOP_NEEDSACC (left) // I think this is a net loss now.
7597 operand *tmp = right;
7602 /* if result = right then exchange them */
7603 if (sameRegs (AOP (result), AOP (right)))
7605 operand *tmp = right;
7610 /* if right is bit then exchange them */
7611 if (AOP_TYPE (right) == AOP_CRY &&
7612 AOP_TYPE (left) != AOP_CRY)
7614 operand *tmp = right;
7618 if (AOP_TYPE (right) == AOP_LIT)
7619 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7621 size = AOP_SIZE (result);
7625 if (AOP_TYPE (left) == AOP_CRY)
7627 if (AOP_TYPE (right) == AOP_LIT)
7629 // c = bit | literal;
7632 // lit != 0 => result = 1
7633 if (AOP_TYPE (result) == AOP_CRY)
7636 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7638 continueIfTrue (ifx);
7641 emitcode ("setb", "c");
7645 // lit == 0 => result = left
7646 if (size && sameRegs (AOP (result), AOP (left)))
7648 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7653 if (AOP_TYPE (right) == AOP_CRY)
7656 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7657 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7662 symbol *tlbl = newiTempLabel (NULL);
7663 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
7664 emitcode ("setb", "c");
7665 emitcode ("jb", "%s,!tlabel",
7666 AOP (left)->aopu.aop_dir, tlbl->key + 100);
7668 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7669 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7671 jmpTrueOrFalse (ifx, tlbl);
7686 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7687 genIfxJump (ifx, "c");
7691 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7692 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7693 if ((AOP_TYPE (right) == AOP_LIT) &&
7694 (AOP_TYPE (result) == AOP_CRY) &&
7695 (AOP_TYPE (left) != AOP_CRY))
7701 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7703 continueIfTrue (ifx);
7708 // lit = 0, result = boolean(left)
7710 emitcode ("setb", "c");
7714 symbol *tlbl = newiTempLabel (NULL);
7715 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7721 genIfxJump (ifx, "a");
7729 /* if left is same as result */
7730 if (sameRegs (AOP (result), AOP (left)))
7732 for (; size--; offset++)
7734 if (AOP_TYPE (right) == AOP_LIT)
7736 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7739 /* dummy read of volatile operand */
7740 if (isOperandVolatile (left, FALSE))
7741 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7745 else if (bytelit == 0x0FF)
7747 aopPut (result, "#0xFF", offset);
7749 else if (IS_AOP_PREG (left))
7751 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7752 emitcode ("orl", "a,%s",
7753 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7754 aopPut (result, "a", offset);
7758 emitcode ("orl", "%s,%s",
7759 aopGet (left, offset, FALSE, TRUE, NULL),
7760 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7765 if (AOP_TYPE (left) == AOP_ACC)
7768 emitcode("mov", "a,b");
7769 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7771 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7773 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE, NULL));
7774 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7775 emitcode ("orl", "a,b");
7776 aopPut (result, "a", offset);
7778 else if (aopGetUsesAcc (left, offset))
7780 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7781 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7782 aopPut (result, "a", offset);
7786 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7787 if (IS_AOP_PREG (left))
7789 emitcode ("orl", "a,%s",
7790 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7791 aopPut (result, "a", offset);
7795 emitcode ("orl", "%s,a",
7796 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7804 // left & result in different registers
7805 if (AOP_TYPE (result) == AOP_CRY)
7808 // if(size), result in bit
7809 // if(!size && ifx), conditional oper: if(left | right)
7810 symbol *tlbl = newiTempLabel (NULL);
7811 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7813 emitcode ("setb", "c");
7816 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7817 && AOP_TYPE(left)==AOP_ACC)
7820 emitcode("mov", "a,b");
7821 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7823 else if (AOP_TYPE(left)==AOP_ACC)
7827 bool pushedB = pushB ();
7828 emitcode("mov", "b,a");
7829 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7830 emitcode("orl", "a,b");
7835 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7836 emitcode("orl", "a,b");
7839 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7841 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
7842 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7843 emitcode ("orl", "a,b");
7845 else if (aopGetUsesAcc (left, offset))
7847 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7848 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7852 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7853 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7856 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7866 jmpTrueOrFalse (ifx, tlbl);
7872 _startLazyDPSEvaluation();
7873 for (; (size--); offset++)
7876 // result = left | right
7877 if (AOP_TYPE (right) == AOP_LIT)
7879 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7883 aopGet (left, offset, FALSE, FALSE, NULL),
7887 else if (bytelit == 0x0FF)
7889 /* dummy read of volatile operand */
7890 if (isOperandVolatile (left, FALSE))
7891 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7892 aopPut (result, "#0xFF", offset);
7896 // faster than result <- left, orl result,right
7897 // and better if result is SFR
7898 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7899 && AOP_TYPE(left)==AOP_ACC)
7902 emitcode("mov", "a,b");
7903 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7905 else if (AOP_TYPE(left)==AOP_ACC)
7909 bool pushedB = pushB ();
7910 emitcode("mov", "b,a");
7911 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7912 emitcode("orl", "a,b");
7917 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7918 emitcode("orl", "a,b");
7921 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7923 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
7924 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7925 emitcode ("orl", "a,b");
7927 else if (aopGetUsesAcc (left, offset))
7929 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7930 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7934 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7935 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7937 aopPut (result, "a", offset);
7939 _endLazyDPSEvaluation();
7944 freeAsmop (result, NULL, ic, TRUE);
7945 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7946 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7949 /*-----------------------------------------------------------------*/
7950 /* genXor - code for xclusive or */
7951 /*-----------------------------------------------------------------*/
7953 genXor (iCode * ic, iCode * ifx)
7955 operand *left, *right, *result;
7956 int size, offset = 0;
7957 unsigned long lit = 0L;
7961 D (emitcode (";", "genXor"));
7963 AOP_OP_3_NOFATAL (ic, pushResult);
7964 AOP_SET_LOCALS (ic);
7968 genFarFarLogicOp(ic, "xrl");
7973 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7975 AOP_TYPE (left), AOP_TYPE (right));
7976 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7978 AOP_SIZE (left), AOP_SIZE (right));
7981 /* if left is a literal & right is not ||
7982 if left needs acc & right does not */
7983 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7984 #ifdef LOGIC_OPS_BROKEN
7985 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
7989 operand *tmp = right;
7994 /* if result = right then exchange them */
7995 if (sameRegs (AOP (result), AOP (right)))
7997 operand *tmp = right;
8002 /* if right is bit then exchange them */
8003 if (AOP_TYPE (right) == AOP_CRY &&
8004 AOP_TYPE (left) != AOP_CRY)
8006 operand *tmp = right;
8010 if (AOP_TYPE (right) == AOP_LIT)
8011 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8013 size = AOP_SIZE (result);
8017 if (AOP_TYPE (left) == AOP_CRY)
8019 if (AOP_TYPE (right) == AOP_LIT)
8021 // c = bit & literal;
8024 // lit>>1 != 0 => result = 1
8025 if (AOP_TYPE (result) == AOP_CRY)
8028 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
8030 continueIfTrue (ifx);
8033 emitcode ("setb", "c");
8040 // lit == 0, result = left
8041 if (size && sameRegs (AOP (result), AOP (left)))
8043 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
8047 // lit == 1, result = not(left)
8048 if (size && sameRegs (AOP (result), AOP (left)))
8050 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
8055 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
8056 emitcode ("cpl", "c");
8064 symbol *tlbl = newiTempLabel (NULL);
8065 if (AOP_TYPE (right) == AOP_CRY)
8068 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8072 int sizer = AOP_SIZE (right);
8074 // if val>>1 != 0, result = 1
8075 emitcode ("setb", "c");
8078 MOVA (aopGet (right, sizer - 1, FALSE, FALSE, NULL));
8080 // test the msb of the lsb
8081 emitcode ("anl", "a,#!constbyte",0xfe);
8082 emitcode ("jnz", "!tlabel", tlbl->key + 100);
8086 emitcode ("rrc", "a");
8088 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
8089 emitcode ("cpl", "c");
8097 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
8098 genIfxJump (ifx, "c");
8102 /* if left is same as result */
8103 if (sameRegs (AOP (result), AOP (left)))
8105 for (; size--; offset++)
8107 if (AOP_TYPE (right) == AOP_LIT)
8109 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
8112 /* dummy read of volatile operand */
8113 if (isOperandVolatile (left, FALSE))
8114 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8118 else if (IS_AOP_PREG (left))
8120 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8121 emitcode ("xrl", "a,%s",
8122 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG));
8123 aopPut (result, "a", offset);
8127 emitcode ("xrl", "%s,%s",
8128 aopGet (left, offset, FALSE, TRUE, NULL),
8129 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8134 if (AOP_TYPE (left) == AOP_ACC)
8137 emitcode("mov", "a,b");
8138 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8140 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
8142 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
8143 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8144 emitcode ("xrl", "a,b");
8145 aopPut (result, "a", offset);
8147 else if (aopGetUsesAcc (left, offset))
8149 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8150 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8151 aopPut (result, "a", offset);
8155 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
8156 if (IS_AOP_PREG (left))
8158 emitcode ("xrl", "a,%s",
8159 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
8160 aopPut (result, "a", offset);
8163 emitcode ("xrl", "%s,a",
8164 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
8171 // left & result in different registers
8172 if (AOP_TYPE (result) == AOP_CRY)
8175 // if(size), result in bit
8176 // if(!size && ifx), conditional oper: if(left ^ right)
8177 symbol *tlbl = newiTempLabel (NULL);
8178 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
8181 emitcode ("setb", "c");
8184 if ((AOP_TYPE (right) == AOP_LIT) &&
8185 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
8187 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8189 else if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
8190 && AOP_TYPE(left)==AOP_ACC)
8193 emitcode("mov", "a,b");
8194 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8196 else if (AOP_TYPE(left)==AOP_ACC)
8200 bool pushedB = pushB ();
8201 emitcode("mov", "b,a");
8202 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8203 emitcode("xrl", "a,b");
8208 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8209 emitcode("xrl", "a,b");
8212 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
8214 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
8215 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8216 emitcode ("xrl", "a,b");
8218 else if (aopGetUsesAcc (left, offset))
8220 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8221 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8225 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
8226 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
8229 emitcode ("jnz", "!tlabel", tlbl->key + 100);
8239 jmpTrueOrFalse (ifx, tlbl);
8243 for (; (size--); offset++)
8246 // result = left ^ right
8247 if (AOP_TYPE (right) == AOP_LIT)
8249 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
8253 aopGet (left, offset, FALSE, FALSE, NULL),
8257 D (emitcode (";", "better literal XOR."));
8258 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8259 emitcode ("xrl", "a, %s",
8260 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8264 // faster than result <- left, anl result,right
8265 // and better if result is SFR
8266 if (AOP_TYPE (left) == AOP_ACC)
8268 emitcode ("xrl", "a,%s",
8269 aopGet (right, offset,
8270 FALSE, FALSE, DP2_RESULT_REG));
8274 char *rOp = aopGet (right, offset, FALSE, FALSE, NULL);
8275 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
8277 emitcode("mov", "b,a");
8281 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8282 emitcode ("xrl", "a,%s", rOp);
8285 aopPut (result, "a", offset);
8291 freeAsmop (result, NULL, ic, TRUE);
8292 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
8293 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
8296 /*-----------------------------------------------------------------*/
8297 /* genInline - write the inline code out */
8298 /*-----------------------------------------------------------------*/
8300 genInline (iCode * ic)
8302 char *buffer, *bp, *bp1;
8304 D (emitcode (";", "genInline"));
8306 _G.inLine += (!options.asmpeep);
8308 buffer = bp = bp1 = Safe_strdup(IC_INLINE(ic));
8310 /* emit each line as a code */
8321 /* Add \n for labels, not dirs such as c:\mydir */
8322 if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
8336 /* emitcode("",buffer); */
8337 _G.inLine -= (!options.asmpeep);
8340 /*-----------------------------------------------------------------*/
8341 /* genRRC - rotate right with carry */
8342 /*-----------------------------------------------------------------*/
8346 operand *left, *result;
8350 D (emitcode (";", "genRRC"));
8352 /* rotate right with carry */
8353 left = IC_LEFT (ic);
8354 result = IC_RESULT (ic);
8355 aopOp (left, ic, FALSE, FALSE);
8356 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8358 /* move it to the result */
8359 size = AOP_SIZE (result);
8363 _startLazyDPSEvaluation ();
8366 l = aopGet (left, offset, FALSE, FALSE, NULL);
8368 emitcode ("rrc", "a");
8369 if (AOP_SIZE (result) > 1)
8370 aopPut (result, "a", offset--);
8372 _endLazyDPSEvaluation ();
8374 /* now we need to put the carry into the
8375 highest order byte of the result */
8376 if (AOP_SIZE (result) > 1)
8378 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE, NULL);
8381 emitcode ("mov", "acc.7,c");
8382 aopPut (result, "a", AOP_SIZE (result) - 1);
8383 freeAsmop (result, NULL, ic, TRUE);
8384 freeAsmop (left, NULL, ic, TRUE);
8387 /*-----------------------------------------------------------------*/
8388 /* genRLC - generate code for rotate left with carry */
8389 /*-----------------------------------------------------------------*/
8393 operand *left, *result;
8397 D (emitcode (";", "genRLC"));
8399 /* rotate right with carry */
8400 left = IC_LEFT (ic);
8401 result = IC_RESULT (ic);
8402 aopOp (left, ic, FALSE, FALSE);
8403 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8405 /* move it to the result */
8406 size = AOP_SIZE (result);
8410 l = aopGet (left, offset, FALSE, FALSE, NULL);
8412 emitcode ("add", "a,acc");
8413 if (AOP_SIZE (result) > 1)
8415 aopPut (result, "a", offset++);
8418 _startLazyDPSEvaluation ();
8421 l = aopGet (left, offset, FALSE, FALSE, NULL);
8423 emitcode ("rlc", "a");
8424 if (AOP_SIZE (result) > 1)
8425 aopPut (result, "a", offset++);
8427 _endLazyDPSEvaluation ();
8429 /* now we need to put the carry into the
8430 highest order byte of the result */
8431 if (AOP_SIZE (result) > 1)
8433 l = aopGet (result, 0, FALSE, FALSE, NULL);
8436 emitcode ("mov", "acc.0,c");
8437 aopPut (result, "a", 0);
8438 freeAsmop (result, NULL, ic, TRUE);
8439 freeAsmop (left, NULL, ic, TRUE);
8442 /*-----------------------------------------------------------------*/
8443 /* genGetHbit - generates code get highest order bit */
8444 /*-----------------------------------------------------------------*/
8446 genGetHbit (iCode * ic)
8448 operand *left, *result;
8450 D (emitcode (";", "genGetHbit"));
8452 left = IC_LEFT (ic);
8453 result = IC_RESULT (ic);
8454 aopOp (left, ic, FALSE, FALSE);
8455 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8457 /* get the highest order byte into a */
8458 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
8459 if (AOP_TYPE (result) == AOP_CRY)
8461 emitcode ("rlc", "a");
8466 emitcode ("rl", "a");
8467 emitcode ("anl", "a,#1");
8472 freeAsmop (result, NULL, ic, TRUE);
8473 freeAsmop (left, NULL, ic, TRUE);
8476 /*-----------------------------------------------------------------*/
8477 /* genSwap - generates code to swap nibbles or bytes */
8478 /*-----------------------------------------------------------------*/
8480 genSwap (iCode * ic)
8482 operand *left, *result;
8484 D(emitcode ("; genSwap",""));
8486 left = IC_LEFT (ic);
8487 result = IC_RESULT (ic);
8488 aopOp (left, ic, FALSE, FALSE);
8489 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8491 _startLazyDPSEvaluation ();
8492 switch (AOP_SIZE (left))
8494 case 1: /* swap nibbles in byte */
8495 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
8496 emitcode ("swap", "a");
8497 aopPut (result, "a", 0);
8499 case 2: /* swap bytes in word */
8500 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
8502 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
8503 aopPut (result, aopGet (left, 1, FALSE, FALSE, NULL), 0);
8504 aopPut (result, "a", 1);
8506 else if (operandsEqu (left, result))
8509 bool pushedB = FALSE, leftInB = FALSE;
8511 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
8512 if (AOP_NEEDSACC (left) || AOP_NEEDSACC (result))
8515 emitcode ("mov", "b,a");
8519 aopPut (result, aopGet (left, 1, FALSE, FALSE, NULL), 0);
8520 aopPut (result, reg, 1);
8527 aopPut (result, aopGet (left, 1, FALSE, FALSE, NULL), 0);
8528 aopPut (result, aopGet (left, 0, FALSE, FALSE, NULL), 1);
8532 wassertl(FALSE, "unsupported SWAP operand size");
8534 _endLazyDPSEvaluation ();
8536 freeAsmop (result, NULL, ic, TRUE);
8537 freeAsmop (left, NULL, ic, TRUE);
8540 /*-----------------------------------------------------------------*/
8541 /* AccRol - rotate left accumulator by known count */
8542 /*-----------------------------------------------------------------*/
8544 AccRol (int shCount)
8546 shCount &= 0x0007; // shCount : 0..7
8553 emitcode ("rl", "a");
8556 emitcode ("rl", "a");
8557 emitcode ("rl", "a");
8560 emitcode ("swap", "a");
8561 emitcode ("rr", "a");
8564 emitcode ("swap", "a");
8567 emitcode ("swap", "a");
8568 emitcode ("rl", "a");
8571 emitcode ("rr", "a");
8572 emitcode ("rr", "a");
8575 emitcode ("rr", "a");
8580 /*-----------------------------------------------------------------*/
8581 /* AccLsh - left shift accumulator by known count */
8582 /*-----------------------------------------------------------------*/
8584 AccLsh (int shCount)
8589 emitcode ("add", "a,acc");
8590 else if (shCount == 2)
8592 emitcode ("add", "a,acc");
8593 emitcode ("add", "a,acc");
8597 /* rotate left accumulator */
8599 /* and kill the lower order bits */
8600 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
8605 /*-----------------------------------------------------------------*/
8606 /* AccRsh - right shift accumulator by known count */
8607 /*-----------------------------------------------------------------*/
8609 AccRsh (int shCount)
8616 emitcode ("rrc", "a");
8620 /* rotate right accumulator */
8621 AccRol (8 - shCount);
8622 /* and kill the higher order bits */
8623 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
8628 #ifdef BETTER_LITERAL_SHIFT
8629 /*-----------------------------------------------------------------*/
8630 /* AccSRsh - signed right shift accumulator by known count */
8631 /*-----------------------------------------------------------------*/
8633 AccSRsh (int shCount)
8640 emitcode ("mov", "c,acc.7");
8641 emitcode ("rrc", "a");
8643 else if (shCount == 2)
8645 emitcode ("mov", "c,acc.7");
8646 emitcode ("rrc", "a");
8647 emitcode ("mov", "c,acc.7");
8648 emitcode ("rrc", "a");
8652 tlbl = newiTempLabel (NULL);
8653 /* rotate right accumulator */
8654 AccRol (8 - shCount);
8655 /* and kill the higher order bits */
8656 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
8657 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8658 emitcode ("orl", "a,#!constbyte",
8659 (unsigned char) ~SRMask[shCount]);
8666 #ifdef BETTER_LITERAL_SHIFT
8667 /*-----------------------------------------------------------------*/
8668 /* shiftR1Left2Result - shift right one byte from left to result */
8669 /*-----------------------------------------------------------------*/
8671 shiftR1Left2Result (operand * left, int offl,
8672 operand * result, int offr,
8673 int shCount, int sign)
8675 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
8676 /* shift right accumulator */
8681 aopPut (result, "a", offr);
8685 #ifdef BETTER_LITERAL_SHIFT
8686 /*-----------------------------------------------------------------*/
8687 /* shiftL1Left2Result - shift left one byte from left to result */
8688 /*-----------------------------------------------------------------*/
8690 shiftL1Left2Result (operand * left, int offl,
8691 operand * result, int offr, int shCount)
8694 l = aopGet (left, offl, FALSE, FALSE, NULL);
8696 /* shift left accumulator */
8698 aopPut (result, "a", offr);
8702 #ifdef BETTER_LITERAL_SHIFT
8703 /*-----------------------------------------------------------------*/
8704 /* movLeft2Result - move byte from left to result */
8705 /*-----------------------------------------------------------------*/
8707 movLeft2Result (operand * left, int offl,
8708 operand * result, int offr, int sign)
8711 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8713 l = aopGet (left, offl, FALSE, FALSE, NULL);
8715 if (*l == '@' && (IS_AOP_PREG (result)))
8717 emitcode ("mov", "a,%s", l);
8718 aopPut (result, "a", offr);
8724 aopPut (result, l, offr);
8728 /* MSB sign in acc.7 ! */
8729 if (getDataSize (left) == offl + 1)
8732 aopPut (result, "a", offr);
8740 #ifdef BETTER_LITERAL_SHIFT
8741 /*-----------------------------------------------------------------*/
8742 /* AccAXRrl1 - right rotate a:x by 1 */
8743 /*-----------------------------------------------------------------*/
8747 emitcode ("mov", "c,acc.0");
8748 emitcode ("xch", "a,%s", x);
8749 emitcode ("rrc", "a");
8750 emitcode ("xch", "a,%s", x);
8751 emitcode ("rrc", "a");
8755 #ifdef BETTER_LITERAL_SHIFT
8757 /*-----------------------------------------------------------------*/
8758 /* AccAXLrl1 - left rotate a:x by 1 */
8759 /*-----------------------------------------------------------------*/
8763 emitcode ("mov", "c,acc.7");
8764 emitcode ("xch", "a,%s", x);
8765 emitcode ("rlc", "a");
8766 emitcode ("xch", "a,%s", x);
8767 emitcode ("rlc", "a");
8771 #ifdef BETTER_LITERAL_SHIFT
8772 /*-----------------------------------------------------------------*/
8773 /* AccAXRsh1 - right shift c->a:x->c by 1 */
8774 /*-----------------------------------------------------------------*/
8778 emitcode ("rrc", "a");
8779 emitcode ("xch", "a,%s", x);
8780 emitcode ("rrc", "a");
8781 emitcode ("xch", "a,%s", x);
8785 #ifdef BETTER_LITERAL_SHIFT
8786 /*-----------------------------------------------------------------*/
8787 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8788 /*-----------------------------------------------------------------*/
8792 emitcode ("xch", "a,%s", x);
8793 emitcode ("add", "a,acc");
8794 emitcode ("xch", "a,%s", x);
8795 emitcode ("rlc", "a");
8799 #ifdef BETTER_LITERAL_SHIFT
8800 /*-----------------------------------------------------------------*/
8801 /* AccAXLsh - left shift a:x by known count (0..7) */
8802 /*-----------------------------------------------------------------*/
8804 AccAXLsh (char *x, int shCount)
8819 case 5: // AAAAABBB:CCCCCDDD
8821 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8823 emitcode ("anl", "a,#!constbyte",
8824 SLMask[shCount]); // BBB00000:CCCCCDDD
8826 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8828 AccRol (shCount); // DDDCCCCC:BBB00000
8830 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8832 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8834 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8836 emitcode ("anl", "a,#!constbyte",
8837 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8839 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8841 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8844 case 6: // AAAAAABB:CCCCCCDD
8845 emitcode ("anl", "a,#!constbyte",
8846 SRMask[shCount]); // 000000BB:CCCCCCDD
8848 AccAXRrl1 (x); // D000000B:BCCCCCCD
8849 AccAXRrl1 (x); // DD000000:BBCCCCCC
8850 emitcode ("xch", "a,%s", x); // BBCCCCCC:DD000000
8852 emitcode ("mov", "c,acc.0"); // c = B
8853 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8854 emitcode("rrc","a");
8855 emitcode("xch","a,%s", x);
8856 emitcode("rrc","a");
8857 emitcode("mov","c,acc.0"); //<< get correct bit
8858 emitcode("xch","a,%s", x);
8860 emitcode("rrc","a");
8861 emitcode("xch","a,%s", x);
8862 emitcode("rrc","a");
8863 emitcode("xch","a,%s", x);
8866 case 7: // a:x <<= 7
8868 emitcode ("anl", "a,#!constbyte",
8869 SRMask[shCount]); // 0000000B:CCCCCCCD
8871 AccAXRrl1 (x); // D0000000:BCCCCCCC
8873 emitcode ("xch", "a,%s", x); // BCCCCCCC:D0000000
8882 #ifdef BETTER_LITERAL_SHIFT
8884 /*-----------------------------------------------------------------*/
8885 /* AccAXRsh - right shift a:x known count (0..7) */
8886 /*-----------------------------------------------------------------*/
8888 AccAXRsh (char *x, int shCount)
8896 AccAXRsh1 (x); // 0->a:x
8901 AccAXRsh1 (x); // 0->a:x
8904 AccAXRsh1 (x); // 0->a:x
8909 case 5: // AAAAABBB:CCCCCDDD = a:x
8911 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8913 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8915 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8917 emitcode ("anl", "a,#!constbyte",
8918 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8920 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8922 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8924 emitcode ("anl", "a,#!constbyte",
8925 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8927 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8929 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8931 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8934 case 6: // AABBBBBB:CCDDDDDD
8936 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDE
8937 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8939 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8941 emitcode ("anl", "a,#!constbyte",
8942 SRMask[shCount]); // 000000AA:BBBBBBCC
8945 case 7: // ABBBBBBB:CDDDDDDD
8947 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8949 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8951 emitcode ("anl", "a,#!constbyte",
8952 SRMask[shCount]); // 0000000A:BBBBBBBC
8961 #ifdef BETTER_LITERAL_SHIFT
8962 /*-----------------------------------------------------------------*/
8963 /* AccAXRshS - right shift signed a:x known count (0..7) */
8964 /*-----------------------------------------------------------------*/
8966 AccAXRshS (char *x, int shCount)
8974 emitcode ("mov", "c,acc.7");
8975 AccAXRsh1 (x); // s->a:x
8979 emitcode ("mov", "c,acc.7");
8980 AccAXRsh1 (x); // s->a:x
8982 emitcode ("mov", "c,acc.7");
8983 AccAXRsh1 (x); // s->a:x
8988 case 5: // AAAAABBB:CCCCCDDD = a:x
8990 tlbl = newiTempLabel (NULL);
8991 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8993 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8995 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8997 emitcode ("anl", "a,#!constbyte",
8998 SRMask[shCount]); // 000CCCCC:BBBAAAAA
9000 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
9002 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
9004 emitcode ("anl", "a,#!constbyte",
9005 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
9007 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
9009 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
9011 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
9013 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
9014 emitcode ("orl", "a,#!constbyte",
9015 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
9018 break; // SSSSAAAA:BBBCCCCC
9020 case 6: // AABBBBBB:CCDDDDDD
9022 tlbl = newiTempLabel (NULL);
9024 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
9025 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
9027 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
9029 emitcode ("anl", "a,#!constbyte",
9030 SRMask[shCount]); // 000000AA:BBBBBBCC
9032 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
9033 emitcode ("orl", "a,#!constbyte",
9034 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
9038 case 7: // ABBBBBBB:CDDDDDDD
9040 tlbl = newiTempLabel (NULL);
9042 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
9044 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
9046 emitcode ("anl", "a,#!constbyte",
9047 SRMask[shCount]); // 0000000A:BBBBBBBC
9049 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
9050 emitcode ("orl", "a,#!constbyte",
9051 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
9061 #ifdef BETTER_LITERAL_SHIFT
9063 _loadLeftIntoAx(char **lsb,
9069 // Get the initial value from left into a pair of registers.
9070 // MSB must be in A, LSB can be any register.
9072 // If the result is held in registers, it is an optimization
9073 // if the LSB can be held in the register which will hold the,
9074 // result LSB since this saves us from having to copy it into
9075 // the result following AccAXLsh.
9077 // If the result is addressed indirectly, this is not a gain.
9078 if (AOP_NEEDSACC(result))
9082 _startLazyDPSEvaluation();
9083 if (AOP_TYPE(left) == AOP_DPTR2)
9086 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE, NULL));
9087 // get LSB in DP2_RESULT_REG.
9088 leftByte = aopGet (left, offl, FALSE, FALSE, DP2_RESULT_REG);
9089 assert(!strcmp(leftByte, DP2_RESULT_REG));
9093 // get LSB into DP2_RESULT_REG
9094 leftByte = aopGet (left, offl, FALSE, FALSE, NULL);
9095 if (strcmp(leftByte, DP2_RESULT_REG))
9098 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
9101 leftByte = aopGet (left, offl + MSB16, FALSE, FALSE, NULL);
9102 assert(strcmp(leftByte, DP2_RESULT_REG));
9105 _endLazyDPSEvaluation();
9106 *lsb = DP2_RESULT_REG;
9110 if (sameRegs (AOP (result), AOP (left)) &&
9111 ((offl + MSB16) == offr))
9113 /* don't crash result[offr] */
9114 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
9115 emitcode ("xch", "a,%s",
9116 aopGet (left, offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
9120 movLeft2Result (left, offl, result, offr, 0);
9121 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE, NULL));
9123 *lsb = aopGet (result, offr, FALSE, FALSE, DP2_RESULT_REG);
9124 assert(strcmp(*lsb,"a"));
9129 _storeAxResults(char *lsb,
9133 _startLazyDPSEvaluation();
9134 if (AOP_NEEDSACC(result))
9136 /* We have to explicitly update the result LSB.
9138 emitcode ("xch","a,%s", lsb);
9139 aopPut (result, "a", offr);
9140 emitcode ("mov","a,%s", lsb);
9142 if (getDataSize (result) > 1)
9144 aopPut (result, "a", offr + MSB16);
9146 _endLazyDPSEvaluation();
9149 /*-----------------------------------------------------------------*/
9150 /* shiftL2Left2Result - shift left two bytes from left to result */
9151 /*-----------------------------------------------------------------*/
9153 shiftL2Left2Result (operand * left, int offl,
9154 operand * result, int offr, int shCount)
9158 _loadLeftIntoAx(&lsb, left, result, offl, offr);
9160 AccAXLsh (lsb, shCount);
9162 _storeAxResults(lsb, result, offr);
9166 #ifdef BETTER_LITERAL_SHIFT
9167 /*-----------------------------------------------------------------*/
9168 /* shiftR2Left2Result - shift right two bytes from left to result */
9169 /*-----------------------------------------------------------------*/
9171 shiftR2Left2Result (operand * left, int offl,
9172 operand * result, int offr,
9173 int shCount, int sign)
9177 _loadLeftIntoAx(&lsb, left, result, offl, offr);
9179 /* a:x >> shCount (x = lsb(result)) */
9182 AccAXRshS(lsb, shCount);
9186 AccAXRsh(lsb, shCount);
9189 _storeAxResults(lsb, result, offr);
9193 /*-----------------------------------------------------------------*/
9194 /* shiftLLeftOrResult - shift left one byte from left, or to result */
9195 /*-----------------------------------------------------------------*/
9197 shiftLLeftOrResult (operand * left, int offl,
9198 operand * result, int offr, int shCount)
9200 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
9201 /* shift left accumulator */
9203 /* or with result */
9204 emitcode ("orl", "a,%s",
9205 aopGet (result, offr, FALSE, FALSE, DP2_RESULT_REG));
9206 /* back to result */
9207 aopPut (result, "a", offr);
9212 /*-----------------------------------------------------------------*/
9213 /* shiftRLeftOrResult - shift right one byte from left,or to result */
9214 /*-----------------------------------------------------------------*/
9216 shiftRLeftOrResult (operand * left, int offl,
9217 operand * result, int offr, int shCount)
9219 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
9220 /* shift right accumulator */
9222 /* or with result */
9223 emitcode ("orl", "a,%s",
9224 aopGet (result, offr, FALSE, FALSE, DP2_RESULT_REG));
9225 /* back to result */
9226 aopPut (result, "a", offr);
9230 #ifdef BETTER_LITERAL_SHIFT
9231 /*-----------------------------------------------------------------*/
9232 /* genlshOne - left shift a one byte quantity by known count */
9233 /*-----------------------------------------------------------------*/
9235 genlshOne (operand * result, operand * left, int shCount)
9237 D (emitcode (";", "genlshOne"));
9239 shiftL1Left2Result (left, LSB, result, LSB, shCount);
9243 #ifdef BETTER_LITERAL_SHIFT
9244 /*-----------------------------------------------------------------*/
9245 /* genlshTwo - left shift two bytes by known amount != 0 */
9246 /*-----------------------------------------------------------------*/
9248 genlshTwo (operand * result, operand * left, int shCount)
9252 D (emitcode (";", "genlshTwo"));
9254 size = getDataSize (result);
9256 /* if shCount >= 8 */
9261 _startLazyDPSEvaluation();
9267 _endLazyDPSEvaluation();
9268 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9269 aopPut (result, zero, LSB);
9273 movLeft2Result (left, LSB, result, MSB16, 0);
9274 aopPut (result, zero, LSB);
9275 _endLazyDPSEvaluation();
9280 aopPut (result, zero, LSB);
9281 _endLazyDPSEvaluation();
9285 /* 1 <= shCount <= 7 */
9289 shiftL1Left2Result (left, LSB, result, LSB, shCount);
9291 shiftL2Left2Result (left, LSB, result, LSB, shCount);
9298 /*-----------------------------------------------------------------*/
9299 /* shiftLLong - shift left one long from left to result */
9300 /* offl = LSB or MSB16 */
9301 /*-----------------------------------------------------------------*/
9303 shiftLLong (operand * left, operand * result, int offr)
9306 int size = AOP_SIZE (result);
9308 if (size >= LSB + offr)
9310 l = aopGet (left, LSB, FALSE, FALSE, NULL);
9312 emitcode ("add", "a,acc");
9313 if (sameRegs (AOP (left), AOP (result)) &&
9314 size >= MSB16 + offr && offr != LSB)
9315 emitcode ("xch", "a,%s",
9316 aopGet (left, LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
9318 aopPut (result, "a", LSB + offr);
9321 if (size >= MSB16 + offr)
9323 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
9325 l = aopGet (left, MSB16, FALSE, FALSE, TRUE);
9328 emitcode ("rlc", "a");
9329 if (sameRegs (AOP (left), AOP (result)) &&
9330 size >= MSB24 + offr && offr != LSB)
9331 emitcode ("xch", "a,%s",
9332 aopGet (left, MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
9334 aopPut (result, "a", MSB16 + offr);
9337 if (size >= MSB24 + offr)
9339 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
9341 l = aopGet (left, MSB24, FALSE, FALSE, NULL);
9344 emitcode ("rlc", "a");
9345 if (sameRegs (AOP (left), AOP (result)) &&
9346 size >= MSB32 + offr && offr != LSB)
9347 emitcode ("xch", "a,%s",
9348 aopGet (left, MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
9350 aopPut (result, "a", MSB24 + offr);
9353 if (size > MSB32 + offr)
9355 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
9357 l = aopGet (left, MSB32, FALSE, FALSE, NULL);
9360 emitcode ("rlc", "a");
9361 aopPut (result, "a", MSB32 + offr);
9364 aopPut (result, zero, LSB);
9370 /*-----------------------------------------------------------------*/
9371 /* genlshFour - shift four byte by a known amount != 0 */
9372 /*-----------------------------------------------------------------*/
9374 genlshFour (operand * result, operand * left, int shCount)
9378 D (emitcode (";", "genlshFour"));
9380 size = AOP_SIZE (result);
9382 /* if shifting more that 3 bytes */
9387 /* lowest order of left goes to the highest
9388 order of the destination */
9389 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
9391 movLeft2Result (left, LSB, result, MSB32, 0);
9392 aopPut (result, zero, LSB);
9393 aopPut (result, zero, MSB16);
9394 aopPut (result, zero, MSB24);
9398 /* more than two bytes */
9399 else if (shCount >= 16)
9401 /* lower order two bytes goes to higher order two bytes */
9403 /* if some more remaining */
9405 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
9408 movLeft2Result (left, MSB16, result, MSB32, 0);
9409 movLeft2Result (left, LSB, result, MSB24, 0);
9411 aopPut (result, zero, MSB16);
9412 aopPut (result, zero, LSB);
9416 /* if more than 1 byte */
9417 else if (shCount >= 8)
9419 /* lower order three bytes goes to higher order three bytes */
9424 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9426 movLeft2Result (left, LSB, result, MSB16, 0);
9432 movLeft2Result (left, MSB24, result, MSB32, 0);
9433 movLeft2Result (left, MSB16, result, MSB24, 0);
9434 movLeft2Result (left, LSB, result, MSB16, 0);
9435 aopPut (result, zero, LSB);
9437 else if (shCount == 1)
9438 shiftLLong (left, result, MSB16);
9441 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
9442 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9443 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
9444 aopPut (result, zero, LSB);
9449 /* 1 <= shCount <= 7 */
9450 else if (shCount <= 2)
9452 shiftLLong (left, result, LSB);
9454 shiftLLong (result, result, LSB);
9456 /* 3 <= shCount <= 7, optimize */
9459 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
9460 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
9461 shiftL2Left2Result (left, LSB, result, LSB, shCount);
9466 #ifdef BETTER_LITERAL_SHIFT
9467 /*-----------------------------------------------------------------*/
9468 /* genLeftShiftLiteral - left shifting by known count */
9469 /*-----------------------------------------------------------------*/
9471 genLeftShiftLiteral (operand * left,
9476 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9479 size = getSize (operandType (result));
9481 D (emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
9483 /* We only handle certain easy cases so far. */
9485 && (shCount < (size * 8))
9489 D(emitcode (";", "genLeftShiftLiteral wimping out"););
9493 freeAsmop (right, NULL, ic, TRUE);
9495 aopOp(left, ic, FALSE, FALSE);
9496 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
9499 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
9501 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
9502 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
9504 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
9507 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
9509 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
9510 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
9512 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
9518 emitcode ("; shift left ", "result %d, left %d", size,
9522 /* I suppose that the left size >= result size */
9525 _startLazyDPSEvaluation();
9528 movLeft2Result (left, size, result, size, 0);
9530 _endLazyDPSEvaluation();
9532 else if (shCount >= (size * 8))
9534 _startLazyDPSEvaluation();
9537 aopPut (result, zero, size);
9539 _endLazyDPSEvaluation();
9546 genlshOne (result, left, shCount);
9550 genlshTwo (result, left, shCount);
9554 genlshFour (result, left, shCount);
9558 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9559 "*** ack! mystery literal shift!\n");
9563 freeAsmop (result, NULL, ic, TRUE);
9564 freeAsmop (left, NULL, ic, TRUE);
9569 /*-----------------------------------------------------------------*/
9570 /* genLeftShift - generates code for left shifting */
9571 /*-----------------------------------------------------------------*/
9573 genLeftShift (iCode * ic)
9575 operand *left, *right, *result;
9578 symbol *tlbl, *tlbl1;
9581 D (emitcode (";", "genLeftShift"));
9583 right = IC_RIGHT (ic);
9584 left = IC_LEFT (ic);
9585 result = IC_RESULT (ic);
9587 aopOp (right, ic, FALSE, FALSE);
9590 #ifdef BETTER_LITERAL_SHIFT
9591 /* if the shift count is known then do it
9592 as efficiently as possible */
9593 if (AOP_TYPE (right) == AOP_LIT)
9595 if (genLeftShiftLiteral (left, right, result, ic))
9602 /* shift count is unknown then we have to form
9603 a loop get the loop count in B : Note: we take
9604 only the lower order byte since shifting
9605 more that 32 bits make no sense anyway, ( the
9606 largest size of an object can be only 32 bits ) */
9609 if (AOP_TYPE (right) == AOP_LIT)
9611 /* Really should be handled by genLeftShiftLiteral,
9612 * but since I'm too lazy to fix that today, at least we can make
9613 * some small improvement.
9615 emitcode("mov", "b,#!constbyte",
9616 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9620 MOVB (aopGet (right, 0, FALSE, FALSE, "b"));
9621 emitcode ("inc", "b");
9623 freeAsmop (right, NULL, ic, TRUE);
9624 aopOp (left, ic, FALSE, FALSE);
9625 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9627 /* now move the left to the result if they are not the same */
9628 if (!sameRegs (AOP (left), AOP (result)) &&
9629 AOP_SIZE (result) > 1)
9632 size = AOP_SIZE (result);
9634 _startLazyDPSEvaluation ();
9637 l = aopGet (left, offset, FALSE, TRUE, NULL);
9638 if (*l == '@' && (IS_AOP_PREG (result)))
9641 emitcode ("mov", "a,%s", l);
9642 aopPut (result, "a", offset);
9645 aopPut (result, l, offset);
9648 _endLazyDPSEvaluation ();
9651 tlbl = newiTempLabel (NULL);
9652 size = AOP_SIZE (result);
9654 tlbl1 = newiTempLabel (NULL);
9656 /* if it is only one byte then */
9659 symbol *tlbl1 = newiTempLabel (NULL);
9661 l = aopGet (left, 0, FALSE, FALSE, NULL);
9663 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9665 emitcode ("add", "a,acc");
9667 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9669 aopPut (result, "a", 0);
9673 reAdjustPreg (AOP (result));
9675 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9677 l = aopGet (result, offset, FALSE, FALSE, NULL);
9679 emitcode ("add", "a,acc");
9680 aopPut (result, "a", offset++);
9681 _startLazyDPSEvaluation ();
9684 l = aopGet (result, offset, FALSE, FALSE, NULL);
9686 emitcode ("rlc", "a");
9687 aopPut (result, "a", offset++);
9689 _endLazyDPSEvaluation ();
9690 reAdjustPreg (AOP (result));
9693 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9696 freeAsmop (result, NULL, ic, TRUE);
9697 freeAsmop (left, NULL, ic, TRUE);
9700 #ifdef BETTER_LITERAL_SHIFT
9701 /*-----------------------------------------------------------------*/
9702 /* genrshOne - right shift a one byte quantity by known count */
9703 /*-----------------------------------------------------------------*/
9705 genrshOne (operand * result, operand * left,
9706 int shCount, int sign)
9708 D (emitcode (";", "genrshOne"));
9710 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9714 #ifdef BETTER_LITERAL_SHIFT
9715 /*-----------------------------------------------------------------*/
9716 /* genrshTwo - right shift two bytes by known amount != 0 */
9717 /*-----------------------------------------------------------------*/
9719 genrshTwo (operand * result, operand * left,
9720 int shCount, int sign)
9722 D (emitcode (";", "genrshTwo"));
9724 /* if shCount >= 8 */
9728 _startLazyDPSEvaluation();
9730 shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9732 movLeft2Result (left, MSB16, result, LSB, sign);
9733 addSign (result, MSB16, sign);
9734 _endLazyDPSEvaluation();
9737 /* 1 <= shCount <= 7 */
9739 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9743 /*-----------------------------------------------------------------*/
9744 /* shiftRLong - shift right one long from left to result */
9745 /* offl = LSB or MSB16 */
9746 /*-----------------------------------------------------------------*/
9748 shiftRLong (operand * left, int offl,
9749 operand * result, int sign)
9751 bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9753 if (overlapping && offl>1)
9755 // we are in big trouble, but this shouldn't happen
9756 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9759 MOVA (aopGet (left, MSB32, FALSE, FALSE, NULL));
9766 emitcode ("rlc", "a");
9767 emitcode ("subb", "a,acc");
9768 emitcode ("xch", "a,%s",
9769 aopGet(left, MSB32, FALSE, FALSE, DP2_RESULT_REG));
9773 aopPut (result, zero, MSB32);
9779 emitcode ("clr", "c");
9783 emitcode ("mov", "c,acc.7");
9786 emitcode ("rrc", "a");
9788 if (overlapping && offl==MSB16)
9790 emitcode ("xch", "a,%s", aopGet (left, MSB24, FALSE, FALSE, DP2_RESULT_REG));
9794 aopPut (result, "a", MSB32 - offl);
9795 MOVA (aopGet (left, MSB24, FALSE, FALSE, NULL));
9798 emitcode ("rrc", "a");
9800 if (overlapping && offl==MSB16)
9802 emitcode ("xch", "a,%s", aopGet (left, MSB16, FALSE, FALSE, DP2_RESULT_REG));
9806 aopPut (result, "a", MSB24 - offl);
9807 MOVA (aopGet (left, MSB16, FALSE, FALSE, NULL));
9810 emitcode ("rrc", "a");
9813 aopPut (result, "a", MSB16 - offl);
9817 if (overlapping && offl==MSB16)
9819 emitcode ("xch", "a,%s", aopGet (left, LSB, FALSE, FALSE, DP2_RESULT_REG));
9823 aopPut (result, "a", MSB16 - offl);
9824 MOVA (aopGet (left, LSB, FALSE, FALSE, NULL));
9826 emitcode ("rrc", "a");
9827 aopPut (result, "a", LSB);
9831 /*-----------------------------------------------------------------*/
9832 /* genrshFour - shift four byte by a known amount != 0 */
9833 /*-----------------------------------------------------------------*/
9835 genrshFour (operand * result, operand * left,
9836 int shCount, int sign)
9838 D (emitcode (";", "genrshFour"));
9840 /* if shifting more that 3 bytes */
9844 _startLazyDPSEvaluation();
9846 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9848 movLeft2Result (left, MSB32, result, LSB, sign);
9849 addSign (result, MSB16, sign);
9850 _endLazyDPSEvaluation();
9852 else if (shCount >= 16)
9855 _startLazyDPSEvaluation();
9857 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9860 movLeft2Result (left, MSB24, result, LSB, 0);
9861 movLeft2Result (left, MSB32, result, MSB16, sign);
9863 addSign (result, MSB24, sign);
9864 _endLazyDPSEvaluation();
9866 else if (shCount >= 8)
9869 _startLazyDPSEvaluation();
9872 shiftRLong (left, MSB16, result, sign);
9874 else if (shCount == 0)
9876 movLeft2Result (left, MSB16, result, LSB, 0);
9877 movLeft2Result (left, MSB24, result, MSB16, 0);
9878 movLeft2Result (left, MSB32, result, MSB24, sign);
9879 addSign (result, MSB32, sign);
9883 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9884 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9885 /* the last shift is signed */
9886 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9887 addSign (result, MSB32, sign);
9889 _endLazyDPSEvaluation();
9893 /* 1 <= shCount <= 7 */
9896 shiftRLong (left, LSB, result, sign);
9898 shiftRLong (result, LSB, result, sign);
9902 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9903 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9904 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9909 #ifdef BETTER_LITERAL_SHIFT
9910 /*-----------------------------------------------------------------*/
9911 /* genRightShiftLiteral - right shifting by known count */
9912 /*-----------------------------------------------------------------*/
9914 genRightShiftLiteral (operand * left,
9920 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9923 size = getSize (operandType (result));
9925 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
9927 /* We only handle certain easy cases so far. */
9929 && (shCount < (size * 8))
9934 D(emitcode (";", "genRightShiftLiteral wimping out"););
9938 freeAsmop (right, NULL, ic, TRUE);
9940 aopOp (left, ic, FALSE, FALSE);
9941 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9944 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9948 /* test the LEFT size !!! */
9950 /* I suppose that the left size >= result size */
9953 size = getDataSize (result);
9954 _startLazyDPSEvaluation();
9956 movLeft2Result (left, size, result, size, 0);
9957 _endLazyDPSEvaluation();
9959 else if (shCount >= (size * 8))
9963 /* get sign in acc.7 */
9964 MOVA (aopGet (left, size - 1, FALSE, FALSE, NULL));
9966 addSign (result, LSB, sign);
9973 genrshOne (result, left, shCount, sign);
9977 genrshTwo (result, left, shCount, sign);
9981 genrshFour (result, left, shCount, sign);
9988 freeAsmop (result, NULL, ic, TRUE);
9989 freeAsmop (left, NULL, ic, TRUE);
9995 /*-----------------------------------------------------------------*/
9996 /* genSignedRightShift - right shift of signed number */
9997 /*-----------------------------------------------------------------*/
9999 genSignedRightShift (iCode * ic)
10001 operand *right, *left, *result;
10004 symbol *tlbl, *tlbl1;
10007 D (emitcode (";", "genSignedRightShift"));
10009 /* we do it the hard way put the shift count in b
10010 and loop thru preserving the sign */
10012 right = IC_RIGHT (ic);
10013 left = IC_LEFT (ic);
10014 result = IC_RESULT (ic);
10016 aopOp (right, ic, FALSE, FALSE);
10018 #ifdef BETTER_LITERAL_SHIFT
10019 if (AOP_TYPE (right) == AOP_LIT)
10021 if (genRightShiftLiteral (left, right, result, ic, 1))
10027 /* shift count is unknown then we have to form
10028 a loop get the loop count in B : Note: we take
10029 only the lower order byte since shifting
10030 more that 32 bits make no sense anyway, ( the
10031 largest size of an object can be only 32 bits ) */
10033 pushedB = pushB ();
10034 if (AOP_TYPE (right) == AOP_LIT)
10036 /* Really should be handled by genRightShiftLiteral,
10037 * but since I'm too lazy to fix that today, at least we can make
10038 * some small improvement.
10040 emitcode("mov", "b,#!constbyte",
10041 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
10045 MOVB (aopGet (right, 0, FALSE, FALSE, "b"));
10046 emitcode ("inc", "b");
10048 freeAsmop (right, NULL, ic, TRUE);
10049 aopOp (left, ic, FALSE, FALSE);
10050 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
10052 /* now move the left to the result if they are not the
10054 if (!sameRegs (AOP (left), AOP (result)) &&
10055 AOP_SIZE (result) > 1)
10058 size = AOP_SIZE (result);
10060 _startLazyDPSEvaluation ();
10063 l = aopGet (left, offset, FALSE, TRUE, NULL);
10064 if (*l == '@' && IS_AOP_PREG (result))
10067 emitcode ("mov", "a,%s", l);
10068 aopPut (result, "a", offset);
10071 aopPut (result, l, offset);
10074 _endLazyDPSEvaluation ();
10077 /* mov the highest order bit to OVR */
10078 tlbl = newiTempLabel (NULL);
10079 tlbl1 = newiTempLabel (NULL);
10081 size = AOP_SIZE (result);
10083 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
10084 emitcode ("rlc", "a");
10085 emitcode ("mov", "ov,c");
10086 /* if it is only one byte then */
10089 l = aopGet (left, 0, FALSE, FALSE, NULL);
10091 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10093 emitcode ("mov", "c,ov");
10094 emitcode ("rrc", "a");
10096 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10098 aopPut (result, "a", 0);
10102 reAdjustPreg (AOP (result));
10103 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10105 emitcode ("mov", "c,ov");
10106 _startLazyDPSEvaluation ();
10109 l = aopGet (result, offset, FALSE, FALSE, NULL);
10111 emitcode ("rrc", "a");
10112 aopPut (result, "a", offset--);
10114 _endLazyDPSEvaluation ();
10115 reAdjustPreg (AOP (result));
10117 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10121 freeAsmop (result, NULL, ic, TRUE);
10122 freeAsmop (left, NULL, ic, TRUE);
10125 /*-----------------------------------------------------------------*/
10126 /* genRightShift - generate code for right shifting */
10127 /*-----------------------------------------------------------------*/
10129 genRightShift (iCode * ic)
10131 operand *right, *left, *result;
10135 symbol *tlbl, *tlbl1;
10138 D (emitcode (";", "genRightShift"));
10140 /* if signed then we do it the hard way preserve the
10141 sign bit moving it inwards */
10142 letype = getSpec (operandType (IC_LEFT (ic)));
10144 if (!SPEC_USIGN (letype))
10146 genSignedRightShift (ic);
10150 /* signed & unsigned types are treated the same : i.e. the
10151 signed is NOT propagated inwards : quoting from the
10152 ANSI - standard : "for E1 >> E2, is equivalent to division
10153 by 2**E2 if unsigned or if it has a non-negative value,
10154 otherwise the result is implementation defined ", MY definition
10155 is that the sign does not get propagated */
10157 right = IC_RIGHT (ic);
10158 left = IC_LEFT (ic);
10159 result = IC_RESULT (ic);
10161 aopOp (right, ic, FALSE, FALSE);
10163 #ifdef BETTER_LITERAL_SHIFT
10164 /* if the shift count is known then do it
10165 as efficiently as possible */
10166 if (AOP_TYPE (right) == AOP_LIT)
10168 if (genRightShiftLiteral (left, right, result, ic, 0))
10175 /* shift count is unknown then we have to form
10176 a loop get the loop count in B : Note: we take
10177 only the lower order byte since shifting
10178 more that 32 bits make no sense anyway, ( the
10179 largest size of an object can be only 32 bits ) */
10181 pushedB = pushB ();
10182 if (AOP_TYPE (right) == AOP_LIT)
10184 /* Really should be handled by genRightShiftLiteral,
10185 * but since I'm too lazy to fix that today, at least we can make
10186 * some small improvement.
10188 emitcode("mov", "b,#!constbyte",
10189 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
10193 MOVB (aopGet (right, 0, FALSE, FALSE, "b"));
10194 emitcode ("inc", "b");
10196 freeAsmop (right, NULL, ic, TRUE);
10197 aopOp (left, ic, FALSE, FALSE);
10198 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
10200 /* now move the left to the result if they are not the
10202 if (!sameRegs (AOP (left), AOP (result)) &&
10203 AOP_SIZE (result) > 1)
10205 size = AOP_SIZE (result);
10207 _startLazyDPSEvaluation ();
10210 l = aopGet (left, offset, FALSE, TRUE, NULL);
10211 if (*l == '@' && IS_AOP_PREG (result))
10214 emitcode ("mov", "a,%s", l);
10215 aopPut (result, "a", offset);
10218 aopPut (result, l, offset);
10221 _endLazyDPSEvaluation ();
10224 tlbl = newiTempLabel (NULL);
10225 tlbl1 = newiTempLabel (NULL);
10226 size = AOP_SIZE (result);
10229 /* if it is only one byte then */
10232 l = aopGet (left, 0, FALSE, FALSE, NULL);
10234 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10237 emitcode ("rrc", "a");
10239 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10241 aopPut (result, "a", 0);
10245 reAdjustPreg (AOP (result));
10246 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10249 _startLazyDPSEvaluation ();
10252 l = aopGet (result, offset, FALSE, FALSE, NULL);
10254 emitcode ("rrc", "a");
10255 aopPut (result, "a", offset--);
10257 _endLazyDPSEvaluation ();
10258 reAdjustPreg (AOP (result));
10261 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10265 freeAsmop (result, NULL, ic, TRUE);
10266 freeAsmop (left, NULL, ic, TRUE);
10269 /*-----------------------------------------------------------------*/
10270 /* emitPtrByteGet - emits code to get a byte into A through a */
10271 /* pointer register (R0, R1, or DPTR). The */
10272 /* original value of A can be preserved in B. */
10273 /*-----------------------------------------------------------------*/
10275 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
10282 emitcode ("mov", "b,a");
10283 emitcode ("mov", "a,@%s", rname);
10288 emitcode ("mov", "b,a");
10289 emitcode ("movx", "a,@%s", rname);
10294 emitcode ("mov", "b,a");
10295 emitcode ("movx", "a,@dptr");
10300 emitcode ("mov", "b,a");
10301 emitcode ("clr", "a");
10302 emitcode ("movc", "a,@a+dptr");
10308 emitcode ("push", "b");
10309 emitcode ("push", "acc");
10311 emitcode ("lcall", "__gptrget");
10313 emitcode ("pop", "b");
10318 /*-----------------------------------------------------------------*/
10319 /* emitPtrByteSet - emits code to set a byte from src through a */
10320 /* pointer register (R0, R1, or DPTR). */
10321 /*-----------------------------------------------------------------*/
10323 emitPtrByteSet (char *rname, int p_type, char *src)
10332 emitcode ("mov", "@%s,a", rname);
10335 emitcode ("mov", "@%s,%s", rname, src);
10340 emitcode ("movx", "@%s,a", rname);
10345 emitcode ("movx", "@dptr,a");
10350 emitcode ("lcall", "__gptrput");
10355 /*-----------------------------------------------------------------*/
10356 /* genUnpackBits - generates code for unpacking bits */
10357 /*-----------------------------------------------------------------*/
10359 genUnpackBits (operand * result, char *rname, int ptype)
10361 int offset = 0; /* result byte offset */
10362 int rsize; /* result size */
10363 int rlen = 0; /* remaining bitfield length */
10364 sym_link *etype; /* bitfield type information */
10365 int blen; /* bitfield length */
10366 int bstr; /* bitfield starting bit within byte */
10368 D(emitcode ("; genUnpackBits",""));
10370 etype = getSpec (operandType (result));
10371 rsize = getSize (operandType (result));
10372 blen = SPEC_BLEN (etype);
10373 bstr = SPEC_BSTR (etype);
10375 /* If the bitfield length is less than a byte */
10378 emitPtrByteGet (rname, ptype, FALSE);
10380 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
10381 if (!SPEC_USIGN (etype))
10383 /* signed bitfield */
10384 symbol *tlbl = newiTempLabel (NULL);
10386 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
10387 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
10390 aopPut (result, "a", offset++);
10394 /* Bit field did not fit in a byte. Copy all
10395 but the partial byte at the end. */
10396 for (rlen=blen;rlen>=8;rlen-=8)
10398 emitPtrByteGet (rname, ptype, FALSE);
10399 aopPut (result, "a", offset++);
10401 emitcode ("inc", "%s", rname);
10404 /* Handle the partial byte at the end */
10407 emitPtrByteGet (rname, ptype, FALSE);
10408 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
10409 if (!SPEC_USIGN (etype))
10411 /* signed bitfield */
10412 symbol *tlbl = newiTempLabel (NULL);
10414 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
10415 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
10418 aopPut (result, "a", offset++);
10422 if (offset < rsize)
10426 if (SPEC_USIGN (etype))
10430 /* signed bitfield: sign extension with 0x00 or 0xff */
10431 emitcode ("rlc", "a");
10432 emitcode ("subb", "a,acc");
10438 aopPut (result, source, offset++);
10443 /*-----------------------------------------------------------------*/
10444 /* genDataPointerGet - generates code when ptr offset is known */
10445 /*-----------------------------------------------------------------*/
10447 genDataPointerGet (operand * left,
10453 int size, offset = 0;
10454 aopOp (result, ic, TRUE, FALSE);
10456 /* get the string representation of the name */
10457 l = aopGet (left, 0, FALSE, TRUE, NULL);
10458 size = AOP_SIZE (result);
10459 _startLazyDPSEvaluation ();
10464 SNPRINTF (buffer, sizeof(buffer),
10465 "(%s + %d)", l + 1, offset);
10469 SNPRINTF (buffer, sizeof(buffer),
10472 aopPut (result, buffer, offset++);
10474 _endLazyDPSEvaluation ();
10476 freeAsmop (result, NULL, ic, TRUE);
10477 freeAsmop (left, NULL, ic, TRUE);
10480 /*-----------------------------------------------------------------*/
10481 /* genNearPointerGet - emitcode for near pointer fetch */
10482 /*-----------------------------------------------------------------*/
10484 genNearPointerGet (operand * left,
10492 sym_link *rtype, *retype, *letype;
10493 sym_link *ltype = operandType (left);
10496 rtype = operandType (result);
10497 retype = getSpec (rtype);
10498 letype = getSpec (ltype);
10500 aopOp (left, ic, FALSE, FALSE);
10502 /* if left is rematerialisable and
10503 result is not bitfield variable type and
10504 the left is pointer to data space i.e
10505 lower 128 bytes of space */
10506 if (AOP_TYPE (left) == AOP_IMMD &&
10507 !IS_BITFIELD (retype) &&
10508 !IS_BITFIELD (letype) &&
10509 DCL_TYPE (ltype) == POINTER)
10511 genDataPointerGet (left, result, ic);
10515 /* if the value is already in a pointer register
10516 then don't need anything more */
10517 if (!AOP_INPREG (AOP (left)))
10519 /* otherwise get a free pointer register */
10520 aop = newAsmop (0);
10521 preg = getFreePtr (ic, &aop, FALSE);
10522 emitcode ("mov", "%s,%s",
10524 aopGet (left, 0, FALSE, TRUE, DP2_RESULT_REG));
10525 rname = preg->name;
10528 rname = aopGet (left, 0, FALSE, FALSE, DP2_RESULT_REG);
10530 freeAsmop (left, NULL, ic, TRUE);
10531 aopOp (result, ic, FALSE, FALSE);
10533 /* if bitfield then unpack the bits */
10534 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10535 genUnpackBits (result, rname, POINTER);
10538 /* we have can just get the values */
10539 int size = AOP_SIZE (result);
10544 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
10547 emitcode ("mov", "a,@%s", rname);
10548 aopPut (result, "a", offset);
10552 SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
10553 aopPut (result, buffer, offset);
10557 emitcode ("inc", "%s", rname);
10561 /* now some housekeeping stuff */
10562 if (aop) /* we had to allocate for this iCode */
10564 if (pi) { /* post increment present */
10565 aopPut (left, rname, 0);
10567 freeAsmop (NULL, aop, ic, TRUE);
10571 /* we did not allocate which means left
10572 already in a pointer register, then
10573 if size > 0 && this could be used again
10574 we have to point it back to where it
10576 if (AOP_SIZE (result) > 1 &&
10577 !OP_SYMBOL (left)->remat &&
10578 (OP_SYMBOL (left)->liveTo > ic->seq ||
10582 int size = AOP_SIZE (result) - 1;
10584 emitcode ("dec", "%s", rname);
10589 freeAsmop (result, NULL, ic, TRUE);
10590 if (pi) pi->generated = 1;
10593 /*-----------------------------------------------------------------*/
10594 /* genPagedPointerGet - emitcode for paged pointer fetch */
10595 /*-----------------------------------------------------------------*/
10597 genPagedPointerGet (operand * left,
10605 sym_link *rtype, *retype, *letype;
10607 rtype = operandType (result);
10608 retype = getSpec (rtype);
10609 letype = getSpec (operandType (left));
10610 aopOp (left, ic, FALSE, FALSE);
10612 /* if the value is already in a pointer register
10613 then don't need anything more */
10614 if (!AOP_INPREG (AOP (left)))
10616 /* otherwise get a free pointer register */
10617 aop = newAsmop (0);
10618 preg = getFreePtr (ic, &aop, FALSE);
10619 emitcode ("mov", "%s,%s",
10621 aopGet (left, 0, FALSE, TRUE, NULL));
10622 rname = preg->name;
10625 rname = aopGet (left, 0, FALSE, FALSE, NULL);
10627 freeAsmop (left, NULL, ic, TRUE);
10628 aopOp (result, ic, FALSE, FALSE);
10630 /* if bitfield then unpack the bits */
10631 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10632 genUnpackBits (result, rname, PPOINTER);
10635 /* we have can just get the values */
10636 int size = AOP_SIZE (result);
10642 emitcode ("movx", "a,@%s", rname);
10643 aopPut (result, "a", offset);
10648 emitcode ("inc", "%s", rname);
10652 /* now some housekeeping stuff */
10653 if (aop) /* we had to allocate for this iCode */
10656 aopPut (left, rname, 0);
10657 freeAsmop (NULL, aop, ic, TRUE);
10661 /* we did not allocate which means left
10662 already in a pointer register, then
10663 if size > 0 && this could be used again
10664 we have to point it back to where it
10666 if (AOP_SIZE (result) > 1 &&
10667 !OP_SYMBOL (left)->remat &&
10668 (OP_SYMBOL (left)->liveTo > ic->seq ||
10672 int size = AOP_SIZE (result) - 1;
10674 emitcode ("dec", "%s", rname);
10679 freeAsmop (result, NULL, ic, TRUE);
10680 if (pi) pi->generated = 1;
10683 /*-----------------------------------------------------------------*/
10684 /* genFarPointerGet - get value from far space */
10685 /*-----------------------------------------------------------------*/
10687 genFarPointerGet (operand * left,
10688 operand * result, iCode * ic, iCode *pi)
10690 int size, offset, dopi=1;
10691 sym_link *retype = getSpec (operandType (result));
10692 sym_link *letype = getSpec (operandType (left));
10693 D (emitcode (";", "genFarPointerGet"););
10695 aopOp (left, ic, FALSE, FALSE);
10697 /* if the operand is already in dptr
10698 then we do nothing else we move the value to dptr */
10699 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
10701 /* if this is rematerializable */
10702 if (AOP_TYPE (left) == AOP_IMMD)
10704 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
10708 /* we need to get it byte by byte */
10709 _startLazyDPSEvaluation ();
10710 if (AOP_TYPE (left) != AOP_DPTR)
10712 emitcode ("mov", "dpl,%s", aopGet (left, 0, FALSE, FALSE, NULL));
10713 emitcode ("mov", "dph,%s", aopGet (left, 1, FALSE, FALSE, NULL));
10714 if (options.model == MODEL_FLAT24)
10715 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10719 /* We need to generate a load to DPTR indirect through DPTR. */
10720 D (emitcode (";", "genFarPointerGet -- indirection special case."););
10721 emitcode ("push", "%s", aopGet (left, 0, FALSE, TRUE, NULL));
10722 emitcode ("push", "%s", aopGet (left, 1, FALSE, TRUE, NULL));
10723 if (options.model == MODEL_FLAT24)
10724 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10725 emitcode ("pop", "dph");
10726 emitcode ("pop", "dpl");
10729 _endLazyDPSEvaluation ();
10732 /* so dptr now contains the address */
10733 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10735 /* if bit then unpack */
10736 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
10737 if (AOP_INDPTRn(left)) {
10738 genSetDPTR(AOP(left)->aopu.dptr);
10740 genUnpackBits (result, "dptr", FPOINTER);
10741 if (AOP_INDPTRn(left)) {
10746 size = AOP_SIZE (result);
10749 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10751 genSetDPTR(AOP(left)->aopu.dptr);
10752 emitcode ("movx", "a,@dptr");
10753 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10754 emitcode ("inc", "dptr");
10756 aopPut (result, "a", offset++);
10759 _startLazyDPSEvaluation ();
10761 if (AOP_INDPTRn(left)) {
10762 genSetDPTR(AOP(left)->aopu.dptr);
10768 emitcode ("movx", "a,@dptr");
10769 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10770 emitcode ("inc", "dptr");
10772 aopPut (result, "a", offset++);
10774 _endLazyDPSEvaluation ();
10777 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10778 if (!AOP_INDPTRn(left)) {
10779 _startLazyDPSEvaluation ();
10780 aopPut (left, "dpl", 0);
10781 aopPut (left, "dph", 1);
10782 if (options.model == MODEL_FLAT24)
10783 aopPut (left, "dpx", 2);
10784 _endLazyDPSEvaluation ();
10787 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
10788 AOP_SIZE(result) > 1 &&
10790 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
10792 size = AOP_SIZE (result) - 1;
10793 if (AOP_INDPTRn(left)) {
10794 genSetDPTR(AOP(left)->aopu.dptr);
10796 while (size--) emitcode ("lcall","__decdptr");
10797 if (AOP_INDPTRn(left)) {
10802 freeAsmop (result, NULL, ic, TRUE);
10803 freeAsmop (left, NULL, ic, TRUE);
10806 /*-----------------------------------------------------------------*/
10807 /* genCodePointerGet - get value from code space */
10808 /*-----------------------------------------------------------------*/
10810 genCodePointerGet (operand * left,
10811 operand * result, iCode * ic, iCode *pi)
10813 int size, offset, dopi=1;
10814 sym_link *retype = getSpec (operandType (result));
10816 aopOp (left, ic, FALSE, FALSE);
10818 /* if the operand is already in dptr
10819 then we do nothing else we move the value to dptr */
10820 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
10822 /* if this is rematerializable */
10823 if (AOP_TYPE (left) == AOP_IMMD)
10825 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
10828 { /* we need to get it byte by byte */
10829 _startLazyDPSEvaluation ();
10830 if (AOP_TYPE (left) != AOP_DPTR)
10832 emitcode ("mov", "dpl,%s", aopGet (left, 0, FALSE, FALSE, NULL));
10833 emitcode ("mov", "dph,%s", aopGet (left, 1, FALSE, FALSE, NULL));
10834 if (options.model == MODEL_FLAT24)
10835 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10839 /* We need to generate a load to DPTR indirect through DPTR. */
10840 D (emitcode (";", "gencodePointerGet -- indirection special case."););
10841 emitcode ("push", "%s", aopGet (left, 0, FALSE, TRUE, NULL));
10842 emitcode ("push", "%s", aopGet (left, 1, FALSE, TRUE, NULL));
10843 if (options.model == MODEL_FLAT24)
10844 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10845 emitcode ("pop", "dph");
10846 emitcode ("pop", "dpl");
10849 _endLazyDPSEvaluation ();
10852 /* so dptr now contains the address */
10853 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10855 /* if bit then unpack */
10856 if (IS_BITFIELD (retype)) {
10857 if (AOP_INDPTRn(left)) {
10858 genSetDPTR(AOP(left)->aopu.dptr);
10860 genUnpackBits (result, "dptr", CPOINTER);
10861 if (AOP_INDPTRn(left)) {
10866 size = AOP_SIZE (result);
10868 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10870 genSetDPTR(AOP(left)->aopu.dptr);
10871 emitcode ("clr", "a");
10872 emitcode ("movc", "a,@a+dptr");
10873 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10874 emitcode ("inc", "dptr");
10876 aopPut (result, "a", offset++);
10879 _startLazyDPSEvaluation ();
10882 if (AOP_INDPTRn(left)) {
10883 genSetDPTR(AOP(left)->aopu.dptr);
10889 emitcode ("clr", "a");
10890 emitcode ("movc", "a,@a+dptr");
10891 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10892 emitcode ("inc", "dptr");
10893 aopPut (result, "a", offset++);
10895 _endLazyDPSEvaluation ();
10898 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10899 if (!AOP_INDPTRn(left)) {
10900 _startLazyDPSEvaluation ();
10902 aopPut (left, "dpl", 0);
10903 aopPut (left, "dph", 1);
10904 if (options.model == MODEL_FLAT24)
10905 aopPut (left, "dpx", 2);
10907 _endLazyDPSEvaluation ();
10910 } else if (IS_SYMOP(left) &&
10911 (OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
10912 AOP_SIZE(result) > 1 &&
10913 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10915 size = AOP_SIZE (result) - 1;
10916 if (AOP_INDPTRn(left)) {
10917 genSetDPTR(AOP(left)->aopu.dptr);
10919 while (size--) emitcode ("lcall","__decdptr");
10920 if (AOP_INDPTRn(left)) {
10925 freeAsmop (result, NULL, ic, TRUE);
10926 freeAsmop (left, NULL, ic, TRUE);
10929 /*-----------------------------------------------------------------*/
10930 /* genGenPointerGet - get value from generic pointer space */
10931 /*-----------------------------------------------------------------*/
10933 genGenPointerGet (operand * left,
10934 operand * result, iCode * ic, iCode * pi)
10938 sym_link *retype = getSpec (operandType (result));
10939 sym_link *letype = getSpec (operandType (left));
10941 D (emitcode (";", "genGenPointerGet"));
10943 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
10945 pushedB = pushB ();
10946 /* if the operand is already in dptr
10947 then we do nothing else we move the value to dptr */
10948 if (AOP_TYPE (left) != AOP_STR)
10950 /* if this is rematerializable */
10951 if (AOP_TYPE (left) == AOP_IMMD)
10953 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
10954 if (AOP(left)->aopu.aop_immd.from_cast_remat)
10956 MOVB (aopGet (left, AOP_SIZE(left)-1, FALSE, FALSE, NULL));
10960 emitcode ("mov", "b,#%d", pointerCode (retype));
10964 { /* we need to get it byte by byte */
10965 _startLazyDPSEvaluation ();
10966 emitcode ("mov", "dpl,%s", aopGet (left,0,FALSE,FALSE,NULL));
10967 emitcode ("mov", "dph,%s", aopGet (left,1,FALSE,FALSE,NULL));
10968 if (options.model == MODEL_FLAT24) {
10969 emitcode ("mov", "dpx,%s", aopGet (left,2,FALSE,FALSE,NULL));
10970 emitcode ("mov", "b,%s", aopGet (left,3,FALSE,FALSE,NULL));
10972 emitcode ("mov", "b,%s", aopGet (left,2,FALSE,FALSE,NULL));
10974 _endLazyDPSEvaluation ();
10978 /* so dptr-b now contains the address */
10979 aopOp (result, ic, FALSE, TRUE);
10981 /* if bit then unpack */
10982 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10984 genUnpackBits (result, "dptr", GPOINTER);
10988 size = AOP_SIZE (result);
10995 // Get two bytes at a time, results in _AP & A.
10996 // dptr will be incremented ONCE by __gptrgetWord.
10998 // Note: any change here must be coordinated
10999 // with the implementation of __gptrgetWord
11000 // in device/lib/_gptrget.c
11001 emitcode ("lcall", "__gptrgetWord");
11002 aopPut (result, DP2_RESULT_REG, offset++);
11003 aopPut (result, "a", offset++);
11008 // Only one byte to get.
11009 emitcode ("lcall", "__gptrget");
11010 aopPut (result, "a", offset++);
11013 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
11015 emitcode ("inc", "dptr");
11020 if (pi && AOP_TYPE (left) != AOP_IMMD) {
11021 _startLazyDPSEvaluation ();
11023 aopPut (left, "dpl", 0);
11024 aopPut (left, "dph", 1);
11025 if (options.model == MODEL_FLAT24) {
11026 aopPut (left, "dpx", 2);
11027 aopPut (left, "b", 3);
11028 } else aopPut (left, "b", 2);
11030 _endLazyDPSEvaluation ();
11033 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
11034 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
11036 size = AOP_SIZE (result) - 1;
11037 while (size--) emitcode ("lcall","__decdptr");
11041 freeAsmop (result, NULL, ic, TRUE);
11042 freeAsmop (left, NULL, ic, TRUE);
11045 /*-----------------------------------------------------------------*/
11046 /* genPointerGet - generate code for pointer get */
11047 /*-----------------------------------------------------------------*/
11049 genPointerGet (iCode * ic, iCode *pi)
11051 operand *left, *result;
11052 sym_link *type, *etype;
11055 D (emitcode (";", "genPointerGet"));
11057 left = IC_LEFT (ic);
11058 result = IC_RESULT (ic);
11060 /* depending on the type of pointer we need to
11061 move it to the correct pointer register */
11062 type = operandType (left);
11063 etype = getSpec (type);
11064 /* if left is of type of pointer then it is simple */
11065 if (IS_PTR (type) && !IS_FUNC (type->next))
11066 p_type = DCL_TYPE (type);
11069 /* we have to go by the storage class */
11070 p_type = PTR_TYPE (SPEC_OCLS (etype));
11073 /* special case when cast remat */
11074 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
11075 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
11077 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
11078 type = operandType (left);
11079 p_type = DCL_TYPE (type);
11081 /* now that we have the pointer type we assign
11082 the pointer values */
11088 genNearPointerGet (left, result, ic, pi);
11092 genPagedPointerGet (left, result, ic, pi);
11096 genFarPointerGet (left, result, ic, pi);
11100 genCodePointerGet (left, result, ic, pi);
11104 genGenPointerGet (left, result, ic, pi);
11110 /*-----------------------------------------------------------------*/
11111 /* genPackBits - generates code for packed bit storage */
11112 /*-----------------------------------------------------------------*/
11114 genPackBits (sym_link * etype,
11116 char *rname, int p_type)
11118 int offset = 0; /* source byte offset */
11119 int rlen = 0; /* remaining bitfield length */
11120 int blen; /* bitfield length */
11121 int bstr; /* bitfield starting bit within byte */
11122 int litval; /* source literal value (if AOP_LIT) */
11123 unsigned char mask; /* bitmask within current byte */
11125 D(emitcode ("; genPackBits",""));
11127 blen = SPEC_BLEN (etype);
11128 bstr = SPEC_BSTR (etype);
11130 /* If the bitfield length is less than a byte */
11133 mask = ((unsigned char) (0xFF << (blen + bstr)) |
11134 (unsigned char) (0xFF >> (8 - bstr)));
11136 if (AOP_TYPE (right) == AOP_LIT)
11138 /* Case with a bitfield length <8 and literal source
11140 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
11142 litval &= (~mask) & 0xff;
11143 emitPtrByteGet (rname, p_type, FALSE);
11144 if ((mask|litval)!=0xff)
11145 emitcode ("anl","a,#!constbyte", mask);
11147 emitcode ("orl","a,#!constbyte", litval);
11151 if ((blen==1) && (p_type!=GPOINTER))
11153 /* Case with a bitfield length == 1 and no generic pointer
11155 if (AOP_TYPE (right) == AOP_CRY)
11156 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
11159 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
11160 emitcode ("rrc","a");
11162 emitPtrByteGet (rname, p_type, FALSE);
11163 emitcode ("mov","acc.%d,c",bstr);
11168 /* Case with a bitfield length < 8 and arbitrary source
11170 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
11171 /* shift and mask source value */
11173 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
11175 pushedB = pushB ();
11176 /* transfer A to B and get next byte */
11177 emitPtrByteGet (rname, p_type, TRUE);
11179 emitcode ("anl", "a,#!constbyte", mask);
11180 emitcode ("orl", "a,b");
11181 if (p_type == GPOINTER)
11182 emitcode ("pop", "b");
11188 emitPtrByteSet (rname, p_type, "a");
11192 /* Bit length is greater than 7 bits. In this case, copy */
11193 /* all except the partial byte at the end */
11194 for (rlen=blen;rlen>=8;rlen-=8)
11196 emitPtrByteSet (rname, p_type,
11197 aopGet (right, offset++, FALSE, TRUE, NULL) );
11199 emitcode ("inc", "%s", rname);
11202 /* If there was a partial byte at the end */
11205 mask = (((unsigned char) -1 << rlen) & 0xff);
11207 if (AOP_TYPE (right) == AOP_LIT)
11209 /* Case with partial byte and literal source
11211 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
11212 litval >>= (blen-rlen);
11213 litval &= (~mask) & 0xff;
11214 emitPtrByteGet (rname, p_type, FALSE);
11215 if ((mask|litval)!=0xff)
11216 emitcode ("anl","a,#!constbyte", mask);
11218 emitcode ("orl","a,#!constbyte", litval);
11223 /* Case with partial byte and arbitrary source
11225 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11226 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
11228 pushedB = pushB ();
11229 /* transfer A to B and get next byte */
11230 emitPtrByteGet (rname, p_type, TRUE);
11232 emitcode ("anl", "a,#!constbyte", mask);
11233 emitcode ("orl", "a,b");
11234 if (p_type == GPOINTER)
11235 emitcode ("pop", "b");
11239 emitPtrByteSet (rname, p_type, "a");
11244 /*-----------------------------------------------------------------*/
11245 /* genDataPointerSet - remat pointer to data space */
11246 /*-----------------------------------------------------------------*/
11248 genDataPointerSet (operand * right,
11252 int size, offset = 0;
11253 char *l, buffer[256];
11255 D (emitcode (";", "genDataPointerSet"));
11257 aopOp (right, ic, FALSE, FALSE);
11259 l = aopGet (result, 0, FALSE, TRUE, NULL);
11260 size = AOP_SIZE (right);
11264 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l + 1, offset);
11266 SNPRINTF (buffer, sizeof(buffer), "%s", l + 1);
11267 emitcode ("mov", "%s,%s", buffer,
11268 aopGet (right, offset++, FALSE, FALSE, NULL));
11271 freeAsmop (result, NULL, ic, TRUE);
11272 freeAsmop (right, NULL, ic, TRUE);
11275 /*-----------------------------------------------------------------*/
11276 /* genNearPointerSet - emitcode for near pointer put */
11277 /*-----------------------------------------------------------------*/
11279 genNearPointerSet (operand * right,
11286 sym_link *retype, *letype;
11287 sym_link *ptype = operandType (result);
11289 D (emitcode (";", "genNearPointerSet"));
11291 retype = getSpec (operandType (right));
11292 letype = getSpec (ptype);
11294 aopOp (result, ic, FALSE, FALSE);
11296 /* if the result is rematerializable &
11297 in data space & not a bit variable */
11298 if (AOP_TYPE (result) == AOP_IMMD &&
11299 DCL_TYPE (ptype) == POINTER &&
11300 !IS_BITVAR (retype) &&
11301 !IS_BITVAR (letype))
11303 genDataPointerSet (right, result, ic);
11307 /* if the value is already in a pointer register
11308 then don't need anything more */
11309 if (!AOP_INPREG (AOP (result)))
11311 /* otherwise get a free pointer register */
11314 aop = newAsmop (0);
11315 preg = getFreePtr (ic, &aop, FALSE);
11316 emitcode ("mov", "%s,%s",
11318 aopGet (result, 0, FALSE, TRUE, NULL));
11319 rname = preg->name;
11323 rname = aopGet (result, 0, FALSE, FALSE, NULL);
11326 aopOp (right, ic, FALSE, FALSE);
11328 /* if bitfield then unpack the bits */
11329 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11330 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
11333 /* we can just get the values */
11334 int size = AOP_SIZE (right);
11339 l = aopGet (right, offset, FALSE, TRUE, NULL);
11340 if ((*l == '@') || (strcmp (l, "acc") == 0))
11343 emitcode ("mov", "@%s,a", rname);
11346 emitcode ("mov", "@%s,%s", rname, l);
11348 emitcode ("inc", "%s", rname);
11353 /* now some housekeeping stuff */
11354 if (aop) /* we had to allocate for this iCode */
11357 aopPut (result, rname, 0);
11358 freeAsmop (NULL, aop, ic, TRUE);
11362 /* we did not allocate which means left
11363 already in a pointer register, then
11364 if size > 0 && this could be used again
11365 we have to point it back to where it
11367 if (AOP_SIZE (right) > 1 &&
11368 !OP_SYMBOL (result)->remat &&
11369 (OP_SYMBOL (result)->liveTo > ic->seq ||
11373 int size = AOP_SIZE (right) - 1;
11375 emitcode ("dec", "%s", rname);
11380 if (pi) pi->generated = 1;
11381 freeAsmop (result, NULL, ic, TRUE);
11382 freeAsmop (right, NULL, ic, TRUE);
11385 /*-----------------------------------------------------------------*/
11386 /* genPagedPointerSet - emitcode for Paged pointer put */
11387 /*-----------------------------------------------------------------*/
11389 genPagedPointerSet (operand * right,
11396 sym_link *retype, *letype;
11398 D (emitcode (";", "genPagedPointerSet"));
11400 retype = getSpec (operandType (right));
11401 letype = getSpec (operandType (result));
11403 aopOp (result, ic, FALSE, FALSE);
11405 /* if the value is already in a pointer register
11406 then don't need anything more */
11407 if (!AOP_INPREG (AOP (result)))
11409 /* otherwise get a free pointer register */
11412 aop = newAsmop (0);
11413 preg = getFreePtr (ic, &aop, FALSE);
11414 emitcode ("mov", "%s,%s",
11416 aopGet (result, 0, FALSE, TRUE, NULL));
11417 rname = preg->name;
11420 rname = aopGet (result, 0, FALSE, FALSE, NULL);
11422 aopOp (right, ic, FALSE, FALSE);
11424 /* if bitfield then unpack the bits */
11425 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11426 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
11429 /* we have can just get the values */
11430 int size = AOP_SIZE (right);
11435 l = aopGet (right, offset, FALSE, TRUE, NULL);
11437 emitcode ("movx", "@%s,a", rname);
11440 emitcode ("inc", "%s", rname);
11446 /* now some housekeeping stuff */
11450 aopPut (result, rname, 0);
11451 /* we had to allocate for this iCode */
11452 freeAsmop (NULL, aop, ic, TRUE);
11456 /* we did not allocate which means left
11457 already in a pointer register, then
11458 if size > 0 && this could be used again
11459 we have to point it back to where it
11461 if (AOP_SIZE (right) > 1 &&
11462 !OP_SYMBOL (result)->remat &&
11463 (OP_SYMBOL (result)->liveTo > ic->seq ||
11467 int size = AOP_SIZE (right) - 1;
11469 emitcode ("dec", "%s", rname);
11474 if (pi) pi->generated = 1;
11475 freeAsmop (result, NULL, ic, TRUE);
11476 freeAsmop (right, NULL, ic, TRUE);
11479 /*-----------------------------------------------------------------*/
11480 /* genFarPointerSet - set value from far space */
11481 /*-----------------------------------------------------------------*/
11483 genFarPointerSet (operand * right,
11484 operand * result, iCode * ic, iCode *pi)
11486 int size, offset, dopi=1;
11487 sym_link *retype = getSpec (operandType (right));
11488 sym_link *letype = getSpec (operandType (result));
11490 aopOp (result, ic, FALSE, FALSE);
11492 /* if the operand is already in dptr
11493 then we do nothing else we move the value to dptr */
11494 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
11496 /* if this is remateriazable */
11497 if (AOP_TYPE (result) == AOP_IMMD)
11498 emitcode ("mov", "dptr,%s",
11499 aopGet (result, 0, TRUE, FALSE, NULL));
11502 /* we need to get it byte by byte */
11503 _startLazyDPSEvaluation ();
11504 if (AOP_TYPE (result) != AOP_DPTR)
11506 emitcode ("mov", "dpl,%s", aopGet (result, 0, FALSE, FALSE, NULL));
11507 emitcode ("mov", "dph,%s", aopGet (result, 1, FALSE, FALSE, NULL));
11508 if (options.model == MODEL_FLAT24)
11509 emitcode ("mov", "dpx,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11513 /* We need to generate a load to DPTR indirect through DPTR. */
11514 D (emitcode (";", "genFarPointerSet -- indirection special case."););
11516 emitcode ("push", "%s", aopGet (result, 0, FALSE, TRUE, NULL));
11517 emitcode ("push", "%s", aopGet (result, 1, FALSE, TRUE, NULL));
11518 if (options.model == MODEL_FLAT24)
11519 emitcode ("mov", "dpx,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11520 emitcode ("pop", "dph");
11521 emitcode ("pop", "dpl");
11524 _endLazyDPSEvaluation ();
11527 /* so dptr now contains the address */
11528 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
11530 /* if bit then unpack */
11531 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11533 if (AOP_INDPTRn(result)) {
11534 genSetDPTR(AOP(result)->aopu.dptr);
11536 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
11537 if (AOP_INDPTRn(result)) {
11541 size = AOP_SIZE (right);
11543 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
11545 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11547 genSetDPTR(AOP(result)->aopu.dptr);
11548 emitcode ("movx", "@dptr,a");
11549 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
11550 emitcode ("inc", "dptr");
11554 _startLazyDPSEvaluation ();
11556 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11558 if (AOP_INDPTRn(result)) {
11559 genSetDPTR(AOP(result)->aopu.dptr);
11565 emitcode ("movx", "@dptr,a");
11566 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
11567 emitcode ("inc", "dptr");
11569 _endLazyDPSEvaluation ();
11573 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
11574 if (!AOP_INDPTRn(result)) {
11575 _startLazyDPSEvaluation ();
11577 aopPut (result,"dpl",0);
11578 aopPut (result,"dph",1);
11579 if (options.model == MODEL_FLAT24)
11580 aopPut (result,"dpx",2);
11582 _endLazyDPSEvaluation ();
11585 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
11586 AOP_SIZE(right) > 1 &&
11587 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
11589 size = AOP_SIZE (right) - 1;
11590 if (AOP_INDPTRn(result)) {
11591 genSetDPTR(AOP(result)->aopu.dptr);
11593 while (size--) emitcode ("lcall","__decdptr");
11594 if (AOP_INDPTRn(result)) {
11598 freeAsmop (result, NULL, ic, TRUE);
11599 freeAsmop (right, NULL, ic, TRUE);
11602 /*-----------------------------------------------------------------*/
11603 /* genGenPointerSet - set value from generic pointer space */
11604 /*-----------------------------------------------------------------*/
11606 genGenPointerSet (operand * right,
11607 operand * result, iCode * ic, iCode *pi)
11611 sym_link *retype = getSpec (operandType (right));
11612 sym_link *letype = getSpec (operandType (result));
11614 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
11616 pushedB = pushB ();
11617 /* if the operand is already in dptr
11618 then we do nothing else we move the value to dptr */
11619 if (AOP_TYPE (result) != AOP_STR)
11621 _startLazyDPSEvaluation ();
11622 /* if this is remateriazable */
11623 if (AOP_TYPE (result) == AOP_IMMD)
11625 emitcode ("mov", "dptr,%s", aopGet (result, 0, TRUE, FALSE, NULL));
11626 if (AOP(result)->aopu.aop_immd.from_cast_remat)
11628 MOVB (aopGet (result, AOP_SIZE(result)-1, FALSE, FALSE, NULL));
11633 "b,%s + 1", aopGet (result, 0, TRUE, FALSE, NULL));
11637 { /* we need to get it byte by byte */
11638 emitcode ("mov", "dpl,%s", aopGet (result, 0, FALSE, FALSE, NULL));
11639 emitcode ("mov", "dph,%s", aopGet (result, 1, FALSE, FALSE, NULL));
11640 if (options.model == MODEL_FLAT24) {
11641 emitcode ("mov", "dpx,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11642 emitcode ("mov", "b,%s", aopGet (result, 3, FALSE, FALSE, NULL));
11644 emitcode ("mov", "b,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11647 _endLazyDPSEvaluation ();
11649 /* so dptr + b now contains the address */
11650 aopOp (right, ic, FALSE, TRUE);
11652 /* if bit then unpack */
11653 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11655 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
11659 size = AOP_SIZE (right);
11662 _startLazyDPSEvaluation ();
11667 // Set two bytes at a time, passed in _AP & A.
11668 // dptr will be incremented ONCE by __gptrputWord.
11670 // Note: any change here must be coordinated
11671 // with the implementation of __gptrputWord
11672 // in device/lib/_gptrput.c
11673 emitcode("mov", "_ap, %s",
11674 aopGet (right, offset++, FALSE, FALSE, NULL));
11675 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11679 emitcode ("lcall", "__gptrputWord");
11684 // Only one byte to put.
11685 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11689 emitcode ("lcall", "__gptrput");
11692 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
11694 emitcode ("inc", "dptr");
11697 _endLazyDPSEvaluation ();
11700 if (pi && AOP_TYPE (result) != AOP_IMMD) {
11701 _startLazyDPSEvaluation ();
11703 aopPut (result, "dpl",0);
11704 aopPut (result, "dph",1);
11705 if (options.model == MODEL_FLAT24) {
11706 aopPut (result, "dpx",2);
11707 aopPut (result, "b",3);
11709 aopPut (result, "b",2);
11711 _endLazyDPSEvaluation ();
11714 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
11715 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
11717 size = AOP_SIZE (right) - 1;
11718 while (size--) emitcode ("lcall","__decdptr");
11722 freeAsmop (result, NULL, ic, TRUE);
11723 freeAsmop (right, NULL, ic, TRUE);
11726 /*-----------------------------------------------------------------*/
11727 /* genPointerSet - stores the value into a pointer location */
11728 /*-----------------------------------------------------------------*/
11730 genPointerSet (iCode * ic, iCode *pi)
11732 operand *right, *result;
11733 sym_link *type, *etype;
11736 D (emitcode (";", "genPointerSet"));
11738 right = IC_RIGHT (ic);
11739 result = IC_RESULT (ic);
11741 /* depending on the type of pointer we need to
11742 move it to the correct pointer register */
11743 type = operandType (result);
11744 etype = getSpec (type);
11745 /* if left is of type of pointer then it is simple */
11746 if (IS_PTR (type) && !IS_FUNC (type->next))
11748 p_type = DCL_TYPE (type);
11752 /* we have to go by the storage class */
11753 p_type = PTR_TYPE (SPEC_OCLS (etype));
11756 /* special case when cast remat */
11757 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
11758 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
11759 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
11760 type = operandType (result);
11761 p_type = DCL_TYPE (type);
11764 /* now that we have the pointer type we assign
11765 the pointer values */
11771 genNearPointerSet (right, result, ic, pi);
11775 genPagedPointerSet (right, result, ic, pi);
11779 genFarPointerSet (right, result, ic, pi);
11783 genGenPointerSet (right, result, ic, pi);
11787 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11788 "genPointerSet: illegal pointer type");
11792 /*-----------------------------------------------------------------*/
11793 /* genIfx - generate code for Ifx statement */
11794 /*-----------------------------------------------------------------*/
11796 genIfx (iCode * ic, iCode * popIc)
11798 operand *cond = IC_COND (ic);
11802 D (emitcode (";", "genIfx"));
11804 aopOp (cond, ic, FALSE, FALSE);
11806 /* get the value into acc */
11807 if (AOP_TYPE (cond) != AOP_CRY)
11814 if (AOP(cond)->aopu.aop_dir)
11815 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
11818 /* the result is now in the accumulator or a directly addressable bit */
11819 freeAsmop (cond, NULL, ic, TRUE);
11821 /* if there was something to be popped then do it */
11825 /* if the condition is a bit variable */
11827 genIfxJump (ic, dup);
11828 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
11829 genIfxJump (ic, SPIL_LOC (cond)->rname);
11830 else if (isbit && !IS_ITEMP (cond))
11831 genIfxJump (ic, OP_SYMBOL (cond)->rname);
11833 genIfxJump (ic, "a");
11838 /*-----------------------------------------------------------------*/
11839 /* genAddrOf - generates code for address of */
11840 /*-----------------------------------------------------------------*/
11842 genAddrOf (iCode * ic)
11844 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11847 D (emitcode (";", "genAddrOf"));
11849 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11851 /* if the operand is on the stack then we
11852 need to get the stack offset of this
11857 /* if 10 bit stack */
11858 if (options.stack10bit) {
11862 tsprintf(buff, sizeof(buff),
11863 "#!constbyte",(options.stack_loc >> 16) & 0xff);
11864 /* if it has an offset then we need to compute it */
11865 /* emitcode ("subb", "a,#!constbyte", */
11866 /* -((sym->stack < 0) ? */
11867 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11868 /* ((short) sym->stack)) & 0xff); */
11869 /* emitcode ("mov","b,a"); */
11870 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
11871 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11872 /* ((short) sym->stack)) >> 8) & 0xff); */
11874 emitcode ("mov", "a,_bpx");
11875 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
11876 ((char) (sym->stack - _G.nRegsSaved)) :
11877 ((char) sym->stack )) & 0xff);
11878 emitcode ("mov", "b,a");
11879 emitcode ("mov", "a,_bpx+1");
11881 offset = (((sym->stack < 0) ?
11882 ((short) (sym->stack - _G.nRegsSaved)) :
11883 ((short) sym->stack )) >> 8) & 0xff;
11885 emitcode ("addc","a,#!constbyte", offset);
11887 aopPut (IC_RESULT (ic), "b", 0);
11888 aopPut (IC_RESULT (ic), "a", 1);
11889 aopPut (IC_RESULT (ic), buff, 2);
11891 /* we can just move _bp */
11892 aopPut (IC_RESULT (ic), "_bpx", 0);
11893 aopPut (IC_RESULT (ic), "_bpx+1", 1);
11894 aopPut (IC_RESULT (ic), buff, 2);
11897 /* if it has an offset then we need to compute it */
11900 emitcode ("mov", "a,_bp");
11901 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
11902 aopPut (IC_RESULT (ic), "a", 0);
11906 /* we can just move _bp */
11907 aopPut (IC_RESULT (ic), "_bp", 0);
11909 /* fill the result with zero */
11910 size = AOP_SIZE (IC_RESULT (ic)) - 1;
11913 if (options.stack10bit && size < (FPTRSIZE - 1)) {
11915 "*** warning: pointer to stack var truncated.\n");
11921 aopPut (IC_RESULT (ic), zero, offset++);
11927 /* object not on stack then we need the name */
11928 size = AOP_SIZE (IC_RESULT (ic));
11933 char s[SDCC_NAME_MAX];
11937 tsprintf(s, sizeof(s), "#!his",sym->rname);
11940 tsprintf(s, sizeof(s), "#!hihis",sym->rname);
11943 tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
11945 default: /* should not need this (just in case) */
11946 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
11953 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11956 aopPut (IC_RESULT (ic), s, offset++);
11960 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11964 #if 0 // obsolete, and buggy for != xdata
11965 /*-----------------------------------------------------------------*/
11966 /* genArrayInit - generates code for address of */
11967 /*-----------------------------------------------------------------*/
11969 genArrayInit (iCode * ic)
11971 literalList *iLoop;
11973 int elementSize = 0, eIndex;
11974 unsigned val, lastVal;
11976 operand *left=IC_LEFT(ic);
11978 D (emitcode (";", "genArrayInit"));
11980 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
11982 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
11984 // Load immediate value into DPTR.
11985 emitcode("mov", "dptr, %s",
11986 aopGet (IC_LEFT(ic), 0, TRUE, FALSE, NULL));
11988 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
11991 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11992 "Unexpected operand to genArrayInit.\n");
11995 // a regression because of SDCCcse.c:1.52
11996 emitcode ("mov", "dpl,%s", aopGet (left, 0, FALSE, FALSE, NULL));
11997 emitcode ("mov", "dph,%s", aopGet (left, 1, FALSE, FALSE, NULL));
11998 if (options.model == MODEL_FLAT24)
11999 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
12003 type = operandType(IC_LEFT(ic));
12005 if (type && type->next)
12007 elementSize = getSize(type->next);
12011 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12012 "can't determine element size in genArrayInit.\n");
12016 iLoop = IC_ARRAYILIST(ic);
12021 bool firstpass = TRUE;
12023 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
12024 iLoop->count, (int)iLoop->literalValue, elementSize);
12030 symbol *tlbl = NULL;
12032 count = ix > 256 ? 256 : ix;
12036 tlbl = newiTempLabel (NULL);
12037 if (firstpass || (count & 0xff))
12039 emitcode("mov", "b, #!constbyte", count & 0xff);
12047 for (eIndex = 0; eIndex < elementSize; eIndex++)
12049 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
12050 if (val != lastVal)
12052 emitcode("mov", "a, #!constbyte", val);
12056 emitcode("movx", "@dptr, a");
12057 emitcode("inc", "dptr");
12062 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
12068 iLoop = iLoop->next;
12071 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
12075 /*-----------------------------------------------------------------*/
12076 /* genFarFarAssign - assignment when both are in far space */
12077 /*-----------------------------------------------------------------*/
12079 genFarFarAssign (operand * result, operand * right, iCode * ic)
12081 int size = AOP_SIZE (right);
12083 symbol *rSym = NULL;
12087 /* quick & easy case. */
12088 D (emitcode(";","genFarFarAssign (1 byte case)"));
12089 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
12090 freeAsmop (right, NULL, ic, FALSE);
12091 /* now assign DPTR to result */
12093 aopOp(result, ic, FALSE, FALSE);
12095 aopPut (result, "a", 0);
12096 freeAsmop(result, NULL, ic, FALSE);
12100 /* See if we've got an underlying symbol to abuse. */
12101 if (IS_SYMOP(result) && OP_SYMBOL(result))
12103 if (IS_TRUE_SYMOP(result))
12105 rSym = OP_SYMBOL(result);
12107 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
12109 rSym = OP_SYMBOL(result)->usl.spillLoc;
12113 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
12115 /* We can use the '390 auto-toggle feature to good effect here. */
12117 D (emitcode(";", "genFarFarAssign (390 auto-toggle fun)"));
12118 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12119 emitcode ("mov", "dptr,#%s", rSym->rname);
12120 /* DP2 = result, DP1 = right, DP1 is current. */
12123 emitcode("movx", "a,@dptr");
12124 emitcode("movx", "@dptr,a");
12127 emitcode("inc", "dptr");
12128 emitcode("inc", "dptr");
12131 emitcode("mov", "dps,#0");
12132 freeAsmop (right, NULL, ic, FALSE);
12134 some alternative code for processors without auto-toggle
12135 no time to test now, so later well put in...kpb
12136 D (emitcode(";", "genFarFarAssign (dual-dptr fun)"));
12137 emitcode("mov", "dps,#1"); /* Select DPTR2. */
12138 emitcode ("mov", "dptr,#%s", rSym->rname);
12139 /* DP2 = result, DP1 = right, DP1 is current. */
12143 emitcode("movx", "a,@dptr");
12145 emitcode("inc", "dptr");
12146 emitcode("inc", "dps");
12147 emitcode("movx", "@dptr,a");
12149 emitcode("inc", "dptr");
12150 emitcode("inc", "dps");
12152 emitcode("mov", "dps,#0");
12153 freeAsmop (right, NULL, ic, FALSE);
12158 D (emitcode (";", "genFarFarAssign"));
12159 aopOp (result, ic, TRUE, TRUE);
12161 _startLazyDPSEvaluation ();
12166 aopGet (right, offset, FALSE, FALSE, NULL), offset);
12169 _endLazyDPSEvaluation ();
12170 freeAsmop (result, NULL, ic, FALSE);
12171 freeAsmop (right, NULL, ic, FALSE);
12175 /*-----------------------------------------------------------------*/
12176 /* genAssign - generate code for assignment */
12177 /*-----------------------------------------------------------------*/
12179 genAssign (iCode * ic)
12181 operand *result, *right;
12183 unsigned long lit = 0L;
12185 D (emitcode (";", "genAssign"));
12187 result = IC_RESULT (ic);
12188 right = IC_RIGHT (ic);
12190 /* if they are the same */
12191 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
12194 aopOp (right, ic, FALSE, FALSE);
12196 emitcode (";", "genAssign: resultIsFar = %s",
12197 isOperandInFarSpace (result) ?
12200 /* special case both in far space */
12201 if ((AOP_TYPE (right) == AOP_DPTR ||
12202 AOP_TYPE (right) == AOP_DPTR2) &&
12203 /* IS_TRUE_SYMOP(result) && */
12204 isOperandInFarSpace (result))
12206 genFarFarAssign (result, right, ic);
12210 aopOp (result, ic, TRUE, FALSE);
12212 /* if they are the same registers */
12213 if (sameRegs (AOP (right), AOP (result)))
12216 /* if the result is a bit */
12217 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
12219 /* if the right size is a literal then
12220 we know what the value is */
12221 if (AOP_TYPE (right) == AOP_LIT)
12223 if (((int) operandLitValue (right)))
12224 aopPut (result, one, 0);
12226 aopPut (result, zero, 0);
12230 /* the right is also a bit variable */
12231 if (AOP_TYPE (right) == AOP_CRY)
12233 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12234 aopPut (result, "c", 0);
12238 /* we need to or */
12240 aopPut (result, "a", 0);
12244 /* bit variables done */
12246 size = AOP_SIZE (result);
12248 if (AOP_TYPE (right) == AOP_LIT)
12249 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
12252 (AOP_TYPE (result) != AOP_REG) &&
12253 (AOP_TYPE (right) == AOP_LIT) &&
12254 !IS_FLOAT (operandType (right)))
12256 _startLazyDPSEvaluation ();
12257 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
12260 aopGet (right, offset, FALSE, FALSE, NULL),
12265 /* And now fill the rest with zeros. */
12268 emitcode ("clr", "a");
12272 aopPut (result, "a", offset++);
12274 _endLazyDPSEvaluation ();
12278 _startLazyDPSEvaluation ();
12282 aopGet (right, offset, FALSE, FALSE, NULL),
12286 _endLazyDPSEvaluation ();
12290 freeAsmop (result, NULL, ic, TRUE);
12291 freeAsmop (right, NULL, ic, TRUE);
12294 /*-----------------------------------------------------------------*/
12295 /* genJumpTab - generates code for jump table */
12296 /*-----------------------------------------------------------------*/
12298 genJumpTab (iCode * ic)
12303 D (emitcode (";", "genJumpTab"));
12305 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
12306 /* get the condition into accumulator */
12307 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE, NULL);
12309 /* multiply by four! */
12310 emitcode ("add", "a,acc");
12311 emitcode ("add", "a,acc");
12312 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
12314 jtab = newiTempLabel (NULL);
12315 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
12316 emitcode ("jmp", "@a+dptr");
12318 /* now generate the jump labels */
12319 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
12320 jtab = setNextItem (IC_JTLABELS (ic)))
12321 emitcode ("ljmp", "!tlabel", jtab->key + 100);
12325 /*-----------------------------------------------------------------*/
12326 /* genCast - gen code for casting */
12327 /*-----------------------------------------------------------------*/
12329 genCast (iCode * ic)
12331 operand *result = IC_RESULT (ic);
12332 sym_link *ctype = operandType (IC_LEFT (ic));
12333 sym_link *rtype = operandType (IC_RIGHT (ic));
12334 operand *right = IC_RIGHT (ic);
12337 D (emitcode (";", "genCast"));
12339 /* if they are equivalent then do nothing */
12340 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
12343 aopOp (right, ic, FALSE, AOP_IS_STR (result));
12344 aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
12346 /* if the result is a bit (and not a bitfield) */
12347 if (IS_BIT (OP_SYMBOL (result)->type))
12349 /* if the right size is a literal then
12350 we know what the value is */
12351 if (AOP_TYPE (right) == AOP_LIT)
12353 if (((int) operandLitValue (right)))
12354 aopPut (result, one, 0);
12356 aopPut (result, zero, 0);
12361 /* the right is also a bit variable */
12362 if (AOP_TYPE (right) == AOP_CRY)
12364 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12365 aopPut (result, "c", 0);
12369 /* we need to or */
12371 aopPut (result, "a", 0);
12375 /* if they are the same size : or less */
12376 if (AOP_SIZE (result) <= AOP_SIZE (right))
12379 /* if they are in the same place */
12380 if (sameRegs (AOP (right), AOP (result)))
12383 /* if they in different places then copy */
12384 size = AOP_SIZE (result);
12386 _startLazyDPSEvaluation ();
12390 aopGet (right, offset, FALSE, FALSE, NULL),
12394 _endLazyDPSEvaluation ();
12398 /* if the result is of type pointer */
12399 if (IS_PTR (ctype))
12403 sym_link *type = operandType (right);
12405 /* pointer to generic pointer */
12406 if (IS_GENPTR (ctype))
12410 p_type = DCL_TYPE (type);
12414 #if OLD_CAST_BEHAVIOR
12415 /* KV: we are converting a non-pointer type to
12416 * a generic pointer. This (ifdef'd out) code
12417 * says that the resulting generic pointer
12418 * should have the same class as the storage
12419 * location of the non-pointer variable.
12421 * For example, converting an int (which happens
12422 * to be stored in DATA space) to a pointer results
12423 * in a DATA generic pointer; if the original int
12424 * in XDATA space, so will be the resulting pointer.
12426 * I don't like that behavior, and thus this change:
12427 * all such conversions will be forced to XDATA and
12428 * throw a warning. If you want some non-XDATA
12429 * type, or you want to suppress the warning, you
12430 * must go through an intermediate cast, like so:
12432 * char _generic *gp = (char _xdata *)(intVar);
12434 sym_link *etype = getSpec (type);
12436 /* we have to go by the storage class */
12437 if (SPEC_OCLS (etype) != generic)
12439 p_type = PTR_TYPE (SPEC_OCLS (etype));
12444 /* Converting unknown class (i.e. register variable)
12445 * to generic pointer. This is not good, but
12446 * we'll make a guess (and throw a warning).
12449 werror (W_INT_TO_GEN_PTR_CAST);
12453 /* the first two bytes are known */
12454 size = GPTRSIZE - 1;
12456 _startLazyDPSEvaluation ();
12460 aopGet (right, offset, FALSE, FALSE, NULL),
12464 _endLazyDPSEvaluation ();
12466 /* the last byte depending on type */
12468 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
12473 // pointerTypeToGPByte will have bitched.
12477 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%x", gpVal);
12478 aopPut (result, gpValStr, GPTRSIZE - 1);
12483 /* just copy the pointers */
12484 size = AOP_SIZE (result);
12486 _startLazyDPSEvaluation ();
12490 aopGet (right, offset, FALSE, FALSE, NULL),
12494 _endLazyDPSEvaluation ();
12498 /* so we now know that the size of destination is greater
12499 than the size of the source */
12500 /* we move to result for the size of source */
12501 size = AOP_SIZE (right);
12503 _startLazyDPSEvaluation ();
12507 aopGet (right, offset, FALSE, FALSE, NULL),
12511 _endLazyDPSEvaluation ();
12513 /* now depending on the sign of the source && destination */
12514 size = AOP_SIZE (result) - AOP_SIZE (right);
12515 /* if unsigned or not an integral type */
12516 /* also, if the source is a bit, we don't need to sign extend, because
12517 * it can't possibly have set the sign bit.
12519 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
12523 aopPut (result, zero, offset++);
12528 /* we need to extend the sign :{ */
12529 MOVA (aopGet (right, AOP_SIZE (right) - 1,
12530 FALSE, FALSE, NULL));
12531 emitcode ("rlc", "a");
12532 emitcode ("subb", "a,acc");
12534 aopPut (result, "a", offset++);
12537 /* we are done hurray !!!! */
12540 freeAsmop (right, NULL, ic, TRUE);
12541 freeAsmop (result, NULL, ic, TRUE);
12545 /*-----------------------------------------------------------------*/
12546 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
12547 /*-----------------------------------------------------------------*/
12548 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
12550 operand *from , *to , *count;
12555 /* we know it has to be 3 parameters */
12556 assert (nparms == 3);
12558 rsave = newBitVect(16);
12559 /* save DPTR if it needs to be saved */
12560 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12561 if (bitVectBitValue(ic->rMask,i))
12562 rsave = bitVectSetBit(rsave,i);
12564 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12565 ds390_rUmaskForOp (IC_RESULT(ic))));
12572 aopOp (from, ic->next, FALSE, FALSE);
12574 /* get from into DPTR1 */
12575 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12576 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12577 if (options.model == MODEL_FLAT24) {
12578 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12581 freeAsmop (from, NULL, ic, FALSE);
12582 aopOp (to, ic, FALSE, FALSE);
12583 /* get "to" into DPTR */
12584 /* if the operand is already in dptr
12585 then we do nothing else we move the value to dptr */
12586 if (AOP_TYPE (to) != AOP_STR) {
12587 /* if already in DPTR then we need to push */
12588 if (AOP_TYPE(to) == AOP_DPTR) {
12589 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12590 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12591 if (options.model == MODEL_FLAT24)
12592 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12593 emitcode ("pop", "dph");
12594 emitcode ("pop", "dpl");
12596 _startLazyDPSEvaluation ();
12597 /* if this is remateriazable */
12598 if (AOP_TYPE (to) == AOP_IMMD) {
12599 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12600 } else { /* we need to get it byte by byte */
12601 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12602 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12603 if (options.model == MODEL_FLAT24) {
12604 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12607 _endLazyDPSEvaluation ();
12610 freeAsmop (to, NULL, ic, FALSE);
12611 _G.dptrInUse = _G.dptr1InUse = 1;
12612 aopOp (count, ic->next->next, FALSE,FALSE);
12613 lbl =newiTempLabel(NULL);
12615 /* now for the actual copy */
12616 if (AOP_TYPE(count) == AOP_LIT &&
12617 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12618 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12620 emitcode ("lcall","__bi_memcpyc2x_s");
12622 emitcode ("lcall","__bi_memcpyx2x_s");
12624 freeAsmop (count, NULL, ic, FALSE);
12626 symbol *lbl1 = newiTempLabel(NULL);
12628 emitcode (";"," Auto increment but no djnz");
12629 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12630 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12631 freeAsmop (count, NULL, ic, FALSE);
12632 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12635 emitcode ("clr","a");
12636 emitcode ("movc", "a,@a+dptr");
12638 emitcode ("movx", "a,@dptr");
12639 emitcode ("movx", "@dptr,a");
12640 emitcode ("inc", "dptr");
12641 emitcode ("inc", "dptr");
12642 emitcode ("mov","a,b");
12643 emitcode ("orl","a,_ap");
12644 emitcode ("jz","!tlabel",lbl1->key+100);
12645 emitcode ("mov","a,_ap");
12646 emitcode ("add","a,#!constbyte",0xFF);
12647 emitcode ("mov","_ap,a");
12648 emitcode ("mov","a,b");
12649 emitcode ("addc","a,#!constbyte",0xFF);
12650 emitcode ("mov","b,a");
12651 emitcode ("sjmp","!tlabel",lbl->key+100);
12654 emitcode ("mov", "dps,#0");
12655 _G.dptrInUse = _G.dptr1InUse = 0;
12656 unsavermask(rsave);
12660 /*-----------------------------------------------------------------*/
12661 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
12662 /*-----------------------------------------------------------------*/
12663 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
12665 operand *from , *to , *count;
12670 /* we know it has to be 3 parameters */
12671 assert (nparms == 3);
12673 rsave = newBitVect(16);
12674 /* save DPTR if it needs to be saved */
12675 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12676 if (bitVectBitValue(ic->rMask,i))
12677 rsave = bitVectSetBit(rsave,i);
12679 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12680 ds390_rUmaskForOp (IC_RESULT(ic))));
12687 aopOp (from, ic->next, FALSE, FALSE);
12689 /* get from into DPTR1 */
12690 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12691 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12692 if (options.model == MODEL_FLAT24) {
12693 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12696 freeAsmop (from, NULL, ic, FALSE);
12697 aopOp (to, ic, FALSE, FALSE);
12698 /* get "to" into DPTR */
12699 /* if the operand is already in dptr
12700 then we do nothing else we move the value to dptr */
12701 if (AOP_TYPE (to) != AOP_STR) {
12702 /* if already in DPTR then we need to push */
12703 if (AOP_TYPE(to) == AOP_DPTR) {
12704 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12705 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12706 if (options.model == MODEL_FLAT24)
12707 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12708 emitcode ("pop", "dph");
12709 emitcode ("pop", "dpl");
12711 _startLazyDPSEvaluation ();
12712 /* if this is remateriazable */
12713 if (AOP_TYPE (to) == AOP_IMMD) {
12714 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12715 } else { /* we need to get it byte by byte */
12716 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12717 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12718 if (options.model == MODEL_FLAT24) {
12719 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12722 _endLazyDPSEvaluation ();
12725 freeAsmop (to, NULL, ic, FALSE);
12726 _G.dptrInUse = _G.dptr1InUse = 1;
12727 aopOp (count, ic->next->next, FALSE,FALSE);
12728 lbl =newiTempLabel(NULL);
12729 lbl2 =newiTempLabel(NULL);
12731 /* now for the actual compare */
12732 if (AOP_TYPE(count) == AOP_LIT &&
12733 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12734 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12736 emitcode("lcall","__bi_memcmpc2x_s");
12738 emitcode("lcall","__bi_memcmpx2x_s");
12739 freeAsmop (count, NULL, ic, FALSE);
12740 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12741 aopPut(IC_RESULT(ic),"a",0);
12742 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12744 symbol *lbl1 = newiTempLabel(NULL);
12746 emitcode("push","ar0");
12747 emitcode (";"," Auto increment but no djnz");
12748 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12749 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12750 freeAsmop (count, NULL, ic, FALSE);
12751 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12754 emitcode ("clr","a");
12755 emitcode ("movc", "a,@a+dptr");
12757 emitcode ("movx", "a,@dptr");
12758 emitcode ("mov","r0,a");
12759 emitcode ("movx", "a,@dptr");
12760 emitcode ("clr","c");
12761 emitcode ("subb","a,r0");
12762 emitcode ("jnz","!tlabel",lbl2->key+100);
12763 emitcode ("inc", "dptr");
12764 emitcode ("inc", "dptr");
12765 emitcode ("mov","a,b");
12766 emitcode ("orl","a,_ap");
12767 emitcode ("jz","!tlabel",lbl1->key+100);
12768 emitcode ("mov","a,_ap");
12769 emitcode ("add","a,#!constbyte",0xFF);
12770 emitcode ("mov","_ap,a");
12771 emitcode ("mov","a,b");
12772 emitcode ("addc","a,#!constbyte",0xFF);
12773 emitcode ("mov","b,a");
12774 emitcode ("sjmp","!tlabel",lbl->key+100);
12776 emitcode ("clr","a");
12778 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12779 aopPut(IC_RESULT(ic),"a",0);
12780 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12781 emitcode("pop","ar0");
12782 emitcode ("mov", "dps,#0");
12784 _G.dptrInUse = _G.dptr1InUse = 0;
12785 unsavermask(rsave);
12789 /*-----------------------------------------------------------------*/
12790 /* genInp - gen code for __builtin_inp read data from a mem mapped */
12791 /* port, first parameter output area second parameter pointer to */
12792 /* port third parameter count */
12793 /*-----------------------------------------------------------------*/
12794 static void genInp( iCode *ic, int nparms, operand **parms)
12796 operand *from , *to , *count;
12801 /* we know it has to be 3 parameters */
12802 assert (nparms == 3);
12804 rsave = newBitVect(16);
12805 /* save DPTR if it needs to be saved */
12806 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12807 if (bitVectBitValue(ic->rMask,i))
12808 rsave = bitVectSetBit(rsave,i);
12810 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12811 ds390_rUmaskForOp (IC_RESULT(ic))));
12818 aopOp (from, ic->next, FALSE, FALSE);
12820 /* get from into DPTR1 */
12821 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12822 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12823 if (options.model == MODEL_FLAT24) {
12824 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12827 freeAsmop (from, NULL, ic, FALSE);
12828 aopOp (to, ic, FALSE, FALSE);
12829 /* get "to" into DPTR */
12830 /* if the operand is already in dptr
12831 then we do nothing else we move the value to dptr */
12832 if (AOP_TYPE (to) != AOP_STR) {
12833 /* if already in DPTR then we need to push */
12834 if (AOP_TYPE(to) == AOP_DPTR) {
12835 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12836 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12837 if (options.model == MODEL_FLAT24)
12838 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12839 emitcode ("pop", "dph");
12840 emitcode ("pop", "dpl");
12842 _startLazyDPSEvaluation ();
12843 /* if this is remateriazable */
12844 if (AOP_TYPE (to) == AOP_IMMD) {
12845 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12846 } else { /* we need to get it byte by byte */
12847 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12848 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12849 if (options.model == MODEL_FLAT24) {
12850 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12853 _endLazyDPSEvaluation ();
12856 freeAsmop (to, NULL, ic, FALSE);
12858 _G.dptrInUse = _G.dptr1InUse = 1;
12859 aopOp (count, ic->next->next, FALSE,FALSE);
12860 lbl =newiTempLabel(NULL);
12862 /* now for the actual copy */
12863 if (AOP_TYPE(count) == AOP_LIT &&
12864 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12865 emitcode (";","OH JOY auto increment with djnz (very fast)");
12866 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12867 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12868 freeAsmop (count, NULL, ic, FALSE);
12870 emitcode ("movx", "a,@dptr"); /* read data from port */
12871 emitcode ("dec","dps"); /* switch to DPTR */
12872 emitcode ("movx", "@dptr,a"); /* save into location */
12873 emitcode ("inc", "dptr"); /* point to next area */
12874 emitcode ("inc","dps"); /* switch to DPTR2 */
12875 emitcode ("djnz","b,!tlabel",lbl->key+100);
12877 symbol *lbl1 = newiTempLabel(NULL);
12879 emitcode (";"," Auto increment but no djnz");
12880 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12881 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12882 freeAsmop (count, NULL, ic, FALSE);
12883 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12885 emitcode ("movx", "a,@dptr");
12886 emitcode ("dec","dps"); /* switch to DPTR */
12887 emitcode ("movx", "@dptr,a");
12888 emitcode ("inc", "dptr");
12889 emitcode ("inc","dps"); /* switch to DPTR2 */
12890 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
12891 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
12892 emitcode ("mov","a,b");
12893 emitcode ("orl","a,_ap");
12894 emitcode ("jz","!tlabel",lbl1->key+100);
12895 emitcode ("mov","a,_ap");
12896 emitcode ("add","a,#!constbyte",0xFF);
12897 emitcode ("mov","_ap,a");
12898 emitcode ("mov","a,b");
12899 emitcode ("addc","a,#!constbyte",0xFF);
12900 emitcode ("mov","b,a");
12901 emitcode ("sjmp","!tlabel",lbl->key+100);
12904 emitcode ("mov", "dps,#0");
12905 _G.dptrInUse = _G.dptr1InUse = 0;
12906 unsavermask(rsave);
12910 /*-----------------------------------------------------------------*/
12911 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
12912 /* port, first parameter output area second parameter pointer to */
12913 /* port third parameter count */
12914 /*-----------------------------------------------------------------*/
12915 static void genOutp( iCode *ic, int nparms, operand **parms)
12917 operand *from , *to , *count;
12922 /* we know it has to be 3 parameters */
12923 assert (nparms == 3);
12925 rsave = newBitVect(16);
12926 /* save DPTR if it needs to be saved */
12927 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12928 if (bitVectBitValue(ic->rMask,i))
12929 rsave = bitVectSetBit(rsave,i);
12931 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12932 ds390_rUmaskForOp (IC_RESULT(ic))));
12939 aopOp (from, ic->next, FALSE, FALSE);
12941 /* get from into DPTR1 */
12942 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12943 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12944 if (options.model == MODEL_FLAT24) {
12945 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12948 freeAsmop (from, NULL, ic, FALSE);
12949 aopOp (to, ic, FALSE, FALSE);
12950 /* get "to" into DPTR */
12951 /* if the operand is already in dptr
12952 then we do nothing else we move the value to dptr */
12953 if (AOP_TYPE (to) != AOP_STR) {
12954 /* if already in DPTR then we need to push */
12955 if (AOP_TYPE(to) == AOP_DPTR) {
12956 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12957 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12958 if (options.model == MODEL_FLAT24)
12959 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12960 emitcode ("pop", "dph");
12961 emitcode ("pop", "dpl");
12963 _startLazyDPSEvaluation ();
12964 /* if this is remateriazable */
12965 if (AOP_TYPE (to) == AOP_IMMD) {
12966 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12967 } else { /* we need to get it byte by byte */
12968 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12969 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12970 if (options.model == MODEL_FLAT24) {
12971 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12974 _endLazyDPSEvaluation ();
12977 freeAsmop (to, NULL, ic, FALSE);
12979 _G.dptrInUse = _G.dptr1InUse = 1;
12980 aopOp (count, ic->next->next, FALSE,FALSE);
12981 lbl =newiTempLabel(NULL);
12983 /* now for the actual copy */
12984 if (AOP_TYPE(count) == AOP_LIT &&
12985 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12986 emitcode (";","OH JOY auto increment with djnz (very fast)");
12987 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
12988 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12990 emitcode ("movx", "a,@dptr"); /* read data from port */
12991 emitcode ("inc","dps"); /* switch to DPTR2 */
12992 emitcode ("movx", "@dptr,a"); /* save into location */
12993 emitcode ("inc", "dptr"); /* point to next area */
12994 emitcode ("dec","dps"); /* switch to DPTR */
12995 emitcode ("djnz","b,!tlabel",lbl->key+100);
12996 freeAsmop (count, NULL, ic, FALSE);
12998 symbol *lbl1 = newiTempLabel(NULL);
13000 emitcode (";"," Auto increment but no djnz");
13001 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
13002 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
13003 freeAsmop (count, NULL, ic, FALSE);
13004 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
13006 emitcode ("movx", "a,@dptr");
13007 emitcode ("inc", "dptr");
13008 emitcode ("inc","dps"); /* switch to DPTR2 */
13009 emitcode ("movx", "@dptr,a");
13010 emitcode ("dec","dps"); /* switch to DPTR */
13011 emitcode ("mov","a,b");
13012 emitcode ("orl","a,_ap");
13013 emitcode ("jz","!tlabel",lbl1->key+100);
13014 emitcode ("mov","a,_ap");
13015 emitcode ("add","a,#!constbyte",0xFF);
13016 emitcode ("mov","_ap,a");
13017 emitcode ("mov","a,b");
13018 emitcode ("addc","a,#!constbyte",0xFF);
13019 emitcode ("mov","b,a");
13020 emitcode ("sjmp","!tlabel",lbl->key+100);
13023 emitcode ("mov", "dps,#0");
13024 _G.dptrInUse = _G.dptr1InUse = 0;
13025 unsavermask(rsave);
13029 /*-----------------------------------------------------------------*/
13030 /* genSwapW - swap lower & high order bytes */
13031 /*-----------------------------------------------------------------*/
13032 static void genSwapW(iCode *ic, int nparms, operand **parms)
13036 assert (nparms==1);
13039 dest=IC_RESULT(ic);
13041 assert(getSize(operandType(src))==2);
13043 aopOp (src, ic, FALSE, FALSE);
13044 emitcode ("mov","a,%s",aopGet(src,0,FALSE,FALSE,NULL));
13046 MOVB(aopGet(src,1,FALSE,FALSE,"b"));
13048 freeAsmop (src, NULL, ic, FALSE);
13050 aopOp (dest,ic, FALSE, FALSE);
13051 aopPut(dest,"b",0);
13052 aopPut(dest,"a",1);
13053 freeAsmop (dest, NULL, ic, FALSE);
13056 /*-----------------------------------------------------------------*/
13057 /* genMemsetX - gencode for memSetX data */
13058 /*-----------------------------------------------------------------*/
13059 static void genMemsetX(iCode *ic, int nparms, operand **parms)
13061 operand *to , *val , *count;
13067 /* we know it has to be 3 parameters */
13068 assert (nparms == 3);
13074 /* save DPTR if it needs to be saved */
13075 rsave = newBitVect(16);
13076 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
13077 if (bitVectBitValue(ic->rMask,i))
13078 rsave = bitVectSetBit(rsave,i);
13080 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
13081 ds390_rUmaskForOp (IC_RESULT(ic))));
13084 aopOp (to, ic, FALSE, FALSE);
13085 /* get "to" into DPTR */
13086 /* if the operand is already in dptr
13087 then we do nothing else we move the value to dptr */
13088 if (AOP_TYPE (to) != AOP_STR) {
13089 /* if already in DPTR then we need to push */
13090 if (AOP_TYPE(to) == AOP_DPTR) {
13091 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
13092 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
13093 if (options.model == MODEL_FLAT24)
13094 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
13095 emitcode ("pop", "dph");
13096 emitcode ("pop", "dpl");
13098 _startLazyDPSEvaluation ();
13099 /* if this is remateriazable */
13100 if (AOP_TYPE (to) == AOP_IMMD) {
13101 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
13102 } else { /* we need to get it byte by byte */
13103 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
13104 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
13105 if (options.model == MODEL_FLAT24) {
13106 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
13109 _endLazyDPSEvaluation ();
13112 freeAsmop (to, NULL, ic, FALSE);
13114 aopOp (val, ic->next->next, FALSE,FALSE);
13115 aopOp (count, ic->next->next, FALSE,FALSE);
13116 lbl =newiTempLabel(NULL);
13117 /* now for the actual copy */
13118 if (AOP_TYPE(count) == AOP_LIT &&
13119 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
13120 l = aopGet(val, 0, FALSE, FALSE, NULL);
13121 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
13124 emitcode ("movx", "@dptr,a");
13125 emitcode ("inc", "dptr");
13126 emitcode ("djnz","b,!tlabel",lbl->key+100);
13128 symbol *lbl1 = newiTempLabel(NULL);
13130 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
13131 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
13133 MOVA (aopGet(val, 0, FALSE, FALSE, NULL));
13134 emitcode ("movx", "@dptr,a");
13135 emitcode ("inc", "dptr");
13136 emitcode ("mov","a,b");
13137 emitcode ("orl","a,_ap");
13138 emitcode ("jz","!tlabel",lbl1->key+100);
13139 emitcode ("mov","a,_ap");
13140 emitcode ("add","a,#!constbyte",0xFF);
13141 emitcode ("mov","_ap,a");
13142 emitcode ("mov","a,b");
13143 emitcode ("addc","a,#!constbyte",0xFF);
13144 emitcode ("mov","b,a");
13145 emitcode ("sjmp","!tlabel",lbl->key+100);
13148 freeAsmop (count, NULL, ic, FALSE);
13149 unsavermask(rsave);
13152 /*-----------------------------------------------------------------*/
13153 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
13154 /*-----------------------------------------------------------------*/
13155 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
13158 operand *pnum, *result;
13161 assert (nparms==1);
13162 /* save registers that need to be saved */
13163 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13164 ds390_rUmaskForOp (IC_RESULT(ic))));
13167 aopOp (pnum, ic, FALSE, FALSE);
13168 emitcode ("mov","a,%s",aopGet(pnum,0,FALSE,FALSE,DP2_RESULT_REG));
13169 freeAsmop (pnum, NULL, ic, FALSE);
13170 emitcode ("lcall","NatLib_LoadPrimitive");
13171 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
13172 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
13173 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
13174 for (i = (size-1) ; i >= 0 ; i-- ) {
13175 emitcode ("push","a%s",javaRet[i]);
13177 for (i=0; i < size ; i++ ) {
13178 emitcode ("pop","a%s",
13179 aopGet(result,i,FALSE,FALSE,DP2_RESULT_REG));
13182 for (i = 0 ; i < size ; i++ ) {
13183 aopPut(result,javaRet[i],i);
13186 freeAsmop (result, NULL, ic, FALSE);
13187 unsavermask(rsave);
13190 /*-----------------------------------------------------------------*/
13191 /* genNatLibLoadPointer - calls TINI api function to load pointer */
13192 /*-----------------------------------------------------------------*/
13193 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
13196 operand *pnum, *result;
13200 assert (nparms==1);
13201 /* save registers that need to be saved */
13202 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13203 ds390_rUmaskForOp (IC_RESULT(ic))));
13206 aopOp (pnum, ic, FALSE, FALSE);
13207 emitcode ("mov","a,%s",aopGet(pnum,0,FALSE,FALSE,DP2_RESULT_REG));
13208 freeAsmop (pnum, NULL, ic, FALSE);
13209 emitcode ("lcall","NatLib_LoadPointer");
13210 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
13211 if (AOP_TYPE(result)!=AOP_STR) {
13212 for (i = 0 ; i < size ; i++ ) {
13213 aopPut(result,fReturn[i],i);
13216 freeAsmop (result, NULL, ic, FALSE);
13217 unsavermask(rsave);
13220 /*-----------------------------------------------------------------*/
13221 /* genNatLibInstallStateBlock - */
13222 /*-----------------------------------------------------------------*/
13223 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
13224 operand **parms, const char *name)
13227 operand *psb, *handle;
13228 assert (nparms==2);
13230 /* save registers that need to be saved */
13231 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13232 ds390_rUmaskForOp (IC_RESULT(ic))));
13236 /* put pointer to state block into DPTR1 */
13237 aopOp (psb, ic, FALSE, FALSE);
13238 if (AOP_TYPE (psb) == AOP_IMMD) {
13239 emitcode ("mov","dps,#1");
13240 emitcode ("mov", "dptr,%s",
13241 aopGet (psb, 0, TRUE, FALSE, DP2_RESULT_REG));
13242 emitcode ("mov","dps,#0");
13244 emitcode ("mov","dpl1,%s",aopGet(psb,0,FALSE,FALSE,DP2_RESULT_REG));
13245 emitcode ("mov","dph1,%s",aopGet(psb,1,FALSE,FALSE,DP2_RESULT_REG));
13246 emitcode ("mov","dpx1,%s",aopGet(psb,2,FALSE,FALSE,DP2_RESULT_REG));
13248 freeAsmop (psb, NULL, ic, FALSE);
13250 /* put libraryID into DPTR */
13251 emitcode ("mov","dptr,#LibraryID");
13253 /* put handle into r3:r2 */
13254 aopOp (handle, ic, FALSE, FALSE);
13255 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13256 emitcode ("push","%s",aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13257 emitcode ("push","%s",aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13258 emitcode ("pop","ar3");
13259 emitcode ("pop","ar2");
13261 emitcode ("mov","r2,%s",aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13262 emitcode ("mov","r3,%s",aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13264 freeAsmop (psb, NULL, ic, FALSE);
13266 /* make the call */
13267 emitcode ("lcall","NatLib_Install%sStateBlock",name);
13269 /* put return value into place*/
13271 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
13273 aopPut(IC_RESULT(ic),"a",0);
13274 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13275 unsavermask(rsave);
13278 /*-----------------------------------------------------------------*/
13279 /* genNatLibRemoveStateBlock - */
13280 /*-----------------------------------------------------------------*/
13281 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
13287 /* save registers that need to be saved */
13288 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13289 ds390_rUmaskForOp (IC_RESULT(ic))));
13291 /* put libraryID into DPTR */
13292 emitcode ("mov","dptr,#LibraryID");
13293 /* make the call */
13294 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
13295 unsavermask(rsave);
13298 /*-----------------------------------------------------------------*/
13299 /* genNatLibGetStateBlock - */
13300 /*-----------------------------------------------------------------*/
13301 static void genNatLibGetStateBlock(iCode *ic,int nparms,
13302 operand **parms,const char *name)
13305 symbol *lbl = newiTempLabel(NULL);
13308 /* save registers that need to be saved */
13309 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13310 ds390_rUmaskForOp (IC_RESULT(ic))));
13312 /* put libraryID into DPTR */
13313 emitcode ("mov","dptr,#LibraryID");
13314 /* make the call */
13315 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
13316 emitcode ("jnz","!tlabel",lbl->key+100);
13318 /* put return value into place */
13319 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
13320 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
13321 emitcode ("push","ar3");
13322 emitcode ("push","ar2");
13323 emitcode ("pop","%s",
13324 aopGet(IC_RESULT(ic),0,FALSE,TRUE,DP2_RESULT_REG));
13325 emitcode ("pop","%s",
13326 aopGet(IC_RESULT(ic),1,FALSE,TRUE,DP2_RESULT_REG));
13328 aopPut(IC_RESULT(ic),"r2",0);
13329 aopPut(IC_RESULT(ic),"r3",1);
13331 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13333 unsavermask(rsave);
13336 /*-----------------------------------------------------------------*/
13337 /* genMMMalloc - */
13338 /*-----------------------------------------------------------------*/
13339 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
13340 int size, const char *name)
13345 symbol *lbl = newiTempLabel(NULL);
13347 assert (nparms == 1);
13348 /* save registers that need to be saved */
13349 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13350 ds390_rUmaskForOp (IC_RESULT(ic))));
13353 aopOp (bsize,ic,FALSE,FALSE);
13355 /* put the size in R4-R2 */
13356 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
13357 emitcode("push","%s",aopGet(bsize,0,FALSE,TRUE,DP2_RESULT_REG));
13358 emitcode("push","%s",aopGet(bsize,1,FALSE,TRUE,DP2_RESULT_REG));
13360 emitcode("push","%s",aopGet(bsize,2,FALSE,TRUE,DP2_RESULT_REG));
13361 emitcode("pop","ar4");
13363 emitcode("pop","ar3");
13364 emitcode("pop","ar2");
13366 emitcode ("mov","r2,%s",aopGet(bsize,0,FALSE,TRUE,DP2_RESULT_REG));
13367 emitcode ("mov","r3,%s",aopGet(bsize,1,FALSE,TRUE,DP2_RESULT_REG));
13369 emitcode("mov","r4,%s",aopGet(bsize,2,FALSE,TRUE,DP2_RESULT_REG));
13372 freeAsmop (bsize, NULL, ic, FALSE);
13374 /* make the call */
13375 emitcode ("lcall","MM_%s",name);
13376 emitcode ("jz","!tlabel",lbl->key+100);
13377 emitcode ("mov","r2,#!constbyte",0xff);
13378 emitcode ("mov","r3,#!constbyte",0xff);
13380 /* we don't care about the pointer : we just save the handle */
13381 rsym = OP_SYMBOL(IC_RESULT(ic));
13382 if (rsym->liveFrom != rsym->liveTo) {
13383 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
13384 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
13385 emitcode ("push","ar3");
13386 emitcode ("push","ar2");
13387 emitcode ("pop","%s",
13388 aopGet(IC_RESULT(ic),0,FALSE,TRUE,DP2_RESULT_REG));
13389 emitcode ("pop","%s",
13390 aopGet(IC_RESULT(ic),1,FALSE,TRUE,DP2_RESULT_REG));
13392 aopPut(IC_RESULT(ic),"r2",0);
13393 aopPut(IC_RESULT(ic),"r3",1);
13395 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13397 unsavermask(rsave);
13400 /*-----------------------------------------------------------------*/
13402 /*-----------------------------------------------------------------*/
13403 static void genMMDeref (iCode *ic,int nparms, operand **parms)
13408 assert (nparms == 1);
13409 /* save registers that need to be saved */
13410 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13411 ds390_rUmaskForOp (IC_RESULT(ic))));
13414 aopOp (handle,ic,FALSE,FALSE);
13416 /* put the size in R4-R2 */
13417 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13418 emitcode("push","%s",
13419 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13420 emitcode("push","%s",
13421 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13422 emitcode("pop","ar3");
13423 emitcode("pop","ar2");
13425 emitcode ("mov","r2,%s",
13426 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13427 emitcode ("mov","r3,%s",
13428 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13430 freeAsmop (handle, NULL, ic, FALSE);
13432 /* make the call */
13433 emitcode ("lcall","MM_Deref");
13436 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13437 if (rsym->liveFrom != rsym->liveTo) {
13438 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13439 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
13440 _startLazyDPSEvaluation ();
13442 aopPut(IC_RESULT(ic),"dpl",0);
13443 aopPut(IC_RESULT(ic),"dph",1);
13444 aopPut(IC_RESULT(ic),"dpx",2);
13446 _endLazyDPSEvaluation ();
13451 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13452 unsavermask(rsave);
13455 /*-----------------------------------------------------------------*/
13456 /* genMMUnrestrictedPersist - */
13457 /*-----------------------------------------------------------------*/
13458 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
13463 assert (nparms == 1);
13464 /* save registers that need to be saved */
13465 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13466 ds390_rUmaskForOp (IC_RESULT(ic))));
13469 aopOp (handle,ic,FALSE,FALSE);
13471 /* put the size in R3-R2 */
13472 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13473 emitcode("push","%s",
13474 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13475 emitcode("push","%s",
13476 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13477 emitcode("pop","ar3");
13478 emitcode("pop","ar2");
13480 emitcode ("mov","r2,%s",
13481 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13482 emitcode ("mov","r3,%s",
13483 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13485 freeAsmop (handle, NULL, ic, FALSE);
13487 /* make the call */
13488 emitcode ("lcall","MM_UnrestrictedPersist");
13491 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13492 if (rsym->liveFrom != rsym->liveTo) {
13493 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13494 aopPut(IC_RESULT(ic),"a",0);
13495 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13498 unsavermask(rsave);
13501 /*-----------------------------------------------------------------*/
13502 /* genSystemExecJavaProcess - */
13503 /*-----------------------------------------------------------------*/
13504 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
13507 operand *handle, *pp;
13509 assert (nparms==2);
13510 /* save registers that need to be saved */
13511 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13512 ds390_rUmaskForOp (IC_RESULT(ic))));
13517 /* put the handle in R3-R2 */
13518 aopOp (handle,ic,FALSE,FALSE);
13519 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13520 emitcode("push","%s",
13521 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13522 emitcode("push","%s",
13523 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13524 emitcode("pop","ar3");
13525 emitcode("pop","ar2");
13527 emitcode ("mov","r2,%s",
13528 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13529 emitcode ("mov","r3,%s",
13530 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13532 freeAsmop (handle, NULL, ic, FALSE);
13534 /* put pointer in DPTR */
13535 aopOp (pp,ic,FALSE,FALSE);
13536 if (AOP_TYPE(pp) == AOP_IMMD) {
13537 emitcode ("mov", "dptr,%s",
13538 aopGet (pp, 0, TRUE, FALSE, NULL));
13539 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
13540 emitcode ("mov","dpl,%s",aopGet(pp,0,FALSE,FALSE,NULL));
13541 emitcode ("mov","dph,%s",aopGet(pp,1,FALSE,FALSE,NULL));
13542 emitcode ("mov","dpx,%s",aopGet(pp,2,FALSE,FALSE,NULL));
13544 freeAsmop (handle, NULL, ic, FALSE);
13546 /* make the call */
13547 emitcode ("lcall","System_ExecJavaProcess");
13549 /* put result in place */
13551 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13552 if (rsym->liveFrom != rsym->liveTo) {
13553 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13554 aopPut(IC_RESULT(ic),"a",0);
13555 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13559 unsavermask(rsave);
13562 /*-----------------------------------------------------------------*/
13563 /* genSystemRTCRegisters - */
13564 /*-----------------------------------------------------------------*/
13565 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
13571 assert (nparms==1);
13572 /* save registers that need to be saved */
13573 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13574 ds390_rUmaskForOp (IC_RESULT(ic))));
13577 /* put pointer in DPTR */
13578 aopOp (pp,ic,FALSE,FALSE);
13579 if (AOP_TYPE (pp) == AOP_IMMD) {
13580 emitcode ("mov","dps,#1");
13581 emitcode ("mov", "dptr,%s",
13582 aopGet (pp, 0, TRUE, FALSE, NULL));
13583 emitcode ("mov","dps,#0");
13585 emitcode ("mov","dpl1,%s",
13586 aopGet(pp,0,FALSE,FALSE,DP2_RESULT_REG));
13587 emitcode ("mov","dph1,%s",
13588 aopGet(pp,1,FALSE,FALSE,DP2_RESULT_REG));
13589 emitcode ("mov","dpx1,%s",
13590 aopGet(pp,2,FALSE,FALSE,DP2_RESULT_REG));
13592 freeAsmop (pp, NULL, ic, FALSE);
13594 /* make the call */
13595 emitcode ("lcall","System_%sRTCRegisters",name);
13597 unsavermask(rsave);
13600 /*-----------------------------------------------------------------*/
13601 /* genSystemThreadSleep - */
13602 /*-----------------------------------------------------------------*/
13603 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
13608 assert (nparms==1);
13609 /* save registers that need to be saved */
13610 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13611 ds390_rUmaskForOp (IC_RESULT(ic))));
13614 aopOp(to,ic,FALSE,FALSE);
13615 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
13616 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
13617 emitcode ("push","%s",
13618 aopGet(to,0,FALSE,TRUE,DP2_RESULT_REG));
13619 emitcode ("push","%s",
13620 aopGet(to,1,FALSE,TRUE,DP2_RESULT_REG));
13621 emitcode ("push","%s",
13622 aopGet(to,2,FALSE,TRUE,DP2_RESULT_REG));
13623 emitcode ("push","%s",
13624 aopGet(to,3,FALSE,TRUE,DP2_RESULT_REG));
13625 emitcode ("pop","ar3");
13626 emitcode ("pop","ar2");
13627 emitcode ("pop","ar1");
13628 emitcode ("pop","ar0");
13630 emitcode ("mov","r0,%s",
13631 aopGet(to,0,FALSE,TRUE,DP2_RESULT_REG));
13632 emitcode ("mov","r1,%s",
13633 aopGet(to,1,FALSE,TRUE,DP2_RESULT_REG));
13634 emitcode ("mov","r2,%s",
13635 aopGet(to,2,FALSE,TRUE,DP2_RESULT_REG));
13636 emitcode ("mov","r3,%s",
13637 aopGet(to,3,FALSE,TRUE,DP2_RESULT_REG));
13639 freeAsmop (to, NULL, ic, FALSE);
13641 /* suspend in acc */
13643 aopOp(s,ic,FALSE,FALSE);
13644 emitcode ("mov","a,%s",
13645 aopGet(s,0,FALSE,TRUE,NULL));
13646 freeAsmop (s, NULL, ic, FALSE);
13648 /* make the call */
13649 emitcode ("lcall","System_%s",name);
13651 unsavermask(rsave);
13654 /*-----------------------------------------------------------------*/
13655 /* genSystemThreadResume - */
13656 /*-----------------------------------------------------------------*/
13657 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
13662 assert (nparms==2);
13663 /* save registers that need to be saved */
13664 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13665 ds390_rUmaskForOp (IC_RESULT(ic))));
13671 aopOp(pid,ic,FALSE,FALSE);
13672 emitcode ("mov","r0,%s",
13673 aopGet(pid,0,FALSE,TRUE,DP2_RESULT_REG));
13674 freeAsmop (pid, NULL, ic, FALSE);
13677 aopOp(tid,ic,FALSE,FALSE);
13678 emitcode ("mov","a,%s",
13679 aopGet(tid,0,FALSE,TRUE,DP2_RESULT_REG));
13680 freeAsmop (tid, NULL, ic, FALSE);
13682 emitcode ("lcall","System_ThreadResume");
13684 /* put result into place */
13686 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13687 if (rsym->liveFrom != rsym->liveTo) {
13688 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13689 aopPut(IC_RESULT(ic),"a",0);
13690 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13693 unsavermask(rsave);
13696 /*-----------------------------------------------------------------*/
13697 /* genSystemProcessResume - */
13698 /*-----------------------------------------------------------------*/
13699 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
13704 assert (nparms==1);
13705 /* save registers that need to be saved */
13706 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13707 ds390_rUmaskForOp (IC_RESULT(ic))));
13712 aopOp(pid,ic,FALSE,FALSE);
13713 emitcode ("mov","a,%s",
13714 aopGet(pid,0,FALSE,TRUE,DP2_RESULT_REG));
13715 freeAsmop (pid, NULL, ic, FALSE);
13717 emitcode ("lcall","System_ProcessResume");
13719 unsavermask(rsave);
13722 /*-----------------------------------------------------------------*/
13724 /*-----------------------------------------------------------------*/
13725 static void genSystem (iCode *ic,int nparms,char *name)
13727 assert(nparms == 0);
13729 emitcode ("lcall","System_%s",name);
13732 /*-----------------------------------------------------------------*/
13733 /* genSystemPoll - */
13734 /*-----------------------------------------------------------------*/
13735 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
13740 assert (nparms==1);
13741 /* save registers that need to be saved */
13742 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13743 ds390_rUmaskForOp (IC_RESULT(ic))));
13746 aopOp (fp,ic,FALSE,FALSE);
13747 if (AOP_TYPE (fp) == AOP_IMMD) {
13748 emitcode ("mov", "dptr,%s",
13749 aopGet (fp, 0, TRUE, FALSE, DP2_RESULT_REG));
13750 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
13751 emitcode ("mov","dpl,%s",
13752 aopGet(fp,0,FALSE,FALSE,DP2_RESULT_REG));
13753 emitcode ("mov","dph,%s",
13754 aopGet(fp,1,FALSE,FALSE,DP2_RESULT_REG));
13755 emitcode ("mov","dpx,%s",
13756 aopGet(fp,2,FALSE,FALSE,DP2_RESULT_REG));
13758 freeAsmop (fp, NULL, ic, FALSE);
13760 emitcode ("lcall","System_%sPoll",name);
13762 /* put result into place */
13764 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13765 if (rsym->liveFrom != rsym->liveTo) {
13766 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13767 aopPut(IC_RESULT(ic),"a",0);
13768 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13771 unsavermask(rsave);
13774 /*-----------------------------------------------------------------*/
13775 /* genSystemGetCurrentID - */
13776 /*-----------------------------------------------------------------*/
13777 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
13779 assert (nparms==0);
13781 emitcode ("lcall","System_GetCurrent%sId",name);
13782 /* put result into place */
13784 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13785 if (rsym->liveFrom != rsym->liveTo) {
13786 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13787 aopPut(IC_RESULT(ic),"a",0);
13788 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13793 /*-----------------------------------------------------------------*/
13794 /* genDjnz - generate decrement & jump if not zero instrucion */
13795 /*-----------------------------------------------------------------*/
13797 genDjnz (iCode * ic, iCode * ifx)
13799 symbol *lbl, *lbl1;
13803 /* if the if condition has a false label
13804 then we cannot save */
13805 if (IC_FALSE (ifx))
13808 /* if the minus is not of the form a = a - 1 */
13809 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
13810 !IS_OP_LITERAL (IC_RIGHT (ic)))
13813 if (operandLitValue (IC_RIGHT (ic)) != 1)
13816 /* if the size of this greater than one then no
13818 if (getSize (operandType (IC_RESULT (ic))) > 1)
13821 /* otherwise we can save BIG */
13823 D (emitcode (";", "genDjnz"));
13825 lbl = newiTempLabel (NULL);
13826 lbl1 = newiTempLabel (NULL);
13828 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
13830 if (AOP_NEEDSACC(IC_RESULT(ic)))
13832 /* If the result is accessed indirectly via
13833 * the accumulator, we must explicitly write
13834 * it back after the decrement.
13836 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE, NULL);
13838 if (strcmp(rByte, "a"))
13840 /* Something is hopelessly wrong */
13841 fprintf(stderr, "*** warning: internal error at %s:%d\n",
13842 __FILE__, __LINE__);
13843 /* We can just give up; the generated code will be inefficient,
13844 * but what the hey.
13846 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13849 emitcode ("dec", "%s", rByte);
13850 aopPut (IC_RESULT (ic), rByte, 0);
13851 emitcode ("jnz", "!tlabel", lbl->key + 100);
13853 else if (IS_AOP_PREG (IC_RESULT (ic)))
13855 emitcode ("dec", "%s",
13856 aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL));
13857 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL));
13858 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13859 ifx->generated = 1;
13860 emitcode ("jnz", "!tlabel", lbl->key + 100);
13864 emitcode ("djnz", "%s,!tlabel", aopGet (IC_RESULT (ic), 0, FALSE, TRUE, NULL),
13867 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
13869 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
13872 if (!ifx->generated)
13873 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13874 ifx->generated = 1;
13878 /*-----------------------------------------------------------------*/
13879 /* genReceive - generate code for a receive iCode */
13880 /*-----------------------------------------------------------------*/
13882 genReceive (iCode * ic)
13884 int size = getSize (operandType (IC_RESULT (ic)));
13888 D (emitcode (";", "genReceive"));
13890 if (ic->argreg == 1)
13892 /* first parameter */
13893 if (AOP_IS_STR(IC_RESULT(ic)))
13895 /* Nothing to do: it's already in the proper place. */
13902 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
13903 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
13904 IS_TRUE_SYMOP (IC_RESULT (ic)));
13907 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
13910 /* Sanity checking... */
13911 if (AOP_USESDPTR(IC_RESULT(ic)))
13913 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13914 "genReceive got unexpected DPTR.");
13916 assignResultValue (IC_RESULT (ic), NULL);
13919 else if (ic->argreg > 12)
13920 { /* bit parameters */
13921 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
13923 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
13924 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
13925 outBitC(IC_RESULT (ic));
13930 /* second receive onwards */
13931 /* this gets a little tricky since unused receives will be
13932 eliminated, we have saved the reg in the type field . and
13933 we use that to figure out which register to use */
13934 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
13935 rb1off = ic->argreg;
13938 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
13941 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13944 /*-----------------------------------------------------------------*/
13945 /* genDummyRead - generate code for dummy read of volatiles */
13946 /*-----------------------------------------------------------------*/
13948 genDummyRead (iCode * ic)
13953 D (emitcode(";", "genDummyRead"));
13955 op = IC_RIGHT (ic);
13956 if (op && IS_SYMOP (op))
13958 aopOp (op, ic, FALSE, FALSE);
13960 /* if the result is a bit */
13961 if (AOP_TYPE (op) == AOP_CRY)
13962 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13965 /* bit variables done */
13967 size = AOP_SIZE (op);
13971 MOVA (aopGet (op, offset, FALSE, FALSE, FALSE));
13976 freeAsmop (op, NULL, ic, TRUE);
13980 if (op && IS_SYMOP (op))
13982 aopOp (op, ic, FALSE, FALSE);
13984 /* if the result is a bit */
13985 if (AOP_TYPE (op) == AOP_CRY)
13986 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13989 /* bit variables done */
13991 size = AOP_SIZE (op);
13995 MOVA (aopGet (op, offset, FALSE, FALSE, FALSE));
14000 freeAsmop (op, NULL, ic, TRUE);
14004 /*-----------------------------------------------------------------*/
14005 /* genCritical - generate code for start of a critical sequence */
14006 /*-----------------------------------------------------------------*/
14008 genCritical (iCode *ic)
14010 symbol *tlbl = newiTempLabel (NULL);
14012 D (emitcode(";", "genCritical"));
14014 if (IC_RESULT (ic))
14016 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
14017 aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
14018 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
14019 aopPut (IC_RESULT (ic), zero, 0);
14021 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
14025 emitcode ("setb", "c");
14026 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
14027 emitcode ("clr", "c");
14029 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
14033 /*-----------------------------------------------------------------*/
14034 /* genEndCritical - generate code for end of a critical sequence */
14035 /*-----------------------------------------------------------------*/
14037 genEndCritical (iCode *ic)
14039 D(emitcode("; genEndCritical",""));
14043 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
14044 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
14046 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
14047 emitcode ("mov", "ea,c");
14051 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE, FALSE));
14052 emitcode ("rrc", "a");
14053 emitcode ("mov", "ea,c");
14055 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
14059 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
14060 emitcode ("mov", "ea,c");
14066 /*-----------------------------------------------------------------*/
14067 /* genBuiltIn - calls the appropriate function to generating code */
14068 /* for a built in function */
14069 /*-----------------------------------------------------------------*/
14070 static void genBuiltIn (iCode *ic)
14072 operand *bi_parms[MAX_BUILTIN_ARGS];
14077 /* get all the arguments for a built in function */
14078 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
14080 /* which function is it */
14081 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
14082 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
14083 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
14084 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
14085 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
14086 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
14087 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
14088 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
14089 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
14090 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
14091 genMemsetX(bi_iCode,nbi_parms,bi_parms);
14092 } else if (strcmp(bif->name,"__builtin_inp")==0) {
14093 genInp(bi_iCode,nbi_parms,bi_parms);
14094 } else if (strcmp(bif->name,"__builtin_outp")==0) {
14095 genOutp(bi_iCode,nbi_parms,bi_parms);
14096 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
14097 genSwapW(bi_iCode,nbi_parms,bi_parms);
14098 /* JavaNative builtIns */
14099 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
14100 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
14101 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
14102 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
14103 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
14104 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
14105 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
14106 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
14107 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
14108 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
14109 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
14110 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
14111 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
14112 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
14113 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
14114 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
14115 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
14116 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
14117 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
14118 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
14119 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
14120 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
14121 } else if (strcmp(bif->name,"MM_Malloc")==0) {
14122 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
14123 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
14124 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
14125 } else if (strcmp(bif->name,"MM_Free")==0) {
14126 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
14127 } else if (strcmp(bif->name,"MM_Deref")==0) {
14128 genMMDeref(bi_iCode,nbi_parms,bi_parms);
14129 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
14130 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
14131 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
14132 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
14133 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
14134 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
14135 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
14136 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
14137 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
14138 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
14139 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
14140 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
14141 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
14142 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
14143 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
14144 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
14145 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
14146 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
14147 } else if (strcmp(bif->name,"System_SaveThread")==0) {
14148 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
14149 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
14150 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
14151 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
14152 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
14153 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
14154 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
14155 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
14156 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
14157 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
14158 genSystem(bi_iCode,nbi_parms,"ProcessYield");
14159 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
14160 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
14161 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
14162 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
14163 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
14164 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
14165 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
14166 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
14167 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
14168 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
14170 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
14176 /*-----------------------------------------------------------------*/
14177 /* gen390Code - generate code for Dallas 390 based controllers */
14178 /*-----------------------------------------------------------------*/
14180 gen390Code (iCode * lic)
14185 _G.currentFunc = NULL;
14186 lineHead = lineCurr = NULL;
14187 dptrn[1][0] = "dpl1";
14188 dptrn[1][1] = "dph1";
14189 dptrn[1][2] = "dpx1";
14191 if (options.model == MODEL_FLAT24) {
14192 fReturnSizeDS390 = 5;
14193 fReturn = fReturn24;
14195 fReturnSizeDS390 = 4;
14196 fReturn = fReturn16;
14197 options.stack10bit=0;
14200 /* print the allocation information */
14201 if (allocInfo && currFunc)
14202 printAllocInfo (currFunc, codeOutFile);
14204 /* if debug information required */
14205 if (options.debug && currFunc)
14207 debugFile->writeFunction (currFunc, lic);
14209 /* stack pointer name */
14210 if (options.useXstack)
14216 for (ic = lic; ic; ic = ic->next)
14218 _G.current_iCode = ic;
14220 if (ic->lineno && cln != ic->lineno)
14224 debugFile->writeCLine (ic);
14226 if (!options.noCcodeInAsm) {
14227 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
14228 printCLine(ic->filename, ic->lineno));
14232 if (options.iCodeInAsm) {
14233 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
14235 /* if the result is marked as
14236 spilt and rematerializable or code for
14237 this has already been generated then
14239 if (resultRemat (ic) || ic->generated)
14242 /* depending on the operation */
14262 /* IPOP happens only when trying to restore a
14263 spilt live range, if there is an ifx statement
14264 following this pop then the if statement might
14265 be using some of the registers being popped which
14266 would destory the contents of the register so
14267 we need to check for this condition and handle it */
14269 ic->next->op == IFX &&
14270 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
14271 genIfx (ic->next, ic);
14289 genEndFunction (ic);
14309 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
14326 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
14330 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
14337 /* note these two are xlated by algebraic equivalence
14338 during parsing SDCC.y */
14339 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
14340 "got '>=' or '<=' shouldn't have come here");
14344 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
14356 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
14360 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
14364 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
14388 genRightShift (ic);
14391 case GET_VALUE_AT_ADDRESS:
14393 hasInc (IC_LEFT (ic), ic,
14394 getSize (operandType (IC_RESULT (ic)))));
14398 if (POINTER_SET (ic))
14400 hasInc (IC_RESULT (ic), ic,
14401 getSize (operandType (IC_RIGHT (ic)))));
14427 if (ic->builtinSEND)
14430 addSet (&_G.sendSet, ic);
14433 case DUMMY_READ_VOLATILE:
14442 genEndCritical (ic);
14449 #if 0 // obsolete, and buggy for != xdata
14461 /* now we are ready to call the
14462 peep hole optimizer */
14463 if (!options.nopeep)
14464 peepHole (&lineHead);
14466 /* now do the actual printing */
14467 printLine (lineHead, codeOutFile);