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 -------------------------------------------------------------------------*/
36 #include "SDCCglobl.h"
39 #ifdef HAVE_SYS_ISA_DEFS_H
40 #include <sys/isa_defs.h>
42 #ifdef HAVE_MACHINE_ENDIAN_H
43 #include <machine/endian.h>
48 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
49 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
50 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
56 #define BETTER_LITERAL_SHIFT
58 char *aopLiteral (value * val, int offset);
61 /* this is the down and dirty file with all kinds of
62 kludgy & hacky stuff. This is what it is all about
63 CODE GENERATION for a specific MCU . some of the
64 routines may be reusable, will have to see */
66 static char *zero = "#0";
67 static char *one = "#1";
72 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
73 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
75 unsigned fReturnSizeDS390 = 5; /* shared with ralloc.c */
76 static char *fReturn24[] =
77 {"dpl", "dph", "dpx", "b", "a"};
78 static char *fReturn16[] =
79 {"dpl", "dph", "b", "a"};
80 static char **fReturn = fReturn24;
81 static char *accUse[] =
83 static char *dptrn[2][3];
84 static char *javaRet[] = { "r0","r1","r2","r3"};
85 static short rbank = -1;
100 static char *rb1regs[] = {
101 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
104 static void saveRBank (int, iCode *, bool);
106 #define RESULTONSTACK(x) \
107 (IC_RESULT(x) && IC_RESULT(x)->aop && \
108 IC_RESULT(x)->aop->type == AOP_STK )
110 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
111 #define MOVA(x) { char *_mova_tmp = strdup(x); \
112 if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
114 emitcode("mov","a,%s",_mova_tmp); \
118 #define CLRC emitcode("clr","c")
119 #define SETC emitcode("setb","c")
121 // A scratch register which will be used to hold
122 // result bytes from operands in far space via DPTR2.
123 #define DP2_RESULT_REG "_ap"
125 static lineNode *lineHead = NULL;
126 static lineNode *lineCurr = NULL;
128 static unsigned char SLMask[] =
129 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
130 0xE0, 0xC0, 0x80, 0x00};
131 static unsigned char SRMask[] =
132 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
133 0x07, 0x03, 0x01, 0x00};
139 #define PROTECT_SP {if (options.protect_sp_update) { \
140 symbol *lbl = newiTempLabel(NULL); \
141 emitcode ("setb","F1"); \
142 emitcode ("jbc","EA,!tlabel",lbl->key+100); \
143 emitcode ("clr","F1"); \
144 emitcode ("","!tlabeldef",lbl->key+100); \
146 #define UNPROTECT_SP { if (options.protect_sp_update) { \
147 symbol *lbl = newiTempLabel(NULL); \
148 emitcode ("jnb","F1,!tlabel",lbl->key+100); \
149 emitcode ("setb","EA"); \
150 emitcode ("","!tlabeldef",lbl->key+100); \
154 /*-----------------------------------------------------------------*/
155 /* emitcode - writes the code into a file : for now it is simple */
156 /*-----------------------------------------------------------------*/
158 emitcode (char *inst, char *fmt,...)
161 char lb[INITIAL_INLINEASM];
169 sprintf (lb, "%s\t", inst);
171 sprintf (lb, "%s", inst);
172 tvsprintf (lb + (strlen (lb)), fmt, ap);
175 tvsprintf (lb, fmt, ap);
177 while (isspace (*lbp))
181 lineCurr = (lineCurr ?
182 connectLine (lineCurr, newLineNode (lb)) :
183 (lineHead = newLineNode (lb)));
184 lineCurr->isInline = _G.inLine;
185 lineCurr->isDebug = _G.debugLine;
189 /*-----------------------------------------------------------------*/
190 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
191 /*-----------------------------------------------------------------*/
193 getFreePtr (iCode * ic, asmop ** aopp, bool result)
195 bool r0iu = FALSE, r1iu = FALSE;
196 bool r0ou = FALSE, r1ou = FALSE;
198 /* the logic: if r0 & r1 used in the instruction
199 then we are in trouble otherwise */
201 /* first check if r0 & r1 are used by this
202 instruction, in which case we are in trouble */
203 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
204 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
209 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
210 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
212 /* if no usage of r0 then return it */
215 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
216 (*aopp)->type = AOP_R0;
218 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
221 /* if no usage of r1 then return it */
224 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
225 (*aopp)->type = AOP_R1;
227 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
230 /* now we know they both have usage */
231 /* if r0 not used in this instruction */
234 /* push it if not already pushed */
237 emitcode ("push", "%s",
238 ds390_regWithIdx (R0_IDX)->dname);
242 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
243 (*aopp)->type = AOP_R0;
245 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
248 /* if r1 not used then */
252 /* push it if not already pushed */
255 emitcode ("push", "%s",
256 ds390_regWithIdx (R1_IDX)->dname);
260 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
261 (*aopp)->type = AOP_R1;
262 return ds390_regWithIdx (R1_IDX);
266 /* I said end of world but not quite end of world yet */
267 /* if this is a result then we can push it on the stack */
270 (*aopp)->type = AOP_STK;
274 /* other wise this is true end of the world */
275 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
276 "getFreePtr should never reach here");
280 /*-----------------------------------------------------------------*/
281 /* newAsmop - creates a new asmOp */
282 /*-----------------------------------------------------------------*/
284 newAsmop (short type)
288 aop = Safe_calloc (1, sizeof (asmop));
293 static int _currentDPS; /* Current processor DPS. */
294 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
295 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
297 /*-----------------------------------------------------------------*/
298 /* genSetDPTR: generate code to select which DPTR is in use (zero */
299 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
300 /* alternate DPTR (DPL1/DPH1/DPX1). */
301 /*-----------------------------------------------------------------*/
306 /* If we are doing lazy evaluation, simply note the desired
307 * change, but don't emit any code yet.
317 emitcode ("mov", "dps,#0");
322 emitcode ("mov", "dps,#1");
326 /*-----------------------------------------------------------------*/
327 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
329 /* Any code that operates on DPTR (NB: not on the individual */
330 /* components, like DPH) *must* call _flushLazyDPS() before using */
331 /* DPTR within a lazy DPS evaluation block. */
333 /* Note that aopPut and aopGet already contain the proper calls to */
334 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
335 /* DPS evaluation block. */
337 /* Also, _flushLazyDPS must be called before any flow control */
338 /* operations that could potentially branch out of the block. */
340 /* Lazy DPS evaluation is simply an optimization (though an */
341 /* important one), so if in doubt, leave it out. */
342 /*-----------------------------------------------------------------*/
344 _startLazyDPSEvaluation (void)
348 #ifdef BETTER_LITERAL_SHIFT
355 /*-----------------------------------------------------------------*/
356 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
357 /* desired one. Call before using DPTR within a lazy DPS evaluation */
359 /*-----------------------------------------------------------------*/
369 if (_desiredDPS != _currentDPS)
373 emitcode ("inc", "dps");
377 emitcode ("dec", "dps");
379 _currentDPS = _desiredDPS;
383 /*-----------------------------------------------------------------*/
384 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
386 /* Forces us back to the safe state (standard DPTR selected). */
387 /*-----------------------------------------------------------------*/
389 _endLazyDPSEvaluation (void)
391 #ifdef BETTER_LITERAL_SHIFT
410 /*-----------------------------------------------------------------*/
411 /* pointerCode - returns the code for a pointer type */
412 /*-----------------------------------------------------------------*/
414 pointerCode (sym_link * etype)
417 return PTR_TYPE (SPEC_OCLS (etype));
421 /*-----------------------------------------------------------------*/
422 /* aopForSym - for a true symbol */
423 /*-----------------------------------------------------------------*/
425 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
428 memmap *space = SPEC_OCLS (sym->etype);
430 /* if already has one */
434 /* assign depending on the storage class */
435 /* if it is on the stack or indirectly addressable */
436 /* space we need to assign either r0 or r1 to it */
437 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
439 sym->aop = aop = newAsmop (0);
440 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
441 aop->size = getSize (sym->type);
443 /* now assign the address of the variable to
444 the pointer register */
445 if (aop->type != AOP_STK)
451 emitcode ("push", "acc");
454 emitcode ("push", "b");
456 emitcode ("mov", "a,_bp");
457 emitcode ("add", "a,#!constbyte",
459 ((char) (sym->stack - _G.nRegsSaved)) :
460 ((char) sym->stack)) & 0xff);
461 emitcode ("mov", "%s,a",
462 aop->aopu.aop_ptr->name);
465 emitcode ("pop", "b");
468 emitcode ("pop", "acc");
471 emitcode ("mov", "%s,#%s",
472 aop->aopu.aop_ptr->name,
474 aop->paged = space->paged;
477 aop->aopu.aop_stk = sym->stack;
481 if (sym->onStack && options.stack10bit)
483 short stack_val = -((sym->stack < 0) ?
484 ((short) (sym->stack - _G.nRegsSaved)) :
485 ((short) sym->stack)) ;
486 /* It's on the 10 bit stack, which is located in
489 if (stack_val < 0 && stack_val > -5) { /* between -5 & -1 */
491 if (options.model == MODEL_FLAT24)
492 emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
494 emitcode ("mov", "dph1,_bpx+1");
495 emitcode ("mov", "dpl1,_bpx");
496 emitcode ("mov","dps,#1");
498 if (options.model == MODEL_FLAT24)
499 emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
500 emitcode ("mov", "dph,_bpx+1");
501 emitcode ("mov", "dpl,_bpx");
503 stack_val = -stack_val;
504 while (stack_val--) {
505 emitcode ("inc","dptr");
508 emitcode("mov","dps,#0");
512 emitcode ("push", "acc");
515 emitcode ("push", "b");
517 emitcode ("mov", "a,_bpx");
518 emitcode ("clr","c");
519 emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
520 emitcode ("mov","b,a");
521 emitcode ("mov","a,_bpx+1");
522 emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
524 if (options.model == MODEL_FLAT24)
525 emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
527 emitcode ("mov", "dph1,a");
528 emitcode ("mov", "dpl1,b");
530 if (options.model == MODEL_FLAT24)
531 emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
532 emitcode ("mov", "dph,a");
533 emitcode ("mov", "dpl,b");
537 emitcode ("pop", "b");
540 emitcode ("pop", "acc");
542 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
543 aop->size = getSize (sym->type);
547 /* if in bit space */
548 if (IN_BITSPACE (space))
550 sym->aop = aop = newAsmop (AOP_CRY);
551 aop->aopu.aop_dir = sym->rname;
552 aop->size = getSize (sym->type);
555 /* if it is in direct space */
556 if (IN_DIRSPACE (space))
558 sym->aop = aop = newAsmop (AOP_DIR);
559 aop->aopu.aop_dir = sym->rname;
560 aop->size = getSize (sym->type);
564 /* special case for a function */
565 if (IS_FUNC (sym->type))
567 sym->aop = aop = newAsmop (AOP_IMMD);
568 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
569 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
570 aop->size = FPTRSIZE;
574 /* only remaining is far space */
575 /* in which case DPTR gets the address */
576 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
581 emitcode ("mov", "dptr,#%s", sym->rname);
586 emitcode ("mov", "dptr,#%s", sym->rname);
588 aop->size = getSize (sym->type);
590 /* if it is in code space */
591 if (IN_CODESPACE (space))
597 /*-----------------------------------------------------------------*/
598 /* aopForRemat - rematerialzes an object */
599 /*-----------------------------------------------------------------*/
601 aopForRemat (symbol * sym)
603 iCode *ic = sym->rematiCode;
604 asmop *aop = newAsmop (AOP_IMMD);
611 val += (int) operandLitValue (IC_RIGHT (ic));
612 else if (ic->op == '-')
613 val -= (int) operandLitValue (IC_RIGHT (ic));
614 else if (IS_CAST_ICODE(ic)) {
615 sym_link *from_type = operandType(IC_RIGHT(ic));
616 aop->aopu.aop_immd.from_cast_remat = 1;
617 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
618 ptr_type = DCL_TYPE(from_type);
619 if (ptr_type == IPOINTER) {
626 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
630 sprintf (buffer, "(%s %c 0x%04x)",
631 OP_SYMBOL (IC_LEFT (ic))->rname,
632 val >= 0 ? '+' : '-',
635 if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
636 sprintf(buffer,"0x%x",(int) operandLitValue (IC_RIGHT (ic)));
638 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
641 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
642 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
643 /* set immd2 field if required */
644 if (aop->aopu.aop_immd.from_cast_remat) {
645 tsprintf(buffer,"#!constbyte",ptr_type);
646 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
647 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
653 /*-----------------------------------------------------------------*/
654 /* aopHasRegs - returns true if aop has regs between from-to */
655 /*-----------------------------------------------------------------*/
656 static int aopHasRegs(asmop *aop, int from, int to)
660 if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
662 for (; size < aop->size ; size++) {
664 for (reg = from ; reg <= to ; reg++)
665 if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
670 /*-----------------------------------------------------------------*/
671 /* regsInCommon - two operands have some registers in common */
672 /*-----------------------------------------------------------------*/
674 regsInCommon (operand * op1, operand * op2)
679 /* if they have registers in common */
680 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
683 sym1 = OP_SYMBOL (op1);
684 sym2 = OP_SYMBOL (op2);
686 if (sym1->nRegs == 0 || sym2->nRegs == 0)
689 for (i = 0; i < sym1->nRegs; i++)
695 for (j = 0; j < sym2->nRegs; j++)
700 if (sym2->regs[j] == sym1->regs[i])
708 /*-----------------------------------------------------------------*/
709 /* operandsEqu - equivalent */
710 /*-----------------------------------------------------------------*/
712 operandsEqu (operand * op1, operand * op2)
716 /* if they not symbols */
717 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
720 sym1 = OP_SYMBOL (op1);
721 sym2 = OP_SYMBOL (op2);
723 /* if both are itemps & one is spilt
724 and the other is not then false */
725 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
726 sym1->isspilt != sym2->isspilt)
729 /* if they are the same */
733 if (strcmp (sym1->rname, sym2->rname) == 0)
737 /* if left is a tmp & right is not */
738 if (IS_ITEMP (op1) &&
741 (sym1->usl.spillLoc == sym2))
744 if (IS_ITEMP (op2) &&
748 (sym2->usl.spillLoc == sym1))
754 /*-----------------------------------------------------------------*/
755 /* sameRegs - two asmops have the same registers */
756 /*-----------------------------------------------------------------*/
758 sameRegs (asmop * aop1, asmop * aop2)
764 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
771 if (aop1->type != AOP_REG ||
772 aop2->type != AOP_REG)
775 if (aop1->size != aop2->size)
778 for (i = 0; i < aop1->size; i++)
779 if (aop1->aopu.aop_reg[i] !=
780 aop2->aopu.aop_reg[i])
786 /*-----------------------------------------------------------------*/
787 /* aopOp - allocates an asmop for an operand : */
788 /*-----------------------------------------------------------------*/
790 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
799 /* if this a literal */
800 if (IS_OP_LITERAL (op))
802 op->aop = aop = newAsmop (AOP_LIT);
803 aop->aopu.aop_lit = op->operand.valOperand;
804 aop->size = getSize (operandType (op));
808 /* if already has a asmop then continue */
812 /* if the underlying symbol has a aop */
813 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
815 op->aop = OP_SYMBOL (op)->aop;
819 /* if this is a true symbol */
820 if (IS_TRUE_SYMOP (op))
822 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
826 /* this is a temporary : this has
832 e) can be a return use only */
834 sym = OP_SYMBOL (op);
837 /* if the type is a conditional */
838 if (sym->regType == REG_CND)
840 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
845 /* if it is spilt then two situations
847 b) has a spill location */
848 if (sym->isspilt || sym->nRegs == 0)
851 /* rematerialize it NOW */
854 sym->aop = op->aop = aop =
856 aop->size = getSize (sym->type);
863 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
864 aop->size = getSize (sym->type);
865 for (i = 0; i < 2; i++)
866 aop->aopu.aop_str[i] = accUse[i];
876 /* a AOP_STR uses DPTR, but DPTR is already in use;
879 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
882 aop = op->aop = sym->aop = newAsmop (AOP_STR);
883 aop->size = getSize (sym->type);
884 for (i = 0; i < (int) fReturnSizeDS390; i++)
885 aop->aopu.aop_str[i] = fReturn[i];
889 if (sym->dptr) { /* has been allocated to a DPTRn */
890 aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
891 aop->size = getSize (sym->type);
892 aop->aopu.dptr = sym->dptr;
895 /* else spill location */
896 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
897 /* force a new aop if sizes differ */
898 sym->usl.spillLoc->aop = NULL;
900 sym->aop = op->aop = aop =
901 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
902 aop->size = getSize (sym->type);
906 /* must be in a register */
907 sym->aop = op->aop = aop = newAsmop (AOP_REG);
908 aop->size = sym->nRegs;
909 for (i = 0; i < sym->nRegs; i++)
910 aop->aopu.aop_reg[i] = sym->regs[i];
913 /*-----------------------------------------------------------------*/
914 /* freeAsmop - free up the asmop given to an operand */
915 /*----------------------------------------------------------------*/
917 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
934 /* depending on the asmop type only three cases need work AOP_RO
935 , AOP_R1 && AOP_STK */
943 emitcode ("pop", "ar0");
947 bitVectUnSetBit (ic->rUsed, R0_IDX);
955 emitcode ("pop", "ar1");
959 bitVectUnSetBit (ic->rUsed, R1_IDX);
965 int stk = aop->aopu.aop_stk + aop->size;
966 bitVectUnSetBit (ic->rUsed, R0_IDX);
967 bitVectUnSetBit (ic->rUsed, R1_IDX);
969 getFreePtr (ic, &aop, FALSE);
971 if (options.stack10bit)
973 /* I'm not sure what to do here yet... */
976 "*** Warning: probably generating bad code for "
977 "10 bit stack mode.\n");
982 emitcode ("mov", "a,_bp");
983 emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
984 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
988 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
993 emitcode ("pop", "acc");
994 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
997 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1000 freeAsmop (op, NULL, ic, TRUE);
1003 emitcode ("pop", "ar0");
1009 emitcode ("pop", "ar1");
1016 /* all other cases just dealloc */
1022 OP_SYMBOL (op)->aop = NULL;
1023 /* if the symbol has a spill */
1025 SPIL_LOC (op)->aop = NULL;
1030 /*------------------------------------------------------------------*/
1031 /* aopGet - for fetching value of the aop */
1033 /* Set canClobberACC if you are sure it is OK to clobber the value */
1034 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
1035 /* just less efficient. */
1036 /*------------------------------------------------------------------*/
1039 aopGet (asmop * aop,
1048 /* offset is greater than
1050 if (offset > (aop->size - 1) &&
1051 aop->type != AOP_LIT)
1054 /* depending on type */
1060 /* if we need to increment it */
1061 while (offset > aop->coff)
1063 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1067 while (offset < aop->coff)
1069 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1076 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1077 return (dname ? "acc" : "a");
1079 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1080 rs = Safe_calloc (1, strlen (s) + 1);
1085 assert(offset <= 3);
1086 return dptrn[aop->aopu.dptr][offset];
1091 if (aop->type == AOP_DPTR2)
1097 emitcode ("xch", "a, %s", DP2_RESULT_REG);
1103 while (offset > aop->coff)
1105 emitcode ("inc", "dptr");
1109 while (offset < aop->coff)
1111 emitcode ("lcall", "__decdptr");
1118 emitcode ("clr", "a");
1119 emitcode ("movc", "a,@a+dptr");
1123 emitcode ("movx", "a,@dptr");
1126 if (aop->type == AOP_DPTR2)
1132 emitcode ("xch", "a, %s", DP2_RESULT_REG);
1133 return DP2_RESULT_REG;
1136 return (dname ? "acc" : "a");
1139 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1140 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1142 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1146 tsprintf(s,"#!his",aop->aopu.aop_immd.aop_immd1);
1149 tsprintf(s,"#!hihis",aop->aopu.aop_immd.aop_immd1);
1152 tsprintf(s,"#!hihihis",aop->aopu.aop_immd.aop_immd1);
1154 default: /* should not need this (just in case) */
1155 sprintf (s, "#(%s >> %d)",
1156 aop->aopu.aop_immd.aop_immd1,
1162 aop->aopu.aop_immd.aop_immd1);
1163 rs = Safe_calloc (1, strlen (s) + 1);
1169 sprintf (s, "(%s + %d)",
1173 sprintf (s, "%s", aop->aopu.aop_dir);
1174 rs = Safe_calloc (1, strlen (s) + 1);
1180 return aop->aopu.aop_reg[offset]->dname;
1182 return aop->aopu.aop_reg[offset]->name;
1185 emitcode ("clr", "a");
1186 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1187 emitcode ("rlc", "a");
1188 return (dname ? "acc" : "a");
1191 if (!offset && dname)
1193 return aop->aopu.aop_str[offset];
1196 return aopLiteral (aop->aopu.aop_lit, offset);
1200 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1204 return aop->aopu.aop_str[offset];
1208 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1209 "aopget got unsupported aop->type");
1212 /*-----------------------------------------------------------------*/
1213 /* aopPut - puts a string for a aop */
1214 /*-----------------------------------------------------------------*/
1216 aopPut (asmop * aop, char *s, int offset)
1220 if (aop->size && offset > (aop->size - 1))
1222 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1223 "aopPut got offset > aop->size");
1227 /* will assign value to value */
1228 /* depending on where it is ofcourse */
1233 sprintf (d, "(%s + %d)",
1234 aop->aopu.aop_dir, offset);
1236 sprintf (d, "%s", aop->aopu.aop_dir);
1239 emitcode ("mov", "%s,%s", d, s);
1244 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1245 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1248 strcmp (s, "r0") == 0 ||
1249 strcmp (s, "r1") == 0 ||
1250 strcmp (s, "r2") == 0 ||
1251 strcmp (s, "r3") == 0 ||
1252 strcmp (s, "r4") == 0 ||
1253 strcmp (s, "r5") == 0 ||
1254 strcmp (s, "r6") == 0 ||
1255 strcmp (s, "r7") == 0)
1256 emitcode ("mov", "%s,%s",
1257 aop->aopu.aop_reg[offset]->dname, s);
1259 emitcode ("mov", "%s,%s",
1260 aop->aopu.aop_reg[offset]->name, s);
1265 emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1271 if (aop->type == AOP_DPTR2)
1279 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1280 "aopPut writting to code space");
1284 while (offset > aop->coff)
1287 emitcode ("inc", "dptr");
1290 while (offset < aop->coff)
1293 emitcode ("lcall", "__decdptr");
1298 /* if not in accumulater */
1301 emitcode ("movx", "@dptr,a");
1303 if (aop->type == AOP_DPTR2)
1311 while (offset > aop->coff)
1314 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1316 while (offset < aop->coff)
1319 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1326 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1332 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1334 else if (strcmp (s, "r0") == 0 ||
1335 strcmp (s, "r1") == 0 ||
1336 strcmp (s, "r2") == 0 ||
1337 strcmp (s, "r3") == 0 ||
1338 strcmp (s, "r4") == 0 ||
1339 strcmp (s, "r5") == 0 ||
1340 strcmp (s, "r6") == 0 ||
1341 strcmp (s, "r7") == 0)
1344 sprintf (buffer, "a%s", s);
1345 emitcode ("mov", "@%s,%s",
1346 aop->aopu.aop_ptr->name, buffer);
1349 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1354 if (strcmp (s, "a") == 0)
1355 emitcode ("push", "acc");
1359 emitcode ("push", "acc");
1361 emitcode ("push", s);
1367 /* if bit variable */
1368 if (!aop->aopu.aop_dir)
1370 emitcode ("clr", "a");
1371 emitcode ("rlc", "a");
1376 emitcode ("clr", "%s", aop->aopu.aop_dir);
1378 emitcode ("setb", "%s", aop->aopu.aop_dir);
1379 else if (!strcmp (s, "c"))
1380 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1383 if (strcmp (s, "a"))
1388 symbol *lbl = newiTempLabel (NULL);
1389 emitcode ("clr", "c");
1390 emitcode ("jz", "!tlabel", lbl->key + 100);
1391 emitcode ("cpl", "c");
1392 emitcode ("", "!tlabeldef", lbl->key + 100);
1393 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1401 if (strcmp (aop->aopu.aop_str[offset], s))
1402 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1407 if (!offset && (strcmp (s, "acc") == 0))
1410 if (strcmp (aop->aopu.aop_str[offset], s))
1411 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1415 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1416 "aopPut got unsupported aop->type");
1423 /*--------------------------------------------------------------------*/
1424 /* reAdjustPreg - points a register back to where it should (coff==0) */
1425 /*--------------------------------------------------------------------*/
1427 reAdjustPreg (asmop * aop)
1429 if ((aop->coff==0) || (aop->size <= 1)) {
1438 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1442 if (aop->type == AOP_DPTR2)
1449 emitcode ("lcall", "__decdptr");
1452 if (aop->type == AOP_DPTR2)
1462 #define AOP(op) op->aop
1463 #define AOP_TYPE(op) AOP(op)->type
1464 #define AOP_SIZE(op) AOP(op)->size
1465 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1466 AOP_TYPE(x) == AOP_R0))
1468 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1469 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1472 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1473 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1474 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1475 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1476 #define AOP_USESDPTR(x) (AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_STR)
1478 /* Workaround for DS80C390 bug: div ab may return bogus results
1479 * if A is accessed in instruction immediately before the div.
1481 * Will be fixed in B4 rev of processor, Dallas claims.
1484 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1485 if (!AOP_NEEDSACC(RIGHT)) \
1487 /* We can load A first, then B, since \
1488 * B (the RIGHT operand) won't clobber A, \
1489 * thus avoiding touching A right before the div. \
1491 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1492 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1494 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1498 /* Just stuff in a nop after loading A. */ \
1499 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1500 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1502 emitcode("nop", "; workaround for DS80C390 div bug."); \
1505 /*-----------------------------------------------------------------*/
1506 /* genNotFloat - generates not for float operations */
1507 /*-----------------------------------------------------------------*/
1509 genNotFloat (operand * op, operand * res)
1515 D (emitcode (";", "genNotFloat ");
1518 /* we will put 127 in the first byte of
1520 aopPut (AOP (res), "#127", 0);
1521 size = AOP_SIZE (op) - 1;
1524 _startLazyDPSEvaluation ();
1525 l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1530 emitcode ("orl", "a,%s",
1532 offset++, FALSE, FALSE, FALSE));
1534 _endLazyDPSEvaluation ();
1536 tlbl = newiTempLabel (NULL);
1537 aopPut (res->aop, one, 1);
1538 emitcode ("jz", "!tlabel", (tlbl->key + 100));
1539 aopPut (res->aop, zero, 1);
1540 emitcode ("", "!tlabeldef", (tlbl->key + 100));
1542 size = res->aop->size - 2;
1544 /* put zeros in the rest */
1546 aopPut (res->aop, zero, offset++);
1549 /*-----------------------------------------------------------------*/
1550 /* opIsGptr: returns non-zero if the passed operand is */
1551 /* a generic pointer type. */
1552 /*-----------------------------------------------------------------*/
1554 opIsGptr (operand * op)
1556 sym_link *type = operandType (op);
1558 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1565 /*-----------------------------------------------------------------*/
1566 /* getDataSize - get the operand data size */
1567 /*-----------------------------------------------------------------*/
1569 getDataSize (operand * op)
1572 size = AOP_SIZE (op);
1573 if (size == GPTRSIZE)
1575 sym_link *type = operandType (op);
1576 if (IS_GENPTR (type))
1578 /* generic pointer; arithmetic operations
1579 * should ignore the high byte (pointer type).
1587 /*-----------------------------------------------------------------*/
1588 /* outAcc - output Acc */
1589 /*-----------------------------------------------------------------*/
1591 outAcc (operand * result)
1594 size = getDataSize (result);
1597 aopPut (AOP (result), "a", 0);
1600 /* unsigned or positive */
1603 aopPut (AOP (result), zero, offset++);
1608 /*-----------------------------------------------------------------*/
1609 /* outBitC - output a bit C */
1610 /*-----------------------------------------------------------------*/
1612 outBitC (operand * result)
1614 /* if the result is bit */
1615 if (AOP_TYPE (result) == AOP_CRY)
1617 aopPut (AOP (result), "c", 0);
1621 emitcode ("clr", "a");
1622 emitcode ("rlc", "a");
1627 /*-----------------------------------------------------------------*/
1628 /* toBoolean - emit code for orl a,operator(sizeop) */
1629 /*-----------------------------------------------------------------*/
1631 toBoolean (operand * oper)
1633 int size = AOP_SIZE (oper) - 1;
1637 /* The generic part of a generic pointer should
1638 * not participate in it's truth value.
1640 * i.e. 0x10000000 is zero.
1642 if (opIsGptr (oper))
1644 D (emitcode (";", "toBoolean: generic ptr special case.");
1649 _startLazyDPSEvaluation ();
1650 if (AOP_NEEDSACC (oper) && size)
1653 emitcode ("push", "b");
1654 emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1658 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1664 emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1668 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1671 _endLazyDPSEvaluation ();
1675 emitcode ("mov", "a,b");
1676 emitcode ("pop", "b");
1681 /*-----------------------------------------------------------------*/
1682 /* genNot - generate code for ! operation */
1683 /*-----------------------------------------------------------------*/
1688 sym_link *optype = operandType (IC_LEFT (ic));
1690 D (emitcode (";", "genNot ");
1693 /* assign asmOps to operand & result */
1694 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1695 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1697 /* if in bit space then a special case */
1698 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1700 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1701 emitcode ("cpl", "c");
1702 outBitC (IC_RESULT (ic));
1706 /* if type float then do float */
1707 if (IS_FLOAT (optype))
1709 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1713 toBoolean (IC_LEFT (ic));
1715 tlbl = newiTempLabel (NULL);
1716 emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1717 emitcode ("", "!tlabeldef", tlbl->key + 100);
1718 outBitC (IC_RESULT (ic));
1721 /* release the aops */
1722 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1723 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1727 /*-----------------------------------------------------------------*/
1728 /* genCpl - generate code for complement */
1729 /*-----------------------------------------------------------------*/
1737 D (emitcode (";", "genCpl ");
1741 /* assign asmOps to operand & result */
1742 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1743 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1745 /* special case if in bit space */
1746 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1747 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1748 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1749 emitcode ("cpl", "c");
1750 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1753 tlbl=newiTempLabel(NULL);
1754 emitcode ("cjne", "%s,#0x01,%05d$",
1755 aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,TRUE), tlbl->key+100);
1756 emitcode ("", "%05d$:", tlbl->key+100);
1757 outBitC (IC_RESULT(ic));
1761 size = AOP_SIZE (IC_RESULT (ic));
1762 _startLazyDPSEvaluation ();
1765 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1767 emitcode ("cpl", "a");
1768 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1770 _endLazyDPSEvaluation ();
1774 /* release the aops */
1775 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1776 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1779 /*-----------------------------------------------------------------*/
1780 /* genUminusFloat - unary minus for floating points */
1781 /*-----------------------------------------------------------------*/
1783 genUminusFloat (operand * op, operand * result)
1785 int size, offset = 0;
1787 /* for this we just need to flip the
1788 first it then copy the rest in place */
1789 D (emitcode (";", "genUminusFloat");
1792 _startLazyDPSEvaluation ();
1793 size = AOP_SIZE (op) - 1;
1794 l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1797 emitcode ("cpl", "acc.7");
1798 aopPut (AOP (result), "a", 3);
1802 aopPut (AOP (result),
1803 aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1807 _endLazyDPSEvaluation ();
1810 /*-----------------------------------------------------------------*/
1811 /* genUminus - unary minus code generation */
1812 /*-----------------------------------------------------------------*/
1814 genUminus (iCode * ic)
1817 sym_link *optype, *rtype;
1819 D (emitcode (";", "genUminus ");
1824 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1825 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1827 /* if both in bit space then special
1829 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1830 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1833 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1834 emitcode ("cpl", "c");
1835 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1839 optype = operandType (IC_LEFT (ic));
1840 rtype = operandType (IC_RESULT (ic));
1842 /* if float then do float stuff */
1843 if (IS_FLOAT (optype))
1845 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1849 /* otherwise subtract from zero */
1850 size = AOP_SIZE (IC_LEFT (ic));
1852 _startLazyDPSEvaluation ();
1855 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1856 if (!strcmp (l, "a"))
1860 emitcode ("cpl", "a");
1861 emitcode ("addc", "a,#0");
1867 emitcode ("clr", "a");
1868 emitcode ("subb", "a,%s", l);
1870 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1872 _endLazyDPSEvaluation ();
1874 /* if any remaining bytes in the result */
1875 /* we just need to propagate the sign */
1876 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1878 emitcode ("rlc", "a");
1879 emitcode ("subb", "a,acc");
1881 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1885 /* release the aops */
1886 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1887 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1890 /*-----------------------------------------------------------------*/
1891 /* savermask - saves registers in the mask */
1892 /*-----------------------------------------------------------------*/
1893 static void savermask(bitVect *rs_mask)
1896 if (options.useXstack) {
1897 if (bitVectBitValue (rs_mask, R0_IDX))
1898 emitcode ("mov", "b,r0");
1899 emitcode ("mov", "r0,%s", spname);
1900 for (i = 0; i < ds390_nRegs; i++) {
1901 if (bitVectBitValue (rs_mask, i)) {
1903 emitcode ("mov", "a,b");
1905 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1906 emitcode ("movx", "@r0,a");
1907 emitcode ("inc", "r0");
1910 emitcode ("mov", "%s,r0", spname);
1911 if (bitVectBitValue (rs_mask, R0_IDX))
1912 emitcode ("mov", "r0,b");
1914 for (i = 0; i < ds390_nRegs; i++) {
1915 if (bitVectBitValue (rs_mask, i))
1916 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1921 /*-----------------------------------------------------------------*/
1922 /* saveRegisters - will look for a call and save the registers */
1923 /*-----------------------------------------------------------------*/
1925 saveRegisters (iCode * lic)
1931 for (ic = lic; ic; ic = ic->next)
1932 if (ic->op == CALL || ic->op == PCALL)
1937 fprintf (stderr, "found parameter push with no function call\n");
1941 /* if the registers have been saved already then
1943 if (ic->regsSaved || IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic)))) return ;
1945 /* special case if DPTR alive across a function call then must save it
1946 even though callee saves */
1947 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
1949 rsave = newBitVect(ic->rMask->size);
1950 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
1951 if (bitVectBitValue(ic->rMask,i))
1952 rsave = bitVectSetBit(rsave,i);
1954 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
1956 /* safe the registers in use at this time but skip the
1957 ones for the result */
1958 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1959 ds390_rUmaskForOp (IC_RESULT(ic)));
1965 /*-----------------------------------------------------------------*/
1966 /* usavermask - restore registers with mask */
1967 /*-----------------------------------------------------------------*/
1968 static void unsavermask(bitVect *rs_mask)
1971 if (options.useXstack) {
1972 emitcode ("mov", "r0,%s", spname);
1973 for (i = ds390_nRegs; i >= 0; i--) {
1974 if (bitVectBitValue (rs_mask, i)) {
1975 emitcode ("dec", "r0");
1976 emitcode ("movx", "a,@r0");
1978 emitcode ("mov", "b,a");
1980 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1983 emitcode ("mov", "%s,r0", spname);
1984 if (bitVectBitValue (rs_mask, R0_IDX))
1985 emitcode ("mov", "r0,b");
1987 for (i = ds390_nRegs; i >= 0; i--) {
1988 if (bitVectBitValue (rs_mask, i))
1989 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1994 /*-----------------------------------------------------------------*/
1995 /* unsaveRegisters - pop the pushed registers */
1996 /*-----------------------------------------------------------------*/
1998 unsaveRegisters (iCode * ic)
2002 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2004 rsave = newBitVect(ic->rMask->size);
2005 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2006 if (bitVectBitValue(ic->rMask,i))
2007 rsave = bitVectSetBit(rsave,i);
2009 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2011 /* restore the registers in use at this time but skip the
2012 ones for the result */
2013 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2014 ds390_rUmaskForOp (IC_RESULT(ic)));
2020 /*-----------------------------------------------------------------*/
2022 /*-----------------------------------------------------------------*/
2024 pushSide (operand * oper, int size)
2027 _startLazyDPSEvaluation ();
2030 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
2031 if (AOP_TYPE (oper) != AOP_REG &&
2032 AOP_TYPE (oper) != AOP_DIR &&
2035 emitcode ("mov", "a,%s", l);
2036 emitcode ("push", "acc");
2039 emitcode ("push", "%s", l);
2041 _endLazyDPSEvaluation ();
2044 /*-----------------------------------------------------------------*/
2045 /* assignResultValue - */
2046 /*-----------------------------------------------------------------*/
2048 assignResultValue (operand * oper)
2051 int size = AOP_SIZE (oper);
2053 _startLazyDPSEvaluation ();
2056 aopPut (AOP (oper), fReturn[offset], offset);
2059 _endLazyDPSEvaluation ();
2063 /*-----------------------------------------------------------------*/
2064 /* genXpush - pushes onto the external stack */
2065 /*-----------------------------------------------------------------*/
2067 genXpush (iCode * ic)
2069 asmop *aop = newAsmop (0);
2071 int size, offset = 0;
2073 D (emitcode (";", "genXpush ");
2076 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2077 r = getFreePtr (ic, &aop, FALSE);
2080 emitcode ("mov", "%s,_spx", r->name);
2082 size = AOP_SIZE (IC_LEFT (ic));
2083 _startLazyDPSEvaluation ();
2087 char *l = aopGet (AOP (IC_LEFT (ic)),
2088 offset++, FALSE, FALSE, TRUE);
2090 emitcode ("movx", "@%s,a", r->name);
2091 emitcode ("inc", "%s", r->name);
2094 _endLazyDPSEvaluation ();
2097 emitcode ("mov", "_spx,%s", r->name);
2099 freeAsmop (NULL, aop, ic, TRUE);
2100 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2103 /*-----------------------------------------------------------------*/
2104 /* genIpush - genrate code for pushing this gets a little complex */
2105 /*-----------------------------------------------------------------*/
2107 genIpush (iCode * ic)
2109 int size, offset = 0;
2112 D (emitcode (";", "genIpush ");
2115 /* if this is not a parm push : ie. it is spill push
2116 and spill push is always done on the local stack */
2120 /* and the item is spilt then do nothing */
2121 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2124 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2125 size = AOP_SIZE (IC_LEFT (ic));
2126 /* push it on the stack */
2127 _startLazyDPSEvaluation ();
2130 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
2136 emitcode ("push", "%s", l);
2138 _endLazyDPSEvaluation ();
2142 /* this is a paramter push: in this case we call
2143 the routine to find the call and save those
2144 registers that need to be saved */
2147 /* if use external stack then call the external
2148 stack pushing routine */
2149 if (options.useXstack)
2155 /* then do the push */
2156 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2158 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2159 size = AOP_SIZE (IC_LEFT (ic));
2161 _startLazyDPSEvaluation ();
2164 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
2165 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2166 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2169 emitcode ("mov", "a,%s", l);
2170 emitcode ("push", "acc");
2173 emitcode ("push", "%s", l);
2175 _endLazyDPSEvaluation ();
2177 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2180 /*-----------------------------------------------------------------*/
2181 /* genIpop - recover the registers: can happen only for spilling */
2182 /*-----------------------------------------------------------------*/
2184 genIpop (iCode * ic)
2188 D (emitcode (";", "genIpop ");
2192 /* if the temp was not pushed then */
2193 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2196 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2197 size = AOP_SIZE (IC_LEFT (ic));
2198 offset = (size - 1);
2199 _startLazyDPSEvaluation ();
2202 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2203 FALSE, TRUE, TRUE));
2205 _endLazyDPSEvaluation ();
2207 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2210 /*-----------------------------------------------------------------*/
2211 /* unsaveRBank - restores the resgister bank from stack */
2212 /*-----------------------------------------------------------------*/
2214 unsaveRBank (int bank, iCode * ic, bool popPsw)
2220 if (options.useXstack)
2224 /* Assume r0 is available for use. */
2225 r = ds390_regWithIdx (R0_IDX);;
2230 r = getFreePtr (ic, &aop, FALSE);
2232 emitcode ("mov", "%s,_spx", r->name);
2237 if (options.useXstack)
2239 emitcode ("movx", "a,@%s", r->name);
2240 emitcode ("mov", "psw,a");
2241 emitcode ("dec", "%s", r->name);
2245 emitcode ("pop", "psw");
2249 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2251 if (options.useXstack)
2253 emitcode ("movx", "a,@%s", r->name);
2254 emitcode ("mov", "(%s+%d),a",
2255 regs390[i].base, 8 * bank + regs390[i].offset);
2256 emitcode ("dec", "%s", r->name);
2260 emitcode ("pop", "(%s+%d)",
2261 regs390[i].base, 8 * bank + regs390[i].offset);
2264 if (options.useXstack)
2266 emitcode ("mov", "_spx,%s", r->name);
2271 freeAsmop (NULL, aop, ic, TRUE);
2275 /*-----------------------------------------------------------------*/
2276 /* saveRBank - saves an entire register bank on the stack */
2277 /*-----------------------------------------------------------------*/
2279 saveRBank (int bank, iCode * ic, bool pushPsw)
2285 if (options.useXstack)
2289 /* Assume r0 is available for use. */
2290 r = ds390_regWithIdx (R0_IDX);;
2295 r = getFreePtr (ic, &aop, FALSE);
2297 emitcode ("mov", "%s,_spx", r->name);
2300 for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2302 if (options.useXstack)
2304 emitcode ("inc", "%s", r->name);
2305 emitcode ("mov", "a,(%s+%d)",
2306 regs390[i].base, 8 * bank + regs390[i].offset);
2307 emitcode ("movx", "@%s,a", r->name);
2310 emitcode ("push", "(%s+%d)",
2311 regs390[i].base, 8 * bank + regs390[i].offset);
2316 if (options.useXstack)
2318 emitcode ("mov", "a,psw");
2319 emitcode ("movx", "@%s,a", r->name);
2320 emitcode ("inc", "%s", r->name);
2321 emitcode ("mov", "_spx,%s", r->name);
2325 emitcode ("push", "psw");
2328 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2333 freeAsmop (NULL, aop, ic, TRUE);
2342 /*-----------------------------------------------------------------*/
2343 /* genSend - gen code for SEND */
2344 /*-----------------------------------------------------------------*/
2345 static void genSend(set *sendSet)
2349 static int rb1_count = 0;
2351 for (sic = setFirstItem (sendSet); sic;
2352 sic = setNextItem (sendSet)) {
2353 int size, offset = 0;
2355 size=getSize(operandType(IC_LEFT(sic)));
2356 D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2357 if (sendCount == 0) { /* first parameter */
2358 // we know that dpl(hxb) is the result, so
2360 _startLazyDPSEvaluation ();
2362 aopOp (IC_LEFT (sic), sic, FALSE,
2363 (IS_SYMOP(IC_LEFT(sic)) && OP_SYMBOL(IC_LEFT(sic))->ruonly ? FALSE : TRUE));
2365 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2368 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2369 FALSE, FALSE, TRUE);
2370 if (strcmp (l, fReturn[offset])) {
2371 emitcode ("mov", "%s,%s",
2377 _endLazyDPSEvaluation ();
2378 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2380 } else { /* if more parameter in registers */
2381 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2383 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2384 FALSE, FALSE, TRUE));
2386 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2392 /*-----------------------------------------------------------------*/
2393 /* genCall - generates a call statement */
2394 /*-----------------------------------------------------------------*/
2396 genCall (iCode * ic)
2399 bool restoreBank = FALSE;
2400 bool swapBanks = FALSE;
2402 D (emitcode (";", "genCall "););
2404 /* if we are calling a not _naked function that is not using
2405 the same register bank then we need to save the
2406 destination registers on the stack */
2407 dtype = operandType (IC_LEFT (ic));
2408 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2409 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2410 IFFUNC_ISISR (currFunc->type))
2414 /* This is unexpected; the bank should have been saved in
2417 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2423 /* if caller saves & we have not saved then */
2427 /* if send set is not empty the assign */
2428 /* We've saved all the registers we care about;
2429 * therefore, we may clobber any register not used
2430 * in the calling convention (i.e. anything not in
2435 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2436 genSend(reverseSet(_G.sendSet));
2438 genSend(_G.sendSet);
2445 emitcode ("mov", "psw,#!constbyte",
2446 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2450 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2451 OP_SYMBOL (IC_LEFT (ic))->rname :
2452 OP_SYMBOL (IC_LEFT (ic))->name));
2456 emitcode ("mov", "psw,#!constbyte",
2457 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2460 /* if we need assign a result value */
2461 if ((IS_ITEMP (IC_RESULT (ic)) &&
2462 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2463 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2464 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2465 IS_TRUE_SYMOP (IC_RESULT (ic)))
2467 if (isOperandInFarSpace (IC_RESULT (ic))
2468 && getSize (operandType (IC_RESULT (ic))) <= 2)
2470 int size = getSize (operandType (IC_RESULT (ic)));
2472 /* Special case for 1 or 2 byte return in far space. */
2476 emitcode ("mov", "b,%s", fReturn[1]);
2479 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2480 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2484 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2486 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2491 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2494 assignResultValue (IC_RESULT (ic));
2496 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2500 /* adjust the stack for parameters if
2502 if (ic->parmBytes) {
2504 if (options.stack10bit) {
2505 if (ic->parmBytes <= 10) {
2506 emitcode(";","stack adjustment for parms");
2507 for (i=0; i < ic->parmBytes ; i++) {
2508 emitcode("pop","acc");
2512 emitcode ("clr","c");
2513 emitcode ("mov","a,sp");
2514 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2515 emitcode ("mov","sp,a");
2516 emitcode ("mov","a,esp");
2517 emitcode ("anl","a,#3");
2518 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2519 emitcode ("mov","esp,a");
2523 if (ic->parmBytes > 3) {
2524 emitcode ("mov", "a,%s", spname);
2525 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2526 emitcode ("mov", "%s,a", spname);
2528 for (i = 0; i < ic->parmBytes; i++)
2529 emitcode ("dec", "%s", spname);
2533 /* if we hade saved some registers then unsave them */
2535 unsaveRegisters (ic);
2537 /* if register bank was saved then pop them */
2539 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2542 /*-----------------------------------------------------------------*/
2543 /* genPcall - generates a call by pointer statement */
2544 /*-----------------------------------------------------------------*/
2546 genPcall (iCode * ic)
2549 symbol *rlbl = newiTempLabel (NULL);
2550 bool restoreBank=FALSE;
2552 D (emitcode (";", "genPcall ");
2556 /* if caller saves & we have not saved then */
2560 /* if we are calling a function that is not using
2561 the same register bank then we need to save the
2562 destination registers on the stack */
2563 dtype = operandType (IC_LEFT (ic));
2564 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2565 IFFUNC_ISISR (currFunc->type) &&
2566 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2567 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2571 /* push the return address on to the stack */
2572 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2573 emitcode ("push", "acc");
2574 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2575 emitcode ("push", "acc");
2577 if (options.model == MODEL_FLAT24)
2579 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2580 emitcode ("push", "acc");
2583 /* now push the calling address */
2584 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2586 pushSide (IC_LEFT (ic), FPTRSIZE);
2588 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2590 /* if send set is not empty the assign */
2593 genSend(reverseSet(_G.sendSet));
2597 emitcode ("ret", "");
2598 emitcode ("", "!tlabeldef", (rlbl->key + 100));
2601 /* if we need assign a result value */
2602 if ((IS_ITEMP (IC_RESULT (ic)) &&
2603 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2604 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2605 IS_TRUE_SYMOP (IC_RESULT (ic)))
2609 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2612 assignResultValue (IC_RESULT (ic));
2614 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2617 /* adjust the stack for parameters if
2622 if (options.stack10bit) {
2623 if (ic->parmBytes <= 10) {
2624 emitcode(";","stack adjustment for parms");
2625 for (i=0; i < ic->parmBytes ; i++) {
2626 emitcode("pop","acc");
2630 emitcode ("clr","c");
2631 emitcode ("mov","a,sp");
2632 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2633 emitcode ("mov","sp,a");
2634 emitcode ("mov","a,esp");
2635 emitcode ("anl","a,#3");
2636 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2637 emitcode ("mov","esp,a");
2641 if (ic->parmBytes > 3) {
2642 emitcode ("mov", "a,%s", spname);
2643 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2644 emitcode ("mov", "%s,a", spname);
2647 for (i = 0; i < ic->parmBytes; i++)
2648 emitcode ("dec", "%s", spname);
2652 /* if register bank was saved then unsave them */
2654 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2656 /* if we hade saved some registers then
2659 unsaveRegisters (ic);
2663 /*-----------------------------------------------------------------*/
2664 /* resultRemat - result is rematerializable */
2665 /*-----------------------------------------------------------------*/
2667 resultRemat (iCode * ic)
2669 if (SKIP_IC (ic) || ic->op == IFX)
2672 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2674 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2675 if (sym->remat && !POINTER_SET (ic))
2682 #if defined(__BORLANDC__) || defined(_MSC_VER)
2683 #define STRCASECMP stricmp
2685 #define STRCASECMP strcasecmp
2688 /*-----------------------------------------------------------------*/
2689 /* inExcludeList - return 1 if the string is in exclude Reg list */
2690 /*-----------------------------------------------------------------*/
2692 inExcludeList (char *s)
2696 if (options.excludeRegs[i] &&
2697 STRCASECMP (options.excludeRegs[i], "none") == 0)
2700 for (i = 0; options.excludeRegs[i]; i++)
2702 if (options.excludeRegs[i] &&
2703 STRCASECMP (s, options.excludeRegs[i]) == 0)
2709 /*-----------------------------------------------------------------*/
2710 /* genFunction - generated code for function entry */
2711 /*-----------------------------------------------------------------*/
2713 genFunction (iCode * ic)
2717 bool switchedPSW = FALSE;
2719 D (emitcode (";", "genFunction "););
2722 /* create the function header */
2723 emitcode (";", "-----------------------------------------");
2724 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2725 emitcode (";", "-----------------------------------------");
2727 emitcode ("", "%s:", sym->rname);
2728 ftype = operandType (IC_LEFT (ic));
2730 if (IFFUNC_ISNAKED(ftype))
2732 emitcode(";", "naked function: no prologue.");
2736 if (options.stack_probe)
2737 emitcode ("lcall","__stack_probe");
2738 /* if critical function then turn interrupts off */
2739 if (IFFUNC_ISCRITICAL (ftype))
2740 emitcode ("clr", "ea");
2742 /* here we need to generate the equates for the
2743 register bank if required */
2744 if (FUNC_REGBANK (ftype) != rbank)
2748 rbank = FUNC_REGBANK (ftype);
2749 for (i = 0; i < ds390_nRegs; i++)
2751 if (regs390[i].print) {
2752 if (strcmp (regs390[i].base, "0") == 0)
2753 emitcode ("", "%s !equ !constbyte",
2755 8 * rbank + regs390[i].offset);
2757 emitcode ("", "%s !equ %s + !constbyte",
2760 8 * rbank + regs390[i].offset);
2765 /* if this is an interrupt service routine then
2766 save acc, b, dpl, dph */
2767 if (IFFUNC_ISISR (sym->type))
2769 if (!inExcludeList ("acc"))
2770 emitcode ("push", "acc");
2771 if (!inExcludeList ("b"))
2772 emitcode ("push", "b");
2773 if (!inExcludeList ("dpl"))
2774 emitcode ("push", "dpl");
2775 if (!inExcludeList ("dph"))
2776 emitcode ("push", "dph");
2777 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2779 emitcode ("push", "dpx");
2780 /* Make sure we're using standard DPTR */
2781 emitcode ("push", "dps");
2782 emitcode ("mov", "dps,#0");
2783 if (options.stack10bit)
2785 /* This ISR could conceivably use DPTR2. Better save it. */
2786 emitcode ("push", "dpl1");
2787 emitcode ("push", "dph1");
2788 emitcode ("push", "dpx1");
2789 emitcode ("push", DP2_RESULT_REG);
2792 /* if this isr has no bank i.e. is going to
2793 run with bank 0 , then we need to save more
2795 if (!FUNC_REGBANK (sym->type))
2799 /* if this function does not call any other
2800 function then we can be economical and
2801 save only those registers that are used */
2802 if (!IFFUNC_HASFCALL(sym->type))
2805 /* if any registers used */
2808 /* save the registers used */
2809 for (i = 0; i < sym->regsUsed->size; i++)
2811 if (bitVectBitValue (sym->regsUsed, i) ||
2812 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2813 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2820 /* this function has a function call cannot
2821 determines register usage so we will have to push the
2823 saveRBank (0, ic, FALSE);
2824 if (options.parms_in_bank1) {
2825 for (i=0; i < 8 ; i++ ) {
2826 emitcode ("push","%s",rb1regs[i]);
2833 /* This ISR uses a non-zero bank.
2835 * We assume that the bank is available for our
2838 * However, if this ISR calls a function which uses some
2839 * other bank, we must save that bank entirely.
2841 unsigned long banksToSave = 0;
2843 if (IFFUNC_HASFCALL(sym->type))
2846 #define MAX_REGISTER_BANKS 4
2851 for (i = ic; i; i = i->next)
2853 if (i->op == ENDFUNCTION)
2855 /* we got to the end OK. */
2863 dtype = operandType (IC_LEFT(i));
2865 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2867 /* Mark this bank for saving. */
2868 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2870 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2874 banksToSave |= (1 << FUNC_REGBANK(dtype));
2877 /* And note that we don't need to do it in
2885 /* This is a mess; we have no idea what
2886 * register bank the called function might
2889 * The only thing I can think of to do is
2890 * throw a warning and hope.
2892 werror(W_FUNCPTR_IN_USING_ISR);
2896 if (banksToSave && options.useXstack)
2898 /* Since we aren't passing it an ic,
2899 * saveRBank will assume r0 is available to abuse.
2901 * So switch to our (trashable) bank now, so
2902 * the caller's R0 isn't trashed.
2904 emitcode ("push", "psw");
2905 emitcode ("mov", "psw,#!constbyte",
2906 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2910 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2912 if (banksToSave & (1 << ix))
2914 saveRBank(ix, NULL, FALSE);
2918 // jwk: this needs a closer look
2919 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2924 /* if callee-save to be used for this function
2925 then save the registers being used in this function */
2926 if (IFFUNC_CALLEESAVES(sym->type))
2930 /* if any registers used */
2933 /* save the registers used */
2934 for (i = 0; i < sym->regsUsed->size; i++)
2936 if (bitVectBitValue (sym->regsUsed, i) ||
2937 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2939 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2947 /* set the register bank to the desired value */
2948 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
2951 emitcode ("push", "psw");
2952 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2955 if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
2956 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
2957 if (options.stack10bit) {
2958 emitcode ("push","_bpx");
2959 emitcode ("push","_bpx+1");
2960 emitcode ("mov","_bpx,%s",spname);
2961 emitcode ("mov","_bpx+1,esp");
2962 emitcode ("anl","_bpx+1,#3");
2964 if (options.useXstack) {
2965 emitcode ("mov", "r0,%s", spname);
2966 emitcode ("mov", "a,_bp");
2967 emitcode ("movx", "@r0,a");
2968 emitcode ("inc", "%s", spname);
2970 /* set up the stack */
2971 emitcode ("push", "_bp"); /* save the callers stack */
2973 emitcode ("mov", "_bp,%s", spname);
2977 /* adjust the stack for the function */
2980 if (options.stack10bit) {
2981 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
2982 assert (sym->recvSize <= 4);
2983 if (sym->stack <= 8) {
2984 while (i--) emitcode ("push","acc");
2987 emitcode ("mov","a,sp");
2988 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
2989 emitcode ("mov","sp,a");
2990 emitcode ("mov","a,esp");
2991 emitcode ("anl","a,#3");
2992 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
2993 emitcode ("mov","esp,a");
2998 werror (W_STACK_OVERFLOW, sym->name);
3000 if (i > 3 && sym->recvSize < 4) {
3002 emitcode ("mov", "a,sp");
3003 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3004 emitcode ("mov", "sp,a");
3008 emitcode ("inc", "sp");
3015 emitcode ("mov", "a,_spx");
3016 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3017 emitcode ("mov", "_spx,a");
3022 /*-----------------------------------------------------------------*/
3023 /* genEndFunction - generates epilogue for functions */
3024 /*-----------------------------------------------------------------*/
3026 genEndFunction (iCode * ic)
3028 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3030 D (emitcode (";", "genEndFunction "););
3032 if (IFFUNC_ISNAKED(sym->type))
3034 emitcode(";", "naked function: no epilogue.");
3038 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3039 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3041 if (options.stack10bit) {
3043 emitcode ("mov", "sp,_bpx", spname);
3044 emitcode ("mov", "esp,_bpx+1", spname);
3047 emitcode ("mov", "%s,_bp", spname);
3051 /* if use external stack but some variables were
3052 added to the local stack then decrement the
3054 if (options.useXstack && sym->stack) {
3055 emitcode ("mov", "a,sp");
3056 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3057 emitcode ("mov", "sp,a");
3061 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3062 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3064 if (options.useXstack) {
3065 emitcode ("mov", "r0,%s", spname);
3066 emitcode ("movx", "a,@r0");
3067 emitcode ("mov", "_bp,a");
3068 emitcode ("dec", "%s", spname);
3070 if (options.stack10bit) {
3071 emitcode ("pop", "_bpx+1");
3072 emitcode ("pop", "_bpx");
3074 emitcode ("pop", "_bp");
3079 /* restore the register bank */
3080 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3082 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3083 || !options.useXstack)
3085 /* Special case of ISR using non-zero bank with useXstack
3088 emitcode ("pop", "psw");
3092 if (IFFUNC_ISISR (sym->type))
3095 /* now we need to restore the registers */
3096 /* if this isr has no bank i.e. is going to
3097 run with bank 0 , then we need to save more
3099 if (!FUNC_REGBANK (sym->type))
3102 /* if this function does not call any other
3103 function then we can be economical and
3104 save only those registers that are used */
3105 if (!IFFUNC_HASFCALL(sym->type))
3108 /* if any registers used */
3111 /* save the registers used */
3112 for (i = sym->regsUsed->size; i >= 0; i--)
3114 if (bitVectBitValue (sym->regsUsed, i) ||
3115 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3116 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3123 /* this function has a function call cannot
3124 determines register usage so we will have to pop the
3126 if (options.parms_in_bank1) {
3127 for (i = 7 ; i >= 0 ; i-- ) {
3128 emitcode ("pop","%s",rb1regs[i]);
3131 unsaveRBank (0, ic, FALSE);
3136 /* This ISR uses a non-zero bank.
3138 * Restore any register banks saved by genFunction
3141 // jwk: this needs a closer look
3142 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3145 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3147 if (savedBanks & (1 << ix))
3149 unsaveRBank(ix, NULL, FALSE);
3153 if (options.useXstack)
3155 /* Restore bank AFTER calling unsaveRBank,
3156 * since it can trash r0.
3158 emitcode ("pop", "psw");
3162 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3164 if (options.stack10bit)
3166 emitcode ("pop", DP2_RESULT_REG);
3167 emitcode ("pop", "dpx1");
3168 emitcode ("pop", "dph1");
3169 emitcode ("pop", "dpl1");
3171 emitcode ("pop", "dps");
3172 emitcode ("pop", "dpx");
3174 if (!inExcludeList ("dph"))
3175 emitcode ("pop", "dph");
3176 if (!inExcludeList ("dpl"))
3177 emitcode ("pop", "dpl");
3178 if (!inExcludeList ("b"))
3179 emitcode ("pop", "b");
3180 if (!inExcludeList ("acc"))
3181 emitcode ("pop", "acc");
3183 if (IFFUNC_ISCRITICAL (sym->type))
3184 emitcode ("setb", "ea");
3186 /* if debug then send end of function */
3187 if (options.debug && currFunc) {
3189 emitcode ("", "C$%s$%d$%d$%d ==.",
3190 FileBaseName (ic->filename), currFunc->lastLine,
3191 ic->level, ic->block);
3192 if (IS_STATIC (currFunc->etype))
3193 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3195 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3199 emitcode ("reti", "");
3203 if (IFFUNC_ISCRITICAL (sym->type))
3204 emitcode ("setb", "ea");
3206 if (IFFUNC_CALLEESAVES(sym->type))
3210 /* if any registers used */
3213 /* save the registers used */
3214 for (i = sym->regsUsed->size; i >= 0; i--)
3216 if (bitVectBitValue (sym->regsUsed, i) ||
3217 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3218 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3224 /* if debug then send end of function */
3225 if (options.debug && currFunc)
3228 emitcode ("", "C$%s$%d$%d$%d ==.",
3229 FileBaseName (ic->filename), currFunc->lastLine,
3230 ic->level, ic->block);
3231 if (IS_STATIC (currFunc->etype))
3232 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3234 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3238 emitcode ("ret", "");
3243 /*-----------------------------------------------------------------*/
3244 /* genJavaNativeRet - generate code for return JavaNative */
3245 /*-----------------------------------------------------------------*/
3246 static void genJavaNativeRet(iCode *ic)
3250 aopOp (IC_LEFT (ic), ic, FALSE,
3251 (IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly ? FALSE :TRUE));
3252 size = AOP_SIZE (IC_LEFT (ic));
3256 /* it is assigned to GPR0-R3 then push them */
3257 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3258 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3259 for (i = 0 ; i < size ; i++ ) {
3260 emitcode ("push","%s",aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,FALSE));
3262 for (i = (size-1) ; i >= 0 ; i--) {
3263 emitcode ("pop","a%s",javaRet[i]);
3266 for (i = 0 ; i < size ; i++)
3267 emitcode ("mov","%s,%s",javaRet[i],aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,FALSE));
3269 for (i = size ; i < 4 ; i++ )
3270 emitcode ("mov","%s,#0",javaRet[i]);
3274 /*-----------------------------------------------------------------*/
3275 /* genRet - generate code for return statement */
3276 /*-----------------------------------------------------------------*/
3280 int size, offset = 0, pushed = 0;
3282 D (emitcode (";", "genRet ");
3285 /* if we have no return value then
3286 just generate the "ret" */
3290 /* if this is a JavaNative function then return
3291 value in different register */
3292 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3293 genJavaNativeRet(ic);
3296 /* we have something to return then
3297 move the return value into place */
3298 aopOp (IC_LEFT (ic), ic, FALSE,
3299 (IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly ? FALSE :TRUE));
3300 size = AOP_SIZE (IC_LEFT (ic));
3302 _startLazyDPSEvaluation ();
3306 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3308 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3309 FALSE, TRUE, FALSE);
3310 emitcode ("push", "%s", l);
3315 /* Since A is the last element of fReturn,
3316 * is is OK to clobber it in the aopGet.
3318 l = aopGet (AOP (IC_LEFT (ic)), offset,
3319 FALSE, FALSE, TRUE);
3320 if (strcmp (fReturn[offset], l))
3321 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3324 _endLazyDPSEvaluation ();
3331 if (strcmp (fReturn[pushed], "a"))
3332 emitcode ("pop", fReturn[pushed]);
3334 emitcode ("pop", "acc");
3337 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3340 /* generate a jump to the return label
3341 if the next is not the return statement */
3342 if (!(ic->next && ic->next->op == LABEL &&
3343 IC_LABEL (ic->next) == returnLabel))
3345 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3349 /*-----------------------------------------------------------------*/
3350 /* genLabel - generates a label */
3351 /*-----------------------------------------------------------------*/
3353 genLabel (iCode * ic)
3355 /* special case never generate */
3356 if (IC_LABEL (ic) == entryLabel)
3359 D (emitcode (";", "genLabel ");
3362 emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3365 /*-----------------------------------------------------------------*/
3366 /* genGoto - generates a ljmp */
3367 /*-----------------------------------------------------------------*/
3369 genGoto (iCode * ic)
3371 D (emitcode (";", "genGoto ");
3373 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3376 /*-----------------------------------------------------------------*/
3377 /* findLabelBackwards: walks back through the iCode chain looking */
3378 /* for the given label. Returns number of iCode instructions */
3379 /* between that label and given ic. */
3380 /* Returns zero if label not found. */
3381 /*-----------------------------------------------------------------*/
3383 findLabelBackwards (iCode * ic, int key)
3392 /* If we have any pushes or pops, we cannot predict the distance.
3393 I don't like this at all, this should be dealt with in the
3395 if (ic->op == IPUSH || ic->op == IPOP) {
3399 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3401 /* printf("findLabelBackwards = %d\n", count); */
3409 /*-----------------------------------------------------------------*/
3410 /* genPlusIncr :- does addition with increment if possible */
3411 /*-----------------------------------------------------------------*/
3413 genPlusIncr (iCode * ic)
3415 unsigned int icount;
3416 unsigned int size = getDataSize (IC_RESULT (ic));
3418 /* will try to generate an increment */
3419 /* if the right side is not a literal
3421 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3424 /* if the literal value of the right hand side
3425 is greater than 4 then it is not worth it */
3426 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3429 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3430 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3432 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3436 /* if increment 16 bits in register */
3438 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3439 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3440 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3448 /* If the next instruction is a goto and the goto target
3449 * is <= 5 instructions previous to this, we can generate
3450 * jumps straight to that target.
3452 if (ic->next && ic->next->op == GOTO
3453 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3456 emitcode (";", "tail increment optimized (range %d)", labelRange);
3457 tlbl = IC_LABEL (ic->next);
3462 tlbl = newiTempLabel (NULL);
3465 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3466 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3467 IS_AOP_PREG (IC_RESULT (ic)))
3468 emitcode ("cjne", "%s,#0,!tlabel"
3469 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3473 emitcode ("clr", "a");
3474 emitcode ("cjne", "a,%s,!tlabel"
3475 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3479 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3482 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3483 IS_AOP_PREG (IC_RESULT (ic)))
3484 emitcode ("cjne", "%s,#0,!tlabel"
3485 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3488 emitcode ("cjne", "a,%s,!tlabel"
3489 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3492 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3496 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3497 IS_AOP_PREG (IC_RESULT (ic)))
3498 emitcode ("cjne", "%s,#0,!tlabel"
3499 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3503 emitcode ("cjne", "a,%s,!tlabel"
3504 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3507 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3512 emitcode ("", "!tlabeldef", tlbl->key + 100);
3517 if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3518 AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3520 emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3521 while (icount--) emitcode ("inc","dptr");
3522 emitcode ("mov","dps,#0");
3526 /* if the sizes are greater than 1 then we cannot */
3527 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3528 AOP_SIZE (IC_LEFT (ic)) > 1)
3531 /* we can if the aops of the left & result match or
3532 if they are in registers and the registers are the
3535 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3536 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3537 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3542 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3543 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3544 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3549 _startLazyDPSEvaluation ();
3552 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3554 _endLazyDPSEvaluation ();
3563 /*-----------------------------------------------------------------*/
3564 /* outBitAcc - output a bit in acc */
3565 /*-----------------------------------------------------------------*/
3567 outBitAcc (operand * result)
3569 symbol *tlbl = newiTempLabel (NULL);
3570 /* if the result is a bit */
3571 if (AOP_TYPE (result) == AOP_CRY)
3573 aopPut (AOP (result), "a", 0);
3577 emitcode ("jz", "!tlabel", tlbl->key + 100);
3578 emitcode ("mov", "a,%s", one);
3579 emitcode ("", "!tlabeldef", tlbl->key + 100);
3584 /*-----------------------------------------------------------------*/
3585 /* genPlusBits - generates code for addition of two bits */
3586 /*-----------------------------------------------------------------*/
3588 genPlusBits (iCode * ic)
3590 D (emitcode (";", "genPlusBits ");
3592 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3594 symbol *lbl = newiTempLabel (NULL);
3595 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3596 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3597 emitcode ("cpl", "c");
3598 emitcode ("", "!tlabeldef", (lbl->key + 100));
3599 outBitC (IC_RESULT (ic));
3603 emitcode ("clr", "a");
3604 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3605 emitcode ("rlc", "a");
3606 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3607 emitcode ("addc", "a,#0");
3608 outAcc (IC_RESULT (ic));
3613 adjustArithmeticResult (iCode * ic)
3615 if (opIsGptr (IC_RESULT (ic)) &&
3616 opIsGptr (IC_LEFT (ic)) &&
3617 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3619 aopPut (AOP (IC_RESULT (ic)),
3620 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3624 if (opIsGptr (IC_RESULT (ic)) &&
3625 opIsGptr (IC_RIGHT (ic)) &&
3626 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3628 aopPut (AOP (IC_RESULT (ic)),
3629 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3633 if (opIsGptr (IC_RESULT (ic)) &&
3634 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3635 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3636 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3637 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3640 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3641 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3645 // Macro to aopOp all three operands of an ic. If this cannot be done,
3646 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3647 // will be set TRUE. The caller must then handle the case specially, noting
3648 // that the IC_RESULT operand is not aopOp'd.
3649 #define AOP_OP_3_NOFATAL(ic, rc) \
3650 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3651 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR) || \
3652 ((OP_SYMBOL(IC_RESULT(ic))->ruonly) && !isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)))); \
3653 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3654 (isOperandInFarSpace(IC_RESULT(ic)) || (OP_SYMBOL(IC_RESULT(ic))->ruonly && !isOperandEqual(IC_LEFT(ic),IC_RESULT(ic))))) \
3656 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3661 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3662 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3664 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3665 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3667 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3669 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3673 // aopOp the left & right operands of an ic.
3674 #define AOP_OP_2(ic) \
3675 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3676 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3678 // convienience macro.
3679 #define AOP_SET_LOCALS(ic) \
3680 left = IC_LEFT(ic); \
3681 right = IC_RIGHT(ic); \
3682 result = IC_RESULT(ic);
3685 // Given an integer value of pushedSize bytes on the stack,
3686 // adjust it to be resultSize bytes, either by discarding
3687 // the most significant bytes or by zero-padding.
3689 // On exit from this macro, pushedSize will have been adjusted to
3690 // equal resultSize, and ACC may be trashed.
3691 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3692 /* If the pushed data is bigger than the result, \
3693 * simply discard unused bytes. Icky, but works. \
3695 while (pushedSize > resultSize) \
3697 D (emitcode (";", "discarding unused result byte."););\
3698 emitcode ("pop", "acc"); \
3701 if (pushedSize < resultSize) \
3703 emitcode ("clr", "a"); \
3704 /* Conversly, we haven't pushed enough here. \
3705 * just zero-pad, and all is well. \
3707 while (pushedSize < resultSize) \
3709 emitcode("push", "acc"); \
3713 assert(pushedSize == resultSize);
3715 /*-----------------------------------------------------------------*/
3716 /* genPlus - generates code for addition */
3717 /*-----------------------------------------------------------------*/
3719 genPlus (iCode * ic)
3721 int size, offset = 0;
3722 bool pushResult = FALSE;
3725 D (emitcode (";", "genPlus "););
3727 /* special cases :- */
3728 if ( IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly &&
3729 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3730 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3731 size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3733 while (size--) emitcode ("inc","dptr");
3735 emitcode ("mov","a,dpl");
3736 emitcode ("add","a,#!constbyte",size & 0xff);
3737 emitcode ("mov","dpl,a");
3738 emitcode ("mov","a,dph");
3739 emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
3740 emitcode ("mov","dph,a");
3741 emitcode ("mov","a,dpx");
3742 emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
3743 emitcode ("mov","dpx,a");
3745 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3748 if ( IS_SYMOP(IC_LEFT(ic)) &&
3749 OP_SYMBOL(IC_LEFT(ic))->remat &&
3750 isOperandInFarSpace(IC_RIGHT(ic))) {
3751 operand *op = IC_RIGHT(ic);
3752 IC_RIGHT(ic) = IC_LEFT(ic);
3756 AOP_OP_3_NOFATAL (ic, pushResult);
3759 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3764 /* if literal, literal on the right or
3765 if left requires ACC or right is already
3767 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3768 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3769 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3771 operand *t = IC_RIGHT (ic);
3772 IC_RIGHT (ic) = IC_LEFT (ic);
3774 emitcode (";", "Swapped plus args.");
3777 /* if both left & right are in bit
3779 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3780 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3786 /* if left in bit space & right literal */
3787 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3788 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3790 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3791 /* if result in bit space */
3792 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3794 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3795 emitcode ("cpl", "c");
3796 outBitC (IC_RESULT (ic));
3800 size = getDataSize (IC_RESULT (ic));
3801 _startLazyDPSEvaluation ();
3804 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3805 emitcode ("addc", "a,#0");
3806 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3808 _endLazyDPSEvaluation ();
3813 /* if I can do an increment instead
3814 of add then GOOD for ME */
3815 if (genPlusIncr (ic) == TRUE)
3817 emitcode (";", "did genPlusIncr");
3822 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3824 _startLazyDPSEvaluation ();
3827 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3829 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3831 emitcode ("add", "a,%s",
3832 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3834 emitcode ("addc", "a,%s",
3835 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3839 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3841 /* right is going to use ACC or we would have taken the
3844 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3846 D(emitcode(";", "+ AOP_ACC special case."););
3847 emitcode("xch", "a, %s", DP2_RESULT_REG);
3849 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3852 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3855 emitcode("add", "a, %s", DP2_RESULT_REG);
3859 emitcode ("add", "a,%s",
3860 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3865 emitcode ("addc", "a,%s",
3866 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3871 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3875 emitcode ("push", "acc");
3879 _endLazyDPSEvaluation ();
3883 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3885 size = getDataSize (IC_LEFT (ic));
3886 rSize = getDataSize (IC_RESULT (ic));
3888 ADJUST_PUSHED_RESULT(size, rSize);
3890 _startLazyDPSEvaluation ();
3893 emitcode ("pop", "acc");
3894 aopPut (AOP (IC_RESULT (ic)), "a", size);
3896 _endLazyDPSEvaluation ();
3899 adjustArithmeticResult (ic);
3902 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3903 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3904 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3907 /*-----------------------------------------------------------------*/
3908 /* genMinusDec :- does subtraction with deccrement if possible */
3909 /*-----------------------------------------------------------------*/
3911 genMinusDec (iCode * ic)
3913 unsigned int icount;
3914 unsigned int size = getDataSize (IC_RESULT (ic));
3916 /* will try to generate an increment */
3917 /* if the right side is not a literal
3919 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3922 /* if the literal value of the right hand side
3923 is greater than 4 then it is not worth it */
3924 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3927 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3928 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3930 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3934 /* if decrement 16 bits in register */
3935 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3936 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3937 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3945 /* If the next instruction is a goto and the goto target
3946 * is <= 5 instructions previous to this, we can generate
3947 * jumps straight to that target.
3949 if (ic->next && ic->next->op == GOTO
3950 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3953 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3954 tlbl = IC_LABEL (ic->next);
3959 tlbl = newiTempLabel (NULL);
3963 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3964 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3965 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3966 IS_AOP_PREG (IC_RESULT (ic)))
3967 emitcode ("cjne", "%s,#!constbyte,!tlabel"
3968 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE), 0xff
3972 emitcode ("mov", "a,#!constbyte",0xff);
3973 emitcode ("cjne", "a,%s,!tlabel"
3974 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3977 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3980 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3981 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3982 IS_AOP_PREG (IC_RESULT (ic)))
3983 emitcode ("cjne", "%s,#!constbyte,!tlabel"
3984 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE),0xff
3988 emitcode ("cjne", "a,%s,!tlabel"
3989 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3992 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3996 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3997 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3998 IS_AOP_PREG (IC_RESULT (ic)))
3999 emitcode ("cjne", "%s,#!constbyte,!tlabel"
4000 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE),0xff
4004 emitcode ("cjne", "a,%s,!tlabel"
4005 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
4008 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
4012 emitcode ("", "!tlabeldef", tlbl->key + 100);
4017 /* if the sizes are greater than 1 then we cannot */
4018 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4019 AOP_SIZE (IC_LEFT (ic)) > 1)
4022 /* we can if the aops of the left & result match or
4023 if they are in registers and the registers are the
4026 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4027 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4028 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4031 _startLazyDPSEvaluation ();
4034 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
4036 _endLazyDPSEvaluation ();
4044 /*-----------------------------------------------------------------*/
4045 /* addSign - complete with sign */
4046 /*-----------------------------------------------------------------*/
4048 addSign (operand * result, int offset, int sign)
4050 int size = (getDataSize (result) - offset);
4053 _startLazyDPSEvaluation();
4056 emitcode ("rlc", "a");
4057 emitcode ("subb", "a,acc");
4060 aopPut (AOP (result), "a", offset++);
4067 aopPut (AOP (result), zero, offset++);
4070 _endLazyDPSEvaluation();
4074 /*-----------------------------------------------------------------*/
4075 /* genMinusBits - generates code for subtraction of two bits */
4076 /*-----------------------------------------------------------------*/
4078 genMinusBits (iCode * ic)
4080 symbol *lbl = newiTempLabel (NULL);
4082 D (emitcode (";", "genMinusBits "););
4084 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4086 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4087 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4088 emitcode ("cpl", "c");
4089 emitcode ("", "!tlabeldef", (lbl->key + 100));
4090 outBitC (IC_RESULT (ic));
4094 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4095 emitcode ("subb", "a,acc");
4096 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4097 emitcode ("inc", "a");
4098 emitcode ("", "!tlabeldef", (lbl->key + 100));
4099 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4100 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4104 /*-----------------------------------------------------------------*/
4105 /* genMinus - generates code for subtraction */
4106 /*-----------------------------------------------------------------*/
4108 genMinus (iCode * ic)
4110 int size, offset = 0;
4112 unsigned long lit = 0L;
4113 bool pushResult = FALSE;
4115 D (emitcode (";", "genMinus "););
4117 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
4118 aopOp (IC_RIGHT (ic), ic, FALSE,
4119 (AOP_INDPTRn(IC_LEFT(ic)) ? FALSE : (AOP_USESDPTR(IC_LEFT(ic)) ? TRUE : FALSE)));
4120 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
4121 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
4127 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
4129 /* special cases :- */
4130 /* if both left & right are in bit space */
4131 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4132 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4138 /* if I can do an decrement instead
4139 of subtract then GOOD for ME */
4140 if (genMinusDec (ic) == TRUE)
4145 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4147 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4153 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4158 /* if literal, add a,#-lit, else normal subb */
4159 _startLazyDPSEvaluation ();
4161 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
4162 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4163 if (AOP_USESDPTR(IC_RIGHT(ic))) {
4164 emitcode ("mov","b,a");
4165 MOVA(aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
4166 emitcode ("xch","a,b");
4167 emitcode ("subb","a,b");
4169 emitcode ("subb", "a,%s",
4170 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
4173 /* first add without previous c */
4175 if (!size && lit==-1) {
4176 emitcode ("dec", "a");
4178 emitcode ("add", "a,#!constbyte",
4179 (unsigned int) (lit & 0x0FFL));
4182 emitcode ("addc", "a,#!constbyte",
4183 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4188 emitcode ("push", "acc");
4190 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4194 _endLazyDPSEvaluation ();
4198 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4200 size = getDataSize (IC_LEFT (ic));
4201 rSize = getDataSize (IC_RESULT (ic));
4203 ADJUST_PUSHED_RESULT(size, rSize);
4205 _startLazyDPSEvaluation ();
4208 emitcode ("pop", "acc");
4209 aopPut (AOP (IC_RESULT (ic)), "a", size);
4211 _endLazyDPSEvaluation ();
4214 adjustArithmeticResult (ic);
4217 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4218 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4219 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4223 /*-----------------------------------------------------------------*/
4224 /* genMultbits :- multiplication of bits */
4225 /*-----------------------------------------------------------------*/
4227 genMultbits (operand * left,
4232 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4233 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4234 aopOp(result, ic, TRUE, FALSE);
4239 /*-----------------------------------------------------------------*/
4240 /* genMultOneByte : 8*8=8/16 bit multiplication */
4241 /*-----------------------------------------------------------------*/
4243 genMultOneByte (operand * left,
4248 sym_link *opetype = operandType (result);
4252 /* (if two literals: the value is computed before) */
4253 /* if one literal, literal on the right */
4254 if (AOP_TYPE (left) == AOP_LIT)
4259 emitcode (";", "swapped left and right");
4262 if (SPEC_USIGN(opetype)
4263 // ignore the sign of left and right, what else can we do?
4264 || (SPEC_USIGN(operandType(left)) &&
4265 SPEC_USIGN(operandType(right)))) {
4266 // just an unsigned 8*8=8/16 multiply
4267 //emitcode (";","unsigned");
4268 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4269 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4270 emitcode ("mul", "ab");
4272 _G.accInUse++; _G.bInUse++;
4273 aopOp(result, ic, TRUE, FALSE);
4275 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4277 // this should never happen
4278 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4279 AOP_SIZE(result), __FILE__, lineno);
4283 aopPut (AOP (result), "a", 0);
4284 _G.accInUse--; _G.bInUse--;
4285 if (AOP_SIZE(result)==2)
4287 aopPut (AOP (result), "b", 1);
4292 // we have to do a signed multiply
4294 emitcode (";", "signed");
4295 emitcode ("clr", "F0"); // reset sign flag
4296 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4298 lbl=newiTempLabel(NULL);
4299 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4300 // left side is negative, 8-bit two's complement, this fails for -128
4301 emitcode ("setb", "F0"); // set sign flag
4302 emitcode ("cpl", "a");
4303 emitcode ("inc", "a");
4305 emitcode ("", "!tlabeldef", lbl->key+100);
4308 if (AOP_TYPE(right)==AOP_LIT) {
4309 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4310 /* AND literal negative */
4311 if ((int) val < 0) {
4312 emitcode ("cpl", "F0"); // complement sign flag
4313 emitcode ("mov", "b,#!constbyte", -val);
4315 emitcode ("mov", "b,#!constbyte", val);
4318 lbl=newiTempLabel(NULL);
4319 emitcode ("mov", "b,a");
4320 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4321 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4322 // right side is negative, 8-bit two's complement
4323 emitcode ("cpl", "F0"); // complement sign flag
4324 emitcode ("cpl", "a");
4325 emitcode ("inc", "a");
4326 emitcode ("", "!tlabeldef", lbl->key+100);
4328 emitcode ("mul", "ab");
4330 _G.accInUse++;_G.bInUse++;
4331 aopOp(result, ic, TRUE, FALSE);
4333 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4335 // this should never happen
4336 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4337 AOP_SIZE(result), __FILE__, lineno);
4341 lbl=newiTempLabel(NULL);
4342 emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4343 // only ONE op was negative, we have to do a 8/16-bit two's complement
4344 emitcode ("cpl", "a"); // lsb
4345 if (AOP_SIZE(result)==1) {
4346 emitcode ("inc", "a");
4348 emitcode ("add", "a,#1");
4349 emitcode ("xch", "a,b");
4350 emitcode ("cpl", "a"); // msb
4351 emitcode ("addc", "a,#0");
4352 emitcode ("xch", "a,b");
4355 emitcode ("", "!tlabeldef", lbl->key+100);
4356 aopPut (AOP (result), "a", 0);
4357 _G.accInUse--;_G.bInUse--;
4358 if (AOP_SIZE(result)==2) {
4359 aopPut (AOP (result), "b", 1);
4363 /*-----------------------------------------------------------------*/
4364 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4365 /*-----------------------------------------------------------------*/
4366 static void genMultTwoByte (operand *left, operand *right,
4367 operand *result, iCode *ic)
4369 sym_link *retype = getSpec(operandType(right));
4370 sym_link *letype = getSpec(operandType(left));
4371 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4374 if (AOP_TYPE (left) == AOP_LIT) {
4379 /* save EA bit in F1 */
4380 lbl = newiTempLabel(NULL);
4381 emitcode ("setb","F1");
4382 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4383 emitcode ("clr","F1");
4384 emitcode("","!tlabeldef",lbl->key+100);
4386 /* load up MB with right */
4388 emitcode("clr","F0");
4389 if (AOP_TYPE(right) == AOP_LIT) {
4390 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4392 emitcode("setb","F0");
4395 emitcode ("mov","mb,#!constbyte",val & 0xff);
4396 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4398 lbl = newiTempLabel(NULL);
4399 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4400 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4401 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4402 emitcode ("xch", "a,b");
4403 emitcode ("cpl","a");
4404 emitcode ("add", "a,#1");
4405 emitcode ("xch", "a,b");
4406 emitcode ("cpl", "a"); // msb
4407 emitcode ("addc", "a,#0");
4408 emitcode ("setb","F0");
4409 emitcode ("","!tlabeldef",lbl->key+100);
4410 emitcode ("mov","mb,b");
4411 emitcode ("mov","mb,a");
4414 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4415 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4417 /* load up MA with left */
4419 lbl = newiTempLabel(NULL);
4420 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4421 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4422 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4423 emitcode ("xch", "a,b");
4424 emitcode ("cpl","a");
4425 emitcode ("add", "a,#1");
4426 emitcode ("xch", "a,b");
4427 emitcode ("cpl", "a"); // msb
4428 emitcode ("addc","a,#0");
4429 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4430 emitcode ("setb","F0");
4431 emitcode ("","!tlabeldef",lbl->key+100);
4432 emitcode ("mov","ma,b");
4433 emitcode ("mov","ma,a");
4435 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4436 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4438 /* wait for multiplication to finish */
4439 lbl = newiTempLabel(NULL);
4440 emitcode("","!tlabeldef", lbl->key+100);
4441 emitcode("mov","a,mcnt1");
4442 emitcode("anl","a,#!constbyte",0x80);
4443 emitcode("jnz","!tlabel",lbl->key+100);
4445 freeAsmop (left, NULL, ic, TRUE);
4446 freeAsmop (right, NULL, ic,TRUE);
4447 aopOp(result, ic, TRUE, FALSE);
4449 /* if unsigned then simple */
4451 emitcode ("mov","a,ma");
4452 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4453 emitcode ("mov","a,ma");
4454 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4455 aopPut(AOP(result),"ma",1);
4456 aopPut(AOP(result),"ma",0);
4458 emitcode("push","ma");
4459 emitcode("push","ma");
4460 emitcode("push","ma");
4462 /* negate result if needed */
4463 lbl = newiTempLabel(NULL);
4464 emitcode("jnb","F0,!tlabel",lbl->key+100);
4465 emitcode("cpl","a");
4466 emitcode("add","a,#1");
4467 emitcode("","!tlabeldef", lbl->key+100);
4468 if (AOP_TYPE(result) == AOP_ACC)
4470 D(emitcode(";", "ACC special case."););
4471 /* We know result is the only live aop, and
4472 * it's obviously not a DPTR2, so AP is available.
4474 emitcode("mov", "%s,acc", DP2_RESULT_REG);
4478 aopPut(AOP(result),"a",0);
4481 emitcode("pop","acc");
4482 lbl = newiTempLabel(NULL);
4483 emitcode("jnb","F0,!tlabel",lbl->key+100);
4484 emitcode("cpl","a");
4485 emitcode("addc","a,#0");
4486 emitcode("","!tlabeldef", lbl->key+100);
4487 aopPut(AOP(result),"a",1);
4488 emitcode("pop","acc");
4489 if (AOP_SIZE(result) >= 3) {
4490 lbl = newiTempLabel(NULL);
4491 emitcode("jnb","F0,!tlabel",lbl->key+100);
4492 emitcode("cpl","a");
4493 emitcode("addc","a,#0");
4494 emitcode("","!tlabeldef", lbl->key+100);
4495 aopPut(AOP(result),"a",2);
4497 emitcode("pop","acc");
4498 if (AOP_SIZE(result) >= 4) {
4499 lbl = newiTempLabel(NULL);
4500 emitcode("jnb","F0,!tlabel",lbl->key+100);
4501 emitcode("cpl","a");
4502 emitcode("addc","a,#0");
4503 emitcode("","!tlabeldef", lbl->key+100);
4504 aopPut(AOP(result),"a",3);
4506 if (AOP_TYPE(result) == AOP_ACC)
4508 /* We stashed the result away above. */
4509 emitcode("mov", "acc,%s", DP2_RESULT_REG);
4513 freeAsmop (result, NULL, ic, TRUE);
4515 /* restore EA bit in F1 */
4516 lbl = newiTempLabel(NULL);
4517 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4518 emitcode ("setb","EA");
4519 emitcode("","!tlabeldef",lbl->key+100);
4523 /*-----------------------------------------------------------------*/
4524 /* genMult - generates code for multiplication */
4525 /*-----------------------------------------------------------------*/
4527 genMult (iCode * ic)
4529 operand *left = IC_LEFT (ic);
4530 operand *right = IC_RIGHT (ic);
4531 operand *result = IC_RESULT (ic);
4533 D (emitcode (";", "genMult "););
4535 /* assign the amsops */
4538 /* special cases first */
4540 if (AOP_TYPE (left) == AOP_CRY &&
4541 AOP_TYPE (right) == AOP_CRY)
4543 genMultbits (left, right, result, ic);
4547 /* if both are of size == 1 */
4548 if (AOP_SIZE (left) == 1 &&
4549 AOP_SIZE (right) == 1)
4551 genMultOneByte (left, right, result, ic);
4555 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4556 /* use the ds390 ARITHMETIC accel UNIT */
4557 genMultTwoByte (left, right, result, ic);
4560 /* should have been converted to function call */
4564 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4565 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4566 freeAsmop (result, NULL, ic, TRUE);
4569 /*-----------------------------------------------------------------*/
4570 /* genDivbits :- division of bits */
4571 /*-----------------------------------------------------------------*/
4573 genDivbits (operand * left,
4581 /* the result must be bit */
4582 LOAD_AB_FOR_DIV (left, right, l);
4583 emitcode ("div", "ab");
4584 emitcode ("rrc", "a");
4585 aopOp(result, ic, TRUE, FALSE);
4587 aopPut (AOP (result), "c", 0);
4590 /*-----------------------------------------------------------------*/
4591 /* genDivOneByte : 8 bit division */
4592 /*-----------------------------------------------------------------*/
4594 genDivOneByte (operand * left,
4599 sym_link *opetype = operandType (result);
4605 /* signed or unsigned */
4606 if (SPEC_USIGN (opetype))
4608 /* unsigned is easy */
4609 LOAD_AB_FOR_DIV (left, right, l);
4610 emitcode ("div", "ab");
4613 aopOp(result, ic, TRUE, FALSE);
4614 aopPut (AOP (result), "a", 0);
4617 size = AOP_SIZE (result) - 1;
4621 aopPut (AOP (result), zero, offset++);
4626 /* signed is a little bit more difficult */
4628 /* save the signs of the operands */
4629 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4631 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4632 emitcode ("push", "acc"); /* save it on the stack */
4634 /* now sign adjust for both left & right */
4635 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4637 lbl = newiTempLabel (NULL);
4638 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4639 emitcode ("cpl", "a");
4640 emitcode ("inc", "a");
4641 emitcode ("", "!tlabeldef", (lbl->key + 100));
4642 emitcode ("mov", "b,a");
4644 /* sign adjust left side */
4645 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4648 lbl = newiTempLabel (NULL);
4649 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4650 emitcode ("cpl", "a");
4651 emitcode ("inc", "a");
4652 emitcode ("", "!tlabeldef", (lbl->key + 100));
4654 /* now the division */
4655 emitcode ("nop", "; workaround for DS80C390 div bug.");
4656 emitcode ("div", "ab");
4657 /* we are interested in the lower order
4659 emitcode ("mov", "b,a");
4660 lbl = newiTempLabel (NULL);
4661 emitcode ("pop", "acc");
4662 /* if there was an over flow we don't
4663 adjust the sign of the result */
4664 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4665 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4667 emitcode ("clr", "a");
4668 emitcode ("subb", "a,b");
4669 emitcode ("mov", "b,a");
4670 emitcode ("", "!tlabeldef", (lbl->key + 100));
4672 /* now we are done */
4673 _G.accInUse++; _G.bInUse++;
4674 aopOp(result, ic, TRUE, FALSE);
4676 aopPut (AOP (result), "b", 0);
4678 size = AOP_SIZE (result) - 1;
4682 emitcode ("mov", "c,b.7");
4683 emitcode ("subb", "a,acc");
4687 aopPut (AOP (result), "a", offset++);
4689 _G.accInUse--; _G.bInUse--;
4693 /*-----------------------------------------------------------------*/
4694 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
4695 /*-----------------------------------------------------------------*/
4696 static void genDivTwoByte (operand *left, operand *right,
4697 operand *result, iCode *ic)
4699 sym_link *retype = getSpec(operandType(right));
4700 sym_link *letype = getSpec(operandType(left));
4701 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4704 /* save EA bit in F1 */
4705 lbl = newiTempLabel(NULL);
4706 emitcode ("setb","F1");
4707 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4708 emitcode ("clr","F1");
4709 emitcode("","!tlabeldef",lbl->key+100);
4711 /* load up MA with left */
4713 emitcode("clr","F0");
4714 lbl = newiTempLabel(NULL);
4715 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4716 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4717 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4718 emitcode ("xch", "a,b");
4719 emitcode ("cpl","a");
4720 emitcode ("add", "a,#1");
4721 emitcode ("xch", "a,b");
4722 emitcode ("cpl", "a"); // msb
4723 emitcode ("addc","a,#0");
4724 emitcode ("setb","F0");
4725 emitcode ("","!tlabeldef",lbl->key+100);
4726 emitcode ("mov","ma,b");
4727 emitcode ("mov","ma,a");
4729 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4730 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4733 /* load up MB with right */
4735 if (AOP_TYPE(right) == AOP_LIT) {
4736 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4738 lbl = newiTempLabel(NULL);
4739 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4740 emitcode("setb","F0");
4741 emitcode ("","!tlabeldef",lbl->key+100);
4744 emitcode ("mov","mb,#!constbyte",val & 0xff);
4745 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4747 lbl = newiTempLabel(NULL);
4748 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4749 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4750 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4751 emitcode ("xch", "a,b");
4752 emitcode ("cpl","a");
4753 emitcode ("add", "a,#1");
4754 emitcode ("xch", "a,b");
4755 emitcode ("cpl", "a"); // msb
4756 emitcode ("addc", "a,#0");
4757 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4758 emitcode ("setb","F0");
4759 emitcode ("","!tlabeldef",lbl->key+100);
4760 emitcode ("mov","mb,b");
4761 emitcode ("mov","mb,a");
4764 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4765 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4768 /* wait for multiplication to finish */
4769 lbl = newiTempLabel(NULL);
4770 emitcode("","!tlabeldef", lbl->key+100);
4771 emitcode("mov","a,mcnt1");
4772 emitcode("anl","a,#!constbyte",0x80);
4773 emitcode("jnz","!tlabel",lbl->key+100);
4775 freeAsmop (left, NULL, ic, TRUE);
4776 freeAsmop (right, NULL, ic,TRUE);
4777 aopOp(result, ic, TRUE, FALSE);
4779 /* if unsigned then simple */
4781 aopPut(AOP(result),"ma",1);
4782 aopPut(AOP(result),"ma",0);
4784 emitcode("push","ma");
4786 /* negate result if needed */
4787 lbl = newiTempLabel(NULL);
4788 emitcode("jnb","F0,!tlabel",lbl->key+100);
4789 emitcode("cpl","a");
4790 emitcode("add","a,#1");
4791 emitcode("","!tlabeldef", lbl->key+100);
4792 aopPut(AOP(result),"a",0);
4793 emitcode("pop","acc");
4794 lbl = newiTempLabel(NULL);
4795 emitcode("jnb","F0,!tlabel",lbl->key+100);
4796 emitcode("cpl","a");
4797 emitcode("addc","a,#0");
4798 emitcode("","!tlabeldef", lbl->key+100);
4799 aopPut(AOP(result),"a",1);
4801 freeAsmop (result, NULL, ic, TRUE);
4802 /* restore EA bit in F1 */
4803 lbl = newiTempLabel(NULL);
4804 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4805 emitcode ("setb","EA");
4806 emitcode("","!tlabeldef",lbl->key+100);
4810 /*-----------------------------------------------------------------*/
4811 /* genDiv - generates code for division */
4812 /*-----------------------------------------------------------------*/
4816 operand *left = IC_LEFT (ic);
4817 operand *right = IC_RIGHT (ic);
4818 operand *result = IC_RESULT (ic);
4820 D (emitcode (";", "genDiv "););
4822 /* assign the amsops */
4825 /* special cases first */
4827 if (AOP_TYPE (left) == AOP_CRY &&
4828 AOP_TYPE (right) == AOP_CRY)
4830 genDivbits (left, right, result, ic);
4834 /* if both are of size == 1 */
4835 if (AOP_SIZE (left) == 1 &&
4836 AOP_SIZE (right) == 1)
4838 genDivOneByte (left, right, result, ic);
4842 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4843 /* use the ds390 ARITHMETIC accel UNIT */
4844 genDivTwoByte (left, right, result, ic);
4847 /* should have been converted to function call */
4850 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4851 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4852 freeAsmop (result, NULL, ic, TRUE);
4855 /*-----------------------------------------------------------------*/
4856 /* genModbits :- modulus of bits */
4857 /*-----------------------------------------------------------------*/
4859 genModbits (operand * left,
4867 /* the result must be bit */
4868 LOAD_AB_FOR_DIV (left, right, l);
4869 emitcode ("div", "ab");
4870 emitcode ("mov", "a,b");
4871 emitcode ("rrc", "a");
4872 aopOp(result, ic, TRUE, FALSE);
4873 aopPut (AOP (result), "c", 0);
4876 /*-----------------------------------------------------------------*/
4877 /* genModOneByte : 8 bit modulus */
4878 /*-----------------------------------------------------------------*/
4880 genModOneByte (operand * left,
4885 sym_link *opetype = operandType (result);
4889 /* signed or unsigned */
4890 if (SPEC_USIGN (opetype))
4892 /* unsigned is easy */
4893 LOAD_AB_FOR_DIV (left, right, l);
4894 emitcode ("div", "ab");
4895 aopOp(result, ic, TRUE, FALSE);
4896 aopPut (AOP (result), "b", 0);
4900 /* signed is a little bit more difficult */
4902 /* save the signs of the operands */
4903 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4906 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4907 emitcode ("push", "acc"); /* save it on the stack */
4909 /* now sign adjust for both left & right */
4910 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4913 lbl = newiTempLabel (NULL);
4914 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4915 emitcode ("cpl", "a");
4916 emitcode ("inc", "a");
4917 emitcode ("", "!tlabeldef", (lbl->key + 100));
4918 emitcode ("mov", "b,a");
4920 /* sign adjust left side */
4921 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4924 lbl = newiTempLabel (NULL);
4925 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4926 emitcode ("cpl", "a");
4927 emitcode ("inc", "a");
4928 emitcode ("", "!tlabeldef", (lbl->key + 100));
4930 /* now the multiplication */
4931 emitcode ("nop", "; workaround for DS80C390 div bug.");
4932 emitcode ("div", "ab");
4933 /* we are interested in the lower order
4935 lbl = newiTempLabel (NULL);
4936 emitcode ("pop", "acc");
4937 /* if there was an over flow we don't
4938 adjust the sign of the result */
4939 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4940 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4942 emitcode ("clr", "a");
4943 emitcode ("subb", "a,b");
4944 emitcode ("mov", "b,a");
4945 emitcode ("", "!tlabeldef", (lbl->key + 100));
4948 /* now we are done */
4949 aopOp(result, ic, TRUE, FALSE);
4950 aopPut (AOP (result), "b", 0);
4955 /*-----------------------------------------------------------------*/
4956 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
4957 /*-----------------------------------------------------------------*/
4958 static void genModTwoByte (operand *left, operand *right,
4959 operand *result, iCode *ic)
4961 sym_link *retype = getSpec(operandType(right));
4962 sym_link *letype = getSpec(operandType(left));
4963 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4966 /* load up MA with left */
4967 /* save EA bit in F1 */
4968 lbl = newiTempLabel(NULL);
4969 emitcode ("setb","F1");
4970 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4971 emitcode ("clr","F1");
4972 emitcode("","!tlabeldef",lbl->key+100);
4975 lbl = newiTempLabel(NULL);
4976 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4977 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4978 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4979 emitcode ("xch", "a,b");
4980 emitcode ("cpl","a");
4981 emitcode ("add", "a,#1");
4982 emitcode ("xch", "a,b");
4983 emitcode ("cpl", "a"); // msb
4984 emitcode ("addc","a,#0");
4985 emitcode ("","!tlabeldef",lbl->key+100);
4986 emitcode ("mov","ma,b");
4987 emitcode ("mov","ma,a");
4989 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4990 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4993 /* load up MB with right */
4995 if (AOP_TYPE(right) == AOP_LIT) {
4996 int val=floatFromVal (AOP (right)->aopu.aop_lit);
5000 emitcode ("mov","mb,#!constbyte",val & 0xff);
5001 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5003 lbl = newiTempLabel(NULL);
5004 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
5005 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
5006 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5007 emitcode ("xch", "a,b");
5008 emitcode ("cpl","a");
5009 emitcode ("add", "a,#1");
5010 emitcode ("xch", "a,b");
5011 emitcode ("cpl", "a"); // msb
5012 emitcode ("addc", "a,#0");
5013 emitcode ("","!tlabeldef",lbl->key+100);
5014 emitcode ("mov","mb,b");
5015 emitcode ("mov","mb,a");
5018 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
5019 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
5022 /* wait for multiplication to finish */
5023 lbl = newiTempLabel(NULL);
5024 emitcode("","!tlabeldef", lbl->key+100);
5025 emitcode("mov","a,mcnt1");
5026 emitcode("anl","a,#!constbyte",0x80);
5027 emitcode("jnz","!tlabel",lbl->key+100);
5029 freeAsmop (left, NULL, ic, TRUE);
5030 freeAsmop (right, NULL, ic,TRUE);
5031 aopOp(result, ic, TRUE, FALSE);
5033 aopPut(AOP(result),"mb",1);
5034 aopPut(AOP(result),"mb",0);
5035 freeAsmop (result, NULL, ic, TRUE);
5037 /* restore EA bit in F1 */
5038 lbl = newiTempLabel(NULL);
5039 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5040 emitcode ("setb","EA");
5041 emitcode("","!tlabeldef",lbl->key+100);
5045 /*-----------------------------------------------------------------*/
5046 /* genMod - generates code for division */
5047 /*-----------------------------------------------------------------*/
5051 operand *left = IC_LEFT (ic);
5052 operand *right = IC_RIGHT (ic);
5053 operand *result = IC_RESULT (ic);
5055 D (emitcode (";", "genMod "); );
5057 /* assign the amsops */
5060 /* special cases first */
5062 if (AOP_TYPE (left) == AOP_CRY &&
5063 AOP_TYPE (right) == AOP_CRY)
5065 genModbits (left, right, result, ic);
5069 /* if both are of size == 1 */
5070 if (AOP_SIZE (left) == 1 &&
5071 AOP_SIZE (right) == 1)
5073 genModOneByte (left, right, result, ic);
5077 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5078 /* use the ds390 ARITHMETIC accel UNIT */
5079 genModTwoByte (left, right, result, ic);
5083 /* should have been converted to function call */
5087 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5088 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5089 freeAsmop (result, NULL, ic, TRUE);
5092 /*-----------------------------------------------------------------*/
5093 /* genIfxJump :- will create a jump depending on the ifx */
5094 /*-----------------------------------------------------------------*/
5096 genIfxJump (iCode * ic, char *jval)
5099 symbol *tlbl = newiTempLabel (NULL);
5102 D (emitcode (";", "genIfxJump ");
5105 /* if true label then we jump if condition
5109 jlbl = IC_TRUE (ic);
5110 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5111 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5115 /* false label is present */
5116 jlbl = IC_FALSE (ic);
5117 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5118 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5120 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5121 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5123 emitcode (inst, "!tlabel", tlbl->key + 100);
5124 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5125 emitcode ("", "!tlabeldef", tlbl->key + 100);
5127 /* mark the icode as generated */
5131 /*-----------------------------------------------------------------*/
5132 /* genCmp :- greater or less than comparison */
5133 /*-----------------------------------------------------------------*/
5135 genCmp (operand * left, operand * right,
5136 iCode * ic, iCode * ifx, int sign)
5138 int size, offset = 0;
5139 unsigned long lit = 0L;
5142 D (emitcode (";", "genCmp");
5145 result = IC_RESULT (ic);
5147 /* if left & right are bit variables */
5148 if (AOP_TYPE (left) == AOP_CRY &&
5149 AOP_TYPE (right) == AOP_CRY)
5151 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5152 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
5156 /* subtract right from left if at the
5157 end the carry flag is set then we know that
5158 left is greater than right */
5159 size = max (AOP_SIZE (left), AOP_SIZE (right));
5161 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5162 if ((size == 1) && !sign &&
5163 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5165 symbol *lbl = newiTempLabel (NULL);
5166 emitcode ("cjne", "%s,%s,!tlabel",
5167 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5168 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5170 emitcode ("", "!tlabeldef", lbl->key + 100);
5174 if (AOP_TYPE (right) == AOP_LIT)
5176 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5177 /* optimize if(x < 0) or if(x >= 0) */
5186 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5188 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5189 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5191 aopOp (result, ic, FALSE, FALSE);
5193 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5195 freeAsmop (result, NULL, ic, TRUE);
5196 genIfxJump (ifx, "acc.7");
5201 emitcode ("rlc", "a");
5203 goto release_freedLR;
5211 //emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5212 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5213 //emitcode (";", "genCmp #2");
5214 if (sign && (size == 0))
5216 //emitcode (";", "genCmp #3");
5217 emitcode ("xrl", "a,#!constbyte",0x80);
5218 if (AOP_TYPE (right) == AOP_LIT)
5220 unsigned long lit = (unsigned long)
5221 floatFromVal (AOP (right)->aopu.aop_lit);
5222 //emitcode (";", "genCmp #3.1");
5223 emitcode ("subb", "a,#!constbyte",
5224 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5228 //emitcode (";", "genCmp #3.2");
5229 if (AOP_NEEDSACC (right))
5231 emitcode ("push", "acc");
5233 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
5234 FALSE, FALSE, FALSE));
5235 emitcode ("xrl", "b,#!constbyte",0x80);
5236 if (AOP_NEEDSACC (right))
5238 emitcode ("pop", "acc");
5240 emitcode ("subb", "a,b");
5247 //emitcode (";", "genCmp #4");
5248 if (AOP_NEEDSACC (right))
5251 //emitcode (";", "genCmp #4.1");
5252 emitcode ("xch", "a, b");
5253 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
5254 emitcode ("xch", "a, b");
5259 //emitcode (";", "genCmp #4.2");
5260 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
5263 emitcode ("subb", "a,%s", s);
5270 /* Don't need the left & right operands any more; do need the result. */
5271 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5272 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5274 aopOp (result, ic, FALSE, FALSE);
5278 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5284 /* if the result is used in the next
5285 ifx conditional branch then generate
5286 code a little differently */
5289 genIfxJump (ifx, "c");
5295 /* leave the result in acc */
5297 freeAsmop (result, NULL, ic, TRUE);
5300 /*-----------------------------------------------------------------*/
5301 /* genCmpGt :- greater than comparison */
5302 /*-----------------------------------------------------------------*/
5304 genCmpGt (iCode * ic, iCode * ifx)
5306 operand *left, *right;
5307 sym_link *letype, *retype;
5310 D (emitcode (";", "genCmpGt ");
5313 left = IC_LEFT (ic);
5314 right = IC_RIGHT (ic);
5316 letype = getSpec (operandType (left));
5317 retype = getSpec (operandType (right));
5318 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5320 /* assign the left & right amsops */
5323 genCmp (right, left, ic, ifx, sign);
5326 /*-----------------------------------------------------------------*/
5327 /* genCmpLt - less than comparisons */
5328 /*-----------------------------------------------------------------*/
5330 genCmpLt (iCode * ic, iCode * ifx)
5332 operand *left, *right;
5333 sym_link *letype, *retype;
5336 D (emitcode (";", "genCmpLt "););
5338 left = IC_LEFT (ic);
5339 right = IC_RIGHT (ic);
5341 letype = getSpec (operandType (left));
5342 retype = getSpec (operandType (right));
5343 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5345 /* assign the left & right amsops */
5348 genCmp (left, right, ic, ifx, sign);
5351 /*-----------------------------------------------------------------*/
5352 /* gencjneshort - compare and jump if not equal */
5353 /*-----------------------------------------------------------------*/
5355 gencjneshort (operand * left, operand * right, symbol * lbl)
5357 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5359 unsigned long lit = 0L;
5361 D (emitcode (";", "gencjneshort");
5364 /* if the left side is a literal or
5365 if the right is in a pointer register and left
5367 if ((AOP_TYPE (left) == AOP_LIT) ||
5368 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5375 if (AOP_TYPE (right) == AOP_LIT)
5376 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5378 if (opIsGptr (left) || opIsGptr (right))
5380 /* We are comparing a generic pointer to something.
5381 * Exclude the generic type byte from the comparison.
5384 D (emitcode (";", "cjneshort: generic ptr special case.");
5389 /* if the right side is a literal then anything goes */
5390 if (AOP_TYPE (right) == AOP_LIT &&
5391 AOP_TYPE (left) != AOP_DIR)
5395 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5397 emitcode ("cjne", "a,%s,!tlabel",
5398 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5404 /* if the right side is in a register or in direct space or
5405 if the left is a pointer register & right is not */
5406 else if (AOP_TYPE (right) == AOP_REG ||
5407 AOP_TYPE (right) == AOP_DIR ||
5408 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5409 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5413 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5414 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5415 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5416 emitcode ("jnz", "!tlabel", lbl->key + 100);
5418 emitcode ("cjne", "a,%s,!tlabel",
5419 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
5426 /* right is a pointer reg need both a & b */
5429 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5430 if (strcmp (l, "b"))
5431 emitcode ("mov", "b,%s", l);
5432 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5433 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5439 /*-----------------------------------------------------------------*/
5440 /* gencjne - compare and jump if not equal */
5441 /*-----------------------------------------------------------------*/
5443 gencjne (operand * left, operand * right, symbol * lbl)
5445 symbol *tlbl = newiTempLabel (NULL);
5447 D (emitcode (";", "gencjne");
5450 gencjneshort (left, right, lbl);
5452 emitcode ("mov", "a,%s", one);
5453 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5454 emitcode ("", "!tlabeldef", lbl->key + 100);
5455 emitcode ("clr", "a");
5456 emitcode ("", "!tlabeldef", tlbl->key + 100);
5459 /*-----------------------------------------------------------------*/
5460 /* genCmpEq - generates code for equal to */
5461 /*-----------------------------------------------------------------*/
5463 genCmpEq (iCode * ic, iCode * ifx)
5465 operand *left, *right, *result;
5467 D (emitcode (";", "genCmpEq ");
5471 AOP_SET_LOCALS (ic);
5473 /* if literal, literal on the right or
5474 if the right is in a pointer register and left
5476 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5477 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5479 operand *t = IC_RIGHT (ic);
5480 IC_RIGHT (ic) = IC_LEFT (ic);
5484 if (ifx && /* !AOP_SIZE(result) */
5485 OP_SYMBOL (result) &&
5486 OP_SYMBOL (result)->regType == REG_CND)
5489 /* if they are both bit variables */
5490 if (AOP_TYPE (left) == AOP_CRY &&
5491 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5493 if (AOP_TYPE (right) == AOP_LIT)
5495 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5498 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5499 emitcode ("cpl", "c");
5503 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5507 emitcode ("clr", "c");
5509 /* AOP_TYPE(right) == AOP_CRY */
5513 symbol *lbl = newiTempLabel (NULL);
5514 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5515 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5516 emitcode ("cpl", "c");
5517 emitcode ("", "!tlabeldef", (lbl->key + 100));
5519 /* if true label then we jump if condition
5521 tlbl = newiTempLabel (NULL);
5524 emitcode ("jnc", "!tlabel", tlbl->key + 100);
5525 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5529 emitcode ("jc", "!tlabel", tlbl->key + 100);
5530 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5532 emitcode ("", "!tlabeldef", tlbl->key + 100);
5536 tlbl = newiTempLabel (NULL);
5537 gencjneshort (left, right, tlbl);
5540 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5541 emitcode ("", "!tlabeldef", tlbl->key + 100);
5545 symbol *lbl = newiTempLabel (NULL);
5546 emitcode ("sjmp", "!tlabel", lbl->key + 100);
5547 emitcode ("", "!tlabeldef", tlbl->key + 100);
5548 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5549 emitcode ("", "!tlabeldef", lbl->key + 100);
5552 /* mark the icode as generated */
5555 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5556 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5560 /* if they are both bit variables */
5561 if (AOP_TYPE (left) == AOP_CRY &&
5562 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5564 if (AOP_TYPE (right) == AOP_LIT)
5566 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5569 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5570 emitcode ("cpl", "c");
5574 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5578 emitcode ("clr", "c");
5580 /* AOP_TYPE(right) == AOP_CRY */
5584 symbol *lbl = newiTempLabel (NULL);
5585 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5586 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5587 emitcode ("cpl", "c");
5588 emitcode ("", "!tlabeldef", (lbl->key + 100));
5591 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5592 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5594 aopOp (result, ic, TRUE, FALSE);
5597 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5604 genIfxJump (ifx, "c");
5607 /* if the result is used in an arithmetic operation
5608 then put the result in place */
5613 gencjne (left, right, newiTempLabel (NULL));
5615 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5616 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5618 aopOp (result, ic, TRUE, FALSE);
5620 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5622 aopPut (AOP (result), "a", 0);
5627 genIfxJump (ifx, "a");
5630 /* if the result is used in an arithmetic operation
5631 then put the result in place */
5632 if (AOP_TYPE (result) != AOP_CRY)
5634 /* leave the result in acc */
5638 freeAsmop (result, NULL, ic, TRUE);
5641 /*-----------------------------------------------------------------*/
5642 /* ifxForOp - returns the icode containing the ifx for operand */
5643 /*-----------------------------------------------------------------*/
5645 ifxForOp (operand * op, iCode * ic)
5647 /* if true symbol then needs to be assigned */
5648 if (IS_TRUE_SYMOP (op))
5651 /* if this has register type condition and
5652 the next instruction is ifx with the same operand
5653 and live to of the operand is upto the ifx only then */
5655 ic->next->op == IFX &&
5656 IC_COND (ic->next)->key == op->key &&
5657 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5662 /*-----------------------------------------------------------------*/
5663 /* hasInc - operand is incremented before any other use */
5664 /*-----------------------------------------------------------------*/
5666 hasInc (operand *op, iCode *ic, int osize)
5668 sym_link *type = operandType(op);
5669 sym_link *retype = getSpec (type);
5670 iCode *lic = ic->next;
5673 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5674 if (!IS_SYMOP(op)) return NULL;
5676 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5677 if (IS_AGGREGATE(type->next)) return NULL;
5678 if (osize != (isize = getSize(type->next))) return NULL;
5681 /* if operand of the form op = op + <sizeof *op> */
5682 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5683 isOperandEqual(IC_RESULT(lic),op) &&
5684 isOperandLiteral(IC_RIGHT(lic)) &&
5685 operandLitValue(IC_RIGHT(lic)) == isize) {
5688 /* if the operand used or deffed */
5689 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5692 /* if GOTO or IFX */
5693 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5699 /*-----------------------------------------------------------------*/
5700 /* genAndOp - for && operation */
5701 /*-----------------------------------------------------------------*/
5703 genAndOp (iCode * ic)
5705 operand *left, *right, *result;
5708 D (emitcode (";", "genAndOp "););
5710 /* note here that && operations that are in an
5711 if statement are taken away by backPatchLabels
5712 only those used in arthmetic operations remain */
5714 AOP_SET_LOCALS (ic);
5716 /* if both are bit variables */
5717 if (AOP_TYPE (left) == AOP_CRY &&
5718 AOP_TYPE (right) == AOP_CRY)
5720 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5721 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5722 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5723 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5725 aopOp (result,ic,FALSE, FALSE);
5730 tlbl = newiTempLabel (NULL);
5732 emitcode ("jz", "!tlabel", tlbl->key + 100);
5734 emitcode ("", "!tlabeldef", tlbl->key + 100);
5735 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5736 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5738 aopOp (result,ic,FALSE, FALSE);
5741 freeAsmop (result, NULL, ic, TRUE);
5745 /*-----------------------------------------------------------------*/
5746 /* genOrOp - for || operation */
5747 /*-----------------------------------------------------------------*/
5749 genOrOp (iCode * ic)
5751 operand *left, *right, *result;
5754 D (emitcode (";", "genOrOp "););
5756 /* note here that || operations that are in an
5757 if statement are taken away by backPatchLabels
5758 only those used in arthmetic operations remain */
5760 AOP_SET_LOCALS (ic);
5762 /* if both are bit variables */
5763 if (AOP_TYPE (left) == AOP_CRY &&
5764 AOP_TYPE (right) == AOP_CRY)
5766 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5767 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5768 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5769 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5771 aopOp (result,ic,FALSE, FALSE);
5777 tlbl = newiTempLabel (NULL);
5779 emitcode ("jnz", "!tlabel", tlbl->key + 100);
5781 emitcode ("", "!tlabeldef", tlbl->key + 100);
5782 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5783 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5785 aopOp (result,ic,FALSE, FALSE);
5790 freeAsmop (result, NULL, ic, TRUE);
5793 /*-----------------------------------------------------------------*/
5794 /* isLiteralBit - test if lit == 2^n */
5795 /*-----------------------------------------------------------------*/
5797 isLiteralBit (unsigned long lit)
5799 unsigned long pw[32] =
5800 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5801 0x100L, 0x200L, 0x400L, 0x800L,
5802 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5803 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5804 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5805 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5806 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5809 for (idx = 0; idx < 32; idx++)
5815 /*-----------------------------------------------------------------*/
5816 /* continueIfTrue - */
5817 /*-----------------------------------------------------------------*/
5819 continueIfTrue (iCode * ic)
5822 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5826 /*-----------------------------------------------------------------*/
5828 /*-----------------------------------------------------------------*/
5830 jumpIfTrue (iCode * ic)
5833 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
5837 /*-----------------------------------------------------------------*/
5838 /* jmpTrueOrFalse - */
5839 /*-----------------------------------------------------------------*/
5841 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5843 // ugly but optimized by peephole
5846 symbol *nlbl = newiTempLabel (NULL);
5847 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
5848 emitcode ("", "!tlabeldef", tlbl->key + 100);
5849 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5850 emitcode ("", "!tlabeldef", nlbl->key + 100);
5854 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
5855 emitcode ("", "!tlabeldef", tlbl->key + 100);
5860 // Generate code to perform a bit-wise logic operation
5861 // on two operands in far space (assumed to already have been
5862 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5863 // in far space. This requires pushing the result on the stack
5864 // then popping it into the result.
5866 genFarFarLogicOp(iCode *ic, char *logicOp)
5868 int size, resultSize, compSize;
5872 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5873 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
5874 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5876 _startLazyDPSEvaluation();
5877 for (size = compSize; (size--); offset++)
5879 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5880 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5881 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5883 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5884 emitcode ("push", "acc");
5886 _endLazyDPSEvaluation();
5888 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5889 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5890 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5892 resultSize = AOP_SIZE(IC_RESULT(ic));
5894 ADJUST_PUSHED_RESULT(compSize, resultSize);
5896 _startLazyDPSEvaluation();
5899 emitcode ("pop", "acc");
5900 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5902 _endLazyDPSEvaluation();
5903 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5907 /*-----------------------------------------------------------------*/
5908 /* genAnd - code for and */
5909 /*-----------------------------------------------------------------*/
5911 genAnd (iCode * ic, iCode * ifx)
5913 operand *left, *right, *result;
5914 int size, offset = 0;
5915 unsigned long lit = 0L;
5920 D (emitcode (";", "genAnd "););
5922 AOP_OP_3_NOFATAL (ic, pushResult);
5923 AOP_SET_LOCALS (ic);
5927 genFarFarLogicOp(ic, "anl");
5932 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5934 AOP_TYPE (left), AOP_TYPE (right));
5935 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5937 AOP_SIZE (left), AOP_SIZE (right));
5940 /* if left is a literal & right is not then exchange them */
5941 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5942 #ifdef LOGIC_OPS_BROKEN
5943 || AOP_NEEDSACC (left)
5947 operand *tmp = right;
5952 /* if result = right then exchange them */
5953 if (sameRegs (AOP (result), AOP (right)))
5955 operand *tmp = right;
5960 /* if right is bit then exchange them */
5961 if (AOP_TYPE (right) == AOP_CRY &&
5962 AOP_TYPE (left) != AOP_CRY)
5964 operand *tmp = right;
5968 if (AOP_TYPE (right) == AOP_LIT)
5969 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5971 size = AOP_SIZE (result);
5974 // result = bit & yy;
5975 if (AOP_TYPE (left) == AOP_CRY)
5977 // c = bit & literal;
5978 if (AOP_TYPE (right) == AOP_LIT)
5982 if (size && sameRegs (AOP (result), AOP (left)))
5985 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5990 if (size && (AOP_TYPE (result) == AOP_CRY))
5992 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5995 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6000 emitcode ("clr", "c");
6005 if (AOP_TYPE (right) == AOP_CRY)
6008 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6009 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6014 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
6016 emitcode ("rrc", "a");
6017 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6025 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6026 genIfxJump (ifx, "c");
6030 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6031 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6032 if ((AOP_TYPE (right) == AOP_LIT) &&
6033 (AOP_TYPE (result) == AOP_CRY) &&
6034 (AOP_TYPE (left) != AOP_CRY))
6036 int posbit = isLiteralBit (lit);
6041 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
6044 emitcode ("mov", "c,acc.%d", posbit & 0x07);
6050 sprintf (buffer, "acc.%d", posbit & 0x07);
6051 genIfxJump (ifx, buffer);
6055 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6062 symbol *tlbl = newiTempLabel (NULL);
6063 int sizel = AOP_SIZE (left);
6065 emitcode ("setb", "c");
6068 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6070 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6072 if ((posbit = isLiteralBit (bytelit)) != 0)
6073 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6076 if (bytelit != 0x0FFL)
6077 emitcode ("anl", "a,%s",
6078 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
6079 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6084 // bit = left & literal
6087 emitcode ("clr", "c");
6088 emitcode ("", "!tlabeldef", tlbl->key + 100);
6090 // if(left & literal)
6094 jmpTrueOrFalse (ifx, tlbl);
6102 /* if left is same as result */
6103 if (sameRegs (AOP (result), AOP (left)))
6105 for (; size--; offset++)
6107 if (AOP_TYPE (right) == AOP_LIT)
6109 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6111 else if (bytelit == 0)
6112 aopPut (AOP (result), zero, offset);
6113 else if (IS_AOP_PREG (result))
6115 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6116 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6117 aopPut (AOP (result), "a", offset);
6120 emitcode ("anl", "%s,%s",
6121 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6122 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6126 if (AOP_TYPE (left) == AOP_ACC)
6127 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6130 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6131 if (IS_AOP_PREG (result))
6133 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6134 aopPut (AOP (result), "a", offset);
6138 emitcode ("anl", "%s,a",
6139 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6146 // left & result in different registers
6147 if (AOP_TYPE (result) == AOP_CRY)
6150 // if(size), result in bit
6151 // if(!size && ifx), conditional oper: if(left & right)
6152 symbol *tlbl = newiTempLabel (NULL);
6153 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6155 emitcode ("setb", "c");
6158 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6159 emitcode ("anl", "a,%s",
6160 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6162 if (AOP_TYPE(left)==AOP_ACC) {
6163 emitcode("mov", "b,a");
6164 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6165 emitcode("anl", "a,b");
6167 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6168 emitcode ("anl", "a,%s",
6169 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6172 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6178 emitcode ("", "!tlabeldef", tlbl->key + 100);
6182 jmpTrueOrFalse (ifx, tlbl);
6186 for (; (size--); offset++)
6189 // result = left & right
6190 if (AOP_TYPE (right) == AOP_LIT)
6192 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6194 aopPut (AOP (result),
6195 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6199 else if (bytelit == 0)
6201 aopPut (AOP (result), zero, offset);
6204 D (emitcode (";", "better literal AND."););
6205 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6206 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6207 FALSE, FALSE, FALSE));
6212 // faster than result <- left, anl result,right
6213 // and better if result is SFR
6214 if (AOP_TYPE (left) == AOP_ACC)
6216 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
6217 FALSE, FALSE, FALSE));
6221 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6222 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6224 emitcode("mov", "b,a");
6228 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6229 emitcode ("anl", "a,%s", rOp);
6232 aopPut (AOP (result), "a", offset);
6238 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6239 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6240 freeAsmop (result, NULL, ic, TRUE);
6244 /*-----------------------------------------------------------------*/
6245 /* genOr - code for or */
6246 /*-----------------------------------------------------------------*/
6248 genOr (iCode * ic, iCode * ifx)
6250 operand *left, *right, *result;
6251 int size, offset = 0;
6252 unsigned long lit = 0L;
6255 D (emitcode (";", "genOr "););
6257 AOP_OP_3_NOFATAL (ic, pushResult);
6258 AOP_SET_LOCALS (ic);
6262 genFarFarLogicOp(ic, "orl");
6268 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6270 AOP_TYPE (left), AOP_TYPE (right));
6271 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6273 AOP_SIZE (left), AOP_SIZE (right));
6276 /* if left is a literal & right is not then exchange them */
6277 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6278 #ifdef LOGIC_OPS_BROKEN
6279 || AOP_NEEDSACC (left) // I think this is a net loss now.
6283 operand *tmp = right;
6288 /* if result = right then exchange them */
6289 if (sameRegs (AOP (result), AOP (right)))
6291 operand *tmp = right;
6296 /* if right is bit then exchange them */
6297 if (AOP_TYPE (right) == AOP_CRY &&
6298 AOP_TYPE (left) != AOP_CRY)
6300 operand *tmp = right;
6304 if (AOP_TYPE (right) == AOP_LIT)
6305 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6307 size = AOP_SIZE (result);
6311 if (AOP_TYPE (left) == AOP_CRY)
6313 if (AOP_TYPE (right) == AOP_LIT)
6315 // c = bit & literal;
6318 // lit != 0 => result = 1
6319 if (AOP_TYPE (result) == AOP_CRY)
6322 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6324 continueIfTrue (ifx);
6327 emitcode ("setb", "c");
6331 // lit == 0 => result = left
6332 if (size && sameRegs (AOP (result), AOP (left)))
6334 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6339 if (AOP_TYPE (right) == AOP_CRY)
6342 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6343 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6348 symbol *tlbl = newiTempLabel (NULL);
6349 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6350 emitcode ("setb", "c");
6351 emitcode ("jb", "%s,!tlabel",
6352 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6354 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6355 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6357 jmpTrueOrFalse (ifx, tlbl);
6363 emitcode ("", "!tlabeldef", tlbl->key + 100);
6372 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6373 genIfxJump (ifx, "c");
6377 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6378 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6379 if ((AOP_TYPE (right) == AOP_LIT) &&
6380 (AOP_TYPE (result) == AOP_CRY) &&
6381 (AOP_TYPE (left) != AOP_CRY))
6387 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6389 continueIfTrue (ifx);
6394 // lit = 0, result = boolean(left)
6396 emitcode ("setb", "c");
6400 symbol *tlbl = newiTempLabel (NULL);
6401 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6403 emitcode ("", "!tlabeldef", tlbl->key + 100);
6407 genIfxJump (ifx, "a");
6415 /* if left is same as result */
6416 if (sameRegs (AOP (result), AOP (left)))
6418 for (; size--; offset++)
6420 if (AOP_TYPE (right) == AOP_LIT)
6422 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6428 if (IS_AOP_PREG (left))
6430 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6431 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6432 aopPut (AOP (result), "a", offset);
6436 emitcode ("orl", "%s,%s",
6437 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6438 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6444 if (AOP_TYPE (left) == AOP_ACC)
6446 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6450 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6451 if (IS_AOP_PREG (left))
6453 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6454 aopPut (AOP (result), "a", offset);
6458 emitcode ("orl", "%s,a",
6459 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6467 // left & result in different registers
6468 if (AOP_TYPE (result) == AOP_CRY)
6471 // if(size), result in bit
6472 // if(!size && ifx), conditional oper: if(left | right)
6473 symbol *tlbl = newiTempLabel (NULL);
6474 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6476 emitcode ("setb", "c");
6479 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6480 emitcode ("orl", "a,%s",
6481 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6483 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6484 emitcode ("orl", "a,%s",
6485 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6487 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6493 emitcode ("", "!tlabeldef", tlbl->key + 100);
6497 jmpTrueOrFalse (ifx, tlbl);
6501 _startLazyDPSEvaluation();
6502 for (; (size--); offset++)
6505 // result = left & right
6506 if (AOP_TYPE (right) == AOP_LIT)
6508 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6510 aopPut (AOP (result),
6511 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6515 D (emitcode (";", "better literal OR."););
6516 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6517 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6518 FALSE, FALSE, FALSE));
6523 // faster than result <- left, anl result,right
6524 // and better if result is SFR
6525 if (AOP_TYPE (left) == AOP_ACC)
6527 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6528 FALSE, FALSE, FALSE));
6532 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6534 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6536 emitcode("mov", "b,a");
6540 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6541 emitcode ("orl", "a,%s", rOp);
6544 aopPut (AOP (result), "a", offset);
6546 _endLazyDPSEvaluation();
6551 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6552 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6553 freeAsmop (result, NULL, ic, TRUE);
6556 /*-----------------------------------------------------------------*/
6557 /* genXor - code for xclusive or */
6558 /*-----------------------------------------------------------------*/
6560 genXor (iCode * ic, iCode * ifx)
6562 operand *left, *right, *result;
6563 int size, offset = 0;
6564 unsigned long lit = 0L;
6567 D (emitcode (";", "genXor "););
6569 AOP_OP_3_NOFATAL (ic, pushResult);
6570 AOP_SET_LOCALS (ic);
6574 genFarFarLogicOp(ic, "xrl");
6579 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6581 AOP_TYPE (left), AOP_TYPE (right));
6582 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6584 AOP_SIZE (left), AOP_SIZE (right));
6587 /* if left is a literal & right is not ||
6588 if left needs acc & right does not */
6589 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6590 #ifdef LOGIC_OPS_BROKEN
6591 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6595 operand *tmp = right;
6600 /* if result = right then exchange them */
6601 if (sameRegs (AOP (result), AOP (right)))
6603 operand *tmp = right;
6608 /* if right is bit then exchange them */
6609 if (AOP_TYPE (right) == AOP_CRY &&
6610 AOP_TYPE (left) != AOP_CRY)
6612 operand *tmp = right;
6616 if (AOP_TYPE (right) == AOP_LIT)
6617 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6619 size = AOP_SIZE (result);
6623 if (AOP_TYPE (left) == AOP_CRY)
6625 if (AOP_TYPE (right) == AOP_LIT)
6627 // c = bit & literal;
6630 // lit>>1 != 0 => result = 1
6631 if (AOP_TYPE (result) == AOP_CRY)
6634 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6636 continueIfTrue (ifx);
6639 emitcode ("setb", "c");
6646 // lit == 0, result = left
6647 if (size && sameRegs (AOP (result), AOP (left)))
6649 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6653 // lit == 1, result = not(left)
6654 if (size && sameRegs (AOP (result), AOP (left)))
6656 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6661 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6662 emitcode ("cpl", "c");
6671 symbol *tlbl = newiTempLabel (NULL);
6672 if (AOP_TYPE (right) == AOP_CRY)
6675 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6679 int sizer = AOP_SIZE (right);
6681 // if val>>1 != 0, result = 1
6682 emitcode ("setb", "c");
6685 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6687 // test the msb of the lsb
6688 emitcode ("anl", "a,#!constbyte",0xfe);
6689 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6693 emitcode ("rrc", "a");
6695 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6696 emitcode ("cpl", "c");
6697 emitcode ("", "!tlabeldef", (tlbl->key + 100));
6704 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6705 genIfxJump (ifx, "c");
6709 if (sameRegs (AOP (result), AOP (left)))
6711 /* if left is same as result */
6712 for (; size--; offset++)
6714 if (AOP_TYPE (right) == AOP_LIT)
6716 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6718 else if (IS_AOP_PREG (left))
6720 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6721 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6722 aopPut (AOP (result), "a", offset);
6725 emitcode ("xrl", "%s,%s",
6726 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6727 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6731 if (AOP_TYPE (left) == AOP_ACC)
6732 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6735 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6736 if (IS_AOP_PREG (left))
6738 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6739 aopPut (AOP (result), "a", offset);
6742 emitcode ("xrl", "%s,a",
6743 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6750 // left & result in different registers
6751 if (AOP_TYPE (result) == AOP_CRY)
6754 // if(size), result in bit
6755 // if(!size && ifx), conditional oper: if(left ^ right)
6756 symbol *tlbl = newiTempLabel (NULL);
6757 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6760 emitcode ("setb", "c");
6763 if ((AOP_TYPE (right) == AOP_LIT) &&
6764 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6766 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6770 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6771 emitcode ("xrl", "a,%s",
6772 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6774 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6775 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6777 emitcode("mov", "b,a");
6781 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6782 emitcode ("xrl", "a,%s", rOp);
6785 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6791 emitcode ("", "!tlabeldef", tlbl->key + 100);
6795 jmpTrueOrFalse (ifx, tlbl);
6799 for (; (size--); offset++)
6802 // result = left & right
6803 if (AOP_TYPE (right) == AOP_LIT)
6805 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6807 aopPut (AOP (result),
6808 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6812 D (emitcode (";", "better literal XOR."););
6813 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6814 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6815 FALSE, FALSE, FALSE));
6819 // faster than result <- left, anl result,right
6820 // and better if result is SFR
6821 if (AOP_TYPE (left) == AOP_ACC)
6823 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6824 FALSE, FALSE, FALSE));
6828 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6829 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6831 emitcode("mov", "b,a");
6835 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6836 emitcode ("xrl", "a,%s", rOp);
6839 aopPut (AOP (result), "a", offset);
6846 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6847 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6848 freeAsmop (result, NULL, ic, TRUE);
6851 /*-----------------------------------------------------------------*/
6852 /* genInline - write the inline code out */
6853 /*-----------------------------------------------------------------*/
6855 genInline (iCode * ic)
6857 char *buffer, *bp, *bp1;
6859 D (emitcode (";", "genInline ");
6862 _G.inLine += (!options.asmpeep);
6864 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6865 strcpy (buffer, IC_INLINE (ic));
6867 /* emit each line as a code */
6892 /* emitcode("",buffer); */
6893 _G.inLine -= (!options.asmpeep);
6896 /*-----------------------------------------------------------------*/
6897 /* genRRC - rotate right with carry */
6898 /*-----------------------------------------------------------------*/
6902 operand *left, *result;
6903 int size, offset = 0;
6906 D (emitcode (";", "genRRC ");
6909 /* rotate right with carry */
6910 left = IC_LEFT (ic);
6911 result = IC_RESULT (ic);
6912 aopOp (left, ic, FALSE, FALSE);
6913 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6915 /* move it to the result */
6916 size = AOP_SIZE (result);
6920 _startLazyDPSEvaluation ();
6923 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6925 emitcode ("rrc", "a");
6926 if (AOP_SIZE (result) > 1)
6927 aopPut (AOP (result), "a", offset--);
6929 _endLazyDPSEvaluation ();
6931 /* now we need to put the carry into the
6932 highest order byte of the result */
6933 if (AOP_SIZE (result) > 1)
6935 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6938 emitcode ("mov", "acc.7,c");
6939 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6940 freeAsmop (left, NULL, ic, TRUE);
6941 freeAsmop (result, NULL, ic, TRUE);
6944 /*-----------------------------------------------------------------*/
6945 /* genRLC - generate code for rotate left with carry */
6946 /*-----------------------------------------------------------------*/
6950 operand *left, *result;
6951 int size, offset = 0;
6954 D (emitcode (";", "genRLC ");
6957 /* rotate right with carry */
6958 left = IC_LEFT (ic);
6959 result = IC_RESULT (ic);
6960 aopOp (left, ic, FALSE, FALSE);
6961 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6963 /* move it to the result */
6964 size = AOP_SIZE (result);
6968 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6970 emitcode ("add", "a,acc");
6971 if (AOP_SIZE (result) > 1)
6973 aopPut (AOP (result), "a", offset++);
6976 _startLazyDPSEvaluation ();
6979 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6981 emitcode ("rlc", "a");
6982 if (AOP_SIZE (result) > 1)
6983 aopPut (AOP (result), "a", offset++);
6985 _endLazyDPSEvaluation ();
6987 /* now we need to put the carry into the
6988 highest order byte of the result */
6989 if (AOP_SIZE (result) > 1)
6991 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6994 emitcode ("mov", "acc.0,c");
6995 aopPut (AOP (result), "a", 0);
6996 freeAsmop (left, NULL, ic, TRUE);
6997 freeAsmop (result, NULL, ic, TRUE);
7000 /*-----------------------------------------------------------------*/
7001 /* genGetHbit - generates code get highest order bit */
7002 /*-----------------------------------------------------------------*/
7004 genGetHbit (iCode * ic)
7006 operand *left, *result;
7007 left = IC_LEFT (ic);
7008 result = IC_RESULT (ic);
7009 aopOp (left, ic, FALSE, FALSE);
7010 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7012 D (emitcode (";", "genGetHbit ");
7015 /* get the highest order byte into a */
7016 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
7017 if (AOP_TYPE (result) == AOP_CRY)
7019 emitcode ("rlc", "a");
7024 emitcode ("rl", "a");
7025 emitcode ("anl", "a,#1");
7030 freeAsmop (left, NULL, ic, TRUE);
7031 freeAsmop (result, NULL, ic, TRUE);
7034 /*-----------------------------------------------------------------*/
7035 /* AccRol - rotate left accumulator by known count */
7036 /*-----------------------------------------------------------------*/
7038 AccRol (int shCount)
7040 shCount &= 0x0007; // shCount : 0..7
7047 emitcode ("rl", "a");
7050 emitcode ("rl", "a");
7051 emitcode ("rl", "a");
7054 emitcode ("swap", "a");
7055 emitcode ("rr", "a");
7058 emitcode ("swap", "a");
7061 emitcode ("swap", "a");
7062 emitcode ("rl", "a");
7065 emitcode ("rr", "a");
7066 emitcode ("rr", "a");
7069 emitcode ("rr", "a");
7074 /*-----------------------------------------------------------------*/
7075 /* AccLsh - left shift accumulator by known count */
7076 /*-----------------------------------------------------------------*/
7078 AccLsh (int shCount)
7083 emitcode ("add", "a,acc");
7084 else if (shCount == 2)
7086 emitcode ("add", "a,acc");
7087 emitcode ("add", "a,acc");
7091 /* rotate left accumulator */
7093 /* and kill the lower order bits */
7094 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7099 /*-----------------------------------------------------------------*/
7100 /* AccRsh - right shift accumulator by known count */
7101 /*-----------------------------------------------------------------*/
7103 AccRsh (int shCount)
7110 emitcode ("rrc", "a");
7114 /* rotate right accumulator */
7115 AccRol (8 - shCount);
7116 /* and kill the higher order bits */
7117 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7122 #ifdef BETTER_LITERAL_SHIFT
7123 /*-----------------------------------------------------------------*/
7124 /* AccSRsh - signed right shift accumulator by known count */
7125 /*-----------------------------------------------------------------*/
7127 AccSRsh (int shCount)
7134 emitcode ("mov", "c,acc.7");
7135 emitcode ("rrc", "a");
7137 else if (shCount == 2)
7139 emitcode ("mov", "c,acc.7");
7140 emitcode ("rrc", "a");
7141 emitcode ("mov", "c,acc.7");
7142 emitcode ("rrc", "a");
7146 tlbl = newiTempLabel (NULL);
7147 /* rotate right accumulator */
7148 AccRol (8 - shCount);
7149 /* and kill the higher order bits */
7150 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7151 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7152 emitcode ("orl", "a,#!constbyte",
7153 (unsigned char) ~SRMask[shCount]);
7154 emitcode ("", "!tlabeldef", tlbl->key + 100);
7160 #ifdef BETTER_LITERAL_SHIFT
7161 /*-----------------------------------------------------------------*/
7162 /* shiftR1Left2Result - shift right one byte from left to result */
7163 /*-----------------------------------------------------------------*/
7165 shiftR1Left2Result (operand * left, int offl,
7166 operand * result, int offr,
7167 int shCount, int sign)
7169 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7170 /* shift right accumulator */
7175 aopPut (AOP (result), "a", offr);
7179 #ifdef BETTER_LITERAL_SHIFT
7180 /*-----------------------------------------------------------------*/
7181 /* shiftL1Left2Result - shift left one byte from left to result */
7182 /*-----------------------------------------------------------------*/
7184 shiftL1Left2Result (operand * left, int offl,
7185 operand * result, int offr, int shCount)
7187 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7188 /* shift left accumulator */
7190 aopPut (AOP (result), "a", offr);
7194 #ifdef BETTER_LITERAL_SHIFT
7195 /*-----------------------------------------------------------------*/
7196 /* movLeft2Result - move byte from left to result */
7197 /*-----------------------------------------------------------------*/
7199 movLeft2Result (operand * left, int offl,
7200 operand * result, int offr, int sign)
7203 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7205 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
7207 if (*l == '@' && (IS_AOP_PREG (result)))
7209 emitcode ("mov", "a,%s", l);
7210 aopPut (AOP (result), "a", offr);
7216 aopPut (AOP (result), l, offr);
7220 /* MSB sign in acc.7 ! */
7221 if (getDataSize (left) == offl + 1)
7223 emitcode ("mov", "a,%s", l);
7224 aopPut (AOP (result), "a", offr);
7232 #ifdef BETTER_LITERAL_SHIFT
7233 /*-----------------------------------------------------------------*/
7234 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7235 /*-----------------------------------------------------------------*/
7239 emitcode ("rrc", "a");
7240 emitcode ("xch", "a,%s", x);
7241 emitcode ("rrc", "a");
7242 emitcode ("xch", "a,%s", x);
7246 #ifdef BETTER_LITERAL_SHIFT
7248 /*-----------------------------------------------------------------*/
7249 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7250 /*-----------------------------------------------------------------*/
7254 emitcode ("xch", "a,%s", x);
7255 emitcode ("rlc", "a");
7256 emitcode ("xch", "a,%s", x);
7257 emitcode ("rlc", "a");
7261 #ifdef BETTER_LITERAL_SHIFT
7262 /*-----------------------------------------------------------------*/
7263 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7264 /*-----------------------------------------------------------------*/
7268 emitcode ("xch", "a,%s", x);
7269 emitcode ("add", "a,acc");
7270 emitcode ("xch", "a,%s", x);
7271 emitcode ("rlc", "a");
7275 #ifdef BETTER_LITERAL_SHIFT
7276 /*-----------------------------------------------------------------*/
7277 /* AccAXLsh - left shift a:x by known count (0..7) */
7278 /*-----------------------------------------------------------------*/
7280 AccAXLsh (char *x, int shCount)
7295 case 5: // AAAAABBB:CCCCCDDD
7297 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7299 emitcode ("anl", "a,#!constbyte",
7300 SLMask[shCount]); // BBB00000:CCCCCDDD
7302 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7304 AccRol (shCount); // DDDCCCCC:BBB00000
7306 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7308 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7310 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7312 emitcode ("anl", "a,#!constbyte",
7313 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7315 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7317 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7320 case 6: // AAAAAABB:CCCCCCDD
7321 emitcode ("anl", "a,#!constbyte",
7322 SRMask[shCount]); // 000000BB:CCCCCCDD
7323 emitcode ("mov", "c,acc.0"); // c = B
7324 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7326 AccAXRrl1 (x); // BCCCCCCD:D000000B
7327 AccAXRrl1 (x); // BBCCCCCC:DD000000
7329 emitcode("rrc","a");
7330 emitcode("xch","a,%s", x);
7331 emitcode("rrc","a");
7332 emitcode("mov","c,acc.0"); //<< get correct bit
7333 emitcode("xch","a,%s", x);
7335 emitcode("rrc","a");
7336 emitcode("xch","a,%s", x);
7337 emitcode("rrc","a");
7338 emitcode("xch","a,%s", x);
7341 case 7: // a:x <<= 7
7343 emitcode ("anl", "a,#!constbyte",
7344 SRMask[shCount]); // 0000000B:CCCCCCCD
7346 emitcode ("mov", "c,acc.0"); // c = B
7348 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7350 AccAXRrl1 (x); // BCCCCCCC:D0000000
7359 #ifdef BETTER_LITERAL_SHIFT
7361 /*-----------------------------------------------------------------*/
7362 /* AccAXRsh - right shift a:x known count (0..7) */
7363 /*-----------------------------------------------------------------*/
7365 AccAXRsh (char *x, int shCount)
7373 AccAXRrl1 (x); // 0->a:x
7378 AccAXRrl1 (x); // 0->a:x
7381 AccAXRrl1 (x); // 0->a:x
7386 case 5: // AAAAABBB:CCCCCDDD = a:x
7388 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7390 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7392 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7394 emitcode ("anl", "a,#!constbyte",
7395 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7397 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7399 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7401 emitcode ("anl", "a,#!constbyte",
7402 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7404 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7406 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7408 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7411 case 6: // AABBBBBB:CCDDDDDD
7413 emitcode ("mov", "c,acc.7");
7414 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7416 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7418 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7420 emitcode ("anl", "a,#!constbyte",
7421 SRMask[shCount]); // 000000AA:BBBBBBCC
7424 case 7: // ABBBBBBB:CDDDDDDD
7426 emitcode ("mov", "c,acc.7"); // c = A
7428 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7430 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7432 emitcode ("anl", "a,#!constbyte",
7433 SRMask[shCount]); // 0000000A:BBBBBBBC
7442 #ifdef BETTER_LITERAL_SHIFT
7443 /*-----------------------------------------------------------------*/
7444 /* AccAXRshS - right shift signed a:x known count (0..7) */
7445 /*-----------------------------------------------------------------*/
7447 AccAXRshS (char *x, int shCount)
7455 emitcode ("mov", "c,acc.7");
7456 AccAXRrl1 (x); // s->a:x
7460 emitcode ("mov", "c,acc.7");
7461 AccAXRrl1 (x); // s->a:x
7463 emitcode ("mov", "c,acc.7");
7464 AccAXRrl1 (x); // s->a:x
7469 case 5: // AAAAABBB:CCCCCDDD = a:x
7471 tlbl = newiTempLabel (NULL);
7472 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7474 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7476 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7478 emitcode ("anl", "a,#!constbyte",
7479 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7481 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7483 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7485 emitcode ("anl", "a,#!constbyte",
7486 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7488 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7490 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7492 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7494 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7495 emitcode ("orl", "a,#!constbyte",
7496 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7498 emitcode ("", "!tlabeldef", tlbl->key + 100);
7499 break; // SSSSAAAA:BBBCCCCC
7501 case 6: // AABBBBBB:CCDDDDDD
7503 tlbl = newiTempLabel (NULL);
7504 emitcode ("mov", "c,acc.7");
7505 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7507 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7509 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7511 emitcode ("anl", "a,#!constbyte",
7512 SRMask[shCount]); // 000000AA:BBBBBBCC
7514 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7515 emitcode ("orl", "a,#!constbyte",
7516 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7518 emitcode ("", "!tlabeldef", tlbl->key + 100);
7520 case 7: // ABBBBBBB:CDDDDDDD
7522 tlbl = newiTempLabel (NULL);
7523 emitcode ("mov", "c,acc.7"); // c = A
7525 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7527 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7529 emitcode ("anl", "a,#!constbyte",
7530 SRMask[shCount]); // 0000000A:BBBBBBBC
7532 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7533 emitcode ("orl", "a,#!constbyte",
7534 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7536 emitcode ("", "!tlabeldef", tlbl->key + 100);
7544 #ifdef BETTER_LITERAL_SHIFT
7546 _loadLeftIntoAx(char **lsb,
7552 // Get the initial value from left into a pair of registers.
7553 // MSB must be in A, LSB can be any register.
7555 // If the result is held in registers, it is an optimization
7556 // if the LSB can be held in the register which will hold the,
7557 // result LSB since this saves us from having to copy it into
7558 // the result following AccAXLsh.
7560 // If the result is addressed indirectly, this is not a gain.
7561 if (AOP_NEEDSACC(result))
7565 _startLazyDPSEvaluation();
7566 if (AOP_TYPE(left) == AOP_DPTR2)
7569 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7570 // get LSB in DP2_RESULT_REG.
7571 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7572 assert(!strcmp(leftByte, DP2_RESULT_REG));
7576 // get LSB into DP2_RESULT_REG
7577 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7578 if (strcmp(leftByte, DP2_RESULT_REG))
7581 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7584 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7585 assert(strcmp(leftByte, DP2_RESULT_REG));
7588 _endLazyDPSEvaluation();
7589 *lsb = DP2_RESULT_REG;
7593 if (sameRegs (AOP (result), AOP (left)) &&
7594 ((offl + MSB16) == offr))
7596 /* don't crash result[offr] */
7597 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7598 emitcode ("xch", "a,%s",
7599 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7603 movLeft2Result (left, offl, result, offr, 0);
7604 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7606 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7607 assert(strcmp(*lsb,"a"));
7612 _storeAxResults(char *lsb,
7616 _startLazyDPSEvaluation();
7617 if (AOP_NEEDSACC(result))
7619 /* We have to explicitly update the result LSB.
7621 emitcode("xch","a,%s", lsb);
7622 aopPut(AOP(result), "a", offr);
7623 emitcode("mov","a,%s", lsb);
7625 if (getDataSize (result) > 1)
7627 aopPut (AOP (result), "a", offr + MSB16);
7629 _endLazyDPSEvaluation();
7632 /*-----------------------------------------------------------------*/
7633 /* shiftL2Left2Result - shift left two bytes from left to result */
7634 /*-----------------------------------------------------------------*/
7636 shiftL2Left2Result (operand * left, int offl,
7637 operand * result, int offr, int shCount)
7641 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7643 AccAXLsh (lsb, shCount);
7645 _storeAxResults(lsb, result, offr);
7649 #ifdef BETTER_LITERAL_SHIFT
7650 /*-----------------------------------------------------------------*/
7651 /* shiftR2Left2Result - shift right two bytes from left to result */
7652 /*-----------------------------------------------------------------*/
7654 shiftR2Left2Result (operand * left, int offl,
7655 operand * result, int offr,
7656 int shCount, int sign)
7660 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7662 /* a:x >> shCount (x = lsb(result)) */
7665 AccAXRshS(lsb, shCount);
7669 AccAXRsh(lsb, shCount);
7672 _storeAxResults(lsb, result, offr);
7678 /*-----------------------------------------------------------------*/
7679 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7680 /*-----------------------------------------------------------------*/
7682 shiftLLeftOrResult (operand * left, int offl,
7683 operand * result, int offr, int shCount)
7685 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7686 /* shift left accumulator */
7688 /* or with result */
7689 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7690 /* back to result */
7691 aopPut (AOP (result), "a", offr);
7697 /*-----------------------------------------------------------------*/
7698 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7699 /*-----------------------------------------------------------------*/
7701 shiftRLeftOrResult (operand * left, int offl,
7702 operand * result, int offr, int shCount)
7704 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7705 /* shift right accumulator */
7707 /* or with result */
7708 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7709 /* back to result */
7710 aopPut (AOP (result), "a", offr);
7714 #ifdef BETTER_LITERAL_SHIFT
7715 /*-----------------------------------------------------------------*/
7716 /* genlshOne - left shift a one byte quantity by known count */
7717 /*-----------------------------------------------------------------*/
7719 genlshOne (operand * result, operand * left, int shCount)
7721 D (emitcode (";", "genlshOne "););
7722 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7726 #ifdef BETTER_LITERAL_SHIFT
7727 /*-----------------------------------------------------------------*/
7728 /* genlshTwo - left shift two bytes by known amount != 0 */
7729 /*-----------------------------------------------------------------*/
7731 genlshTwo (operand * result, operand * left, int shCount)
7735 D (emitcode (";", "genlshTwo "););
7737 size = getDataSize (result);
7739 /* if shCount >= 8 */
7744 _startLazyDPSEvaluation();
7750 _endLazyDPSEvaluation();
7751 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7752 aopPut (AOP (result), zero, LSB);
7756 movLeft2Result (left, LSB, result, MSB16, 0);
7757 aopPut (AOP (result), zero, LSB);
7758 _endLazyDPSEvaluation();
7763 aopPut (AOP (result), zero, LSB);
7764 _endLazyDPSEvaluation();
7768 /* 1 <= shCount <= 7 */
7773 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7777 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7785 /*-----------------------------------------------------------------*/
7786 /* shiftLLong - shift left one long from left to result */
7787 /* offl = LSB or MSB16 */
7788 /*-----------------------------------------------------------------*/
7790 shiftLLong (operand * left, operand * result, int offr)
7793 int size = AOP_SIZE (result);
7795 if (size >= LSB + offr)
7797 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7799 emitcode ("add", "a,acc");
7800 if (sameRegs (AOP (left), AOP (result)) &&
7801 size >= MSB16 + offr && offr != LSB)
7802 emitcode ("xch", "a,%s",
7803 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7805 aopPut (AOP (result), "a", LSB + offr);
7808 if (size >= MSB16 + offr)
7810 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7812 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7815 emitcode ("rlc", "a");
7816 if (sameRegs (AOP (left), AOP (result)) &&
7817 size >= MSB24 + offr && offr != LSB)
7818 emitcode ("xch", "a,%s",
7819 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7821 aopPut (AOP (result), "a", MSB16 + offr);
7824 if (size >= MSB24 + offr)
7826 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7828 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7831 emitcode ("rlc", "a");
7832 if (sameRegs (AOP (left), AOP (result)) &&
7833 size >= MSB32 + offr && offr != LSB)
7834 emitcode ("xch", "a,%s",
7835 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7837 aopPut (AOP (result), "a", MSB24 + offr);
7840 if (size > MSB32 + offr)
7842 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7844 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7847 emitcode ("rlc", "a");
7848 aopPut (AOP (result), "a", MSB32 + offr);
7851 aopPut (AOP (result), zero, LSB);
7857 /*-----------------------------------------------------------------*/
7858 /* genlshFour - shift four byte by a known amount != 0 */
7859 /*-----------------------------------------------------------------*/
7861 genlshFour (operand * result, operand * left, int shCount)
7865 D (emitcode (";", "genlshFour ");
7868 size = AOP_SIZE (result);
7870 /* if shifting more that 3 bytes */
7875 /* lowest order of left goes to the highest
7876 order of the destination */
7877 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7879 movLeft2Result (left, LSB, result, MSB32, 0);
7880 aopPut (AOP (result), zero, LSB);
7881 aopPut (AOP (result), zero, MSB16);
7882 aopPut (AOP (result), zero, MSB24);
7886 /* more than two bytes */
7887 else if (shCount >= 16)
7889 /* lower order two bytes goes to higher order two bytes */
7891 /* if some more remaining */
7893 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7896 movLeft2Result (left, MSB16, result, MSB32, 0);
7897 movLeft2Result (left, LSB, result, MSB24, 0);
7899 aopPut (AOP (result), zero, MSB16);
7900 aopPut (AOP (result), zero, LSB);
7904 /* if more than 1 byte */
7905 else if (shCount >= 8)
7907 /* lower order three bytes goes to higher order three bytes */
7912 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7914 movLeft2Result (left, LSB, result, MSB16, 0);
7920 movLeft2Result (left, MSB24, result, MSB32, 0);
7921 movLeft2Result (left, MSB16, result, MSB24, 0);
7922 movLeft2Result (left, LSB, result, MSB16, 0);
7923 aopPut (AOP (result), zero, LSB);
7925 else if (shCount == 1)
7926 shiftLLong (left, result, MSB16);
7929 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7930 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7931 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7932 aopPut (AOP (result), zero, LSB);
7937 /* 1 <= shCount <= 7 */
7938 else if (shCount <= 2)
7940 shiftLLong (left, result, LSB);
7942 shiftLLong (result, result, LSB);
7944 /* 3 <= shCount <= 7, optimize */
7947 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7948 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7949 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7954 #ifdef BETTER_LITERAL_SHIFT
7955 /*-----------------------------------------------------------------*/
7956 /* genLeftShiftLiteral - left shifting by known count */
7957 /*-----------------------------------------------------------------*/
7959 genLeftShiftLiteral (operand * left,
7964 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7967 size = getSize (operandType (result));
7969 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7971 /* We only handle certain easy cases so far. */
7973 && (shCount < (size * 8))
7977 D(emitcode (";", "genLeftShiftLiteral wimping out"););
7981 freeAsmop (right, NULL, ic, TRUE);
7983 aopOp(left, ic, FALSE, FALSE);
7984 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7987 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7989 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7990 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7992 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7995 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7997 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7998 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8000 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8006 emitcode ("; shift left ", "result %d, left %d", size,
8010 /* I suppose that the left size >= result size */
8013 _startLazyDPSEvaluation();
8016 movLeft2Result (left, size, result, size, 0);
8018 _endLazyDPSEvaluation();
8020 else if (shCount >= (size * 8))
8022 _startLazyDPSEvaluation();
8025 aopPut (AOP (result), zero, size);
8027 _endLazyDPSEvaluation();
8034 genlshOne (result, left, shCount);
8038 genlshTwo (result, left, shCount);
8042 genlshFour (result, left, shCount);
8046 fprintf(stderr, "*** ack! mystery literal shift!\n");
8050 freeAsmop (left, NULL, ic, TRUE);
8051 freeAsmop (result, NULL, ic, TRUE);
8056 /*-----------------------------------------------------------------*/
8057 /* genLeftShift - generates code for left shifting */
8058 /*-----------------------------------------------------------------*/
8060 genLeftShift (iCode * ic)
8062 operand *left, *right, *result;
8065 symbol *tlbl, *tlbl1;
8067 D (emitcode (";", "genLeftShift "););
8069 right = IC_RIGHT (ic);
8070 left = IC_LEFT (ic);
8071 result = IC_RESULT (ic);
8073 aopOp (right, ic, FALSE, FALSE);
8076 #ifdef BETTER_LITERAL_SHIFT
8077 /* if the shift count is known then do it
8078 as efficiently as possible */
8079 if (AOP_TYPE (right) == AOP_LIT)
8081 if (genLeftShiftLiteral (left, right, result, ic))
8088 /* shift count is unknown then we have to form
8089 a loop get the loop count in B : Note: we take
8090 only the lower order byte since shifting
8091 more that 32 bits make no sense anyway, ( the
8092 largest size of an object can be only 32 bits ) */
8094 if (AOP_TYPE (right) == AOP_LIT)
8096 /* Really should be handled by genLeftShiftLiteral,
8097 * but since I'm too lazy to fix that today, at least we can make
8098 * some small improvement.
8100 emitcode("mov", "b,#!constbyte",
8101 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8105 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8106 emitcode ("inc", "b");
8108 freeAsmop (right, NULL, ic, TRUE);
8109 aopOp (left, ic, FALSE, FALSE);
8110 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8112 /* now move the left to the result if they are not the
8114 if (!sameRegs (AOP (left), AOP (result)) &&
8115 AOP_SIZE (result) > 1)
8118 size = AOP_SIZE (result);
8120 _startLazyDPSEvaluation ();
8123 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8124 if (*l == '@' && (IS_AOP_PREG (result)))
8127 emitcode ("mov", "a,%s", l);
8128 aopPut (AOP (result), "a", offset);
8131 aopPut (AOP (result), l, offset);
8134 _endLazyDPSEvaluation ();
8137 tlbl = newiTempLabel (NULL);
8138 size = AOP_SIZE (result);
8140 tlbl1 = newiTempLabel (NULL);
8142 /* if it is only one byte then */
8145 symbol *tlbl1 = newiTempLabel (NULL);
8147 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8149 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8150 emitcode ("", "!tlabeldef", tlbl->key + 100);
8151 emitcode ("add", "a,acc");
8152 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8153 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8154 aopPut (AOP (result), "a", 0);
8158 reAdjustPreg (AOP (result));
8160 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8161 emitcode ("", "!tlabeldef", tlbl->key + 100);
8162 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8164 emitcode ("add", "a,acc");
8165 aopPut (AOP (result), "a", offset++);
8166 _startLazyDPSEvaluation ();
8169 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8171 emitcode ("rlc", "a");
8172 aopPut (AOP (result), "a", offset++);
8174 _endLazyDPSEvaluation ();
8175 reAdjustPreg (AOP (result));
8177 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8178 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8180 freeAsmop (left, NULL, ic, TRUE);
8181 freeAsmop (result, NULL, ic, TRUE);
8184 #ifdef BETTER_LITERAL_SHIFT
8185 /*-----------------------------------------------------------------*/
8186 /* genrshOne - right shift a one byte quantity by known count */
8187 /*-----------------------------------------------------------------*/
8189 genrshOne (operand * result, operand * left,
8190 int shCount, int sign)
8192 D (emitcode (";", "genrshOne"););
8193 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8197 #ifdef BETTER_LITERAL_SHIFT
8198 /*-----------------------------------------------------------------*/
8199 /* genrshTwo - right shift two bytes by known amount != 0 */
8200 /*-----------------------------------------------------------------*/
8202 genrshTwo (operand * result, operand * left,
8203 int shCount, int sign)
8205 D (emitcode (";", "genrshTwo"););
8207 /* if shCount >= 8 */
8211 _startLazyDPSEvaluation();
8214 shiftR1Left2Result (left, MSB16, result, LSB,
8219 movLeft2Result (left, MSB16, result, LSB, sign);
8221 addSign (result, MSB16, sign);
8222 _endLazyDPSEvaluation();
8225 /* 1 <= shCount <= 7 */
8228 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8235 /*-----------------------------------------------------------------*/
8236 /* shiftRLong - shift right one long from left to result */
8237 /* offl = LSB or MSB16 */
8238 /*-----------------------------------------------------------------*/
8240 shiftRLong (operand * left, int offl,
8241 operand * result, int sign)
8243 int isSameRegs=sameRegs(AOP(left),AOP(result));
8245 if (isSameRegs && offl>1) {
8246 // we are in big trouble, but this shouldn't happen
8247 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8250 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
8255 emitcode ("rlc", "a");
8256 emitcode ("subb", "a,acc");
8257 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
8259 aopPut (AOP(result), zero, MSB32);
8264 emitcode ("clr", "c");
8266 emitcode ("mov", "c,acc.7");
8269 emitcode ("rrc", "a");
8271 if (isSameRegs && offl==MSB16) {
8272 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
8274 aopPut (AOP (result), "a", MSB32);
8275 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
8278 emitcode ("rrc", "a");
8279 if (isSameRegs && offl==1) {
8280 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
8282 aopPut (AOP (result), "a", MSB24);
8283 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
8285 emitcode ("rrc", "a");
8286 aopPut (AOP (result), "a", MSB16 - offl);
8290 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
8291 emitcode ("rrc", "a");
8292 aopPut (AOP (result), "a", LSB);
8299 /*-----------------------------------------------------------------*/
8300 /* genrshFour - shift four byte by a known amount != 0 */
8301 /*-----------------------------------------------------------------*/
8303 genrshFour (operand * result, operand * left,
8304 int shCount, int sign)
8306 D (emitcode (";", "genrshFour");
8309 /* if shifting more that 3 bytes */
8314 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8316 movLeft2Result (left, MSB32, result, LSB, sign);
8317 addSign (result, MSB16, sign);
8319 else if (shCount >= 16)
8323 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8326 movLeft2Result (left, MSB24, result, LSB, 0);
8327 movLeft2Result (left, MSB32, result, MSB16, sign);
8329 addSign (result, MSB24, sign);
8331 else if (shCount >= 8)
8335 shiftRLong (left, MSB16, result, sign);
8336 else if (shCount == 0)
8338 movLeft2Result (left, MSB16, result, LSB, 0);
8339 movLeft2Result (left, MSB24, result, MSB16, 0);
8340 movLeft2Result (left, MSB32, result, MSB24, sign);
8341 addSign (result, MSB32, sign);
8345 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8346 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8347 /* the last shift is signed */
8348 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8349 addSign (result, MSB32, sign);
8353 { /* 1 <= shCount <= 7 */
8356 shiftRLong (left, LSB, result, sign);
8358 shiftRLong (result, LSB, result, sign);
8362 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8363 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8364 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8370 #ifdef BETTER_LITERAL_SHIFT
8371 /*-----------------------------------------------------------------*/
8372 /* genRightShiftLiteral - right shifting by known count */
8373 /*-----------------------------------------------------------------*/
8375 genRightShiftLiteral (operand * left,
8381 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8384 size = getSize (operandType (result));
8386 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8388 /* We only handle certain easy cases so far. */
8390 && (shCount < (size * 8))
8394 D(emitcode (";", "genRightShiftLiteral wimping out"););
8398 freeAsmop (right, NULL, ic, TRUE);
8400 aopOp (left, ic, FALSE, FALSE);
8401 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8404 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8408 /* test the LEFT size !!! */
8410 /* I suppose that the left size >= result size */
8413 size = getDataSize (result);
8414 _startLazyDPSEvaluation();
8417 movLeft2Result (left, size, result, size, 0);
8419 _endLazyDPSEvaluation();
8421 else if (shCount >= (size * 8))
8425 /* get sign in acc.7 */
8426 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8428 addSign (result, LSB, sign);
8435 genrshOne (result, left, shCount, sign);
8439 genrshTwo (result, left, shCount, sign);
8443 genrshFour (result, left, shCount, sign);
8450 freeAsmop (left, NULL, ic, TRUE);
8451 freeAsmop (result, NULL, ic, TRUE);
8457 /*-----------------------------------------------------------------*/
8458 /* genSignedRightShift - right shift of signed number */
8459 /*-----------------------------------------------------------------*/
8461 genSignedRightShift (iCode * ic)
8463 operand *right, *left, *result;
8466 symbol *tlbl, *tlbl1;
8468 D (emitcode (";", "genSignedRightShift "););
8470 /* we do it the hard way put the shift count in b
8471 and loop thru preserving the sign */
8473 right = IC_RIGHT (ic);
8474 left = IC_LEFT (ic);
8475 result = IC_RESULT (ic);
8477 aopOp (right, ic, FALSE, FALSE);
8479 #ifdef BETTER_LITERAL_SHIFT
8480 if (AOP_TYPE (right) == AOP_LIT)
8482 if (genRightShiftLiteral (left, right, result, ic, 1))
8488 /* shift count is unknown then we have to form
8489 a loop get the loop count in B : Note: we take
8490 only the lower order byte since shifting
8491 more that 32 bits make no sense anyway, ( the
8492 largest size of an object can be only 32 bits ) */
8494 if (AOP_TYPE (right) == AOP_LIT)
8496 /* Really should be handled by genRightShiftLiteral,
8497 * but since I'm too lazy to fix that today, at least we can make
8498 * some small improvement.
8500 emitcode("mov", "b,#!constbyte",
8501 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8505 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8506 emitcode ("inc", "b");
8508 freeAsmop (right, NULL, ic, TRUE);
8509 aopOp (left, ic, FALSE, FALSE);
8510 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8512 /* now move the left to the result if they are not the
8514 if (!sameRegs (AOP (left), AOP (result)) &&
8515 AOP_SIZE (result) > 1)
8518 size = AOP_SIZE (result);
8520 _startLazyDPSEvaluation ();
8523 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8524 if (*l == '@' && IS_AOP_PREG (result))
8527 emitcode ("mov", "a,%s", l);
8528 aopPut (AOP (result), "a", offset);
8531 aopPut (AOP (result), l, offset);
8534 _endLazyDPSEvaluation ();
8537 /* mov the highest order bit to OVR */
8538 tlbl = newiTempLabel (NULL);
8539 tlbl1 = newiTempLabel (NULL);
8541 size = AOP_SIZE (result);
8543 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8544 emitcode ("rlc", "a");
8545 emitcode ("mov", "ov,c");
8546 /* if it is only one byte then */
8549 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8551 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8552 emitcode ("", "!tlabeldef", tlbl->key + 100);
8553 emitcode ("mov", "c,ov");
8554 emitcode ("rrc", "a");
8555 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8556 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8557 aopPut (AOP (result), "a", 0);
8561 reAdjustPreg (AOP (result));
8562 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8563 emitcode ("", "!tlabeldef", tlbl->key + 100);
8564 emitcode ("mov", "c,ov");
8565 _startLazyDPSEvaluation ();
8568 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8570 emitcode ("rrc", "a");
8571 aopPut (AOP (result), "a", offset--);
8573 _endLazyDPSEvaluation ();
8574 reAdjustPreg (AOP (result));
8575 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8576 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8579 freeAsmop (left, NULL, ic, TRUE);
8580 freeAsmop (result, NULL, ic, TRUE);
8583 /*-----------------------------------------------------------------*/
8584 /* genRightShift - generate code for right shifting */
8585 /*-----------------------------------------------------------------*/
8587 genRightShift (iCode * ic)
8589 operand *right, *left, *result;
8593 symbol *tlbl, *tlbl1;
8595 D (emitcode (";", "genRightShift "););
8597 /* if signed then we do it the hard way preserve the
8598 sign bit moving it inwards */
8599 retype = getSpec (operandType (IC_RESULT (ic)));
8601 if (!SPEC_USIGN (retype))
8603 genSignedRightShift (ic);
8607 /* signed & unsigned types are treated the same : i.e. the
8608 signed is NOT propagated inwards : quoting from the
8609 ANSI - standard : "for E1 >> E2, is equivalent to division
8610 by 2**E2 if unsigned or if it has a non-negative value,
8611 otherwise the result is implementation defined ", MY definition
8612 is that the sign does not get propagated */
8614 right = IC_RIGHT (ic);
8615 left = IC_LEFT (ic);
8616 result = IC_RESULT (ic);
8618 aopOp (right, ic, FALSE, FALSE);
8620 #ifdef BETTER_LITERAL_SHIFT
8621 /* if the shift count is known then do it
8622 as efficiently as possible */
8623 if (AOP_TYPE (right) == AOP_LIT)
8625 if (genRightShiftLiteral (left, right, result, ic, 0))
8632 /* shift count is unknown then we have to form
8633 a loop get the loop count in B : Note: we take
8634 only the lower order byte since shifting
8635 more that 32 bits make no sense anyway, ( the
8636 largest size of an object can be only 32 bits ) */
8638 if (AOP_TYPE (right) == AOP_LIT)
8640 /* Really should be handled by genRightShiftLiteral,
8641 * but since I'm too lazy to fix that today, at least we can make
8642 * some small improvement.
8644 emitcode("mov", "b,#!constbyte",
8645 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8649 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8650 emitcode ("inc", "b");
8652 freeAsmop (right, NULL, ic, TRUE);
8653 aopOp (left, ic, FALSE, FALSE);
8654 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8656 /* now move the left to the result if they are not the
8658 if (!sameRegs (AOP (left), AOP (result)) &&
8659 AOP_SIZE (result) > 1)
8662 size = AOP_SIZE (result);
8664 _startLazyDPSEvaluation ();
8667 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8668 if (*l == '@' && IS_AOP_PREG (result))
8671 emitcode ("mov", "a,%s", l);
8672 aopPut (AOP (result), "a", offset);
8675 aopPut (AOP (result), l, offset);
8678 _endLazyDPSEvaluation ();
8681 tlbl = newiTempLabel (NULL);
8682 tlbl1 = newiTempLabel (NULL);
8683 size = AOP_SIZE (result);
8686 /* if it is only one byte then */
8689 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8691 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8692 emitcode ("", "!tlabeldef", tlbl->key + 100);
8694 emitcode ("rrc", "a");
8695 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8696 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8697 aopPut (AOP (result), "a", 0);
8701 reAdjustPreg (AOP (result));
8702 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8703 emitcode ("", "!tlabeldef", tlbl->key + 100);
8705 _startLazyDPSEvaluation ();
8708 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8710 emitcode ("rrc", "a");
8711 aopPut (AOP (result), "a", offset--);
8713 _endLazyDPSEvaluation ();
8714 reAdjustPreg (AOP (result));
8716 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8717 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8720 freeAsmop (left, NULL, ic, TRUE);
8721 freeAsmop (result, NULL, ic, TRUE);
8724 /*-----------------------------------------------------------------*/
8725 /* genUnpackBits - generates code for unpacking bits */
8726 /*-----------------------------------------------------------------*/
8728 genUnpackBits (operand * result, char *rname, int ptype)
8735 D (emitcode (";", "genUnpackBits ");
8738 etype = getSpec (operandType (result));
8740 /* read the first byte */
8746 emitcode ("mov", "a,@%s", rname);
8750 emitcode ("movx", "a,@%s", rname);
8754 emitcode ("movx", "a,@dptr");
8758 emitcode ("clr", "a");
8759 emitcode ("movc", "a,@a+dptr");
8763 emitcode ("lcall", "__gptrget");
8767 /* if we have bitdisplacement then it fits */
8768 /* into this byte completely or if length is */
8769 /* less than a byte */
8770 if ((shCnt = SPEC_BSTR (etype)) ||
8771 (SPEC_BLEN (etype) <= 8))
8774 /* shift right acc */
8777 emitcode ("anl", "a,#!constbyte",
8778 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8779 aopPut (AOP (result), "a", offset);
8783 /* bit field did not fit in a byte */
8784 rlen = SPEC_BLEN (etype) - 8;
8785 aopPut (AOP (result), "a", offset++);
8794 emitcode ("inc", "%s", rname);
8795 emitcode ("mov", "a,@%s", rname);
8799 emitcode ("inc", "%s", rname);
8800 emitcode ("movx", "a,@%s", rname);
8804 emitcode ("inc", "dptr");
8805 emitcode ("movx", "a,@dptr");
8809 emitcode ("clr", "a");
8810 emitcode ("inc", "dptr");
8811 emitcode ("movc", "a,@a+dptr");
8815 emitcode ("inc", "dptr");
8816 emitcode ("lcall", "__gptrget");
8821 /* if we are done */
8825 aopPut (AOP (result), "a", offset++);
8831 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (rlen));
8832 aopPut (AOP (result), "a", offset);
8839 /*-----------------------------------------------------------------*/
8840 /* genDataPointerGet - generates code when ptr offset is known */
8841 /*-----------------------------------------------------------------*/
8843 genDataPointerGet (operand * left,
8849 int size, offset = 0;
8850 aopOp (result, ic, TRUE, FALSE);
8852 /* get the string representation of the name */
8853 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8854 size = AOP_SIZE (result);
8855 _startLazyDPSEvaluation ();
8859 sprintf (buffer, "(%s + %d)", l + 1, offset);
8861 sprintf (buffer, "%s", l + 1);
8862 aopPut (AOP (result), buffer, offset++);
8864 _endLazyDPSEvaluation ();
8866 freeAsmop (left, NULL, ic, TRUE);
8867 freeAsmop (result, NULL, ic, TRUE);
8870 /*-----------------------------------------------------------------*/
8871 /* genNearPointerGet - emitcode for near pointer fetch */
8872 /*-----------------------------------------------------------------*/
8874 genNearPointerGet (operand * left,
8882 sym_link *rtype, *retype, *letype;
8883 sym_link *ltype = operandType (left);
8886 rtype = operandType (result);
8887 retype = getSpec (rtype);
8888 letype = getSpec (ltype);
8890 aopOp (left, ic, FALSE, FALSE);
8892 /* if left is rematerialisable and
8893 result is not bit variable type and
8894 the left is pointer to data space i.e
8895 lower 128 bytes of space */
8896 if (AOP_TYPE (left) == AOP_IMMD &&
8897 !IS_BITVAR (retype) &&
8898 !IS_BITVAR (letype) &&
8899 DCL_TYPE (ltype) == POINTER)
8901 genDataPointerGet (left, result, ic);
8905 /* if the value is already in a pointer register
8906 then don't need anything more */
8907 if (!AOP_INPREG (AOP (left)))
8909 /* otherwise get a free pointer register */
8911 preg = getFreePtr (ic, &aop, FALSE);
8912 emitcode ("mov", "%s,%s",
8914 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8918 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8920 freeAsmop (left, NULL, ic, TRUE);
8921 aopOp (result, ic, FALSE, FALSE);
8923 /* if bitfield then unpack the bits */
8924 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8925 genUnpackBits (result, rname, POINTER);
8928 /* we have can just get the values */
8929 int size = AOP_SIZE (result);
8934 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8937 emitcode ("mov", "a,@%s", rname);
8938 aopPut (AOP (result), "a", offset);
8942 sprintf (buffer, "@%s", rname);
8943 aopPut (AOP (result), buffer, offset);
8947 emitcode ("inc", "%s", rname);
8951 /* now some housekeeping stuff */
8954 /* we had to allocate for this iCode */
8955 if (pi) { /* post increment present */
8956 aopPut(AOP ( left ),rname,0);
8958 freeAsmop (NULL, aop, ic, TRUE);
8962 /* we did not allocate which means left
8963 already in a pointer register, then
8964 if size > 0 && this could be used again
8965 we have to point it back to where it
8967 if (AOP_SIZE (result) > 1 &&
8968 !OP_SYMBOL (left)->remat &&
8969 (OP_SYMBOL (left)->liveTo > ic->seq ||
8973 int size = AOP_SIZE (result) - 1;
8975 emitcode ("dec", "%s", rname);
8980 freeAsmop (result, NULL, ic, TRUE);
8981 if (pi) pi->generated = 1;
8984 /*-----------------------------------------------------------------*/
8985 /* genPagedPointerGet - emitcode for paged pointer fetch */
8986 /*-----------------------------------------------------------------*/
8988 genPagedPointerGet (operand * left,
8996 sym_link *rtype, *retype, *letype;
8998 rtype = operandType (result);
8999 retype = getSpec (rtype);
9000 letype = getSpec (operandType (left));
9001 aopOp (left, ic, FALSE, FALSE);
9003 /* if the value is already in a pointer register
9004 then don't need anything more */
9005 if (!AOP_INPREG (AOP (left)))
9007 /* otherwise get a free pointer register */
9009 preg = getFreePtr (ic, &aop, FALSE);
9010 emitcode ("mov", "%s,%s",
9012 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
9016 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
9018 freeAsmop (left, NULL, ic, TRUE);
9019 aopOp (result, ic, FALSE, FALSE);
9021 /* if bitfield then unpack the bits */
9022 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9023 genUnpackBits (result, rname, PPOINTER);
9026 /* we have can just get the values */
9027 int size = AOP_SIZE (result);
9033 emitcode ("movx", "a,@%s", rname);
9034 aopPut (AOP (result), "a", offset);
9039 emitcode ("inc", "%s", rname);
9043 /* now some housekeeping stuff */
9046 /* we had to allocate for this iCode */
9047 if (pi) aopPut ( AOP (left), rname, 0);
9048 freeAsmop (NULL, aop, ic, TRUE);
9052 /* we did not allocate which means left
9053 already in a pointer register, then
9054 if size > 0 && this could be used again
9055 we have to point it back to where it
9057 if (AOP_SIZE (result) > 1 &&
9058 !OP_SYMBOL (left)->remat &&
9059 (OP_SYMBOL (left)->liveTo > ic->seq ||
9063 int size = AOP_SIZE (result) - 1;
9065 emitcode ("dec", "%s", rname);
9070 freeAsmop (result, NULL, ic, TRUE);
9071 if (pi) pi->generated = 1;
9074 /*-----------------------------------------------------------------*/
9075 /* genFarPointerGet - gget value from far space */
9076 /*-----------------------------------------------------------------*/
9078 genFarPointerGet (operand * left,
9079 operand * result, iCode * ic, iCode *pi)
9081 int size, offset, dopi=1;
9082 sym_link *retype = getSpec (operandType (result));
9083 sym_link *letype = getSpec (operandType (left));
9084 D (emitcode (";", "genFarPointerGet");
9087 aopOp (left, ic, FALSE, FALSE);
9089 /* if the operand is already in dptr
9090 then we do nothing else we move the value to dptr */
9091 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9093 /* if this is remateriazable */
9094 if (AOP_TYPE (left) == AOP_IMMD)
9096 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9100 /* we need to get it byte by byte */
9101 _startLazyDPSEvaluation ();
9102 if (AOP_TYPE (left) != AOP_DPTR)
9104 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9105 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9106 if (options.model == MODEL_FLAT24)
9107 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9111 /* We need to generate a load to DPTR indirect through DPTR. */
9112 D (emitcode (";", "genFarPointerGet -- indirection special case.");
9114 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9115 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9116 if (options.model == MODEL_FLAT24)
9117 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9118 emitcode ("pop", "dph");
9119 emitcode ("pop", "dpl");
9122 _endLazyDPSEvaluation ();
9125 /* so dptr know contains the address */
9126 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9128 /* if bit then unpack */
9129 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9130 if (AOP_INDPTRn(left)) {
9131 genSetDPTR(AOP(left)->aopu.dptr);
9133 genUnpackBits (result, "dptr", FPOINTER);
9134 if (AOP_INDPTRn(left)) {
9139 size = AOP_SIZE (result);
9142 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9144 genSetDPTR(AOP(left)->aopu.dptr);
9145 emitcode ("movx", "a,@dptr");
9146 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9147 emitcode ("inc", "dptr");
9149 aopPut (AOP (result), "a", offset++);
9152 _startLazyDPSEvaluation ();
9154 if (AOP_INDPTRn(left)) {
9155 genSetDPTR(AOP(left)->aopu.dptr);
9161 emitcode ("movx", "a,@dptr");
9162 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9163 emitcode ("inc", "dptr");
9165 aopPut (AOP (result), "a", offset++);
9167 _endLazyDPSEvaluation ();
9170 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9171 if (!AOP_INDPTRn(left)) {
9172 aopPut ( AOP (left), "dpl", 0);
9173 aopPut ( AOP (left), "dph", 1);
9174 if (options.model == MODEL_FLAT24)
9175 aopPut ( AOP (left), "dpx", 2);
9178 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
9179 AOP_SIZE(result) > 1 &&
9180 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9182 size = AOP_SIZE (result) - 1;
9183 if (AOP_INDPTRn(left)) {
9184 genSetDPTR(AOP(left)->aopu.dptr);
9186 while (size--) emitcode ("lcall","__decdptr");
9187 if (AOP_INDPTRn(left)) {
9192 freeAsmop (left, NULL, ic, TRUE);
9193 freeAsmop (result, NULL, ic, TRUE);
9196 /*-----------------------------------------------------------------*/
9197 /* emitcodePointerGet - gget value from code space */
9198 /*-----------------------------------------------------------------*/
9200 emitcodePointerGet (operand * left,
9201 operand * result, iCode * ic, iCode *pi)
9203 int size, offset, dopi=1;
9204 sym_link *retype = getSpec (operandType (result));
9206 aopOp (left, ic, FALSE, FALSE);
9208 /* if the operand is already in dptr
9209 then we do nothing else we move the value to dptr */
9210 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9212 /* if this is remateriazable */
9213 if (AOP_TYPE (left) == AOP_IMMD)
9215 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9218 { /* we need to get it byte by byte */
9219 _startLazyDPSEvaluation ();
9220 if (AOP_TYPE (left) != AOP_DPTR)
9222 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9223 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9224 if (options.model == MODEL_FLAT24)
9225 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9229 /* We need to generate a load to DPTR indirect through DPTR. */
9230 D (emitcode (";", "gencodePointerGet -- indirection special case.");
9232 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9233 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9234 if (options.model == MODEL_FLAT24)
9235 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9236 emitcode ("pop", "dph");
9237 emitcode ("pop", "dpl");
9240 _endLazyDPSEvaluation ();
9243 /* so dptr know contains the address */
9244 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9246 /* if bit then unpack */
9247 if (IS_BITVAR (retype)) {
9248 if (AOP_INDPTRn(left)) {
9249 genSetDPTR(AOP(left)->aopu.dptr);
9251 genUnpackBits (result, "dptr", CPOINTER);
9252 if (AOP_INDPTRn(left)) {
9257 size = AOP_SIZE (result);
9259 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9261 genSetDPTR(AOP(left)->aopu.dptr);
9262 emitcode ("clr", "a");
9263 emitcode ("movc", "a,@a+dptr");
9264 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9265 emitcode ("inc", "dptr");
9267 aopPut (AOP (result), "a", offset++);
9270 _startLazyDPSEvaluation ();
9273 if (AOP_INDPTRn(left)) {
9274 genSetDPTR(AOP(left)->aopu.dptr);
9280 emitcode ("clr", "a");
9281 emitcode ("movc", "a,@a+dptr");
9282 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9283 emitcode ("inc", "dptr");
9284 aopPut (AOP (result), "a", offset++);
9286 _endLazyDPSEvaluation ();
9289 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9290 if (!AOP_INDPTRn(left)) {
9291 aopPut ( AOP (left), "dpl", 0);
9292 aopPut ( AOP (left), "dph", 1);
9293 if (options.model == MODEL_FLAT24)
9294 aopPut ( AOP (left), "dpx", 2);
9297 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
9298 AOP_SIZE(result) > 1 &&
9299 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9301 size = AOP_SIZE (result) - 1;
9302 if (AOP_INDPTRn(left)) {
9303 genSetDPTR(AOP(left)->aopu.dptr);
9305 while (size--) emitcode ("lcall","__decdptr");
9306 if (AOP_INDPTRn(left)) {
9311 freeAsmop (left, NULL, ic, TRUE);
9312 freeAsmop (result, NULL, ic, TRUE);
9315 /*-----------------------------------------------------------------*/
9316 /* genGenPointerGet - gget value from generic pointer space */
9317 /*-----------------------------------------------------------------*/
9319 genGenPointerGet (operand * left,
9320 operand * result, iCode * ic, iCode * pi)
9323 sym_link *retype = getSpec (operandType (result));
9324 sym_link *letype = getSpec (operandType (left));
9326 D (emitcode (";", "genGenPointerGet "); );
9328 aopOp (left, ic, FALSE, (OP_SYMBOL(left)->ruonly ? FALSE : TRUE));
9330 /* if the operand is already in dptr
9331 then we do nothing else we move the value to dptr */
9332 if (AOP_TYPE (left) != AOP_STR)
9334 /* if this is remateriazable */
9335 if (AOP_TYPE (left) == AOP_IMMD)
9337 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9338 if (AOP(left)->aopu.aop_immd.from_cast_remat)
9339 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, FALSE));
9341 emitcode ("mov", "b,#%d", pointerCode (retype));
9344 { /* we need to get it byte by byte */
9345 _startLazyDPSEvaluation ();
9346 if (AOP(left)->type==AOP_DPTR2) {
9348 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
9351 emitcode ("mov", "dpl,%s", l);
9352 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
9355 emitcode ("mov", "dph,%s", l);
9356 if (options.model == MODEL_FLAT24) {
9357 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
9360 emitcode ("mov", "dpx,%s", l);
9361 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9363 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9366 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
9367 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
9368 if (options.model == MODEL_FLAT24) {
9369 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9370 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9372 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9375 _endLazyDPSEvaluation ();
9378 /* so dptr know contains the address */
9379 aopOp (result, ic, FALSE, TRUE);
9381 /* if bit then unpack */
9382 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9383 genUnpackBits (result, "dptr", GPOINTER);
9386 size = AOP_SIZE (result);
9391 emitcode ("lcall", "__gptrget");
9392 aopPut (AOP (result), "a", offset++);
9393 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9394 emitcode ("inc", "dptr");
9398 if (pi && AOP_TYPE (left) != AOP_IMMD) {
9399 aopPut ( AOP (left), "dpl", 0);
9400 aopPut ( AOP (left), "dph", 1);
9401 if (options.model == MODEL_FLAT24) {
9402 aopPut ( AOP (left), "dpx", 2);
9403 aopPut ( AOP (left), "b", 3);
9404 } else aopPut ( AOP (left), "b", 2);
9406 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9407 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9409 size = AOP_SIZE (result) - 1;
9410 while (size--) emitcode ("lcall","__decdptr");
9413 freeAsmop (left, NULL, ic, TRUE);
9414 freeAsmop (result, NULL, ic, TRUE);
9417 /*-----------------------------------------------------------------*/
9418 /* genPointerGet - generate code for pointer get */
9419 /*-----------------------------------------------------------------*/
9421 genPointerGet (iCode * ic, iCode *pi)
9423 operand *left, *result;
9424 sym_link *type, *etype;
9427 D (emitcode (";", "genPointerGet ");
9430 left = IC_LEFT (ic);
9431 result = IC_RESULT (ic);
9433 /* depending on the type of pointer we need to
9434 move it to the correct pointer register */
9435 type = operandType (left);
9436 etype = getSpec (type);
9437 /* if left is of type of pointer then it is simple */
9438 if (IS_PTR (type) && !IS_FUNC (type->next))
9439 p_type = DCL_TYPE (type);
9442 /* we have to go by the storage class */
9443 p_type = PTR_TYPE (SPEC_OCLS (etype));
9445 /* special case when cast remat */
9446 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9447 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9448 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9449 type = type = operandType (left);
9450 p_type = DCL_TYPE (type);
9452 /* now that we have the pointer type we assign
9453 the pointer values */
9459 genNearPointerGet (left, result, ic, pi);
9463 genPagedPointerGet (left, result, ic, pi);
9467 genFarPointerGet (left, result, ic, pi);
9471 emitcodePointerGet (left, result, ic, pi);
9475 genGenPointerGet (left, result, ic, pi);
9481 /*-----------------------------------------------------------------*/
9482 /* genPackBits - generates code for packed bit storage */
9483 /*-----------------------------------------------------------------*/
9485 genPackBits (sym_link * etype,
9487 char *rname, int p_type)
9495 blen = SPEC_BLEN (etype);
9496 bstr = SPEC_BSTR (etype);
9498 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9501 /* if the bit lenth is less than or */
9502 /* it exactly fits a byte then */
9503 if (SPEC_BLEN (etype) <= 8)
9505 shCount = SPEC_BSTR (etype);
9507 /* shift left acc */
9510 if (SPEC_BLEN (etype) < 8)
9511 { /* if smaller than a byte */
9517 emitcode ("mov", "b,a");
9518 emitcode ("mov", "a,@%s", rname);
9522 emitcode ("mov", "b,a");
9523 emitcode ("movx", "a,@dptr");
9527 emitcode ("push", "b");
9528 emitcode ("push", "acc");
9529 emitcode ("lcall", "__gptrget");
9530 emitcode ("pop", "b");
9534 emitcode ("anl", "a,#!constbyte", (unsigned char)
9535 ((unsigned char) (0xFF << (blen + bstr)) |
9536 (unsigned char) (0xFF >> (8 - bstr))));
9537 emitcode ("orl", "a,b");
9538 if (p_type == GPOINTER)
9539 emitcode ("pop", "b");
9546 emitcode ("mov", "@%s,a", rname);
9550 emitcode ("movx", "@dptr,a");
9554 emitcode ("lcall", "__gptrput");
9559 if (SPEC_BLEN (etype) <= 8)
9562 emitcode ("inc", "%s", rname);
9563 rLen = SPEC_BLEN (etype);
9565 /* now generate for lengths greater than one byte */
9569 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9581 emitcode ("mov", "@%s,a", rname);
9584 emitcode ("mov", "@%s,%s", rname, l);
9589 emitcode ("movx", "@dptr,a");
9594 emitcode ("lcall", "__gptrput");
9597 emitcode ("inc", "%s", rname);
9602 /* last last was not complete */
9605 /* save the byte & read byte */
9609 emitcode ("mov", "b,a");
9610 emitcode ("mov", "a,@%s", rname);
9614 emitcode ("mov", "b,a");
9615 emitcode ("movx", "a,@dptr");
9619 emitcode ("push", "b");
9620 emitcode ("push", "acc");
9621 emitcode ("lcall", "__gptrget");
9622 emitcode ("pop", "b");
9626 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1 << rLen));
9627 emitcode ("orl", "a,b");
9630 if (p_type == GPOINTER)
9631 emitcode ("pop", "b");
9637 emitcode ("mov", "@%s,a", rname);
9641 emitcode ("movx", "@dptr,a");
9645 emitcode ("lcall", "__gptrput");
9649 /*-----------------------------------------------------------------*/
9650 /* genDataPointerSet - remat pointer to data space */
9651 /*-----------------------------------------------------------------*/
9653 genDataPointerSet (operand * right,
9657 int size, offset = 0;
9658 char *l, buffer[256];
9660 aopOp (right, ic, FALSE, FALSE);
9662 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9663 size = AOP_SIZE (right);
9667 sprintf (buffer, "(%s + %d)", l + 1, offset);
9669 sprintf (buffer, "%s", l + 1);
9670 emitcode ("mov", "%s,%s", buffer,
9671 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9674 freeAsmop (right, NULL, ic, TRUE);
9675 freeAsmop (result, NULL, ic, TRUE);
9678 /*-----------------------------------------------------------------*/
9679 /* genNearPointerSet - emitcode for near pointer put */
9680 /*-----------------------------------------------------------------*/
9682 genNearPointerSet (operand * right,
9690 sym_link *retype, *letype;
9691 sym_link *ptype = operandType (result);
9693 retype = getSpec (operandType (right));
9694 letype = getSpec (ptype);
9696 aopOp (result, ic, FALSE, FALSE);
9698 /* if the result is rematerializable &
9699 in data space & not a bit variable */
9700 if (AOP_TYPE (result) == AOP_IMMD &&
9701 DCL_TYPE (ptype) == POINTER &&
9702 !IS_BITVAR (retype) &&
9703 !IS_BITVAR (letype))
9705 genDataPointerSet (right, result, ic);
9709 /* if the value is already in a pointer register
9710 then don't need anything more */
9711 if (!AOP_INPREG (AOP (result)))
9713 /* otherwise get a free pointer register */
9715 preg = getFreePtr (ic, &aop, FALSE);
9716 emitcode ("mov", "%s,%s",
9718 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9722 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9724 aopOp (right, ic, FALSE, FALSE);
9726 /* if bitfield then unpack the bits */
9727 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9728 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9731 /* we have can just get the values */
9732 int size = AOP_SIZE (right);
9737 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
9741 emitcode ("mov", "@%s,a", rname);
9744 emitcode ("mov", "@%s,%s", rname, l);
9746 emitcode ("inc", "%s", rname);
9751 /* now some housekeeping stuff */
9754 /* we had to allocate for this iCode */
9755 if (pi) aopPut (AOP (result),rname,0);
9756 freeAsmop (NULL, aop, ic, TRUE);
9760 /* we did not allocate which means left
9761 already in a pointer register, then
9762 if size > 0 && this could be used again
9763 we have to point it back to where it
9765 if (AOP_SIZE (right) > 1 &&
9766 !OP_SYMBOL (result)->remat &&
9767 (OP_SYMBOL (result)->liveTo > ic->seq ||
9771 int size = AOP_SIZE (right) - 1;
9773 emitcode ("dec", "%s", rname);
9778 if (pi) pi->generated = 1;
9779 freeAsmop (result, NULL, ic, TRUE);
9780 freeAsmop (right, NULL, ic, TRUE);
9785 /*-----------------------------------------------------------------*/
9786 /* genPagedPointerSet - emitcode for Paged pointer put */
9787 /*-----------------------------------------------------------------*/
9789 genPagedPointerSet (operand * right,
9797 sym_link *retype, *letype;
9799 retype = getSpec (operandType (right));
9800 letype = getSpec (operandType (result));
9802 aopOp (result, ic, FALSE, FALSE);
9804 /* if the value is already in a pointer register
9805 then don't need anything more */
9806 if (!AOP_INPREG (AOP (result)))
9808 /* otherwise get a free pointer register */
9810 preg = getFreePtr (ic, &aop, FALSE);
9811 emitcode ("mov", "%s,%s",
9813 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9817 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9819 aopOp (right, ic, FALSE, FALSE);
9821 /* if bitfield then unpack the bits */
9822 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9823 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
9826 /* we have can just get the values */
9827 int size = AOP_SIZE (right);
9832 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
9835 emitcode ("movx", "@%s,a", rname);
9838 emitcode ("inc", "%s", rname);
9844 /* now some housekeeping stuff */
9847 if (pi) aopPut (AOP (result),rname,0);
9848 /* we had to allocate for this iCode */
9849 freeAsmop (NULL, aop, ic, TRUE);
9853 /* we did not allocate which means left
9854 already in a pointer register, then
9855 if size > 0 && this could be used again
9856 we have to point it back to where it
9858 if (AOP_SIZE (right) > 1 &&
9859 !OP_SYMBOL (result)->remat &&
9860 (OP_SYMBOL (result)->liveTo > ic->seq ||
9864 int size = AOP_SIZE (right) - 1;
9866 emitcode ("dec", "%s", rname);
9871 if (pi) pi->generated = 1;
9872 freeAsmop (result, NULL, ic, TRUE);
9873 freeAsmop (right, NULL, ic, TRUE);
9878 /*-----------------------------------------------------------------*/
9879 /* genFarPointerSet - set value from far space */
9880 /*-----------------------------------------------------------------*/
9882 genFarPointerSet (operand * right,
9883 operand * result, iCode * ic, iCode *pi)
9885 int size, offset, dopi=1;
9886 sym_link *retype = getSpec (operandType (right));
9887 sym_link *letype = getSpec (operandType (result));
9889 aopOp (result, ic, FALSE, FALSE);
9891 /* if the operand is already in dptr
9892 then we do nothing else we move the value to dptr */
9893 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
9895 /* if this is remateriazable */
9896 if (AOP_TYPE (result) == AOP_IMMD)
9897 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9900 /* we need to get it byte by byte */
9901 _startLazyDPSEvaluation ();
9902 if (AOP_TYPE (result) != AOP_DPTR)
9904 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9905 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9906 if (options.model == MODEL_FLAT24)
9907 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9911 /* We need to generate a load to DPTR indirect through DPTR. */
9912 D (emitcode (";", "genFarPointerSet -- indirection special case.");
9914 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9915 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9916 if (options.model == MODEL_FLAT24)
9917 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9918 emitcode ("pop", "dph");
9919 emitcode ("pop", "dpl");
9922 _endLazyDPSEvaluation ();
9925 /* so dptr know contains the address */
9926 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
9928 /* if bit then unpack */
9929 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9930 if (AOP_INDPTRn(result)) {
9931 genSetDPTR(AOP(result)->aopu.dptr);
9933 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9934 if (AOP_INDPTRn(result)) {
9938 size = AOP_SIZE (right);
9940 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
9942 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9945 genSetDPTR(AOP(result)->aopu.dptr);
9946 emitcode ("movx", "@dptr,a");
9947 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
9948 emitcode ("inc", "dptr");
9952 _startLazyDPSEvaluation ();
9954 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9957 if (AOP_INDPTRn(result)) {
9958 genSetDPTR(AOP(result)->aopu.dptr);
9964 emitcode ("movx", "@dptr,a");
9965 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
9966 emitcode ("inc", "dptr");
9968 _endLazyDPSEvaluation ();
9972 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
9973 if (!AOP_INDPTRn(result)) {
9974 aopPut (AOP(result),"dpl",0);
9975 aopPut (AOP(result),"dph",1);
9976 if (options.model == MODEL_FLAT24)
9977 aopPut (AOP(result),"dpx",2);
9980 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
9981 AOP_SIZE(right) > 1 &&
9982 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9984 size = AOP_SIZE (right) - 1;
9985 if (AOP_INDPTRn(result)) {
9986 genSetDPTR(AOP(result)->aopu.dptr);
9988 while (size--) emitcode ("lcall","__decdptr");
9989 if (AOP_INDPTRn(result)) {
9993 freeAsmop (result, NULL, ic, TRUE);
9994 freeAsmop (right, NULL, ic, TRUE);
9997 /*-----------------------------------------------------------------*/
9998 /* genGenPointerSet - set value from generic pointer space */
9999 /*-----------------------------------------------------------------*/
10001 genGenPointerSet (operand * right,
10002 operand * result, iCode * ic, iCode *pi)
10005 sym_link *retype = getSpec (operandType (right));
10006 sym_link *letype = getSpec (operandType (result));
10008 aopOp (result, ic, FALSE, OP_SYMBOL(result)->ruonly ? FALSE : TRUE);
10010 /* if the operand is already in dptr
10011 then we do nothing else we move the value to dptr */
10012 if (AOP_TYPE (result) != AOP_STR)
10014 _startLazyDPSEvaluation ();
10015 /* if this is remateriazable */
10016 if (AOP_TYPE (result) == AOP_IMMD)
10018 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
10019 if (AOP(result)->aopu.aop_immd.from_cast_remat)
10020 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, FALSE));
10022 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
10025 { /* we need to get it byte by byte */
10026 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
10027 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
10028 if (options.model == MODEL_FLAT24) {
10029 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
10030 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
10032 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
10035 _endLazyDPSEvaluation ();
10037 /* so dptr know contains the address */
10038 aopOp (right, ic, FALSE, TRUE);
10040 /* if bit then unpack */
10041 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10042 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10045 size = AOP_SIZE (right);
10048 _startLazyDPSEvaluation ();
10051 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
10057 emitcode ("lcall", "__gptrput");
10058 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10059 emitcode ("inc", "dptr");
10061 _endLazyDPSEvaluation ();
10064 if (pi && AOP_TYPE (result) != AOP_IMMD) {
10065 aopPut (AOP(result),"dpl",0);
10066 aopPut (AOP(result),"dph",1);
10067 if (options.model == MODEL_FLAT24) {
10068 aopPut (AOP(result),"dpx",2);
10069 aopPut (AOP(result),"b",3);
10071 aopPut (AOP(result),"b",2);
10074 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10075 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10077 size = AOP_SIZE (right) - 1;
10078 while (size--) emitcode ("lcall","__decdptr");
10080 freeAsmop (result, NULL, ic, TRUE);
10081 freeAsmop (right, NULL, ic, TRUE);
10084 /*-----------------------------------------------------------------*/
10085 /* genPointerSet - stores the value into a pointer location */
10086 /*-----------------------------------------------------------------*/
10088 genPointerSet (iCode * ic, iCode *pi)
10090 operand *right, *result;
10091 sym_link *type, *etype;
10094 D (emitcode (";", "genPointerSet ");
10097 right = IC_RIGHT (ic);
10098 result = IC_RESULT (ic);
10100 /* depending on the type of pointer we need to
10101 move it to the correct pointer register */
10102 type = operandType (result);
10103 etype = getSpec (type);
10104 /* if left is of type of pointer then it is simple */
10105 if (IS_PTR (type) && !IS_FUNC (type->next))
10107 p_type = DCL_TYPE (type);
10111 /* we have to go by the storage class */
10112 p_type = PTR_TYPE (SPEC_OCLS (etype));
10114 /* special case when cast remat */
10115 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10116 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10117 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10118 type = type = operandType (result);
10119 p_type = DCL_TYPE (type);
10122 /* now that we have the pointer type we assign
10123 the pointer values */
10129 genNearPointerSet (right, result, ic, pi);
10133 genPagedPointerSet (right, result, ic, pi);
10137 genFarPointerSet (right, result, ic, pi);
10141 genGenPointerSet (right, result, ic, pi);
10147 /*-----------------------------------------------------------------*/
10148 /* genIfx - generate code for Ifx statement */
10149 /*-----------------------------------------------------------------*/
10151 genIfx (iCode * ic, iCode * popIc)
10153 operand *cond = IC_COND (ic);
10156 D (emitcode (";", "genIfx "););
10158 aopOp (cond, ic, FALSE, FALSE);
10160 /* get the value into acc */
10161 if (AOP_TYPE (cond) != AOP_CRY)
10165 /* the result is now in the accumulator */
10166 freeAsmop (cond, NULL, ic, TRUE);
10168 /* if there was something to be popped then do it */
10172 /* if the condition is a bit variable */
10173 if (isbit && IS_ITEMP (cond) &&
10175 genIfxJump (ic, SPIL_LOC (cond)->rname);
10176 else if (isbit && !IS_ITEMP (cond))
10177 genIfxJump (ic, OP_SYMBOL (cond)->rname);
10179 genIfxJump (ic, "a");
10184 /*-----------------------------------------------------------------*/
10185 /* genAddrOf - generates code for address of */
10186 /*-----------------------------------------------------------------*/
10188 genAddrOf (iCode * ic)
10190 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10193 D (emitcode (";", "genAddrOf ");
10196 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10198 /* if the operand is on the stack then we
10199 need to get the stack offset of this
10201 if (sym->onStack) {
10203 /* if 10 bit stack */
10204 if (options.stack10bit) {
10206 tsprintf(buff,"#!constbyte",(options.stack_loc >> 16) & 0xff);
10207 /* if it has an offset then we need to compute it */
10208 emitcode ("subb", "a,#!constbyte",
10209 -((sym->stack < 0) ?
10210 ((short) (sym->stack - _G.nRegsSaved)) :
10211 ((short) sym->stack)) & 0xff);
10212 emitcode ("mov","b,a");
10213 emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ?
10214 ((short) (sym->stack - _G.nRegsSaved)) :
10215 ((short) sym->stack)) >> 8) & 0xff);
10217 emitcode ("mov", "a,_bpx");
10218 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
10219 ((char) (sym->stack - _G.nRegsSaved)) :
10220 ((char) sym->stack )) & 0xff);
10221 emitcode ("mov", "b,a");
10222 emitcode ("mov", "a,_bpx+1");
10223 emitcode ("addc","a,#!constbyte", (((sym->stack < 0) ?
10224 ((short) (sym->stack - _G.nRegsSaved)) :
10225 ((short) sym->stack )) >> 8) & 0xff);
10226 aopPut (AOP (IC_RESULT (ic)), "b", 0);
10227 aopPut (AOP (IC_RESULT (ic)), "a", 1);
10228 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10230 /* we can just move _bp */
10231 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10232 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10233 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10236 /* if it has an offset then we need to compute it */
10238 emitcode ("mov", "a,_bp");
10239 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10240 aopPut (AOP (IC_RESULT (ic)), "a", 0);
10242 /* we can just move _bp */
10243 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10245 /* fill the result with zero */
10246 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10249 if (options.stack10bit && size < (FPTRSIZE - 1)) {
10251 "*** warning: pointer to stack var truncated.\n");
10256 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10262 /* object not on stack then we need the name */
10263 size = AOP_SIZE (IC_RESULT (ic));
10268 char s[SDCC_NAME_MAX];
10272 tsprintf(s,"!his",sym->rname);
10275 tsprintf(s,"!hihis",sym->rname);
10278 tsprintf(s,"!hihihis",sym->rname);
10280 default: /* should not need this (just in case) */
10281 sprintf (s, "#(%s >> %d)",
10286 sprintf (s, "#%s", sym->rname);
10287 aopPut (AOP (IC_RESULT (ic)), s, offset++);
10291 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10295 /*-----------------------------------------------------------------*/
10296 /* genArrayInit - generates code for address of */
10297 /*-----------------------------------------------------------------*/
10299 genArrayInit (iCode * ic)
10301 literalList *iLoop;
10303 int elementSize = 0, eIndex;
10304 unsigned val, lastVal;
10306 operand *left=IC_LEFT(ic);
10308 D (emitcode (";", "genArrayInit "););
10310 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10312 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10314 // Load immediate value into DPTR.
10315 emitcode("mov", "dptr, %s",
10316 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
10318 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10321 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10322 "Unexpected operand to genArrayInit.\n");
10325 // a regression because of SDCCcse.c:1.52
10326 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
10327 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
10328 if (options.model == MODEL_FLAT24)
10329 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
10333 type = operandType(IC_LEFT(ic));
10335 if (type && type->next)
10337 elementSize = getSize(type->next);
10341 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10342 "can't determine element size in genArrayInit.\n");
10346 iLoop = IC_ARRAYILIST(ic);
10351 bool firstpass = TRUE;
10353 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
10354 iLoop->count, (int)iLoop->literalValue, elementSize);
10360 symbol *tlbl = NULL;
10362 count = ix > 256 ? 256 : ix;
10366 tlbl = newiTempLabel (NULL);
10367 if (firstpass || (count & 0xff))
10369 emitcode("mov", "b, #!constbyte", count & 0xff);
10372 emitcode ("", "!tlabeldef", tlbl->key + 100);
10377 for (eIndex = 0; eIndex < elementSize; eIndex++)
10379 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10380 if (val != lastVal)
10382 emitcode("mov", "a, #!constbyte", val);
10386 emitcode("movx", "@dptr, a");
10387 emitcode("inc", "dptr");
10392 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10398 iLoop = iLoop->next;
10401 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10404 /*-----------------------------------------------------------------*/
10405 /* genFarFarAssign - assignment when both are in far space */
10406 /*-----------------------------------------------------------------*/
10408 genFarFarAssign (operand * result, operand * right, iCode * ic)
10410 int size = AOP_SIZE (right);
10412 symbol *rSym = NULL;
10416 /* quick & easy case. */
10417 D(emitcode(";","genFarFarAssign (1 byte case)"););
10418 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
10419 freeAsmop (right, NULL, ic, FALSE);
10420 /* now assign DPTR to result */
10422 aopOp(result, ic, FALSE, FALSE);
10424 aopPut(AOP(result), "a", 0);
10425 freeAsmop(result, NULL, ic, FALSE);
10429 /* See if we've got an underlying symbol to abuse. */
10430 if (IS_SYMOP(result) && OP_SYMBOL(result))
10432 if (IS_TRUE_SYMOP(result))
10434 rSym = OP_SYMBOL(result);
10436 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10438 rSym = OP_SYMBOL(result)->usl.spillLoc;
10442 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10444 /* We can use the '390 auto-toggle feature to good effect here. */
10446 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10447 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10448 emitcode ("mov", "dptr,#%s", rSym->rname);
10449 /* DP2 = result, DP1 = right, DP1 is current. */
10452 emitcode("movx", "a,@dptr");
10453 emitcode("movx", "@dptr,a");
10456 emitcode("inc", "dptr");
10457 emitcode("inc", "dptr");
10460 emitcode("mov", "dps,#0");
10461 freeAsmop (right, NULL, ic, FALSE);
10463 some alternative code for processors without auto-toggle
10464 no time to test now, so later well put in...kpb
10465 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10466 emitcode("mov", "dps,#1"); /* Select DPTR2. */
10467 emitcode ("mov", "dptr,#%s", rSym->rname);
10468 /* DP2 = result, DP1 = right, DP1 is current. */
10472 emitcode("movx", "a,@dptr");
10474 emitcode("inc", "dptr");
10475 emitcode("inc", "dps");
10476 emitcode("movx", "@dptr,a");
10478 emitcode("inc", "dptr");
10479 emitcode("inc", "dps");
10481 emitcode("mov", "dps,#0");
10482 freeAsmop (right, NULL, ic, FALSE);
10487 D (emitcode (";", "genFarFarAssign"););
10488 aopOp (result, ic, TRUE, TRUE);
10490 _startLazyDPSEvaluation ();
10494 aopPut (AOP (result),
10495 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
10498 _endLazyDPSEvaluation ();
10499 freeAsmop (result, NULL, ic, FALSE);
10500 freeAsmop (right, NULL, ic, FALSE);
10504 /*-----------------------------------------------------------------*/
10505 /* genAssign - generate code for assignment */
10506 /*-----------------------------------------------------------------*/
10508 genAssign (iCode * ic)
10510 operand *result, *right;
10512 unsigned long lit = 0L;
10514 D (emitcode (";", "genAssign ");
10517 result = IC_RESULT (ic);
10518 right = IC_RIGHT (ic);
10520 /* if they are the same */
10521 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10524 aopOp (right, ic, FALSE, FALSE);
10526 emitcode (";", "genAssign: resultIsFar = %s",
10527 isOperandInFarSpace (result) ?
10530 /* special case both in far space */
10531 if ((AOP_TYPE (right) == AOP_DPTR ||
10532 AOP_TYPE (right) == AOP_DPTR2) &&
10533 /* IS_TRUE_SYMOP(result) && */
10534 isOperandInFarSpace (result))
10536 genFarFarAssign (result, right, ic);
10540 aopOp (result, ic, TRUE, FALSE);
10542 /* if they are the same registers */
10543 if (sameRegs (AOP (right), AOP (result)))
10546 /* if the result is a bit */
10547 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10549 /* if the right size is a literal then
10550 we know what the value is */
10551 if (AOP_TYPE (right) == AOP_LIT)
10553 if (((int) operandLitValue (right)))
10554 aopPut (AOP (result), one, 0);
10556 aopPut (AOP (result), zero, 0);
10560 /* the right is also a bit variable */
10561 if (AOP_TYPE (right) == AOP_CRY)
10563 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10564 aopPut (AOP (result), "c", 0);
10568 /* we need to or */
10570 aopPut (AOP (result), "a", 0);
10574 /* bit variables done */
10576 size = AOP_SIZE (result);
10578 if (AOP_TYPE (right) == AOP_LIT)
10579 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10582 (AOP_TYPE (result) != AOP_REG) &&
10583 (AOP_TYPE (right) == AOP_LIT) &&
10584 !IS_FLOAT (operandType (right)))
10586 _startLazyDPSEvaluation ();
10587 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10589 aopPut (AOP (result),
10590 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
10595 /* And now fill the rest with zeros. */
10598 emitcode ("clr", "a");
10602 aopPut (AOP (result), "a", offset++);
10604 _endLazyDPSEvaluation ();
10608 _startLazyDPSEvaluation ();
10611 aopPut (AOP (result),
10612 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10616 _endLazyDPSEvaluation ();
10620 freeAsmop (right, NULL, ic, FALSE);
10621 freeAsmop (result, NULL, ic, TRUE);
10624 /*-----------------------------------------------------------------*/
10625 /* genJumpTab - generates code for jump table */
10626 /*-----------------------------------------------------------------*/
10628 genJumpTab (iCode * ic)
10633 D (emitcode (";", "genJumpTab ");
10636 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10637 /* get the condition into accumulator */
10638 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10640 /* multiply by four! */
10641 emitcode ("add", "a,acc");
10642 emitcode ("add", "a,acc");
10643 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10645 jtab = newiTempLabel (NULL);
10646 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10647 emitcode ("jmp", "@a+dptr");
10648 emitcode ("", "!tlabeldef", jtab->key + 100);
10649 /* now generate the jump labels */
10650 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10651 jtab = setNextItem (IC_JTLABELS (ic)))
10652 emitcode ("ljmp", "!tlabel", jtab->key + 100);
10656 /*-----------------------------------------------------------------*/
10657 /* genCast - gen code for casting */
10658 /*-----------------------------------------------------------------*/
10660 genCast (iCode * ic)
10662 operand *result = IC_RESULT (ic);
10663 sym_link *ctype = operandType (IC_LEFT (ic));
10664 sym_link *rtype = operandType (IC_RIGHT (ic));
10665 operand *right = IC_RIGHT (ic);
10668 D (emitcode (";", "genCast ");
10671 /* if they are equivalent then do nothing */
10672 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10675 aopOp (right, ic, FALSE, FALSE);
10676 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10678 /* if the result is a bit */
10679 // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10680 if (IS_BITVAR(OP_SYMBOL(result)->type))
10682 /* if the right size is a literal then
10683 we know what the value is */
10684 if (AOP_TYPE (right) == AOP_LIT)
10686 if (((int) operandLitValue (right)))
10687 aopPut (AOP (result), one, 0);
10689 aopPut (AOP (result), zero, 0);
10694 /* the right is also a bit variable */
10695 if (AOP_TYPE (right) == AOP_CRY)
10697 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10698 aopPut (AOP (result), "c", 0);
10702 /* we need to or */
10704 aopPut (AOP (result), "a", 0);
10708 /* if they are the same size : or less */
10709 if (AOP_SIZE (result) <= AOP_SIZE (right))
10712 /* if they are in the same place */
10713 if (sameRegs (AOP (right), AOP (result)))
10716 /* if they in different places then copy */
10717 size = AOP_SIZE (result);
10719 _startLazyDPSEvaluation ();
10722 aopPut (AOP (result),
10723 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10727 _endLazyDPSEvaluation ();
10732 /* if the result is of type pointer */
10733 if (IS_PTR (ctype))
10737 sym_link *type = operandType (right);
10739 /* pointer to generic pointer */
10740 if (IS_GENPTR (ctype))
10746 p_type = DCL_TYPE (type);
10750 #if OLD_CAST_BEHAVIOR
10751 /* KV: we are converting a non-pointer type to
10752 * a generic pointer. This (ifdef'd out) code
10753 * says that the resulting generic pointer
10754 * should have the same class as the storage
10755 * location of the non-pointer variable.
10757 * For example, converting an int (which happens
10758 * to be stored in DATA space) to a pointer results
10759 * in a DATA generic pointer; if the original int
10760 * in XDATA space, so will be the resulting pointer.
10762 * I don't like that behavior, and thus this change:
10763 * all such conversions will be forced to XDATA and
10764 * throw a warning. If you want some non-XDATA
10765 * type, or you want to suppress the warning, you
10766 * must go through an intermediate cast, like so:
10768 * char _generic *gp = (char _xdata *)(intVar);
10770 sym_link *etype = getSpec (type);
10772 /* we have to go by the storage class */
10773 if (SPEC_OCLS (etype) != generic)
10775 p_type = PTR_TYPE (SPEC_OCLS (etype));
10780 /* Converting unknown class (i.e. register variable)
10781 * to generic pointer. This is not good, but
10782 * we'll make a guess (and throw a warning).
10785 werror (W_INT_TO_GEN_PTR_CAST);
10789 /* the first two bytes are known */
10790 size = GPTRSIZE - 1;
10792 _startLazyDPSEvaluation ();
10795 aopPut (AOP (result),
10796 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10800 _endLazyDPSEvaluation ();
10802 /* the last byte depending on type */
10820 /* this should never happen */
10821 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10822 "got unknown pointer type");
10825 aopPut (AOP (result), l, GPTRSIZE - 1);
10829 /* just copy the pointers */
10830 size = AOP_SIZE (result);
10832 _startLazyDPSEvaluation ();
10835 aopPut (AOP (result),
10836 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10840 _endLazyDPSEvaluation ();
10844 /* so we now know that the size of destination is greater
10845 than the size of the source */
10846 /* we move to result for the size of source */
10847 size = AOP_SIZE (right);
10849 _startLazyDPSEvaluation ();
10852 aopPut (AOP (result),
10853 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10857 _endLazyDPSEvaluation ();
10859 /* now depending on the sign of the source && destination */
10860 size = AOP_SIZE (result) - AOP_SIZE (right);
10861 /* if unsigned or not an integral type */
10862 /* also, if the source is a bit, we don't need to sign extend, because
10863 * it can't possibly have set the sign bit.
10865 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
10869 aopPut (AOP (result), zero, offset++);
10874 /* we need to extend the sign :{ */
10875 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10876 FALSE, FALSE, TRUE);
10878 emitcode ("rlc", "a");
10879 emitcode ("subb", "a,acc");
10881 aopPut (AOP (result), "a", offset++);
10884 /* we are done hurray !!!! */
10887 freeAsmop (right, NULL, ic, TRUE);
10888 freeAsmop (result, NULL, ic, TRUE);
10892 /*-----------------------------------------------------------------*/
10893 /* genDjnz - generate decrement & jump if not zero instrucion */
10894 /*-----------------------------------------------------------------*/
10896 genDjnz (iCode * ic, iCode * ifx)
10898 symbol *lbl, *lbl1;
10902 /* if the if condition has a false label
10903 then we cannot save */
10904 if (IC_FALSE (ifx))
10907 /* if the minus is not of the form
10909 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10910 !IS_OP_LITERAL (IC_RIGHT (ic)))
10913 if (operandLitValue (IC_RIGHT (ic)) != 1)
10916 /* if the size of this greater than one then no
10918 if (getSize (operandType (IC_RESULT (ic))) > 1)
10921 /* otherwise we can save BIG */
10922 D(emitcode(";", "genDjnz"););
10924 lbl = newiTempLabel (NULL);
10925 lbl1 = newiTempLabel (NULL);
10927 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10929 if (AOP_NEEDSACC(IC_RESULT(ic)))
10931 /* If the result is accessed indirectly via
10932 * the accumulator, we must explicitly write
10933 * it back after the decrement.
10935 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
10937 if (strcmp(rByte, "a"))
10939 /* Something is hopelessly wrong */
10940 fprintf(stderr, "*** warning: internal error at %s:%d\n",
10941 __FILE__, __LINE__);
10942 /* We can just give up; the generated code will be inefficient,
10943 * but what the hey.
10945 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10948 emitcode ("dec", "%s", rByte);
10949 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
10950 emitcode ("jnz", "!tlabel", lbl->key + 100);
10952 else if (IS_AOP_PREG (IC_RESULT (ic)))
10954 emitcode ("dec", "%s",
10955 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10956 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10957 emitcode ("jnz", "!tlabel", lbl->key + 100);
10961 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
10964 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
10965 emitcode ("", "!tlabeldef", lbl->key + 100);
10966 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
10967 emitcode ("", "!tlabeldef", lbl1->key + 100);
10969 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10970 ifx->generated = 1;
10974 /*-----------------------------------------------------------------*/
10975 /* genReceive - generate code for a receive iCode */
10976 /*-----------------------------------------------------------------*/
10978 genReceive (iCode * ic)
10981 int size = getSize (operandType (IC_RESULT (ic)));
10985 D (emitcode (";", "genReceive ");
10988 if (ic->argreg == 1) { /* first parameter */
10989 if (isOperandInFarSpace (IC_RESULT (ic)) &&
10990 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10991 IS_TRUE_SYMOP (IC_RESULT (ic))))
10993 offset = fReturnSizeDS390 - size;
10996 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
10997 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
11000 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11001 size = AOP_SIZE (IC_RESULT (ic));
11005 emitcode ("pop", "acc");
11006 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
11011 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11013 assignResultValue (IC_RESULT (ic));
11015 } else { /* second receive onwards */
11016 /* this gets a little tricky since unused recevies will be
11017 eliminated, we have saved the reg in the type field . and
11018 we use that to figure out which register to use */
11019 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11020 rb1off = ic->argreg;
11022 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11026 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11029 /*-----------------------------------------------------------------*/
11030 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
11031 /*-----------------------------------------------------------------*/
11032 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11034 operand *from , *to , *count;
11039 /* we know it has to be 3 parameters */
11040 assert (nparms == 3);
11042 rsave = newBitVect(16);
11043 /* save DPTR if it needs to be saved */
11044 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11045 if (bitVectBitValue(ic->rMask,i))
11046 rsave = bitVectSetBit(rsave,i);
11048 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11049 ds390_rUmaskForOp (IC_RESULT(ic))));
11056 aopOp (from, ic->next, FALSE, FALSE);
11058 /* get from into DPTR1 */
11059 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
11060 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
11061 if (options.model == MODEL_FLAT24) {
11062 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
11065 freeAsmop (from, NULL, ic, FALSE);
11066 aopOp (to, ic, FALSE, FALSE);
11067 /* get "to" into DPTR */
11068 /* if the operand is already in dptr
11069 then we do nothing else we move the value to dptr */
11070 if (AOP_TYPE (to) != AOP_STR) {
11071 /* if already in DPTR then we need to push */
11072 if (AOP_TYPE(to) == AOP_DPTR) {
11073 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11074 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11075 if (options.model == MODEL_FLAT24)
11076 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11077 emitcode ("pop", "dph");
11078 emitcode ("pop", "dpl");
11080 _startLazyDPSEvaluation ();
11081 /* if this is remateriazable */
11082 if (AOP_TYPE (to) == AOP_IMMD) {
11083 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11084 } else { /* we need to get it byte by byte */
11085 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11086 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11087 if (options.model == MODEL_FLAT24) {
11088 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11091 _endLazyDPSEvaluation ();
11094 freeAsmop (to, NULL, ic, FALSE);
11096 aopOp (count, ic->next->next, FALSE,FALSE);
11097 lbl =newiTempLabel(NULL);
11099 /* now for the actual copy */
11100 if (AOP_TYPE(count) == AOP_LIT &&
11101 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11102 emitcode (";","OH JOY auto increment with djnz (very fast)");
11103 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11104 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11105 emitcode ("","!tlabeldef",lbl->key+100);
11107 emitcode ("clr","a");
11108 emitcode ("movc", "a,@a+dptr");
11110 emitcode ("movx", "a,@dptr");
11111 emitcode ("movx", "@dptr,a");
11112 emitcode ("inc", "dptr");
11113 emitcode ("inc", "dptr");
11114 emitcode ("djnz","b,!tlabel",lbl->key+100);
11116 symbol *lbl1 = newiTempLabel(NULL);
11118 emitcode (";"," Auto increment but no djnz");
11119 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11120 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11121 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11122 emitcode ("","!tlabeldef",lbl->key+100);
11124 emitcode ("clr","a");
11125 emitcode ("movc", "a,@a+dptr");
11127 emitcode ("movx", "a,@dptr");
11128 emitcode ("movx", "@dptr,a");
11129 emitcode ("inc", "dptr");
11130 emitcode ("inc", "dptr");
11131 emitcode ("mov","a,b");
11132 emitcode ("orl","a,_ap");
11133 emitcode ("jz","!tlabel",lbl1->key+100);
11134 emitcode ("mov","a,_ap");
11135 emitcode ("add","a,#!constbyte",0xFF);
11136 emitcode ("mov","_ap,a");
11137 emitcode ("mov","a,b");
11138 emitcode ("addc","a,#!constbyte",0xFF);
11139 emitcode ("mov","b,a");
11140 emitcode ("sjmp","!tlabel",lbl->key+100);
11141 emitcode ("","!tlabeldef",lbl1->key+100);
11143 emitcode ("mov", "dps,#0");
11144 freeAsmop (count, NULL, ic, FALSE);
11145 unsavermask(rsave);
11149 /*-----------------------------------------------------------------*/
11150 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
11151 /*-----------------------------------------------------------------*/
11152 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11154 operand *from , *to , *count;
11159 /* we know it has to be 3 parameters */
11160 assert (nparms == 3);
11162 rsave = newBitVect(16);
11163 /* save DPTR if it needs to be saved */
11164 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11165 if (bitVectBitValue(ic->rMask,i))
11166 rsave = bitVectSetBit(rsave,i);
11168 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11169 ds390_rUmaskForOp (IC_RESULT(ic))));
11176 aopOp (from, ic->next, FALSE, FALSE);
11178 /* get from into DPTR1 */
11179 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
11180 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
11181 if (options.model == MODEL_FLAT24) {
11182 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
11185 freeAsmop (from, NULL, ic, FALSE);
11186 aopOp (to, ic, FALSE, FALSE);
11187 /* get "to" into DPTR */
11188 /* if the operand is already in dptr
11189 then we do nothing else we move the value to dptr */
11190 if (AOP_TYPE (to) != AOP_STR) {
11191 /* if already in DPTR then we need to push */
11192 if (AOP_TYPE(to) == AOP_DPTR) {
11193 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11194 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11195 if (options.model == MODEL_FLAT24)
11196 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11197 emitcode ("pop", "dph");
11198 emitcode ("pop", "dpl");
11200 _startLazyDPSEvaluation ();
11201 /* if this is remateriazable */
11202 if (AOP_TYPE (to) == AOP_IMMD) {
11203 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11204 } else { /* we need to get it byte by byte */
11205 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11206 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11207 if (options.model == MODEL_FLAT24) {
11208 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11211 _endLazyDPSEvaluation ();
11214 freeAsmop (to, NULL, ic, FALSE);
11216 aopOp (count, ic->next->next, FALSE,FALSE);
11217 lbl =newiTempLabel(NULL);
11218 lbl2 =newiTempLabel(NULL);
11220 /* now for the actual compare */
11221 emitcode("push","ar0");
11222 if (AOP_TYPE(count) == AOP_LIT &&
11223 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11224 emitcode (";","OH JOY auto increment with djnz (very fast)");
11225 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11226 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11227 emitcode ("","!tlabeldef",lbl->key+100);
11229 emitcode ("clr","a");
11230 emitcode ("movc", "a,@a+dptr");
11232 emitcode ("movx", "a,@dptr");
11233 emitcode ("mov","r0,a");
11234 emitcode ("movx", "a,@dptr");
11235 emitcode ("clr","c");
11236 emitcode ("subb","a,r0");
11237 emitcode ("jnz","!tlabel",lbl2->key+100);
11238 emitcode ("inc", "dptr");
11239 emitcode ("inc", "dptr");
11240 emitcode ("djnz","b,!tlabel",lbl->key+100);
11241 emitcode ("clr","a");
11243 symbol *lbl1 = newiTempLabel(NULL);
11245 emitcode (";"," Auto increment but no djnz");
11246 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11247 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11248 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11249 emitcode ("","!tlabeldef",lbl->key+100);
11251 emitcode ("clr","a");
11252 emitcode ("movc", "a,@a+dptr");
11254 emitcode ("movx", "a,@dptr");
11255 emitcode ("mov","r0,a");
11256 emitcode ("movx", "a,@dptr");
11257 emitcode ("clr","c");
11258 emitcode ("subb","a,r0");
11259 emitcode ("jnz","!tlabel",lbl2->key+100);
11260 emitcode ("inc", "dptr");
11261 emitcode ("inc", "dptr");
11262 emitcode ("mov","a,b");
11263 emitcode ("orl","a,_ap");
11264 emitcode ("jz","!tlabel",lbl1->key+100);
11265 emitcode ("mov","a,_ap");
11266 emitcode ("add","a,#!constbyte",0xFF);
11267 emitcode ("mov","_ap,a");
11268 emitcode ("mov","a,b");
11269 emitcode ("addc","a,#!constbyte",0xFF);
11270 emitcode ("mov","b,a");
11271 emitcode ("sjmp","!tlabel",lbl->key+100);
11272 emitcode ("","!tlabeldef",lbl1->key+100);
11273 emitcode ("clr","a");
11275 freeAsmop (count, NULL, ic, FALSE);
11276 emitcode ("","!tlabeldef",lbl2->key+100);
11277 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11278 aopPut(AOP(IC_RESULT(ic)),"a",0);
11279 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11280 emitcode("pop","ar0");
11281 emitcode ("mov", "dps,#0");
11283 unsavermask(rsave);
11287 /*-----------------------------------------------------------------*/
11288 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11289 /* port, first parameter output area second parameter pointer to */
11290 /* port third parameter count */
11291 /*-----------------------------------------------------------------*/
11292 static void genInp( iCode *ic, int nparms, operand **parms)
11294 operand *from , *to , *count;
11299 /* we know it has to be 3 parameters */
11300 assert (nparms == 3);
11302 rsave = newBitVect(16);
11303 /* save DPTR if it needs to be saved */
11304 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11305 if (bitVectBitValue(ic->rMask,i))
11306 rsave = bitVectSetBit(rsave,i);
11308 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11309 ds390_rUmaskForOp (IC_RESULT(ic))));
11316 aopOp (from, ic->next, FALSE, FALSE);
11318 /* get from into DPTR1 */
11319 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
11320 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
11321 if (options.model == MODEL_FLAT24) {
11322 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
11325 freeAsmop (from, NULL, ic, FALSE);
11326 aopOp (to, ic, FALSE, FALSE);
11327 /* get "to" into DPTR */
11328 /* if the operand is already in dptr
11329 then we do nothing else we move the value to dptr */
11330 if (AOP_TYPE (to) != AOP_STR) {
11331 /* if already in DPTR then we need to push */
11332 if (AOP_TYPE(to) == AOP_DPTR) {
11333 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11334 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11335 if (options.model == MODEL_FLAT24)
11336 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11337 emitcode ("pop", "dph");
11338 emitcode ("pop", "dpl");
11340 _startLazyDPSEvaluation ();
11341 /* if this is remateriazable */
11342 if (AOP_TYPE (to) == AOP_IMMD) {
11343 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11344 } else { /* we need to get it byte by byte */
11345 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11346 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11347 if (options.model == MODEL_FLAT24) {
11348 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11351 _endLazyDPSEvaluation ();
11354 freeAsmop (to, NULL, ic, FALSE);
11356 aopOp (count, ic->next->next, FALSE,FALSE);
11357 lbl =newiTempLabel(NULL);
11359 /* now for the actual copy */
11360 if (AOP_TYPE(count) == AOP_LIT &&
11361 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11362 emitcode (";","OH JOY auto increment with djnz (very fast)");
11363 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11364 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11365 emitcode ("","!tlabeldef",lbl->key+100);
11366 emitcode ("movx", "a,@dptr"); /* read data from port */
11367 emitcode ("dec","dps"); /* switch to DPTR */
11368 emitcode ("movx", "@dptr,a"); /* save into location */
11369 emitcode ("inc", "dptr"); /* point to next area */
11370 emitcode ("inc","dps"); /* switch to DPTR2 */
11371 emitcode ("djnz","b,!tlabel",lbl->key+100);
11373 symbol *lbl1 = newiTempLabel(NULL);
11375 emitcode (";"," Auto increment but no djnz");
11376 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11377 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11378 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11379 emitcode ("","!tlabeldef",lbl->key+100);
11380 emitcode ("movx", "a,@dptr");
11381 emitcode ("dec","dps"); /* switch to DPTR */
11382 emitcode ("movx", "@dptr,a");
11383 emitcode ("inc", "dptr");
11384 emitcode ("inc","dps"); /* switch to DPTR2 */
11385 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
11386 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11387 emitcode ("mov","a,b");
11388 emitcode ("orl","a,_ap");
11389 emitcode ("jz","!tlabel",lbl1->key+100);
11390 emitcode ("mov","a,_ap");
11391 emitcode ("add","a,#!constbyte",0xFF);
11392 emitcode ("mov","_ap,a");
11393 emitcode ("mov","a,b");
11394 emitcode ("addc","a,#!constbyte",0xFF);
11395 emitcode ("mov","b,a");
11396 emitcode ("sjmp","!tlabel",lbl->key+100);
11397 emitcode ("","!tlabeldef",lbl1->key+100);
11399 emitcode ("mov", "dps,#0");
11400 freeAsmop (count, NULL, ic, FALSE);
11401 unsavermask(rsave);
11405 /*-----------------------------------------------------------------*/
11406 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11407 /* port, first parameter output area second parameter pointer to */
11408 /* port third parameter count */
11409 /*-----------------------------------------------------------------*/
11410 static void genOutp( iCode *ic, int nparms, operand **parms)
11412 operand *from , *to , *count;
11417 /* we know it has to be 3 parameters */
11418 assert (nparms == 3);
11420 rsave = newBitVect(16);
11421 /* save DPTR if it needs to be saved */
11422 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11423 if (bitVectBitValue(ic->rMask,i))
11424 rsave = bitVectSetBit(rsave,i);
11426 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11427 ds390_rUmaskForOp (IC_RESULT(ic))));
11434 aopOp (from, ic->next, FALSE, FALSE);
11436 /* get from into DPTR1 */
11437 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
11438 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
11439 if (options.model == MODEL_FLAT24) {
11440 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
11443 freeAsmop (from, NULL, ic, FALSE);
11444 aopOp (to, ic, FALSE, FALSE);
11445 /* get "to" into DPTR */
11446 /* if the operand is already in dptr
11447 then we do nothing else we move the value to dptr */
11448 if (AOP_TYPE (to) != AOP_STR) {
11449 /* if already in DPTR then we need to push */
11450 if (AOP_TYPE(to) == AOP_DPTR) {
11451 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11452 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11453 if (options.model == MODEL_FLAT24)
11454 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11455 emitcode ("pop", "dph");
11456 emitcode ("pop", "dpl");
11458 _startLazyDPSEvaluation ();
11459 /* if this is remateriazable */
11460 if (AOP_TYPE (to) == AOP_IMMD) {
11461 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11462 } else { /* we need to get it byte by byte */
11463 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11464 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11465 if (options.model == MODEL_FLAT24) {
11466 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11469 _endLazyDPSEvaluation ();
11472 freeAsmop (to, NULL, ic, FALSE);
11474 aopOp (count, ic->next->next, FALSE,FALSE);
11475 lbl =newiTempLabel(NULL);
11477 /* now for the actual copy */
11478 if (AOP_TYPE(count) == AOP_LIT &&
11479 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11480 emitcode (";","OH JOY auto increment with djnz (very fast)");
11481 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11482 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11483 emitcode ("","!tlabeldef",lbl->key+100);
11484 emitcode ("movx", "a,@dptr"); /* read data from port */
11485 emitcode ("inc","dps"); /* switch to DPTR2 */
11486 emitcode ("movx", "@dptr,a"); /* save into location */
11487 emitcode ("inc", "dptr"); /* point to next area */
11488 emitcode ("dec","dps"); /* switch to DPTR */
11489 emitcode ("djnz","b,!tlabel",lbl->key+100);
11491 symbol *lbl1 = newiTempLabel(NULL);
11493 emitcode (";"," Auto increment but no djnz");
11494 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11495 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11496 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11497 emitcode ("","!tlabeldef",lbl->key+100);
11498 /* emitcode ("push","acc"); */
11499 emitcode ("movx", "a,@dptr");
11500 emitcode ("inc", "dptr");
11501 emitcode ("inc","dps"); /* switch to DPTR2 */
11502 emitcode ("movx", "@dptr,a");
11503 emitcode ("dec","dps"); /* switch to DPTR */
11504 /* emitcode ("pop","acc"); */
11505 /* emitcode ("djnz","acc,!tlabel",lbl->key+100); */
11506 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
11507 emitcode ("mov","a,b");
11508 emitcode ("orl","a,_ap");
11509 emitcode ("jz","!tlabel",lbl1->key+100);
11510 emitcode ("mov","a,_ap");
11511 emitcode ("add","a,#!constbyte",0xFF);
11512 emitcode ("mov","_ap,a");
11513 emitcode ("mov","a,b");
11514 emitcode ("addc","a,#!constbyte",0xFF);
11515 emitcode ("mov","b,a");
11516 emitcode ("sjmp","!tlabel",lbl->key+100);
11517 emitcode ("","!tlabeldef",lbl1->key+100);
11519 emitcode ("mov", "dps,#0");
11520 freeAsmop (count, NULL, ic, FALSE);
11521 unsavermask(rsave);
11525 /*-----------------------------------------------------------------*/
11526 /* genSwapW - swap lower & high order bytes */
11527 /*-----------------------------------------------------------------*/
11528 static void genSwapW(iCode *ic, int nparms, operand **parms)
11532 assert (nparms==1);
11535 dest=IC_RESULT(ic);
11537 assert(getSize(operandType(src))==2);
11539 aopOp (src, ic, FALSE, FALSE);
11540 emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,TRUE));
11542 emitcode ("mov","b,%s",aopGet(AOP(src),1,FALSE,FALSE,FALSE));
11544 freeAsmop (src, NULL, ic, FALSE);
11546 aopOp (dest,ic, FALSE, FALSE);
11547 aopPut(AOP(dest),"b",0);
11548 aopPut(AOP(dest),"a",1);
11549 freeAsmop (dest, NULL, ic, FALSE);
11552 /*-----------------------------------------------------------------*/
11553 /* genMemsetX - gencode for memSetX data */
11554 /*-----------------------------------------------------------------*/
11555 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11557 operand *to , *val , *count;
11561 bitVect *rsave = NULL;
11563 /* we know it has to be 3 parameters */
11564 assert (nparms == 3);
11570 /* save DPTR if it needs to be saved */
11571 rsave = newBitVect(16);
11572 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11573 if (bitVectBitValue(ic->rMask,i))
11574 rsave = bitVectSetBit(rsave,i);
11576 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11577 ds390_rUmaskForOp (IC_RESULT(ic))));
11580 aopOp (to, ic, FALSE, FALSE);
11581 /* get "to" into DPTR */
11582 /* if the operand is already in dptr
11583 then we do nothing else we move the value to dptr */
11584 if (AOP_TYPE (to) != AOP_STR) {
11585 /* if already in DPTR then we need to push */
11586 if (AOP_TYPE(to) == AOP_DPTR) {
11587 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11588 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11589 if (options.model == MODEL_FLAT24)
11590 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11591 emitcode ("pop", "dph");
11592 emitcode ("pop", "dpl");
11594 _startLazyDPSEvaluation ();
11595 /* if this is remateriazable */
11596 if (AOP_TYPE (to) == AOP_IMMD) {
11597 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11598 } else { /* we need to get it byte by byte */
11599 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11600 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11601 if (options.model == MODEL_FLAT24) {
11602 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11605 _endLazyDPSEvaluation ();
11608 freeAsmop (to, NULL, ic, FALSE);
11610 aopOp (val, ic->next->next, FALSE,FALSE);
11611 aopOp (count, ic->next->next, FALSE,FALSE);
11612 lbl =newiTempLabel(NULL);
11613 /* now for the actual copy */
11614 if (AOP_TYPE(count) == AOP_LIT &&
11615 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11616 l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
11617 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11619 emitcode ("","!tlabeldef",lbl->key+100);
11620 emitcode ("movx", "@dptr,a");
11621 emitcode ("inc", "dptr");
11622 emitcode ("djnz","b,!tlabel",lbl->key+100);
11624 symbol *lbl1 = newiTempLabel(NULL);
11626 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11627 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11628 emitcode ("","!tlabeldef",lbl->key+100);
11629 l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
11631 emitcode ("movx", "@dptr,a");
11632 emitcode ("inc", "dptr");
11633 emitcode ("mov","a,b");
11634 emitcode ("orl","a,_ap");
11635 emitcode ("jz","!tlabel",lbl1->key+100);
11636 emitcode ("mov","a,_ap");
11637 emitcode ("add","a,#!constbyte",0xFF);
11638 emitcode ("mov","_ap,a");
11639 emitcode ("mov","a,b");
11640 emitcode ("addc","a,#!constbyte",0xFF);
11641 emitcode ("mov","b,a");
11642 emitcode ("sjmp","!tlabel",lbl->key+100);
11643 emitcode ("","!tlabeldef",lbl1->key+100);
11645 freeAsmop (count, NULL, ic, FALSE);
11646 unsavermask(rsave);
11649 /*-----------------------------------------------------------------*/
11650 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11651 /*-----------------------------------------------------------------*/
11652 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11655 operand *pnum, *result;
11658 assert (nparms==1);
11659 /* save registers that need to be saved */
11660 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11661 ds390_rUmaskForOp (IC_RESULT(ic))));
11664 aopOp (pnum, ic, FALSE, FALSE);
11665 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,FALSE));
11666 freeAsmop (pnum, NULL, ic, FALSE);
11667 emitcode ("lcall","NatLib_LoadPrimitive");
11668 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11669 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
11670 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
11671 for (i = (size-1) ; i >= 0 ; i-- ) {
11672 emitcode ("push","a%s",javaRet[i]);
11674 for (i=0; i < size ; i++ ) {
11675 emitcode ("pop","a%s",aopGet(AOP(result),i,FALSE,FALSE,FALSE));
11678 for (i = 0 ; i < size ; i++ ) {
11679 aopPut(AOP(result),javaRet[i],i);
11682 freeAsmop (result, NULL, ic, FALSE);
11683 unsavermask(rsave);
11686 /*-----------------------------------------------------------------*/
11687 /* genNatLibLoadPointer - calls TINI api function to load pointer */
11688 /*-----------------------------------------------------------------*/
11689 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
11692 operand *pnum, *result;
11696 assert (nparms==1);
11697 /* save registers that need to be saved */
11698 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11699 ds390_rUmaskForOp (IC_RESULT(ic))));
11702 aopOp (pnum, ic, FALSE, FALSE);
11703 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,FALSE));
11704 freeAsmop (pnum, NULL, ic, FALSE);
11705 emitcode ("lcall","NatLib_LoadPointer");
11706 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11707 if (AOP_TYPE(result)!=AOP_STR) {
11708 for (i = 0 ; i < size ; i++ ) {
11709 aopPut(AOP(result),fReturn[i],i);
11712 freeAsmop (result, NULL, ic, FALSE);
11713 unsavermask(rsave);
11716 /*-----------------------------------------------------------------*/
11717 /* genNatLibInstallStateBlock - */
11718 /*-----------------------------------------------------------------*/
11719 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
11720 operand **parms, const char *name)
11723 operand *psb, *handle;
11724 assert (nparms==2);
11726 /* save registers that need to be saved */
11727 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11728 ds390_rUmaskForOp (IC_RESULT(ic))));
11732 /* put pointer to state block into DPTR1 */
11733 aopOp (psb, ic, FALSE, FALSE);
11734 if (AOP_TYPE (psb) == AOP_IMMD) {
11735 emitcode ("mov","dps,#1");
11736 emitcode ("mov", "dptr,%s", aopGet (AOP (psb), 0, TRUE, FALSE, FALSE));
11737 emitcode ("mov","dps,#0");
11739 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,FALSE));
11740 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,FALSE));
11741 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,FALSE));
11743 freeAsmop (psb, NULL, ic, FALSE);
11745 /* put libraryID into DPTR */
11746 emitcode ("mov","dptr,#LibraryID");
11748 /* put handle into r3:r2 */
11749 aopOp (handle, ic, FALSE, FALSE);
11750 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11751 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11752 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11753 emitcode ("pop","ar3");
11754 emitcode ("pop","ar2");
11756 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11757 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11759 freeAsmop (psb, NULL, ic, FALSE);
11761 /* make the call */
11762 emitcode ("lcall","NatLib_Install%sStateBlock",name);
11764 /* put return value into place*/
11766 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
11768 aopPut(AOP(IC_RESULT(ic)),"a",0);
11769 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11770 unsavermask(rsave);
11773 /*-----------------------------------------------------------------*/
11774 /* genNatLibRemoveStateBlock - */
11775 /*-----------------------------------------------------------------*/
11776 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
11782 /* save registers that need to be saved */
11783 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11784 ds390_rUmaskForOp (IC_RESULT(ic))));
11786 /* put libraryID into DPTR */
11787 emitcode ("mov","dptr,#LibraryID");
11788 /* make the call */
11789 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
11790 unsavermask(rsave);
11793 /*-----------------------------------------------------------------*/
11794 /* genNatLibGetStateBlock - */
11795 /*-----------------------------------------------------------------*/
11796 static void genNatLibGetStateBlock(iCode *ic,int nparms,
11797 operand **parms,const char *name)
11800 symbol *lbl = newiTempLabel(NULL);
11803 /* save registers that need to be saved */
11804 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11805 ds390_rUmaskForOp (IC_RESULT(ic))));
11807 /* put libraryID into DPTR */
11808 emitcode ("mov","dptr,#LibraryID");
11809 /* make the call */
11810 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
11811 emitcode ("jnz","!tlabel",lbl->key+100);
11813 /* put return value into place */
11814 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
11815 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
11816 emitcode ("push","ar3");
11817 emitcode ("push","ar2");
11818 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,FALSE));
11819 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,FALSE));
11821 aopPut(AOP(IC_RESULT(ic)),"r2",0);
11822 aopPut(AOP(IC_RESULT(ic)),"r3",1);
11824 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11825 emitcode ("","!tlabeldef",lbl->key+100);
11826 unsavermask(rsave);
11829 /*-----------------------------------------------------------------*/
11830 /* genMMMalloc - */
11831 /*-----------------------------------------------------------------*/
11832 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
11833 int size, const char *name)
11838 symbol *lbl = newiTempLabel(NULL);
11840 assert (nparms == 1);
11841 /* save registers that need to be saved */
11842 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11843 ds390_rUmaskForOp (IC_RESULT(ic))));
11846 aopOp (bsize,ic,FALSE,FALSE);
11848 /* put the size in R4-R2 */
11849 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
11850 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,FALSE));
11851 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,FALSE));
11853 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,FALSE));
11854 emitcode("pop","ar4");
11856 emitcode("pop","ar3");
11857 emitcode("pop","ar2");
11859 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,FALSE));
11860 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,FALSE));
11862 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,FALSE));
11865 freeAsmop (bsize, NULL, ic, FALSE);
11867 /* make the call */
11868 emitcode ("lcall","MM_%s",name);
11869 emitcode ("jz","!tlabel",lbl->key+100);
11870 emitcode ("mov","r2,#!constbyte",0xff);
11871 emitcode ("mov","r3,#!constbyte",0xff);
11872 emitcode ("","!tlabeldef",lbl->key+100);
11873 /* we don't care about the pointer : we just save the handle */
11874 rsym = OP_SYMBOL(IC_RESULT(ic));
11875 if (rsym->liveFrom != rsym->liveTo) {
11876 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
11877 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
11878 emitcode ("push","ar3");
11879 emitcode ("push","ar2");
11880 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,FALSE));
11881 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,FALSE));
11883 aopPut(AOP(IC_RESULT(ic)),"r2",0);
11884 aopPut(AOP(IC_RESULT(ic)),"r3",1);
11886 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11888 unsavermask(rsave);
11891 /*-----------------------------------------------------------------*/
11893 /*-----------------------------------------------------------------*/
11894 static void genMMDeref (iCode *ic,int nparms, operand **parms)
11899 assert (nparms == 1);
11900 /* save registers that need to be saved */
11901 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11902 ds390_rUmaskForOp (IC_RESULT(ic))));
11905 aopOp (handle,ic,FALSE,FALSE);
11907 /* put the size in R4-R2 */
11908 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11909 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11910 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11911 emitcode("pop","ar3");
11912 emitcode("pop","ar2");
11914 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11915 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11917 freeAsmop (handle, NULL, ic, FALSE);
11919 /* make the call */
11920 emitcode ("lcall","MM_Deref");
11923 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11924 if (rsym->liveFrom != rsym->liveTo) {
11925 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11926 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
11927 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
11928 aopPut(AOP(IC_RESULT(ic)),"dph",1);
11929 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
11933 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11934 unsavermask(rsave);
11937 /*-----------------------------------------------------------------*/
11938 /* genMMUnrestrictedPersist - */
11939 /*-----------------------------------------------------------------*/
11940 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
11945 assert (nparms == 1);
11946 /* save registers that need to be saved */
11947 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11948 ds390_rUmaskForOp (IC_RESULT(ic))));
11951 aopOp (handle,ic,FALSE,FALSE);
11953 /* put the size in R3-R2 */
11954 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11955 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11956 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11957 emitcode("pop","ar3");
11958 emitcode("pop","ar2");
11960 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11961 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11963 freeAsmop (handle, NULL, ic, FALSE);
11965 /* make the call */
11966 emitcode ("lcall","MM_UnrestrictedPersist");
11969 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11970 if (rsym->liveFrom != rsym->liveTo) {
11971 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11972 aopPut(AOP(IC_RESULT(ic)),"a",0);
11973 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11976 unsavermask(rsave);
11979 /*-----------------------------------------------------------------*/
11980 /* genSystemExecJavaProcess - */
11981 /*-----------------------------------------------------------------*/
11982 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
11985 operand *handle, *pp;
11987 assert (nparms==2);
11988 /* save registers that need to be saved */
11989 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11990 ds390_rUmaskForOp (IC_RESULT(ic))));
11995 /* put the handle in R3-R2 */
11996 aopOp (handle,ic,FALSE,FALSE);
11997 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11998 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11999 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
12000 emitcode("pop","ar3");
12001 emitcode("pop","ar2");
12003 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
12004 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
12006 freeAsmop (handle, NULL, ic, FALSE);
12008 /* put pointer in DPTR */
12009 aopOp (pp,ic,FALSE,FALSE);
12010 if (AOP_TYPE(pp) == AOP_IMMD) {
12011 emitcode ("mov", "dptr,%s", aopGet (AOP (pp), 0, TRUE, FALSE, FALSE));
12012 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12013 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,FALSE));
12014 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,FALSE));
12015 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,FALSE));
12017 freeAsmop (handle, NULL, ic, FALSE);
12019 /* make the call */
12020 emitcode ("lcall","System_ExecJavaProcess");
12022 /* put result in place */
12024 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12025 if (rsym->liveFrom != rsym->liveTo) {
12026 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12027 aopPut(AOP(IC_RESULT(ic)),"a",0);
12028 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12032 unsavermask(rsave);
12035 /*-----------------------------------------------------------------*/
12036 /* genSystemRTCRegisters - */
12037 /*-----------------------------------------------------------------*/
12038 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12044 assert (nparms==1);
12045 /* save registers that need to be saved */
12046 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12047 ds390_rUmaskForOp (IC_RESULT(ic))));
12050 /* put pointer in DPTR */
12051 aopOp (pp,ic,FALSE,FALSE);
12052 if (AOP_TYPE (pp) == AOP_IMMD) {
12053 emitcode ("mov","dps,#1");
12054 emitcode ("mov", "dptr,%s", aopGet (AOP (pp), 0, TRUE, FALSE, FALSE));
12055 emitcode ("mov","dps,#0");
12057 emitcode ("mov","dpl1,%s",aopGet(AOP(pp),0,FALSE,FALSE,FALSE));
12058 emitcode ("mov","dph1,%s",aopGet(AOP(pp),1,FALSE,FALSE,FALSE));
12059 emitcode ("mov","dpx1,%s",aopGet(AOP(pp),2,FALSE,FALSE,FALSE));
12061 freeAsmop (pp, NULL, ic, FALSE);
12063 /* make the call */
12064 emitcode ("lcall","System_%sRTCRegisters",name);
12066 unsavermask(rsave);
12069 /*-----------------------------------------------------------------*/
12070 /* genSystemThreadSleep - */
12071 /*-----------------------------------------------------------------*/
12072 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12077 assert (nparms==1);
12078 /* save registers that need to be saved */
12079 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12080 ds390_rUmaskForOp (IC_RESULT(ic))));
12083 aopOp(to,ic,FALSE,FALSE);
12084 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12085 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12086 emitcode ("push","%s",aopGet(AOP(to),0,FALSE,TRUE,FALSE));
12087 emitcode ("push","%s",aopGet(AOP(to),1,FALSE,TRUE,FALSE));
12088 emitcode ("push","%s",aopGet(AOP(to),2,FALSE,TRUE,FALSE));
12089 emitcode ("push","%s",aopGet(AOP(to),3,FALSE,TRUE,FALSE));
12090 emitcode ("pop","ar3");
12091 emitcode ("pop","ar2");
12092 emitcode ("pop","ar1");
12093 emitcode ("pop","ar0");
12095 emitcode ("mov","r0,%s",aopGet(AOP(to),0,FALSE,TRUE,FALSE));
12096 emitcode ("mov","r1,%s",aopGet(AOP(to),1,FALSE,TRUE,FALSE));
12097 emitcode ("mov","r2,%s",aopGet(AOP(to),2,FALSE,TRUE,FALSE));
12098 emitcode ("mov","r3,%s",aopGet(AOP(to),3,FALSE,TRUE,FALSE));
12100 freeAsmop (to, NULL, ic, FALSE);
12102 /* suspend in acc */
12104 aopOp(s,ic,FALSE,FALSE);
12105 emitcode ("mov","a,%s",aopGet(AOP(s),0,FALSE,TRUE,FALSE));
12106 freeAsmop (s, NULL, ic, FALSE);
12108 /* make the call */
12109 emitcode ("lcall","System_%s",name);
12111 unsavermask(rsave);
12114 /*-----------------------------------------------------------------*/
12115 /* genSystemThreadResume - */
12116 /*-----------------------------------------------------------------*/
12117 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12122 assert (nparms==2);
12123 /* save registers that need to be saved */
12124 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12125 ds390_rUmaskForOp (IC_RESULT(ic))));
12131 aopOp(pid,ic,FALSE,FALSE);
12132 emitcode ("mov","r0,%s",aopGet(AOP(pid),0,FALSE,TRUE,FALSE));
12133 freeAsmop (pid, NULL, ic, FALSE);
12136 aopOp(tid,ic,FALSE,FALSE);
12137 emitcode ("mov","a,%s",aopGet(AOP(tid),0,FALSE,TRUE,FALSE));
12138 freeAsmop (tid, NULL, ic, FALSE);
12140 emitcode ("lcall","System_ThreadResume");
12142 /* put result into place */
12144 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12145 if (rsym->liveFrom != rsym->liveTo) {
12146 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12147 aopPut(AOP(IC_RESULT(ic)),"a",0);
12148 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12151 unsavermask(rsave);
12154 /*-----------------------------------------------------------------*/
12155 /* genSystemProcessResume - */
12156 /*-----------------------------------------------------------------*/
12157 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12162 assert (nparms==1);
12163 /* save registers that need to be saved */
12164 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12165 ds390_rUmaskForOp (IC_RESULT(ic))));
12170 aopOp(pid,ic,FALSE,FALSE);
12171 emitcode ("mov","a,%s",aopGet(AOP(pid),0,FALSE,TRUE,FALSE));
12172 freeAsmop (pid, NULL, ic, FALSE);
12174 emitcode ("lcall","System_ProcessResume");
12176 unsavermask(rsave);
12179 /*-----------------------------------------------------------------*/
12181 /*-----------------------------------------------------------------*/
12182 static void genSystem (iCode *ic,int nparms,char *name)
12184 assert(nparms == 0);
12186 emitcode ("lcall","System_%s",name);
12189 /*-----------------------------------------------------------------*/
12190 /* genSystemPoll - */
12191 /*-----------------------------------------------------------------*/
12192 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12197 assert (nparms==1);
12198 /* save registers that need to be saved */
12199 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12200 ds390_rUmaskForOp (IC_RESULT(ic))));
12203 aopOp (fp,ic,FALSE,FALSE);
12204 if (AOP_TYPE (fp) == AOP_IMMD) {
12205 emitcode ("mov", "dptr,%s", aopGet (AOP (fp), 0, TRUE, FALSE, FALSE));
12206 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12207 emitcode ("mov","dpl,%s",aopGet(AOP(fp),0,FALSE,FALSE,FALSE));
12208 emitcode ("mov","dph,%s",aopGet(AOP(fp),1,FALSE,FALSE,FALSE));
12209 emitcode ("mov","dpx,%s",aopGet(AOP(fp),2,FALSE,FALSE,FALSE));
12211 freeAsmop (fp, NULL, ic, FALSE);
12213 emitcode ("lcall","System_%sPoll",name);
12215 /* put result into place */
12217 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12218 if (rsym->liveFrom != rsym->liveTo) {
12219 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12220 aopPut(AOP(IC_RESULT(ic)),"a",0);
12221 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12224 unsavermask(rsave);
12227 /*-----------------------------------------------------------------*/
12228 /* genSystemGetCurrentID - */
12229 /*-----------------------------------------------------------------*/
12230 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12232 assert (nparms==0);
12234 emitcode ("lcall","System_GetCurrent%sId",name);
12235 /* put result into place */
12237 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12238 if (rsym->liveFrom != rsym->liveTo) {
12239 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12240 aopPut(AOP(IC_RESULT(ic)),"a",0);
12241 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12246 /*-----------------------------------------------------------------*/
12247 /* genBuiltIn - calls the appropriate function to generating code */
12248 /* for a built in function */
12249 /*-----------------------------------------------------------------*/
12250 static void genBuiltIn (iCode *ic)
12252 operand *bi_parms[MAX_BUILTIN_ARGS];
12257 /* get all the arguments for a built in function */
12258 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12260 /* which function is it */
12261 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12262 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12263 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12264 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12265 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12266 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12267 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12268 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12269 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12270 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12271 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12272 } else if (strcmp(bif->name,"__builtin_inp")==0) {
12273 genInp(bi_iCode,nbi_parms,bi_parms);
12274 } else if (strcmp(bif->name,"__builtin_outp")==0) {
12275 genOutp(bi_iCode,nbi_parms,bi_parms);
12276 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12277 genSwapW(bi_iCode,nbi_parms,bi_parms);
12278 /* JavaNative builtIns */
12279 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12280 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12281 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12282 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12283 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12284 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12285 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12286 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12287 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12288 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12289 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12290 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12291 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12292 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12293 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12294 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12295 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12296 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12297 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12298 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12299 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12300 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12301 } else if (strcmp(bif->name,"MM_Malloc")==0) {
12302 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12303 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12304 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12305 } else if (strcmp(bif->name,"MM_Free")==0) {
12306 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12307 } else if (strcmp(bif->name,"MM_Deref")==0) {
12308 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12309 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12310 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12311 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12312 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12313 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12314 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12315 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12316 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12317 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12318 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12319 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12320 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12321 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12322 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12323 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12324 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12325 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12326 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12327 } else if (strcmp(bif->name,"System_SaveThread")==0) {
12328 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12329 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12330 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12331 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12332 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12333 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12334 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12335 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12336 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12337 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12338 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12339 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12340 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12341 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12342 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12343 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12344 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12345 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12346 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12347 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12348 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12350 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12356 /*-----------------------------------------------------------------*/
12357 /* gen390Code - generate code for Dallas 390 based controllers */
12358 /*-----------------------------------------------------------------*/
12360 gen390Code (iCode * lic)
12365 lineHead = lineCurr = NULL;
12366 dptrn[1][0] = "dpl1";
12367 dptrn[1][1] = "dph1";
12368 dptrn[1][2] = "dpx1";
12370 if (options.model == MODEL_FLAT24) {
12371 fReturnSizeDS390 = 5;
12372 fReturn = fReturn24;
12374 fReturnSizeDS390 = 4;
12375 fReturn = fReturn16;
12376 options.stack10bit=0;
12379 /* print the allocation information */
12381 printAllocInfo (currFunc, codeOutFile);
12383 /* if debug information required */
12384 if (options.debug && currFunc)
12386 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
12388 if (IS_STATIC (currFunc->etype))
12389 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12391 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12394 /* stack pointer name */
12395 if (options.useXstack)
12401 for (ic = lic; ic; ic = ic->next)
12404 if (ic->lineno && cln != ic->lineno)
12409 emitcode ("", "C$%s$%d$%d$%d ==.",
12410 FileBaseName (ic->filename), ic->lineno,
12411 ic->level, ic->block);
12414 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
12415 printCLine(ic->filename, ic->lineno));
12418 /* if the result is marked as
12419 spilt and rematerializable or code for
12420 this has already been generated then
12422 if (resultRemat (ic) || ic->generated)
12425 /* depending on the operation */
12445 /* IPOP happens only when trying to restore a
12446 spilt live range, if there is an ifx statement
12447 following this pop then the if statement might
12448 be using some of the registers being popped which
12449 would destory the contents of the register so
12450 we need to check for this condition and handle it */
12452 ic->next->op == IFX &&
12453 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
12454 genIfx (ic->next, ic);
12472 genEndFunction (ic);
12492 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12509 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
12513 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
12520 /* note these two are xlated by algebraic equivalence
12521 during parsing SDCC.y */
12522 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12523 "got '>=' or '<=' shouldn't have come here");
12527 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12539 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12543 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12547 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12571 genRightShift (ic);
12574 case GET_VALUE_AT_ADDRESS:
12575 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
12579 if (POINTER_SET (ic))
12580 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
12606 if (ic->builtinSEND) genBuiltIn(ic);
12607 else addSet (&_G.sendSet, ic);
12620 /* now we are ready to call the
12621 peep hole optimizer */
12622 if (!options.nopeep)
12623 peepHole (&lineHead);
12625 /* now do the actual printing */
12626 printLine (lineHead, codeOutFile);