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 /* set C, if a >= 1 */
1389 emitcode ("add", "a,0xff");
1390 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1398 if (strcmp (aop->aopu.aop_str[offset], s))
1399 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1404 if (!offset && (strcmp (s, "acc") == 0))
1407 if (strcmp (aop->aopu.aop_str[offset], s))
1408 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1412 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1413 "aopPut got unsupported aop->type");
1420 /*--------------------------------------------------------------------*/
1421 /* reAdjustPreg - points a register back to where it should (coff==0) */
1422 /*--------------------------------------------------------------------*/
1424 reAdjustPreg (asmop * aop)
1426 if ((aop->coff==0) || (aop->size <= 1)) {
1435 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1439 if (aop->type == AOP_DPTR2)
1446 emitcode ("lcall", "__decdptr");
1449 if (aop->type == AOP_DPTR2)
1459 #define AOP(op) op->aop
1460 #define AOP_TYPE(op) AOP(op)->type
1461 #define AOP_SIZE(op) AOP(op)->size
1462 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1463 AOP_TYPE(x) == AOP_R0))
1465 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1466 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1469 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1470 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1471 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1472 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1473 #define AOP_USESDPTR(x) (AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_STR)
1475 /* Workaround for DS80C390 bug: div ab may return bogus results
1476 * if A is accessed in instruction immediately before the div.
1478 * Will be fixed in B4 rev of processor, Dallas claims.
1481 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1482 if (!AOP_NEEDSACC(RIGHT)) \
1484 /* We can load A first, then B, since \
1485 * B (the RIGHT operand) won't clobber A, \
1486 * thus avoiding touching A right before the div. \
1488 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1489 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1491 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1495 /* Just stuff in a nop after loading A. */ \
1496 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1497 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1499 emitcode("nop", "; workaround for DS80C390 div bug."); \
1502 /*-----------------------------------------------------------------*/
1503 /* genNotFloat - generates not for float operations */
1504 /*-----------------------------------------------------------------*/
1506 genNotFloat (operand * op, operand * res)
1512 D (emitcode (";", "genNotFloat ");
1515 /* we will put 127 in the first byte of
1517 aopPut (AOP (res), "#127", 0);
1518 size = AOP_SIZE (op) - 1;
1521 _startLazyDPSEvaluation ();
1522 l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1527 emitcode ("orl", "a,%s",
1529 offset++, FALSE, FALSE, FALSE));
1531 _endLazyDPSEvaluation ();
1533 tlbl = newiTempLabel (NULL);
1534 aopPut (res->aop, one, 1);
1535 emitcode ("jz", "!tlabel", (tlbl->key + 100));
1536 aopPut (res->aop, zero, 1);
1537 emitcode ("", "!tlabeldef", (tlbl->key + 100));
1539 size = res->aop->size - 2;
1541 /* put zeros in the rest */
1543 aopPut (res->aop, zero, offset++);
1546 /*-----------------------------------------------------------------*/
1547 /* opIsGptr: returns non-zero if the passed operand is */
1548 /* a generic pointer type. */
1549 /*-----------------------------------------------------------------*/
1551 opIsGptr (operand * op)
1553 sym_link *type = operandType (op);
1555 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1562 /*-----------------------------------------------------------------*/
1563 /* getDataSize - get the operand data size */
1564 /*-----------------------------------------------------------------*/
1566 getDataSize (operand * op)
1569 size = AOP_SIZE (op);
1570 if (size == GPTRSIZE)
1572 sym_link *type = operandType (op);
1573 if (IS_GENPTR (type))
1575 /* generic pointer; arithmetic operations
1576 * should ignore the high byte (pointer type).
1584 /*-----------------------------------------------------------------*/
1585 /* outAcc - output Acc */
1586 /*-----------------------------------------------------------------*/
1588 outAcc (operand * result)
1591 size = getDataSize (result);
1594 aopPut (AOP (result), "a", 0);
1597 /* unsigned or positive */
1600 aopPut (AOP (result), zero, offset++);
1605 /*-----------------------------------------------------------------*/
1606 /* outBitC - output a bit C */
1607 /*-----------------------------------------------------------------*/
1609 outBitC (operand * result)
1611 /* if the result is bit */
1612 if (AOP_TYPE (result) == AOP_CRY)
1614 aopPut (AOP (result), "c", 0);
1618 emitcode ("clr", "a");
1619 emitcode ("rlc", "a");
1624 /*-----------------------------------------------------------------*/
1625 /* toBoolean - emit code for orl a,operator(sizeop) */
1626 /*-----------------------------------------------------------------*/
1628 toBoolean (operand * oper)
1630 int size = AOP_SIZE (oper) - 1;
1634 /* The generic part of a generic pointer should
1635 * not participate in it's truth value.
1637 * i.e. 0x10000000 is zero.
1639 if (opIsGptr (oper))
1641 D (emitcode (";", "toBoolean: generic ptr special case.");
1646 _startLazyDPSEvaluation ();
1647 if (AOP_NEEDSACC (oper) && size)
1650 emitcode ("push", "b");
1651 emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1655 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1661 emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1665 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1668 _endLazyDPSEvaluation ();
1672 emitcode ("mov", "a,b");
1673 emitcode ("pop", "b");
1678 /*-----------------------------------------------------------------*/
1679 /* genNot - generate code for ! operation */
1680 /*-----------------------------------------------------------------*/
1685 sym_link *optype = operandType (IC_LEFT (ic));
1687 D (emitcode (";", "genNot ");
1690 /* assign asmOps to operand & result */
1691 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1692 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1694 /* if in bit space then a special case */
1695 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1697 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1698 emitcode ("cpl", "c");
1699 outBitC (IC_RESULT (ic));
1703 /* if type float then do float */
1704 if (IS_FLOAT (optype))
1706 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1710 toBoolean (IC_LEFT (ic));
1712 tlbl = newiTempLabel (NULL);
1713 emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1714 emitcode ("", "!tlabeldef", tlbl->key + 100);
1715 outBitC (IC_RESULT (ic));
1718 /* release the aops */
1719 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1720 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1724 /*-----------------------------------------------------------------*/
1725 /* genCpl - generate code for complement */
1726 /*-----------------------------------------------------------------*/
1734 D (emitcode (";", "genCpl ");
1738 /* assign asmOps to operand & result */
1739 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1740 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1742 /* special case if in bit space */
1743 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1744 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1745 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1746 emitcode ("cpl", "c");
1747 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1750 tlbl=newiTempLabel(NULL);
1751 emitcode ("cjne", "%s,#0x01,%05d$",
1752 aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,TRUE), tlbl->key+100);
1753 emitcode ("", "%05d$:", tlbl->key+100);
1754 outBitC (IC_RESULT(ic));
1758 size = AOP_SIZE (IC_RESULT (ic));
1759 _startLazyDPSEvaluation ();
1762 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1764 emitcode ("cpl", "a");
1765 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1767 _endLazyDPSEvaluation ();
1771 /* release the aops */
1772 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1773 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1776 /*-----------------------------------------------------------------*/
1777 /* genUminusFloat - unary minus for floating points */
1778 /*-----------------------------------------------------------------*/
1780 genUminusFloat (operand * op, operand * result)
1782 int size, offset = 0;
1784 /* for this we just need to flip the
1785 first it then copy the rest in place */
1786 D (emitcode (";", "genUminusFloat");
1789 _startLazyDPSEvaluation ();
1790 size = AOP_SIZE (op) - 1;
1791 l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1794 emitcode ("cpl", "acc.7");
1795 aopPut (AOP (result), "a", 3);
1799 aopPut (AOP (result),
1800 aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1804 _endLazyDPSEvaluation ();
1807 /*-----------------------------------------------------------------*/
1808 /* genUminus - unary minus code generation */
1809 /*-----------------------------------------------------------------*/
1811 genUminus (iCode * ic)
1814 sym_link *optype, *rtype;
1816 D (emitcode (";", "genUminus ");
1821 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1822 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1824 /* if both in bit space then special
1826 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1827 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1830 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1831 emitcode ("cpl", "c");
1832 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1836 optype = operandType (IC_LEFT (ic));
1837 rtype = operandType (IC_RESULT (ic));
1839 /* if float then do float stuff */
1840 if (IS_FLOAT (optype))
1842 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1846 /* otherwise subtract from zero */
1847 size = AOP_SIZE (IC_LEFT (ic));
1849 _startLazyDPSEvaluation ();
1852 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1853 if (!strcmp (l, "a"))
1857 emitcode ("cpl", "a");
1858 emitcode ("addc", "a,#0");
1864 emitcode ("clr", "a");
1865 emitcode ("subb", "a,%s", l);
1867 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1869 _endLazyDPSEvaluation ();
1871 /* if any remaining bytes in the result */
1872 /* we just need to propagate the sign */
1873 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1875 emitcode ("rlc", "a");
1876 emitcode ("subb", "a,acc");
1878 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1882 /* release the aops */
1883 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1884 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1887 /*-----------------------------------------------------------------*/
1888 /* savermask - saves registers in the mask */
1889 /*-----------------------------------------------------------------*/
1890 static void savermask(bitVect *rs_mask)
1893 if (options.useXstack) {
1894 if (bitVectBitValue (rs_mask, R0_IDX))
1895 emitcode ("mov", "b,r0");
1896 emitcode ("mov", "r0,%s", spname);
1897 for (i = 0; i < ds390_nRegs; i++) {
1898 if (bitVectBitValue (rs_mask, i)) {
1900 emitcode ("mov", "a,b");
1902 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1903 emitcode ("movx", "@r0,a");
1904 emitcode ("inc", "r0");
1907 emitcode ("mov", "%s,r0", spname);
1908 if (bitVectBitValue (rs_mask, R0_IDX))
1909 emitcode ("mov", "r0,b");
1911 for (i = 0; i < ds390_nRegs; i++) {
1912 if (bitVectBitValue (rs_mask, i))
1913 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1918 /*-----------------------------------------------------------------*/
1919 /* saveRegisters - will look for a call and save the registers */
1920 /*-----------------------------------------------------------------*/
1922 saveRegisters (iCode * lic)
1928 for (ic = lic; ic; ic = ic->next)
1929 if (ic->op == CALL || ic->op == PCALL)
1934 fprintf (stderr, "found parameter push with no function call\n");
1938 /* if the registers have been saved already then
1940 if (ic->regsSaved || IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic)))) return ;
1942 /* special case if DPTR alive across a function call then must save it
1943 even though callee saves */
1944 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
1946 rsave = newBitVect(ic->rMask->size);
1947 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
1948 if (bitVectBitValue(ic->rMask,i))
1949 rsave = bitVectSetBit(rsave,i);
1951 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
1953 /* safe the registers in use at this time but skip the
1954 ones for the result */
1955 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1956 ds390_rUmaskForOp (IC_RESULT(ic)));
1962 /*-----------------------------------------------------------------*/
1963 /* usavermask - restore registers with mask */
1964 /*-----------------------------------------------------------------*/
1965 static void unsavermask(bitVect *rs_mask)
1968 if (options.useXstack) {
1969 emitcode ("mov", "r0,%s", spname);
1970 for (i = ds390_nRegs; i >= 0; i--) {
1971 if (bitVectBitValue (rs_mask, i)) {
1972 emitcode ("dec", "r0");
1973 emitcode ("movx", "a,@r0");
1975 emitcode ("mov", "b,a");
1977 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1980 emitcode ("mov", "%s,r0", spname);
1981 if (bitVectBitValue (rs_mask, R0_IDX))
1982 emitcode ("mov", "r0,b");
1984 for (i = ds390_nRegs; i >= 0; i--) {
1985 if (bitVectBitValue (rs_mask, i))
1986 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1991 /*-----------------------------------------------------------------*/
1992 /* unsaveRegisters - pop the pushed registers */
1993 /*-----------------------------------------------------------------*/
1995 unsaveRegisters (iCode * ic)
1999 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2001 rsave = newBitVect(ic->rMask->size);
2002 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2003 if (bitVectBitValue(ic->rMask,i))
2004 rsave = bitVectSetBit(rsave,i);
2006 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2008 /* restore the registers in use at this time but skip the
2009 ones for the result */
2010 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2011 ds390_rUmaskForOp (IC_RESULT(ic)));
2017 /*-----------------------------------------------------------------*/
2019 /*-----------------------------------------------------------------*/
2021 pushSide (operand * oper, int size)
2024 _startLazyDPSEvaluation ();
2027 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
2028 if (AOP_TYPE (oper) != AOP_REG &&
2029 AOP_TYPE (oper) != AOP_DIR &&
2032 emitcode ("mov", "a,%s", l);
2033 emitcode ("push", "acc");
2036 emitcode ("push", "%s", l);
2038 _endLazyDPSEvaluation ();
2041 /*-----------------------------------------------------------------*/
2042 /* assignResultValue - */
2043 /*-----------------------------------------------------------------*/
2045 assignResultValue (operand * oper)
2048 int size = AOP_SIZE (oper);
2050 _startLazyDPSEvaluation ();
2053 aopPut (AOP (oper), fReturn[offset], offset);
2056 _endLazyDPSEvaluation ();
2060 /*-----------------------------------------------------------------*/
2061 /* genXpush - pushes onto the external stack */
2062 /*-----------------------------------------------------------------*/
2064 genXpush (iCode * ic)
2066 asmop *aop = newAsmop (0);
2068 int size, offset = 0;
2070 D (emitcode (";", "genXpush ");
2073 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2074 r = getFreePtr (ic, &aop, FALSE);
2077 emitcode ("mov", "%s,_spx", r->name);
2079 size = AOP_SIZE (IC_LEFT (ic));
2080 _startLazyDPSEvaluation ();
2084 char *l = aopGet (AOP (IC_LEFT (ic)),
2085 offset++, FALSE, FALSE, TRUE);
2087 emitcode ("movx", "@%s,a", r->name);
2088 emitcode ("inc", "%s", r->name);
2091 _endLazyDPSEvaluation ();
2094 emitcode ("mov", "_spx,%s", r->name);
2096 freeAsmop (NULL, aop, ic, TRUE);
2097 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2100 /*-----------------------------------------------------------------*/
2101 /* genIpush - genrate code for pushing this gets a little complex */
2102 /*-----------------------------------------------------------------*/
2104 genIpush (iCode * ic)
2106 int size, offset = 0;
2109 D (emitcode (";", "genIpush ");
2112 /* if this is not a parm push : ie. it is spill push
2113 and spill push is always done on the local stack */
2117 /* and the item is spilt then do nothing */
2118 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2121 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2122 size = AOP_SIZE (IC_LEFT (ic));
2123 /* push it on the stack */
2124 _startLazyDPSEvaluation ();
2127 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
2133 emitcode ("push", "%s", l);
2135 _endLazyDPSEvaluation ();
2139 /* this is a paramter push: in this case we call
2140 the routine to find the call and save those
2141 registers that need to be saved */
2144 /* if use external stack then call the external
2145 stack pushing routine */
2146 if (options.useXstack)
2152 /* then do the push */
2153 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2155 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2156 size = AOP_SIZE (IC_LEFT (ic));
2158 _startLazyDPSEvaluation ();
2161 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
2162 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2163 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2166 emitcode ("mov", "a,%s", l);
2167 emitcode ("push", "acc");
2170 emitcode ("push", "%s", l);
2172 _endLazyDPSEvaluation ();
2174 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2177 /*-----------------------------------------------------------------*/
2178 /* genIpop - recover the registers: can happen only for spilling */
2179 /*-----------------------------------------------------------------*/
2181 genIpop (iCode * ic)
2185 D (emitcode (";", "genIpop ");
2189 /* if the temp was not pushed then */
2190 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2193 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2194 size = AOP_SIZE (IC_LEFT (ic));
2195 offset = (size - 1);
2196 _startLazyDPSEvaluation ();
2199 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2200 FALSE, TRUE, TRUE));
2202 _endLazyDPSEvaluation ();
2204 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2207 /*-----------------------------------------------------------------*/
2208 /* unsaveRBank - restores the resgister bank from stack */
2209 /*-----------------------------------------------------------------*/
2211 unsaveRBank (int bank, iCode * ic, bool popPsw)
2217 if (options.useXstack)
2221 /* Assume r0 is available for use. */
2222 r = ds390_regWithIdx (R0_IDX);;
2227 r = getFreePtr (ic, &aop, FALSE);
2229 emitcode ("mov", "%s,_spx", r->name);
2234 if (options.useXstack)
2236 emitcode ("movx", "a,@%s", r->name);
2237 emitcode ("mov", "psw,a");
2238 emitcode ("dec", "%s", r->name);
2242 emitcode ("pop", "psw");
2246 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2248 if (options.useXstack)
2250 emitcode ("movx", "a,@%s", r->name);
2251 emitcode ("mov", "(%s+%d),a",
2252 regs390[i].base, 8 * bank + regs390[i].offset);
2253 emitcode ("dec", "%s", r->name);
2257 emitcode ("pop", "(%s+%d)",
2258 regs390[i].base, 8 * bank + regs390[i].offset);
2261 if (options.useXstack)
2263 emitcode ("mov", "_spx,%s", r->name);
2268 freeAsmop (NULL, aop, ic, TRUE);
2272 /*-----------------------------------------------------------------*/
2273 /* saveRBank - saves an entire register bank on the stack */
2274 /*-----------------------------------------------------------------*/
2276 saveRBank (int bank, iCode * ic, bool pushPsw)
2282 if (options.useXstack)
2286 /* Assume r0 is available for use. */
2287 r = ds390_regWithIdx (R0_IDX);;
2292 r = getFreePtr (ic, &aop, FALSE);
2294 emitcode ("mov", "%s,_spx", r->name);
2297 for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2299 if (options.useXstack)
2301 emitcode ("inc", "%s", r->name);
2302 emitcode ("mov", "a,(%s+%d)",
2303 regs390[i].base, 8 * bank + regs390[i].offset);
2304 emitcode ("movx", "@%s,a", r->name);
2307 emitcode ("push", "(%s+%d)",
2308 regs390[i].base, 8 * bank + regs390[i].offset);
2313 if (options.useXstack)
2315 emitcode ("mov", "a,psw");
2316 emitcode ("movx", "@%s,a", r->name);
2317 emitcode ("inc", "%s", r->name);
2318 emitcode ("mov", "_spx,%s", r->name);
2322 emitcode ("push", "psw");
2325 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2330 freeAsmop (NULL, aop, ic, TRUE);
2339 /*-----------------------------------------------------------------*/
2340 /* genSend - gen code for SEND */
2341 /*-----------------------------------------------------------------*/
2342 static void genSend(set *sendSet)
2346 static int rb1_count = 0;
2348 for (sic = setFirstItem (sendSet); sic;
2349 sic = setNextItem (sendSet)) {
2350 int size, offset = 0;
2352 size=getSize(operandType(IC_LEFT(sic)));
2353 D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2354 if (sendCount == 0) { /* first parameter */
2355 // we know that dpl(hxb) is the result, so
2357 _startLazyDPSEvaluation ();
2359 aopOp (IC_LEFT (sic), sic, FALSE,
2360 (IS_SYMOP(IC_LEFT(sic)) && OP_SYMBOL(IC_LEFT(sic))->ruonly ? FALSE : TRUE));
2362 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2365 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2366 FALSE, FALSE, TRUE);
2367 if (strcmp (l, fReturn[offset])) {
2368 emitcode ("mov", "%s,%s",
2374 _endLazyDPSEvaluation ();
2375 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2377 } else { /* if more parameter in registers */
2378 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2380 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2381 FALSE, FALSE, TRUE));
2383 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2389 /*-----------------------------------------------------------------*/
2390 /* genCall - generates a call statement */
2391 /*-----------------------------------------------------------------*/
2393 genCall (iCode * ic)
2396 bool restoreBank = FALSE;
2397 bool swapBanks = FALSE;
2399 D (emitcode (";", "genCall "););
2401 /* if we are calling a not _naked function that is not using
2402 the same register bank then we need to save the
2403 destination registers on the stack */
2404 dtype = operandType (IC_LEFT (ic));
2405 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2406 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2407 IFFUNC_ISISR (currFunc->type))
2411 /* This is unexpected; the bank should have been saved in
2414 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2420 /* if caller saves & we have not saved then */
2424 /* if send set is not empty the assign */
2425 /* We've saved all the registers we care about;
2426 * therefore, we may clobber any register not used
2427 * in the calling convention (i.e. anything not in
2432 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2433 genSend(reverseSet(_G.sendSet));
2435 genSend(_G.sendSet);
2442 emitcode ("mov", "psw,#!constbyte",
2443 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2447 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2448 OP_SYMBOL (IC_LEFT (ic))->rname :
2449 OP_SYMBOL (IC_LEFT (ic))->name));
2453 emitcode ("mov", "psw,#!constbyte",
2454 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2457 /* if we need assign a result value */
2458 if ((IS_ITEMP (IC_RESULT (ic)) &&
2459 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2460 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2461 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2462 IS_TRUE_SYMOP (IC_RESULT (ic)))
2464 if (isOperandInFarSpace (IC_RESULT (ic))
2465 && getSize (operandType (IC_RESULT (ic))) <= 2)
2467 int size = getSize (operandType (IC_RESULT (ic)));
2469 /* Special case for 1 or 2 byte return in far space. */
2473 emitcode ("mov", "b,%s", fReturn[1]);
2476 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2477 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2481 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2483 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2488 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2491 assignResultValue (IC_RESULT (ic));
2493 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2497 /* adjust the stack for parameters if
2499 if (ic->parmBytes) {
2501 if (options.stack10bit) {
2502 if (ic->parmBytes <= 10) {
2503 emitcode(";","stack adjustment for parms");
2504 for (i=0; i < ic->parmBytes ; i++) {
2505 emitcode("pop","acc");
2509 emitcode ("clr","c");
2510 emitcode ("mov","a,sp");
2511 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2512 emitcode ("mov","sp,a");
2513 emitcode ("mov","a,esp");
2514 emitcode ("anl","a,#3");
2515 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2516 emitcode ("mov","esp,a");
2520 if (ic->parmBytes > 3) {
2521 emitcode ("mov", "a,%s", spname);
2522 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2523 emitcode ("mov", "%s,a", spname);
2525 for (i = 0; i < ic->parmBytes; i++)
2526 emitcode ("dec", "%s", spname);
2530 /* if we hade saved some registers then unsave them */
2532 unsaveRegisters (ic);
2534 /* if register bank was saved then pop them */
2536 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2539 /*-----------------------------------------------------------------*/
2540 /* genPcall - generates a call by pointer statement */
2541 /*-----------------------------------------------------------------*/
2543 genPcall (iCode * ic)
2546 symbol *rlbl = newiTempLabel (NULL);
2547 bool restoreBank=FALSE;
2549 D (emitcode (";", "genPcall ");
2553 /* if caller saves & we have not saved then */
2557 /* if we are calling a function that is not using
2558 the same register bank then we need to save the
2559 destination registers on the stack */
2560 dtype = operandType (IC_LEFT (ic));
2561 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2562 IFFUNC_ISISR (currFunc->type) &&
2563 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2564 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2568 /* push the return address on to the stack */
2569 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2570 emitcode ("push", "acc");
2571 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2572 emitcode ("push", "acc");
2574 if (options.model == MODEL_FLAT24)
2576 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2577 emitcode ("push", "acc");
2580 /* now push the calling address */
2581 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2583 pushSide (IC_LEFT (ic), FPTRSIZE);
2585 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2587 /* if send set is not empty the assign */
2590 genSend(reverseSet(_G.sendSet));
2594 emitcode ("ret", "");
2595 emitcode ("", "!tlabeldef", (rlbl->key + 100));
2598 /* if we need assign a result value */
2599 if ((IS_ITEMP (IC_RESULT (ic)) &&
2600 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2601 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2602 IS_TRUE_SYMOP (IC_RESULT (ic)))
2606 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2609 assignResultValue (IC_RESULT (ic));
2611 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2614 /* adjust the stack for parameters if
2619 if (options.stack10bit) {
2620 if (ic->parmBytes <= 10) {
2621 emitcode(";","stack adjustment for parms");
2622 for (i=0; i < ic->parmBytes ; i++) {
2623 emitcode("pop","acc");
2627 emitcode ("clr","c");
2628 emitcode ("mov","a,sp");
2629 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2630 emitcode ("mov","sp,a");
2631 emitcode ("mov","a,esp");
2632 emitcode ("anl","a,#3");
2633 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2634 emitcode ("mov","esp,a");
2638 if (ic->parmBytes > 3) {
2639 emitcode ("mov", "a,%s", spname);
2640 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2641 emitcode ("mov", "%s,a", spname);
2644 for (i = 0; i < ic->parmBytes; i++)
2645 emitcode ("dec", "%s", spname);
2649 /* if register bank was saved then unsave them */
2651 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2653 /* if we hade saved some registers then
2656 unsaveRegisters (ic);
2660 /*-----------------------------------------------------------------*/
2661 /* resultRemat - result is rematerializable */
2662 /*-----------------------------------------------------------------*/
2664 resultRemat (iCode * ic)
2666 if (SKIP_IC (ic) || ic->op == IFX)
2669 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2671 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2672 if (sym->remat && !POINTER_SET (ic))
2679 #if defined(__BORLANDC__) || defined(_MSC_VER)
2680 #define STRCASECMP stricmp
2682 #define STRCASECMP strcasecmp
2685 /*-----------------------------------------------------------------*/
2686 /* inExcludeList - return 1 if the string is in exclude Reg list */
2687 /*-----------------------------------------------------------------*/
2689 inExcludeList (char *s)
2693 if (options.excludeRegs[i] &&
2694 STRCASECMP (options.excludeRegs[i], "none") == 0)
2697 for (i = 0; options.excludeRegs[i]; i++)
2699 if (options.excludeRegs[i] &&
2700 STRCASECMP (s, options.excludeRegs[i]) == 0)
2706 /*-----------------------------------------------------------------*/
2707 /* genFunction - generated code for function entry */
2708 /*-----------------------------------------------------------------*/
2710 genFunction (iCode * ic)
2714 bool switchedPSW = FALSE;
2716 D (emitcode (";", "genFunction "););
2719 /* create the function header */
2720 emitcode (";", "-----------------------------------------");
2721 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2722 emitcode (";", "-----------------------------------------");
2724 emitcode ("", "%s:", sym->rname);
2725 ftype = operandType (IC_LEFT (ic));
2727 if (IFFUNC_ISNAKED(ftype))
2729 emitcode(";", "naked function: no prologue.");
2733 if (options.stack_probe)
2734 emitcode ("lcall","__stack_probe");
2735 /* if critical function then turn interrupts off */
2736 if (IFFUNC_ISCRITICAL (ftype))
2737 emitcode ("clr", "ea");
2739 /* here we need to generate the equates for the
2740 register bank if required */
2741 if (FUNC_REGBANK (ftype) != rbank)
2745 rbank = FUNC_REGBANK (ftype);
2746 for (i = 0; i < ds390_nRegs; i++)
2748 if (regs390[i].print) {
2749 if (strcmp (regs390[i].base, "0") == 0)
2750 emitcode ("", "%s !equ !constbyte",
2752 8 * rbank + regs390[i].offset);
2754 emitcode ("", "%s !equ %s + !constbyte",
2757 8 * rbank + regs390[i].offset);
2762 /* if this is an interrupt service routine then
2763 save acc, b, dpl, dph */
2764 if (IFFUNC_ISISR (sym->type))
2766 if (!inExcludeList ("acc"))
2767 emitcode ("push", "acc");
2768 if (!inExcludeList ("b"))
2769 emitcode ("push", "b");
2770 if (!inExcludeList ("dpl"))
2771 emitcode ("push", "dpl");
2772 if (!inExcludeList ("dph"))
2773 emitcode ("push", "dph");
2774 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2776 emitcode ("push", "dpx");
2777 /* Make sure we're using standard DPTR */
2778 emitcode ("push", "dps");
2779 emitcode ("mov", "dps,#0");
2780 if (options.stack10bit)
2782 /* This ISR could conceivably use DPTR2. Better save it. */
2783 emitcode ("push", "dpl1");
2784 emitcode ("push", "dph1");
2785 emitcode ("push", "dpx1");
2786 emitcode ("push", DP2_RESULT_REG);
2789 /* if this isr has no bank i.e. is going to
2790 run with bank 0 , then we need to save more
2792 if (!FUNC_REGBANK (sym->type))
2796 /* if this function does not call any other
2797 function then we can be economical and
2798 save only those registers that are used */
2799 if (!IFFUNC_HASFCALL(sym->type))
2802 /* if any registers used */
2805 /* save the registers used */
2806 for (i = 0; i < sym->regsUsed->size; i++)
2808 if (bitVectBitValue (sym->regsUsed, i) ||
2809 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2810 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2817 /* this function has a function call cannot
2818 determines register usage so we will have to push the
2820 saveRBank (0, ic, FALSE);
2821 if (options.parms_in_bank1) {
2822 for (i=0; i < 8 ; i++ ) {
2823 emitcode ("push","%s",rb1regs[i]);
2830 /* This ISR uses a non-zero bank.
2832 * We assume that the bank is available for our
2835 * However, if this ISR calls a function which uses some
2836 * other bank, we must save that bank entirely.
2838 unsigned long banksToSave = 0;
2840 if (IFFUNC_HASFCALL(sym->type))
2843 #define MAX_REGISTER_BANKS 4
2848 for (i = ic; i; i = i->next)
2850 if (i->op == ENDFUNCTION)
2852 /* we got to the end OK. */
2860 dtype = operandType (IC_LEFT(i));
2862 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2864 /* Mark this bank for saving. */
2865 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2867 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2871 banksToSave |= (1 << FUNC_REGBANK(dtype));
2874 /* And note that we don't need to do it in
2882 /* This is a mess; we have no idea what
2883 * register bank the called function might
2886 * The only thing I can think of to do is
2887 * throw a warning and hope.
2889 werror(W_FUNCPTR_IN_USING_ISR);
2893 if (banksToSave && options.useXstack)
2895 /* Since we aren't passing it an ic,
2896 * saveRBank will assume r0 is available to abuse.
2898 * So switch to our (trashable) bank now, so
2899 * the caller's R0 isn't trashed.
2901 emitcode ("push", "psw");
2902 emitcode ("mov", "psw,#!constbyte",
2903 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2907 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2909 if (banksToSave & (1 << ix))
2911 saveRBank(ix, NULL, FALSE);
2915 // jwk: this needs a closer look
2916 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2921 /* if callee-save to be used for this function
2922 then save the registers being used in this function */
2923 if (IFFUNC_CALLEESAVES(sym->type))
2927 /* if any registers used */
2930 /* save the registers used */
2931 for (i = 0; i < sym->regsUsed->size; i++)
2933 if (bitVectBitValue (sym->regsUsed, i) ||
2934 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2936 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2944 /* set the register bank to the desired value */
2945 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
2948 emitcode ("push", "psw");
2949 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2952 if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
2953 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
2954 if (options.stack10bit) {
2955 emitcode ("push","_bpx");
2956 emitcode ("push","_bpx+1");
2957 emitcode ("mov","_bpx,%s",spname);
2958 emitcode ("mov","_bpx+1,esp");
2959 emitcode ("anl","_bpx+1,#3");
2961 if (options.useXstack) {
2962 emitcode ("mov", "r0,%s", spname);
2963 emitcode ("mov", "a,_bp");
2964 emitcode ("movx", "@r0,a");
2965 emitcode ("inc", "%s", spname);
2967 /* set up the stack */
2968 emitcode ("push", "_bp"); /* save the callers stack */
2970 emitcode ("mov", "_bp,%s", spname);
2974 /* adjust the stack for the function */
2977 if (options.stack10bit) {
2978 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
2979 assert (sym->recvSize <= 4);
2980 if (sym->stack <= 8) {
2981 while (i--) emitcode ("push","acc");
2984 emitcode ("mov","a,sp");
2985 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
2986 emitcode ("mov","sp,a");
2987 emitcode ("mov","a,esp");
2988 emitcode ("anl","a,#3");
2989 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
2990 emitcode ("mov","esp,a");
2995 werror (W_STACK_OVERFLOW, sym->name);
2997 if (i > 3 && sym->recvSize < 4) {
2999 emitcode ("mov", "a,sp");
3000 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3001 emitcode ("mov", "sp,a");
3005 emitcode ("inc", "sp");
3012 emitcode ("mov", "a,_spx");
3013 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3014 emitcode ("mov", "_spx,a");
3019 /*-----------------------------------------------------------------*/
3020 /* genEndFunction - generates epilogue for functions */
3021 /*-----------------------------------------------------------------*/
3023 genEndFunction (iCode * ic)
3025 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3027 D (emitcode (";", "genEndFunction "););
3029 if (IFFUNC_ISNAKED(sym->type))
3031 emitcode(";", "naked function: no epilogue.");
3035 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3036 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3038 if (options.stack10bit) {
3040 emitcode ("mov", "sp,_bpx", spname);
3041 emitcode ("mov", "esp,_bpx+1", spname);
3044 emitcode ("mov", "%s,_bp", spname);
3048 /* if use external stack but some variables were
3049 added to the local stack then decrement the
3051 if (options.useXstack && sym->stack) {
3052 emitcode ("mov", "a,sp");
3053 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3054 emitcode ("mov", "sp,a");
3058 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3059 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3061 if (options.useXstack) {
3062 emitcode ("mov", "r0,%s", spname);
3063 emitcode ("movx", "a,@r0");
3064 emitcode ("mov", "_bp,a");
3065 emitcode ("dec", "%s", spname);
3067 if (options.stack10bit) {
3068 emitcode ("pop", "_bpx+1");
3069 emitcode ("pop", "_bpx");
3071 emitcode ("pop", "_bp");
3076 /* restore the register bank */
3077 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3079 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3080 || !options.useXstack)
3082 /* Special case of ISR using non-zero bank with useXstack
3085 emitcode ("pop", "psw");
3089 if (IFFUNC_ISISR (sym->type))
3092 /* now we need to restore the registers */
3093 /* if this isr has no bank i.e. is going to
3094 run with bank 0 , then we need to save more
3096 if (!FUNC_REGBANK (sym->type))
3099 /* if this function does not call any other
3100 function then we can be economical and
3101 save only those registers that are used */
3102 if (!IFFUNC_HASFCALL(sym->type))
3105 /* if any registers used */
3108 /* save the registers used */
3109 for (i = sym->regsUsed->size; i >= 0; i--)
3111 if (bitVectBitValue (sym->regsUsed, i) ||
3112 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3113 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3120 /* this function has a function call cannot
3121 determines register usage so we will have to pop the
3123 if (options.parms_in_bank1) {
3124 for (i = 7 ; i >= 0 ; i-- ) {
3125 emitcode ("pop","%s",rb1regs[i]);
3128 unsaveRBank (0, ic, FALSE);
3133 /* This ISR uses a non-zero bank.
3135 * Restore any register banks saved by genFunction
3138 // jwk: this needs a closer look
3139 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3142 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3144 if (savedBanks & (1 << ix))
3146 unsaveRBank(ix, NULL, FALSE);
3150 if (options.useXstack)
3152 /* Restore bank AFTER calling unsaveRBank,
3153 * since it can trash r0.
3155 emitcode ("pop", "psw");
3159 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3161 if (options.stack10bit)
3163 emitcode ("pop", DP2_RESULT_REG);
3164 emitcode ("pop", "dpx1");
3165 emitcode ("pop", "dph1");
3166 emitcode ("pop", "dpl1");
3168 emitcode ("pop", "dps");
3169 emitcode ("pop", "dpx");
3171 if (!inExcludeList ("dph"))
3172 emitcode ("pop", "dph");
3173 if (!inExcludeList ("dpl"))
3174 emitcode ("pop", "dpl");
3175 if (!inExcludeList ("b"))
3176 emitcode ("pop", "b");
3177 if (!inExcludeList ("acc"))
3178 emitcode ("pop", "acc");
3180 if (IFFUNC_ISCRITICAL (sym->type))
3181 emitcode ("setb", "ea");
3183 /* if debug then send end of function */
3184 if (options.debug && currFunc) {
3186 emitcode ("", "C$%s$%d$%d$%d ==.",
3187 FileBaseName (ic->filename), currFunc->lastLine,
3188 ic->level, ic->block);
3189 if (IS_STATIC (currFunc->etype))
3190 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3192 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3196 emitcode ("reti", "");
3200 if (IFFUNC_ISCRITICAL (sym->type))
3201 emitcode ("setb", "ea");
3203 if (IFFUNC_CALLEESAVES(sym->type))
3207 /* if any registers used */
3210 /* save the registers used */
3211 for (i = sym->regsUsed->size; i >= 0; i--)
3213 if (bitVectBitValue (sym->regsUsed, i) ||
3214 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3215 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3221 /* if debug then send end of function */
3222 if (options.debug && currFunc)
3225 emitcode ("", "C$%s$%d$%d$%d ==.",
3226 FileBaseName (ic->filename), currFunc->lastLine,
3227 ic->level, ic->block);
3228 if (IS_STATIC (currFunc->etype))
3229 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3231 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3235 emitcode ("ret", "");
3240 /*-----------------------------------------------------------------*/
3241 /* genJavaNativeRet - generate code for return JavaNative */
3242 /*-----------------------------------------------------------------*/
3243 static void genJavaNativeRet(iCode *ic)
3247 aopOp (IC_LEFT (ic), ic, FALSE,
3248 (IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly ? FALSE :TRUE));
3249 size = AOP_SIZE (IC_LEFT (ic));
3253 /* it is assigned to GPR0-R3 then push them */
3254 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3255 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3256 for (i = 0 ; i < size ; i++ ) {
3257 emitcode ("push","%s",aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,FALSE));
3259 for (i = (size-1) ; i >= 0 ; i--) {
3260 emitcode ("pop","a%s",javaRet[i]);
3263 for (i = 0 ; i < size ; i++)
3264 emitcode ("mov","%s,%s",javaRet[i],aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,FALSE));
3266 for (i = size ; i < 4 ; i++ )
3267 emitcode ("mov","%s,#0",javaRet[i]);
3271 /*-----------------------------------------------------------------*/
3272 /* genRet - generate code for return statement */
3273 /*-----------------------------------------------------------------*/
3277 int size, offset = 0, pushed = 0;
3279 D (emitcode (";", "genRet ");
3282 /* if we have no return value then
3283 just generate the "ret" */
3287 /* if this is a JavaNative function then return
3288 value in different register */
3289 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3290 genJavaNativeRet(ic);
3293 /* we have something to return then
3294 move the return value into place */
3295 aopOp (IC_LEFT (ic), ic, FALSE,
3296 (IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly ? FALSE :TRUE));
3297 size = AOP_SIZE (IC_LEFT (ic));
3299 _startLazyDPSEvaluation ();
3303 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3305 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3306 FALSE, TRUE, FALSE);
3307 emitcode ("push", "%s", l);
3312 /* Since A is the last element of fReturn,
3313 * is is OK to clobber it in the aopGet.
3315 l = aopGet (AOP (IC_LEFT (ic)), offset,
3316 FALSE, FALSE, TRUE);
3317 if (strcmp (fReturn[offset], l))
3318 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3321 _endLazyDPSEvaluation ();
3328 if (strcmp (fReturn[pushed], "a"))
3329 emitcode ("pop", fReturn[pushed]);
3331 emitcode ("pop", "acc");
3334 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3337 /* generate a jump to the return label
3338 if the next is not the return statement */
3339 if (!(ic->next && ic->next->op == LABEL &&
3340 IC_LABEL (ic->next) == returnLabel))
3342 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3346 /*-----------------------------------------------------------------*/
3347 /* genLabel - generates a label */
3348 /*-----------------------------------------------------------------*/
3350 genLabel (iCode * ic)
3352 /* special case never generate */
3353 if (IC_LABEL (ic) == entryLabel)
3356 D (emitcode (";", "genLabel ");
3359 emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3362 /*-----------------------------------------------------------------*/
3363 /* genGoto - generates a ljmp */
3364 /*-----------------------------------------------------------------*/
3366 genGoto (iCode * ic)
3368 D (emitcode (";", "genGoto ");
3370 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3373 /*-----------------------------------------------------------------*/
3374 /* findLabelBackwards: walks back through the iCode chain looking */
3375 /* for the given label. Returns number of iCode instructions */
3376 /* between that label and given ic. */
3377 /* Returns zero if label not found. */
3378 /*-----------------------------------------------------------------*/
3380 findLabelBackwards (iCode * ic, int key)
3389 /* If we have any pushes or pops, we cannot predict the distance.
3390 I don't like this at all, this should be dealt with in the
3392 if (ic->op == IPUSH || ic->op == IPOP) {
3396 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3398 /* printf("findLabelBackwards = %d\n", count); */
3406 /*-----------------------------------------------------------------*/
3407 /* genPlusIncr :- does addition with increment if possible */
3408 /*-----------------------------------------------------------------*/
3410 genPlusIncr (iCode * ic)
3412 unsigned int icount;
3413 unsigned int size = getDataSize (IC_RESULT (ic));
3415 /* will try to generate an increment */
3416 /* if the right side is not a literal
3418 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3421 /* if the literal value of the right hand side
3422 is greater than 4 then it is not worth it */
3423 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3426 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3427 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3429 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3433 /* if increment 16 bits in register */
3435 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3436 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3437 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3445 /* If the next instruction is a goto and the goto target
3446 * is <= 5 instructions previous to this, we can generate
3447 * jumps straight to that target.
3449 if (ic->next && ic->next->op == GOTO
3450 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3453 emitcode (";", "tail increment optimized (range %d)", labelRange);
3454 tlbl = IC_LABEL (ic->next);
3459 tlbl = newiTempLabel (NULL);
3462 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3463 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3464 IS_AOP_PREG (IC_RESULT (ic)))
3465 emitcode ("cjne", "%s,#0,!tlabel"
3466 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3470 emitcode ("clr", "a");
3471 emitcode ("cjne", "a,%s,!tlabel"
3472 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3476 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3479 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3480 IS_AOP_PREG (IC_RESULT (ic)))
3481 emitcode ("cjne", "%s,#0,!tlabel"
3482 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3485 emitcode ("cjne", "a,%s,!tlabel"
3486 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3489 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3493 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3494 IS_AOP_PREG (IC_RESULT (ic)))
3495 emitcode ("cjne", "%s,#0,!tlabel"
3496 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3500 emitcode ("cjne", "a,%s,!tlabel"
3501 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3504 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3509 emitcode ("", "!tlabeldef", tlbl->key + 100);
3514 if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3515 AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3517 emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3518 while (icount--) emitcode ("inc","dptr");
3519 emitcode ("mov","dps,#0");
3523 /* if the sizes are greater than 1 then we cannot */
3524 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3525 AOP_SIZE (IC_LEFT (ic)) > 1)
3528 /* we can if the aops of the left & result match or
3529 if they are in registers and the registers are the
3532 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3533 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3534 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3539 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3540 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3541 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3546 _startLazyDPSEvaluation ();
3549 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3551 _endLazyDPSEvaluation ();
3560 /*-----------------------------------------------------------------*/
3561 /* outBitAcc - output a bit in acc */
3562 /*-----------------------------------------------------------------*/
3564 outBitAcc (operand * result)
3566 symbol *tlbl = newiTempLabel (NULL);
3567 /* if the result is a bit */
3568 if (AOP_TYPE (result) == AOP_CRY)
3570 aopPut (AOP (result), "a", 0);
3574 emitcode ("jz", "!tlabel", tlbl->key + 100);
3575 emitcode ("mov", "a,%s", one);
3576 emitcode ("", "!tlabeldef", tlbl->key + 100);
3581 /*-----------------------------------------------------------------*/
3582 /* genPlusBits - generates code for addition of two bits */
3583 /*-----------------------------------------------------------------*/
3585 genPlusBits (iCode * ic)
3587 D (emitcode (";", "genPlusBits ");
3589 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3591 symbol *lbl = newiTempLabel (NULL);
3592 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3593 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3594 emitcode ("cpl", "c");
3595 emitcode ("", "!tlabeldef", (lbl->key + 100));
3596 outBitC (IC_RESULT (ic));
3600 emitcode ("clr", "a");
3601 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3602 emitcode ("rlc", "a");
3603 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3604 emitcode ("addc", "a,#0");
3605 outAcc (IC_RESULT (ic));
3610 adjustArithmeticResult (iCode * ic)
3612 if (opIsGptr (IC_RESULT (ic)) &&
3613 opIsGptr (IC_LEFT (ic)) &&
3614 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3616 aopPut (AOP (IC_RESULT (ic)),
3617 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3621 if (opIsGptr (IC_RESULT (ic)) &&
3622 opIsGptr (IC_RIGHT (ic)) &&
3623 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3625 aopPut (AOP (IC_RESULT (ic)),
3626 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3630 if (opIsGptr (IC_RESULT (ic)) &&
3631 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3632 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3633 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3634 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3637 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3638 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3642 // Macro to aopOp all three operands of an ic. If this cannot be done,
3643 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3644 // will be set TRUE. The caller must then handle the case specially, noting
3645 // that the IC_RESULT operand is not aopOp'd.
3646 #define AOP_OP_3_NOFATAL(ic, rc) \
3647 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3648 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR) || \
3649 ((OP_SYMBOL(IC_RESULT(ic))->ruonly) && !isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)))); \
3650 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3651 (isOperandInFarSpace(IC_RESULT(ic)) || (OP_SYMBOL(IC_RESULT(ic))->ruonly && !isOperandEqual(IC_LEFT(ic),IC_RESULT(ic))))) \
3653 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3658 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3659 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3661 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3662 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3664 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3666 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3670 // aopOp the left & right operands of an ic.
3671 #define AOP_OP_2(ic) \
3672 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3673 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3675 // convienience macro.
3676 #define AOP_SET_LOCALS(ic) \
3677 left = IC_LEFT(ic); \
3678 right = IC_RIGHT(ic); \
3679 result = IC_RESULT(ic);
3682 // Given an integer value of pushedSize bytes on the stack,
3683 // adjust it to be resultSize bytes, either by discarding
3684 // the most significant bytes or by zero-padding.
3686 // On exit from this macro, pushedSize will have been adjusted to
3687 // equal resultSize, and ACC may be trashed.
3688 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3689 /* If the pushed data is bigger than the result, \
3690 * simply discard unused bytes. Icky, but works. \
3692 while (pushedSize > resultSize) \
3694 D (emitcode (";", "discarding unused result byte."););\
3695 emitcode ("pop", "acc"); \
3698 if (pushedSize < resultSize) \
3700 emitcode ("clr", "a"); \
3701 /* Conversly, we haven't pushed enough here. \
3702 * just zero-pad, and all is well. \
3704 while (pushedSize < resultSize) \
3706 emitcode("push", "acc"); \
3710 assert(pushedSize == resultSize);
3712 /*-----------------------------------------------------------------*/
3713 /* genPlus - generates code for addition */
3714 /*-----------------------------------------------------------------*/
3716 genPlus (iCode * ic)
3718 int size, offset = 0;
3719 bool pushResult = FALSE;
3722 D (emitcode (";", "genPlus "););
3724 /* special cases :- */
3725 if ( IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly &&
3726 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3727 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3728 size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3730 while (size--) emitcode ("inc","dptr");
3732 emitcode ("mov","a,dpl");
3733 emitcode ("add","a,#!constbyte",size & 0xff);
3734 emitcode ("mov","dpl,a");
3735 emitcode ("mov","a,dph");
3736 emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
3737 emitcode ("mov","dph,a");
3738 emitcode ("mov","a,dpx");
3739 emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
3740 emitcode ("mov","dpx,a");
3742 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3745 if ( IS_SYMOP(IC_LEFT(ic)) &&
3746 OP_SYMBOL(IC_LEFT(ic))->remat &&
3747 isOperandInFarSpace(IC_RIGHT(ic))) {
3748 operand *op = IC_RIGHT(ic);
3749 IC_RIGHT(ic) = IC_LEFT(ic);
3753 AOP_OP_3_NOFATAL (ic, pushResult);
3756 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3761 /* if literal, literal on the right or
3762 if left requires ACC or right is already
3764 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3765 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3766 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3768 operand *t = IC_RIGHT (ic);
3769 IC_RIGHT (ic) = IC_LEFT (ic);
3771 emitcode (";", "Swapped plus args.");
3774 /* if both left & right are in bit
3776 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3777 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3783 /* if left in bit space & right literal */
3784 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3785 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3787 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3788 /* if result in bit space */
3789 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3791 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3792 emitcode ("cpl", "c");
3793 outBitC (IC_RESULT (ic));
3797 size = getDataSize (IC_RESULT (ic));
3798 _startLazyDPSEvaluation ();
3801 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3802 emitcode ("addc", "a,#0");
3803 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3805 _endLazyDPSEvaluation ();
3810 /* if I can do an increment instead
3811 of add then GOOD for ME */
3812 if (genPlusIncr (ic) == TRUE)
3814 emitcode (";", "did genPlusIncr");
3819 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3821 _startLazyDPSEvaluation ();
3824 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3826 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3828 emitcode ("add", "a,%s",
3829 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3831 emitcode ("addc", "a,%s",
3832 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3836 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3838 /* right is going to use ACC or we would have taken the
3841 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3843 D(emitcode(";", "+ AOP_ACC special case."););
3844 emitcode("xch", "a, %s", DP2_RESULT_REG);
3846 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3849 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3852 emitcode("add", "a, %s", DP2_RESULT_REG);
3856 emitcode ("add", "a,%s",
3857 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3862 emitcode ("addc", "a,%s",
3863 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3868 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3872 emitcode ("push", "acc");
3876 _endLazyDPSEvaluation ();
3880 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3882 size = getDataSize (IC_LEFT (ic));
3883 rSize = getDataSize (IC_RESULT (ic));
3885 ADJUST_PUSHED_RESULT(size, rSize);
3887 _startLazyDPSEvaluation ();
3890 emitcode ("pop", "acc");
3891 aopPut (AOP (IC_RESULT (ic)), "a", size);
3893 _endLazyDPSEvaluation ();
3896 adjustArithmeticResult (ic);
3899 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3900 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3901 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3904 /*-----------------------------------------------------------------*/
3905 /* genMinusDec :- does subtraction with deccrement if possible */
3906 /*-----------------------------------------------------------------*/
3908 genMinusDec (iCode * ic)
3910 unsigned int icount;
3911 unsigned int size = getDataSize (IC_RESULT (ic));
3913 /* will try to generate an increment */
3914 /* if the right side is not a literal
3916 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3919 /* if the literal value of the right hand side
3920 is greater than 4 then it is not worth it */
3921 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3924 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3925 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3927 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3931 /* if decrement 16 bits in register */
3932 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3933 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3934 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3942 /* If the next instruction is a goto and the goto target
3943 * is <= 5 instructions previous to this, we can generate
3944 * jumps straight to that target.
3946 if (ic->next && ic->next->op == GOTO
3947 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3950 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3951 tlbl = IC_LABEL (ic->next);
3956 tlbl = newiTempLabel (NULL);
3960 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3961 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3962 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3963 IS_AOP_PREG (IC_RESULT (ic)))
3964 emitcode ("cjne", "%s,#!constbyte,!tlabel"
3965 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE), 0xff
3969 emitcode ("mov", "a,#!constbyte",0xff);
3970 emitcode ("cjne", "a,%s,!tlabel"
3971 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3974 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3977 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3978 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3979 IS_AOP_PREG (IC_RESULT (ic)))
3980 emitcode ("cjne", "%s,#!constbyte,!tlabel"
3981 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE),0xff
3985 emitcode ("cjne", "a,%s,!tlabel"
3986 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3989 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3993 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3994 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3995 IS_AOP_PREG (IC_RESULT (ic)))
3996 emitcode ("cjne", "%s,#!constbyte,!tlabel"
3997 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE),0xff
4001 emitcode ("cjne", "a,%s,!tlabel"
4002 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
4005 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
4009 emitcode ("", "!tlabeldef", tlbl->key + 100);
4014 /* if the sizes are greater than 1 then we cannot */
4015 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4016 AOP_SIZE (IC_LEFT (ic)) > 1)
4019 /* we can if the aops of the left & result match or
4020 if they are in registers and the registers are the
4023 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4024 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4025 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4028 _startLazyDPSEvaluation ();
4031 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
4033 _endLazyDPSEvaluation ();
4041 /*-----------------------------------------------------------------*/
4042 /* addSign - complete with sign */
4043 /*-----------------------------------------------------------------*/
4045 addSign (operand * result, int offset, int sign)
4047 int size = (getDataSize (result) - offset);
4050 _startLazyDPSEvaluation();
4053 emitcode ("rlc", "a");
4054 emitcode ("subb", "a,acc");
4057 aopPut (AOP (result), "a", offset++);
4064 aopPut (AOP (result), zero, offset++);
4067 _endLazyDPSEvaluation();
4071 /*-----------------------------------------------------------------*/
4072 /* genMinusBits - generates code for subtraction of two bits */
4073 /*-----------------------------------------------------------------*/
4075 genMinusBits (iCode * ic)
4077 symbol *lbl = newiTempLabel (NULL);
4079 D (emitcode (";", "genMinusBits "););
4081 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4083 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4084 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4085 emitcode ("cpl", "c");
4086 emitcode ("", "!tlabeldef", (lbl->key + 100));
4087 outBitC (IC_RESULT (ic));
4091 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4092 emitcode ("subb", "a,acc");
4093 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4094 emitcode ("inc", "a");
4095 emitcode ("", "!tlabeldef", (lbl->key + 100));
4096 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4097 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4101 /*-----------------------------------------------------------------*/
4102 /* genMinus - generates code for subtraction */
4103 /*-----------------------------------------------------------------*/
4105 genMinus (iCode * ic)
4107 int size, offset = 0;
4109 unsigned long lit = 0L;
4110 bool pushResult = FALSE;
4112 D (emitcode (";", "genMinus "););
4114 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
4115 aopOp (IC_RIGHT (ic), ic, FALSE,
4116 (AOP_INDPTRn(IC_LEFT(ic)) ? FALSE : (AOP_USESDPTR(IC_LEFT(ic)) ? TRUE : FALSE)));
4117 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
4118 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
4124 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
4126 /* special cases :- */
4127 /* if both left & right are in bit space */
4128 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4129 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4135 /* if I can do an decrement instead
4136 of subtract then GOOD for ME */
4137 if (genMinusDec (ic) == TRUE)
4142 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4144 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4150 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4155 /* if literal, add a,#-lit, else normal subb */
4156 _startLazyDPSEvaluation ();
4158 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
4159 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4160 if (AOP_USESDPTR(IC_RIGHT(ic))) {
4161 emitcode ("mov","b,a");
4162 MOVA(aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
4163 emitcode ("xch","a,b");
4164 emitcode ("subb","a,b");
4166 emitcode ("subb", "a,%s",
4167 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
4170 /* first add without previous c */
4172 if (!size && lit==-1) {
4173 emitcode ("dec", "a");
4175 emitcode ("add", "a,#!constbyte",
4176 (unsigned int) (lit & 0x0FFL));
4179 emitcode ("addc", "a,#!constbyte",
4180 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4185 emitcode ("push", "acc");
4187 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4191 _endLazyDPSEvaluation ();
4195 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4197 size = getDataSize (IC_LEFT (ic));
4198 rSize = getDataSize (IC_RESULT (ic));
4200 ADJUST_PUSHED_RESULT(size, rSize);
4202 _startLazyDPSEvaluation ();
4205 emitcode ("pop", "acc");
4206 aopPut (AOP (IC_RESULT (ic)), "a", size);
4208 _endLazyDPSEvaluation ();
4211 adjustArithmeticResult (ic);
4214 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4215 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4216 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4220 /*-----------------------------------------------------------------*/
4221 /* genMultbits :- multiplication of bits */
4222 /*-----------------------------------------------------------------*/
4224 genMultbits (operand * left,
4229 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4230 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4231 aopOp(result, ic, TRUE, FALSE);
4236 /*-----------------------------------------------------------------*/
4237 /* genMultOneByte : 8*8=8/16 bit multiplication */
4238 /*-----------------------------------------------------------------*/
4240 genMultOneByte (operand * left,
4245 sym_link *opetype = operandType (result);
4249 /* (if two literals: the value is computed before) */
4250 /* if one literal, literal on the right */
4251 if (AOP_TYPE (left) == AOP_LIT)
4256 emitcode (";", "swapped left and right");
4259 if (SPEC_USIGN(opetype)
4260 // ignore the sign of left and right, what else can we do?
4261 || (SPEC_USIGN(operandType(left)) &&
4262 SPEC_USIGN(operandType(right)))) {
4263 // just an unsigned 8*8=8/16 multiply
4264 //emitcode (";","unsigned");
4265 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4266 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4267 emitcode ("mul", "ab");
4269 _G.accInUse++; _G.bInUse++;
4270 aopOp(result, ic, TRUE, FALSE);
4272 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4274 // this should never happen
4275 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4276 AOP_SIZE(result), __FILE__, lineno);
4280 aopPut (AOP (result), "a", 0);
4281 _G.accInUse--; _G.bInUse--;
4282 if (AOP_SIZE(result)==2)
4284 aopPut (AOP (result), "b", 1);
4289 // we have to do a signed multiply
4291 emitcode (";", "signed");
4292 emitcode ("clr", "F0"); // reset sign flag
4293 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4295 lbl=newiTempLabel(NULL);
4296 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4297 // left side is negative, 8-bit two's complement, this fails for -128
4298 emitcode ("setb", "F0"); // set sign flag
4299 emitcode ("cpl", "a");
4300 emitcode ("inc", "a");
4302 emitcode ("", "!tlabeldef", lbl->key+100);
4305 if (AOP_TYPE(right)==AOP_LIT) {
4306 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4307 /* AND literal negative */
4308 if ((int) val < 0) {
4309 emitcode ("cpl", "F0"); // complement sign flag
4310 emitcode ("mov", "b,#!constbyte", -val);
4312 emitcode ("mov", "b,#!constbyte", val);
4315 lbl=newiTempLabel(NULL);
4316 emitcode ("mov", "b,a");
4317 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4318 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4319 // right side is negative, 8-bit two's complement
4320 emitcode ("cpl", "F0"); // complement sign flag
4321 emitcode ("cpl", "a");
4322 emitcode ("inc", "a");
4323 emitcode ("", "!tlabeldef", lbl->key+100);
4325 emitcode ("mul", "ab");
4327 _G.accInUse++;_G.bInUse++;
4328 aopOp(result, ic, TRUE, FALSE);
4330 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4332 // this should never happen
4333 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4334 AOP_SIZE(result), __FILE__, lineno);
4338 lbl=newiTempLabel(NULL);
4339 emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4340 // only ONE op was negative, we have to do a 8/16-bit two's complement
4341 emitcode ("cpl", "a"); // lsb
4342 if (AOP_SIZE(result)==1) {
4343 emitcode ("inc", "a");
4345 emitcode ("add", "a,#1");
4346 emitcode ("xch", "a,b");
4347 emitcode ("cpl", "a"); // msb
4348 emitcode ("addc", "a,#0");
4349 emitcode ("xch", "a,b");
4352 emitcode ("", "!tlabeldef", lbl->key+100);
4353 aopPut (AOP (result), "a", 0);
4354 _G.accInUse--;_G.bInUse--;
4355 if (AOP_SIZE(result)==2) {
4356 aopPut (AOP (result), "b", 1);
4360 /*-----------------------------------------------------------------*/
4361 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4362 /*-----------------------------------------------------------------*/
4363 static void genMultTwoByte (operand *left, operand *right,
4364 operand *result, iCode *ic)
4366 sym_link *retype = getSpec(operandType(right));
4367 sym_link *letype = getSpec(operandType(left));
4368 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4371 if (AOP_TYPE (left) == AOP_LIT) {
4376 /* save EA bit in F1 */
4377 lbl = newiTempLabel(NULL);
4378 emitcode ("setb","F1");
4379 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4380 emitcode ("clr","F1");
4381 emitcode("","!tlabeldef",lbl->key+100);
4383 /* load up MB with right */
4385 emitcode("clr","F0");
4386 if (AOP_TYPE(right) == AOP_LIT) {
4387 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4389 emitcode("setb","F0");
4392 emitcode ("mov","mb,#!constbyte",val & 0xff);
4393 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4395 lbl = newiTempLabel(NULL);
4396 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4397 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4398 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4399 emitcode ("xch", "a,b");
4400 emitcode ("cpl","a");
4401 emitcode ("add", "a,#1");
4402 emitcode ("xch", "a,b");
4403 emitcode ("cpl", "a"); // msb
4404 emitcode ("addc", "a,#0");
4405 emitcode ("setb","F0");
4406 emitcode ("","!tlabeldef",lbl->key+100);
4407 emitcode ("mov","mb,b");
4408 emitcode ("mov","mb,a");
4411 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4412 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4414 /* load up MA with left */
4416 lbl = newiTempLabel(NULL);
4417 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4418 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4419 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4420 emitcode ("xch", "a,b");
4421 emitcode ("cpl","a");
4422 emitcode ("add", "a,#1");
4423 emitcode ("xch", "a,b");
4424 emitcode ("cpl", "a"); // msb
4425 emitcode ("addc","a,#0");
4426 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4427 emitcode ("setb","F0");
4428 emitcode ("","!tlabeldef",lbl->key+100);
4429 emitcode ("mov","ma,b");
4430 emitcode ("mov","ma,a");
4432 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4433 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4435 /* wait for multiplication to finish */
4436 lbl = newiTempLabel(NULL);
4437 emitcode("","!tlabeldef", lbl->key+100);
4438 emitcode("mov","a,mcnt1");
4439 emitcode("anl","a,#!constbyte",0x80);
4440 emitcode("jnz","!tlabel",lbl->key+100);
4442 freeAsmop (left, NULL, ic, TRUE);
4443 freeAsmop (right, NULL, ic,TRUE);
4444 aopOp(result, ic, TRUE, FALSE);
4446 /* if unsigned then simple */
4448 emitcode ("mov","a,ma");
4449 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4450 emitcode ("mov","a,ma");
4451 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4452 aopPut(AOP(result),"ma",1);
4453 aopPut(AOP(result),"ma",0);
4455 emitcode("push","ma");
4456 emitcode("push","ma");
4457 emitcode("push","ma");
4459 /* negate result if needed */
4460 lbl = newiTempLabel(NULL);
4461 emitcode("jnb","F0,!tlabel",lbl->key+100);
4462 emitcode("cpl","a");
4463 emitcode("add","a,#1");
4464 emitcode("","!tlabeldef", lbl->key+100);
4465 if (AOP_TYPE(result) == AOP_ACC)
4467 D(emitcode(";", "ACC special case."););
4468 /* We know result is the only live aop, and
4469 * it's obviously not a DPTR2, so AP is available.
4471 emitcode("mov", "%s,acc", DP2_RESULT_REG);
4475 aopPut(AOP(result),"a",0);
4478 emitcode("pop","acc");
4479 lbl = newiTempLabel(NULL);
4480 emitcode("jnb","F0,!tlabel",lbl->key+100);
4481 emitcode("cpl","a");
4482 emitcode("addc","a,#0");
4483 emitcode("","!tlabeldef", lbl->key+100);
4484 aopPut(AOP(result),"a",1);
4485 emitcode("pop","acc");
4486 if (AOP_SIZE(result) >= 3) {
4487 lbl = newiTempLabel(NULL);
4488 emitcode("jnb","F0,!tlabel",lbl->key+100);
4489 emitcode("cpl","a");
4490 emitcode("addc","a,#0");
4491 emitcode("","!tlabeldef", lbl->key+100);
4492 aopPut(AOP(result),"a",2);
4494 emitcode("pop","acc");
4495 if (AOP_SIZE(result) >= 4) {
4496 lbl = newiTempLabel(NULL);
4497 emitcode("jnb","F0,!tlabel",lbl->key+100);
4498 emitcode("cpl","a");
4499 emitcode("addc","a,#0");
4500 emitcode("","!tlabeldef", lbl->key+100);
4501 aopPut(AOP(result),"a",3);
4503 if (AOP_TYPE(result) == AOP_ACC)
4505 /* We stashed the result away above. */
4506 emitcode("mov", "acc,%s", DP2_RESULT_REG);
4510 freeAsmop (result, NULL, ic, TRUE);
4512 /* restore EA bit in F1 */
4513 lbl = newiTempLabel(NULL);
4514 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4515 emitcode ("setb","EA");
4516 emitcode("","!tlabeldef",lbl->key+100);
4520 /*-----------------------------------------------------------------*/
4521 /* genMult - generates code for multiplication */
4522 /*-----------------------------------------------------------------*/
4524 genMult (iCode * ic)
4526 operand *left = IC_LEFT (ic);
4527 operand *right = IC_RIGHT (ic);
4528 operand *result = IC_RESULT (ic);
4530 D (emitcode (";", "genMult "););
4532 /* assign the amsops */
4535 /* special cases first */
4537 if (AOP_TYPE (left) == AOP_CRY &&
4538 AOP_TYPE (right) == AOP_CRY)
4540 genMultbits (left, right, result, ic);
4544 /* if both are of size == 1 */
4545 if (AOP_SIZE (left) == 1 &&
4546 AOP_SIZE (right) == 1)
4548 genMultOneByte (left, right, result, ic);
4552 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4553 /* use the ds390 ARITHMETIC accel UNIT */
4554 genMultTwoByte (left, right, result, ic);
4557 /* should have been converted to function call */
4561 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4562 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4563 freeAsmop (result, NULL, ic, TRUE);
4566 /*-----------------------------------------------------------------*/
4567 /* genDivbits :- division of bits */
4568 /*-----------------------------------------------------------------*/
4570 genDivbits (operand * left,
4578 /* the result must be bit */
4579 LOAD_AB_FOR_DIV (left, right, l);
4580 emitcode ("div", "ab");
4581 emitcode ("rrc", "a");
4582 aopOp(result, ic, TRUE, FALSE);
4584 aopPut (AOP (result), "c", 0);
4587 /*-----------------------------------------------------------------*/
4588 /* genDivOneByte : 8 bit division */
4589 /*-----------------------------------------------------------------*/
4591 genDivOneByte (operand * left,
4596 sym_link *opetype = operandType (result);
4602 /* signed or unsigned */
4603 if (SPEC_USIGN (opetype))
4605 /* unsigned is easy */
4606 LOAD_AB_FOR_DIV (left, right, l);
4607 emitcode ("div", "ab");
4610 aopOp(result, ic, TRUE, FALSE);
4611 aopPut (AOP (result), "a", 0);
4614 size = AOP_SIZE (result) - 1;
4618 aopPut (AOP (result), zero, offset++);
4623 /* signed is a little bit more difficult */
4625 /* save the signs of the operands */
4626 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4628 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4629 emitcode ("push", "acc"); /* save it on the stack */
4631 /* now sign adjust for both left & right */
4632 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4634 lbl = newiTempLabel (NULL);
4635 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4636 emitcode ("cpl", "a");
4637 emitcode ("inc", "a");
4638 emitcode ("", "!tlabeldef", (lbl->key + 100));
4639 emitcode ("mov", "b,a");
4641 /* sign adjust left side */
4642 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4645 lbl = newiTempLabel (NULL);
4646 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4647 emitcode ("cpl", "a");
4648 emitcode ("inc", "a");
4649 emitcode ("", "!tlabeldef", (lbl->key + 100));
4651 /* now the division */
4652 emitcode ("nop", "; workaround for DS80C390 div bug.");
4653 emitcode ("div", "ab");
4654 /* we are interested in the lower order
4656 emitcode ("mov", "b,a");
4657 lbl = newiTempLabel (NULL);
4658 emitcode ("pop", "acc");
4659 /* if there was an over flow we don't
4660 adjust the sign of the result */
4661 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4662 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4664 emitcode ("clr", "a");
4665 emitcode ("subb", "a,b");
4666 emitcode ("mov", "b,a");
4667 emitcode ("", "!tlabeldef", (lbl->key + 100));
4669 /* now we are done */
4670 _G.accInUse++; _G.bInUse++;
4671 aopOp(result, ic, TRUE, FALSE);
4673 aopPut (AOP (result), "b", 0);
4675 size = AOP_SIZE (result) - 1;
4679 emitcode ("mov", "c,b.7");
4680 emitcode ("subb", "a,acc");
4684 aopPut (AOP (result), "a", offset++);
4686 _G.accInUse--; _G.bInUse--;
4690 /*-----------------------------------------------------------------*/
4691 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
4692 /*-----------------------------------------------------------------*/
4693 static void genDivTwoByte (operand *left, operand *right,
4694 operand *result, iCode *ic)
4696 sym_link *retype = getSpec(operandType(right));
4697 sym_link *letype = getSpec(operandType(left));
4698 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4701 /* save EA bit in F1 */
4702 lbl = newiTempLabel(NULL);
4703 emitcode ("setb","F1");
4704 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4705 emitcode ("clr","F1");
4706 emitcode("","!tlabeldef",lbl->key+100);
4708 /* load up MA with left */
4710 emitcode("clr","F0");
4711 lbl = newiTempLabel(NULL);
4712 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4713 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4714 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4715 emitcode ("xch", "a,b");
4716 emitcode ("cpl","a");
4717 emitcode ("add", "a,#1");
4718 emitcode ("xch", "a,b");
4719 emitcode ("cpl", "a"); // msb
4720 emitcode ("addc","a,#0");
4721 emitcode ("setb","F0");
4722 emitcode ("","!tlabeldef",lbl->key+100);
4723 emitcode ("mov","ma,b");
4724 emitcode ("mov","ma,a");
4726 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4727 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4730 /* load up MB with right */
4732 if (AOP_TYPE(right) == AOP_LIT) {
4733 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4735 lbl = newiTempLabel(NULL);
4736 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4737 emitcode("setb","F0");
4738 emitcode ("","!tlabeldef",lbl->key+100);
4741 emitcode ("mov","mb,#!constbyte",val & 0xff);
4742 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4744 lbl = newiTempLabel(NULL);
4745 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4746 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4747 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4748 emitcode ("xch", "a,b");
4749 emitcode ("cpl","a");
4750 emitcode ("add", "a,#1");
4751 emitcode ("xch", "a,b");
4752 emitcode ("cpl", "a"); // msb
4753 emitcode ("addc", "a,#0");
4754 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4755 emitcode ("setb","F0");
4756 emitcode ("","!tlabeldef",lbl->key+100);
4757 emitcode ("mov","mb,b");
4758 emitcode ("mov","mb,a");
4761 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4762 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4765 /* wait for multiplication to finish */
4766 lbl = newiTempLabel(NULL);
4767 emitcode("","!tlabeldef", lbl->key+100);
4768 emitcode("mov","a,mcnt1");
4769 emitcode("anl","a,#!constbyte",0x80);
4770 emitcode("jnz","!tlabel",lbl->key+100);
4772 freeAsmop (left, NULL, ic, TRUE);
4773 freeAsmop (right, NULL, ic,TRUE);
4774 aopOp(result, ic, TRUE, FALSE);
4776 /* if unsigned then simple */
4778 aopPut(AOP(result),"ma",1);
4779 aopPut(AOP(result),"ma",0);
4781 emitcode("push","ma");
4783 /* negate result if needed */
4784 lbl = newiTempLabel(NULL);
4785 emitcode("jnb","F0,!tlabel",lbl->key+100);
4786 emitcode("cpl","a");
4787 emitcode("add","a,#1");
4788 emitcode("","!tlabeldef", lbl->key+100);
4789 aopPut(AOP(result),"a",0);
4790 emitcode("pop","acc");
4791 lbl = newiTempLabel(NULL);
4792 emitcode("jnb","F0,!tlabel",lbl->key+100);
4793 emitcode("cpl","a");
4794 emitcode("addc","a,#0");
4795 emitcode("","!tlabeldef", lbl->key+100);
4796 aopPut(AOP(result),"a",1);
4798 freeAsmop (result, NULL, ic, TRUE);
4799 /* restore EA bit in F1 */
4800 lbl = newiTempLabel(NULL);
4801 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4802 emitcode ("setb","EA");
4803 emitcode("","!tlabeldef",lbl->key+100);
4807 /*-----------------------------------------------------------------*/
4808 /* genDiv - generates code for division */
4809 /*-----------------------------------------------------------------*/
4813 operand *left = IC_LEFT (ic);
4814 operand *right = IC_RIGHT (ic);
4815 operand *result = IC_RESULT (ic);
4817 D (emitcode (";", "genDiv "););
4819 /* assign the amsops */
4822 /* special cases first */
4824 if (AOP_TYPE (left) == AOP_CRY &&
4825 AOP_TYPE (right) == AOP_CRY)
4827 genDivbits (left, right, result, ic);
4831 /* if both are of size == 1 */
4832 if (AOP_SIZE (left) == 1 &&
4833 AOP_SIZE (right) == 1)
4835 genDivOneByte (left, right, result, ic);
4839 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4840 /* use the ds390 ARITHMETIC accel UNIT */
4841 genDivTwoByte (left, right, result, ic);
4844 /* should have been converted to function call */
4847 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4848 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4849 freeAsmop (result, NULL, ic, TRUE);
4852 /*-----------------------------------------------------------------*/
4853 /* genModbits :- modulus of bits */
4854 /*-----------------------------------------------------------------*/
4856 genModbits (operand * left,
4864 /* the result must be bit */
4865 LOAD_AB_FOR_DIV (left, right, l);
4866 emitcode ("div", "ab");
4867 emitcode ("mov", "a,b");
4868 emitcode ("rrc", "a");
4869 aopOp(result, ic, TRUE, FALSE);
4870 aopPut (AOP (result), "c", 0);
4873 /*-----------------------------------------------------------------*/
4874 /* genModOneByte : 8 bit modulus */
4875 /*-----------------------------------------------------------------*/
4877 genModOneByte (operand * left,
4882 sym_link *opetype = operandType (result);
4886 /* signed or unsigned */
4887 if (SPEC_USIGN (opetype))
4889 /* unsigned is easy */
4890 LOAD_AB_FOR_DIV (left, right, l);
4891 emitcode ("div", "ab");
4892 aopOp(result, ic, TRUE, FALSE);
4893 aopPut (AOP (result), "b", 0);
4897 /* signed is a little bit more difficult */
4899 /* save the signs of the operands */
4900 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4903 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4904 emitcode ("push", "acc"); /* save it on the stack */
4906 /* now sign adjust for both left & right */
4907 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4910 lbl = newiTempLabel (NULL);
4911 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4912 emitcode ("cpl", "a");
4913 emitcode ("inc", "a");
4914 emitcode ("", "!tlabeldef", (lbl->key + 100));
4915 emitcode ("mov", "b,a");
4917 /* sign adjust left side */
4918 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4921 lbl = newiTempLabel (NULL);
4922 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4923 emitcode ("cpl", "a");
4924 emitcode ("inc", "a");
4925 emitcode ("", "!tlabeldef", (lbl->key + 100));
4927 /* now the multiplication */
4928 emitcode ("nop", "; workaround for DS80C390 div bug.");
4929 emitcode ("div", "ab");
4930 /* we are interested in the lower order
4932 lbl = newiTempLabel (NULL);
4933 emitcode ("pop", "acc");
4934 /* if there was an over flow we don't
4935 adjust the sign of the result */
4936 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4937 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4939 emitcode ("clr", "a");
4940 emitcode ("subb", "a,b");
4941 emitcode ("mov", "b,a");
4942 emitcode ("", "!tlabeldef", (lbl->key + 100));
4945 /* now we are done */
4946 aopOp(result, ic, TRUE, FALSE);
4947 aopPut (AOP (result), "b", 0);
4952 /*-----------------------------------------------------------------*/
4953 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
4954 /*-----------------------------------------------------------------*/
4955 static void genModTwoByte (operand *left, operand *right,
4956 operand *result, iCode *ic)
4958 sym_link *retype = getSpec(operandType(right));
4959 sym_link *letype = getSpec(operandType(left));
4960 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4963 /* load up MA with left */
4964 /* save EA bit in F1 */
4965 lbl = newiTempLabel(NULL);
4966 emitcode ("setb","F1");
4967 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4968 emitcode ("clr","F1");
4969 emitcode("","!tlabeldef",lbl->key+100);
4972 lbl = newiTempLabel(NULL);
4973 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4974 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4975 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4976 emitcode ("xch", "a,b");
4977 emitcode ("cpl","a");
4978 emitcode ("add", "a,#1");
4979 emitcode ("xch", "a,b");
4980 emitcode ("cpl", "a"); // msb
4981 emitcode ("addc","a,#0");
4982 emitcode ("","!tlabeldef",lbl->key+100);
4983 emitcode ("mov","ma,b");
4984 emitcode ("mov","ma,a");
4986 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4987 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4990 /* load up MB with right */
4992 if (AOP_TYPE(right) == AOP_LIT) {
4993 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4997 emitcode ("mov","mb,#!constbyte",val & 0xff);
4998 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5000 lbl = newiTempLabel(NULL);
5001 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
5002 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
5003 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5004 emitcode ("xch", "a,b");
5005 emitcode ("cpl","a");
5006 emitcode ("add", "a,#1");
5007 emitcode ("xch", "a,b");
5008 emitcode ("cpl", "a"); // msb
5009 emitcode ("addc", "a,#0");
5010 emitcode ("","!tlabeldef",lbl->key+100);
5011 emitcode ("mov","mb,b");
5012 emitcode ("mov","mb,a");
5015 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
5016 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
5019 /* wait for multiplication to finish */
5020 lbl = newiTempLabel(NULL);
5021 emitcode("","!tlabeldef", lbl->key+100);
5022 emitcode("mov","a,mcnt1");
5023 emitcode("anl","a,#!constbyte",0x80);
5024 emitcode("jnz","!tlabel",lbl->key+100);
5026 freeAsmop (left, NULL, ic, TRUE);
5027 freeAsmop (right, NULL, ic,TRUE);
5028 aopOp(result, ic, TRUE, FALSE);
5030 aopPut(AOP(result),"mb",1);
5031 aopPut(AOP(result),"mb",0);
5032 freeAsmop (result, NULL, ic, TRUE);
5034 /* restore EA bit in F1 */
5035 lbl = newiTempLabel(NULL);
5036 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5037 emitcode ("setb","EA");
5038 emitcode("","!tlabeldef",lbl->key+100);
5042 /*-----------------------------------------------------------------*/
5043 /* genMod - generates code for division */
5044 /*-----------------------------------------------------------------*/
5048 operand *left = IC_LEFT (ic);
5049 operand *right = IC_RIGHT (ic);
5050 operand *result = IC_RESULT (ic);
5052 D (emitcode (";", "genMod "); );
5054 /* assign the amsops */
5057 /* special cases first */
5059 if (AOP_TYPE (left) == AOP_CRY &&
5060 AOP_TYPE (right) == AOP_CRY)
5062 genModbits (left, right, result, ic);
5066 /* if both are of size == 1 */
5067 if (AOP_SIZE (left) == 1 &&
5068 AOP_SIZE (right) == 1)
5070 genModOneByte (left, right, result, ic);
5074 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5075 /* use the ds390 ARITHMETIC accel UNIT */
5076 genModTwoByte (left, right, result, ic);
5080 /* should have been converted to function call */
5084 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5085 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5086 freeAsmop (result, NULL, ic, TRUE);
5089 /*-----------------------------------------------------------------*/
5090 /* genIfxJump :- will create a jump depending on the ifx */
5091 /*-----------------------------------------------------------------*/
5093 genIfxJump (iCode * ic, char *jval)
5096 symbol *tlbl = newiTempLabel (NULL);
5099 D (emitcode (";", "genIfxJump ");
5102 /* if true label then we jump if condition
5106 jlbl = IC_TRUE (ic);
5107 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5108 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5112 /* false label is present */
5113 jlbl = IC_FALSE (ic);
5114 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5115 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5117 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5118 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5120 emitcode (inst, "!tlabel", tlbl->key + 100);
5121 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5122 emitcode ("", "!tlabeldef", tlbl->key + 100);
5124 /* mark the icode as generated */
5128 /*-----------------------------------------------------------------*/
5129 /* genCmp :- greater or less than comparison */
5130 /*-----------------------------------------------------------------*/
5132 genCmp (operand * left, operand * right,
5133 iCode * ic, iCode * ifx, int sign)
5135 int size, offset = 0;
5136 unsigned long lit = 0L;
5139 D (emitcode (";", "genCmp");
5142 result = IC_RESULT (ic);
5144 /* if left & right are bit variables */
5145 if (AOP_TYPE (left) == AOP_CRY &&
5146 AOP_TYPE (right) == AOP_CRY)
5148 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5149 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
5153 /* subtract right from left if at the
5154 end the carry flag is set then we know that
5155 left is greater than right */
5156 size = max (AOP_SIZE (left), AOP_SIZE (right));
5158 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5159 if ((size == 1) && !sign &&
5160 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5162 symbol *lbl = newiTempLabel (NULL);
5163 emitcode ("cjne", "%s,%s,!tlabel",
5164 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5165 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5167 emitcode ("", "!tlabeldef", lbl->key + 100);
5171 if (AOP_TYPE (right) == AOP_LIT)
5173 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5174 /* optimize if(x < 0) or if(x >= 0) */
5183 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5185 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5186 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5188 aopOp (result, ic, FALSE, FALSE);
5190 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5192 freeAsmop (result, NULL, ic, TRUE);
5193 genIfxJump (ifx, "acc.7");
5198 emitcode ("rlc", "a");
5200 goto release_freedLR;
5208 //emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5209 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5210 //emitcode (";", "genCmp #2");
5211 if (sign && (size == 0))
5213 //emitcode (";", "genCmp #3");
5214 emitcode ("xrl", "a,#!constbyte",0x80);
5215 if (AOP_TYPE (right) == AOP_LIT)
5217 unsigned long lit = (unsigned long)
5218 floatFromVal (AOP (right)->aopu.aop_lit);
5219 //emitcode (";", "genCmp #3.1");
5220 emitcode ("subb", "a,#!constbyte",
5221 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5225 //emitcode (";", "genCmp #3.2");
5226 if (AOP_NEEDSACC (right))
5228 emitcode ("push", "acc");
5230 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
5231 FALSE, FALSE, FALSE));
5232 emitcode ("xrl", "b,#!constbyte",0x80);
5233 if (AOP_NEEDSACC (right))
5235 emitcode ("pop", "acc");
5237 emitcode ("subb", "a,b");
5244 //emitcode (";", "genCmp #4");
5245 if (AOP_NEEDSACC (right))
5248 //emitcode (";", "genCmp #4.1");
5249 emitcode ("xch", "a, b");
5250 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
5251 emitcode ("xch", "a, b");
5256 //emitcode (";", "genCmp #4.2");
5257 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
5260 emitcode ("subb", "a,%s", s);
5267 /* Don't need the left & right operands any more; do need the result. */
5268 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5269 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5271 aopOp (result, ic, FALSE, FALSE);
5275 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5281 /* if the result is used in the next
5282 ifx conditional branch then generate
5283 code a little differently */
5286 genIfxJump (ifx, "c");
5292 /* leave the result in acc */
5294 freeAsmop (result, NULL, ic, TRUE);
5297 /*-----------------------------------------------------------------*/
5298 /* genCmpGt :- greater than comparison */
5299 /*-----------------------------------------------------------------*/
5301 genCmpGt (iCode * ic, iCode * ifx)
5303 operand *left, *right;
5304 sym_link *letype, *retype;
5307 D (emitcode (";", "genCmpGt ");
5310 left = IC_LEFT (ic);
5311 right = IC_RIGHT (ic);
5313 letype = getSpec (operandType (left));
5314 retype = getSpec (operandType (right));
5315 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5317 /* assign the left & right amsops */
5320 genCmp (right, left, ic, ifx, sign);
5323 /*-----------------------------------------------------------------*/
5324 /* genCmpLt - less than comparisons */
5325 /*-----------------------------------------------------------------*/
5327 genCmpLt (iCode * ic, iCode * ifx)
5329 operand *left, *right;
5330 sym_link *letype, *retype;
5333 D (emitcode (";", "genCmpLt "););
5335 left = IC_LEFT (ic);
5336 right = IC_RIGHT (ic);
5338 letype = getSpec (operandType (left));
5339 retype = getSpec (operandType (right));
5340 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5342 /* assign the left & right amsops */
5345 genCmp (left, right, ic, ifx, sign);
5348 /*-----------------------------------------------------------------*/
5349 /* gencjneshort - compare and jump if not equal */
5350 /*-----------------------------------------------------------------*/
5352 gencjneshort (operand * left, operand * right, symbol * lbl)
5354 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5356 unsigned long lit = 0L;
5358 D (emitcode (";", "gencjneshort");
5361 /* if the left side is a literal or
5362 if the right is in a pointer register and left
5364 if ((AOP_TYPE (left) == AOP_LIT) ||
5365 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5372 if (AOP_TYPE (right) == AOP_LIT)
5373 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5375 if (opIsGptr (left) || opIsGptr (right))
5377 /* We are comparing a generic pointer to something.
5378 * Exclude the generic type byte from the comparison.
5381 D (emitcode (";", "cjneshort: generic ptr special case.");
5386 /* if the right side is a literal then anything goes */
5387 if (AOP_TYPE (right) == AOP_LIT &&
5388 AOP_TYPE (left) != AOP_DIR)
5392 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5394 emitcode ("cjne", "a,%s,!tlabel",
5395 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5401 /* if the right side is in a register or in direct space or
5402 if the left is a pointer register & right is not */
5403 else if (AOP_TYPE (right) == AOP_REG ||
5404 AOP_TYPE (right) == AOP_DIR ||
5405 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5406 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5410 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5411 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5412 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5413 emitcode ("jnz", "!tlabel", lbl->key + 100);
5415 emitcode ("cjne", "a,%s,!tlabel",
5416 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
5423 /* right is a pointer reg need both a & b */
5426 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5427 if (strcmp (l, "b"))
5428 emitcode ("mov", "b,%s", l);
5429 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5430 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5436 /*-----------------------------------------------------------------*/
5437 /* gencjne - compare and jump if not equal */
5438 /*-----------------------------------------------------------------*/
5440 gencjne (operand * left, operand * right, symbol * lbl)
5442 symbol *tlbl = newiTempLabel (NULL);
5444 D (emitcode (";", "gencjne");
5447 gencjneshort (left, right, lbl);
5449 emitcode ("mov", "a,%s", one);
5450 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5451 emitcode ("", "!tlabeldef", lbl->key + 100);
5452 emitcode ("clr", "a");
5453 emitcode ("", "!tlabeldef", tlbl->key + 100);
5456 /*-----------------------------------------------------------------*/
5457 /* genCmpEq - generates code for equal to */
5458 /*-----------------------------------------------------------------*/
5460 genCmpEq (iCode * ic, iCode * ifx)
5462 operand *left, *right, *result;
5464 D (emitcode (";", "genCmpEq ");
5468 AOP_SET_LOCALS (ic);
5470 /* if literal, literal on the right or
5471 if the right is in a pointer register and left
5473 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5474 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5476 operand *t = IC_RIGHT (ic);
5477 IC_RIGHT (ic) = IC_LEFT (ic);
5481 if (ifx && /* !AOP_SIZE(result) */
5482 OP_SYMBOL (result) &&
5483 OP_SYMBOL (result)->regType == REG_CND)
5486 /* if they are both bit variables */
5487 if (AOP_TYPE (left) == AOP_CRY &&
5488 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5490 if (AOP_TYPE (right) == AOP_LIT)
5492 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5495 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5496 emitcode ("cpl", "c");
5500 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5504 emitcode ("clr", "c");
5506 /* AOP_TYPE(right) == AOP_CRY */
5510 symbol *lbl = newiTempLabel (NULL);
5511 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5512 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5513 emitcode ("cpl", "c");
5514 emitcode ("", "!tlabeldef", (lbl->key + 100));
5516 /* if true label then we jump if condition
5518 tlbl = newiTempLabel (NULL);
5521 emitcode ("jnc", "!tlabel", tlbl->key + 100);
5522 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5526 emitcode ("jc", "!tlabel", tlbl->key + 100);
5527 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5529 emitcode ("", "!tlabeldef", tlbl->key + 100);
5533 tlbl = newiTempLabel (NULL);
5534 gencjneshort (left, right, tlbl);
5537 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5538 emitcode ("", "!tlabeldef", tlbl->key + 100);
5542 symbol *lbl = newiTempLabel (NULL);
5543 emitcode ("sjmp", "!tlabel", lbl->key + 100);
5544 emitcode ("", "!tlabeldef", tlbl->key + 100);
5545 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5546 emitcode ("", "!tlabeldef", lbl->key + 100);
5549 /* mark the icode as generated */
5552 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5553 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5557 /* if they are both bit variables */
5558 if (AOP_TYPE (left) == AOP_CRY &&
5559 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5561 if (AOP_TYPE (right) == AOP_LIT)
5563 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5566 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5567 emitcode ("cpl", "c");
5571 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5575 emitcode ("clr", "c");
5577 /* AOP_TYPE(right) == AOP_CRY */
5581 symbol *lbl = newiTempLabel (NULL);
5582 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5583 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5584 emitcode ("cpl", "c");
5585 emitcode ("", "!tlabeldef", (lbl->key + 100));
5588 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5589 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5591 aopOp (result, ic, TRUE, FALSE);
5594 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5601 genIfxJump (ifx, "c");
5604 /* if the result is used in an arithmetic operation
5605 then put the result in place */
5610 gencjne (left, right, newiTempLabel (NULL));
5612 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5613 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5615 aopOp (result, ic, TRUE, FALSE);
5617 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5619 aopPut (AOP (result), "a", 0);
5624 genIfxJump (ifx, "a");
5627 /* if the result is used in an arithmetic operation
5628 then put the result in place */
5629 if (AOP_TYPE (result) != AOP_CRY)
5631 /* leave the result in acc */
5635 freeAsmop (result, NULL, ic, TRUE);
5638 /*-----------------------------------------------------------------*/
5639 /* ifxForOp - returns the icode containing the ifx for operand */
5640 /*-----------------------------------------------------------------*/
5642 ifxForOp (operand * op, iCode * ic)
5644 /* if true symbol then needs to be assigned */
5645 if (IS_TRUE_SYMOP (op))
5648 /* if this has register type condition and
5649 the next instruction is ifx with the same operand
5650 and live to of the operand is upto the ifx only then */
5652 ic->next->op == IFX &&
5653 IC_COND (ic->next)->key == op->key &&
5654 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5659 /*-----------------------------------------------------------------*/
5660 /* hasInc - operand is incremented before any other use */
5661 /*-----------------------------------------------------------------*/
5663 hasInc (operand *op, iCode *ic, int osize)
5665 sym_link *type = operandType(op);
5666 sym_link *retype = getSpec (type);
5667 iCode *lic = ic->next;
5670 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5671 if (!IS_SYMOP(op)) return NULL;
5673 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5674 if (IS_AGGREGATE(type->next)) return NULL;
5675 if (osize != (isize = getSize(type->next))) return NULL;
5678 /* if operand of the form op = op + <sizeof *op> */
5679 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5680 isOperandEqual(IC_RESULT(lic),op) &&
5681 isOperandLiteral(IC_RIGHT(lic)) &&
5682 operandLitValue(IC_RIGHT(lic)) == isize) {
5685 /* if the operand used or deffed */
5686 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5689 /* if GOTO or IFX */
5690 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5696 /*-----------------------------------------------------------------*/
5697 /* genAndOp - for && operation */
5698 /*-----------------------------------------------------------------*/
5700 genAndOp (iCode * ic)
5702 operand *left, *right, *result;
5705 D (emitcode (";", "genAndOp "););
5707 /* note here that && operations that are in an
5708 if statement are taken away by backPatchLabels
5709 only those used in arthmetic operations remain */
5711 AOP_SET_LOCALS (ic);
5713 /* if both are bit variables */
5714 if (AOP_TYPE (left) == AOP_CRY &&
5715 AOP_TYPE (right) == AOP_CRY)
5717 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5718 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5719 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5720 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5722 aopOp (result,ic,FALSE, FALSE);
5727 tlbl = newiTempLabel (NULL);
5729 emitcode ("jz", "!tlabel", tlbl->key + 100);
5731 emitcode ("", "!tlabeldef", tlbl->key + 100);
5732 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5733 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5735 aopOp (result,ic,FALSE, FALSE);
5738 freeAsmop (result, NULL, ic, TRUE);
5742 /*-----------------------------------------------------------------*/
5743 /* genOrOp - for || operation */
5744 /*-----------------------------------------------------------------*/
5746 genOrOp (iCode * ic)
5748 operand *left, *right, *result;
5751 D (emitcode (";", "genOrOp "););
5753 /* note here that || operations that are in an
5754 if statement are taken away by backPatchLabels
5755 only those used in arthmetic operations remain */
5757 AOP_SET_LOCALS (ic);
5759 /* if both are bit variables */
5760 if (AOP_TYPE (left) == AOP_CRY &&
5761 AOP_TYPE (right) == AOP_CRY)
5763 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5764 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5765 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5766 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5768 aopOp (result,ic,FALSE, FALSE);
5774 tlbl = newiTempLabel (NULL);
5776 emitcode ("jnz", "!tlabel", tlbl->key + 100);
5778 emitcode ("", "!tlabeldef", tlbl->key + 100);
5779 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5780 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5782 aopOp (result,ic,FALSE, FALSE);
5787 freeAsmop (result, NULL, ic, TRUE);
5790 /*-----------------------------------------------------------------*/
5791 /* isLiteralBit - test if lit == 2^n */
5792 /*-----------------------------------------------------------------*/
5794 isLiteralBit (unsigned long lit)
5796 unsigned long pw[32] =
5797 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5798 0x100L, 0x200L, 0x400L, 0x800L,
5799 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5800 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5801 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5802 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5803 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5806 for (idx = 0; idx < 32; idx++)
5812 /*-----------------------------------------------------------------*/
5813 /* continueIfTrue - */
5814 /*-----------------------------------------------------------------*/
5816 continueIfTrue (iCode * ic)
5819 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5823 /*-----------------------------------------------------------------*/
5825 /*-----------------------------------------------------------------*/
5827 jumpIfTrue (iCode * ic)
5830 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
5834 /*-----------------------------------------------------------------*/
5835 /* jmpTrueOrFalse - */
5836 /*-----------------------------------------------------------------*/
5838 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5840 // ugly but optimized by peephole
5843 symbol *nlbl = newiTempLabel (NULL);
5844 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
5845 emitcode ("", "!tlabeldef", tlbl->key + 100);
5846 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5847 emitcode ("", "!tlabeldef", nlbl->key + 100);
5851 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
5852 emitcode ("", "!tlabeldef", tlbl->key + 100);
5857 // Generate code to perform a bit-wise logic operation
5858 // on two operands in far space (assumed to already have been
5859 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5860 // in far space. This requires pushing the result on the stack
5861 // then popping it into the result.
5863 genFarFarLogicOp(iCode *ic, char *logicOp)
5865 int size, resultSize, compSize;
5869 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5870 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
5871 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5873 _startLazyDPSEvaluation();
5874 for (size = compSize; (size--); offset++)
5876 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5877 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5878 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5880 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5881 emitcode ("push", "acc");
5883 _endLazyDPSEvaluation();
5885 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5886 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5887 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5889 resultSize = AOP_SIZE(IC_RESULT(ic));
5891 ADJUST_PUSHED_RESULT(compSize, resultSize);
5893 _startLazyDPSEvaluation();
5896 emitcode ("pop", "acc");
5897 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5899 _endLazyDPSEvaluation();
5900 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5904 /*-----------------------------------------------------------------*/
5905 /* genAnd - code for and */
5906 /*-----------------------------------------------------------------*/
5908 genAnd (iCode * ic, iCode * ifx)
5910 operand *left, *right, *result;
5911 int size, offset = 0;
5912 unsigned long lit = 0L;
5917 D (emitcode (";", "genAnd "););
5919 AOP_OP_3_NOFATAL (ic, pushResult);
5920 AOP_SET_LOCALS (ic);
5924 genFarFarLogicOp(ic, "anl");
5929 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5931 AOP_TYPE (left), AOP_TYPE (right));
5932 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5934 AOP_SIZE (left), AOP_SIZE (right));
5937 /* if left is a literal & right is not then exchange them */
5938 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5939 #ifdef LOGIC_OPS_BROKEN
5940 || AOP_NEEDSACC (left)
5944 operand *tmp = right;
5949 /* if result = right then exchange them */
5950 if (sameRegs (AOP (result), AOP (right)))
5952 operand *tmp = right;
5957 /* if right is bit then exchange them */
5958 if (AOP_TYPE (right) == AOP_CRY &&
5959 AOP_TYPE (left) != AOP_CRY)
5961 operand *tmp = right;
5965 if (AOP_TYPE (right) == AOP_LIT)
5966 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5968 size = AOP_SIZE (result);
5971 // result = bit & yy;
5972 if (AOP_TYPE (left) == AOP_CRY)
5974 // c = bit & literal;
5975 if (AOP_TYPE (right) == AOP_LIT)
5979 if (size && sameRegs (AOP (result), AOP (left)))
5982 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5987 if (size && (AOP_TYPE (result) == AOP_CRY))
5989 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5992 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5997 emitcode ("clr", "c");
6002 if (AOP_TYPE (right) == AOP_CRY)
6005 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6006 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6011 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
6013 emitcode ("rrc", "a");
6014 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6022 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6023 genIfxJump (ifx, "c");
6027 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6028 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6029 if ((AOP_TYPE (right) == AOP_LIT) &&
6030 (AOP_TYPE (result) == AOP_CRY) &&
6031 (AOP_TYPE (left) != AOP_CRY))
6033 int posbit = isLiteralBit (lit);
6038 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
6041 emitcode ("mov", "c,acc.%d", posbit & 0x07);
6047 sprintf (buffer, "acc.%d", posbit & 0x07);
6048 genIfxJump (ifx, buffer);
6052 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6059 symbol *tlbl = newiTempLabel (NULL);
6060 int sizel = AOP_SIZE (left);
6062 emitcode ("setb", "c");
6065 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6067 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6069 if ((posbit = isLiteralBit (bytelit)) != 0)
6070 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6073 if (bytelit != 0x0FFL)
6074 emitcode ("anl", "a,%s",
6075 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
6076 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6081 // bit = left & literal
6084 emitcode ("clr", "c");
6085 emitcode ("", "!tlabeldef", tlbl->key + 100);
6087 // if(left & literal)
6091 jmpTrueOrFalse (ifx, tlbl);
6099 /* if left is same as result */
6100 if (sameRegs (AOP (result), AOP (left)))
6102 for (; size--; offset++)
6104 if (AOP_TYPE (right) == AOP_LIT)
6106 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6108 else if (bytelit == 0)
6109 aopPut (AOP (result), zero, offset);
6110 else if (IS_AOP_PREG (result))
6112 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6113 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6114 aopPut (AOP (result), "a", offset);
6117 emitcode ("anl", "%s,%s",
6118 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6119 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6123 if (AOP_TYPE (left) == AOP_ACC)
6124 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6127 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6128 if (IS_AOP_PREG (result))
6130 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6131 aopPut (AOP (result), "a", offset);
6135 emitcode ("anl", "%s,a",
6136 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6143 // left & result in different registers
6144 if (AOP_TYPE (result) == AOP_CRY)
6147 // if(size), result in bit
6148 // if(!size && ifx), conditional oper: if(left & right)
6149 symbol *tlbl = newiTempLabel (NULL);
6150 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6152 emitcode ("setb", "c");
6155 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6156 emitcode ("anl", "a,%s",
6157 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6159 if (AOP_TYPE(left)==AOP_ACC) {
6160 emitcode("mov", "b,a");
6161 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6162 emitcode("anl", "a,b");
6164 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6165 emitcode ("anl", "a,%s",
6166 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6169 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6175 emitcode ("", "!tlabeldef", tlbl->key + 100);
6179 jmpTrueOrFalse (ifx, tlbl);
6183 for (; (size--); offset++)
6186 // result = left & right
6187 if (AOP_TYPE (right) == AOP_LIT)
6189 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6191 aopPut (AOP (result),
6192 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6196 else if (bytelit == 0)
6198 aopPut (AOP (result), zero, offset);
6201 D (emitcode (";", "better literal AND."););
6202 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6203 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6204 FALSE, FALSE, FALSE));
6209 // faster than result <- left, anl result,right
6210 // and better if result is SFR
6211 if (AOP_TYPE (left) == AOP_ACC)
6213 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
6214 FALSE, FALSE, FALSE));
6218 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6219 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6221 emitcode("mov", "b,a");
6225 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6226 emitcode ("anl", "a,%s", rOp);
6229 aopPut (AOP (result), "a", offset);
6235 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6236 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6237 freeAsmop (result, NULL, ic, TRUE);
6241 /*-----------------------------------------------------------------*/
6242 /* genOr - code for or */
6243 /*-----------------------------------------------------------------*/
6245 genOr (iCode * ic, iCode * ifx)
6247 operand *left, *right, *result;
6248 int size, offset = 0;
6249 unsigned long lit = 0L;
6252 D (emitcode (";", "genOr "););
6254 AOP_OP_3_NOFATAL (ic, pushResult);
6255 AOP_SET_LOCALS (ic);
6259 genFarFarLogicOp(ic, "orl");
6265 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6267 AOP_TYPE (left), AOP_TYPE (right));
6268 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6270 AOP_SIZE (left), AOP_SIZE (right));
6273 /* if left is a literal & right is not then exchange them */
6274 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6275 #ifdef LOGIC_OPS_BROKEN
6276 || AOP_NEEDSACC (left) // I think this is a net loss now.
6280 operand *tmp = right;
6285 /* if result = right then exchange them */
6286 if (sameRegs (AOP (result), AOP (right)))
6288 operand *tmp = right;
6293 /* if right is bit then exchange them */
6294 if (AOP_TYPE (right) == AOP_CRY &&
6295 AOP_TYPE (left) != AOP_CRY)
6297 operand *tmp = right;
6301 if (AOP_TYPE (right) == AOP_LIT)
6302 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6304 size = AOP_SIZE (result);
6308 if (AOP_TYPE (left) == AOP_CRY)
6310 if (AOP_TYPE (right) == AOP_LIT)
6312 // c = bit & literal;
6315 // lit != 0 => result = 1
6316 if (AOP_TYPE (result) == AOP_CRY)
6319 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6321 continueIfTrue (ifx);
6324 emitcode ("setb", "c");
6328 // lit == 0 => result = left
6329 if (size && sameRegs (AOP (result), AOP (left)))
6331 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6336 if (AOP_TYPE (right) == AOP_CRY)
6339 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6340 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6345 symbol *tlbl = newiTempLabel (NULL);
6346 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6347 emitcode ("setb", "c");
6348 emitcode ("jb", "%s,!tlabel",
6349 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6351 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6352 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6354 jmpTrueOrFalse (ifx, tlbl);
6360 emitcode ("", "!tlabeldef", tlbl->key + 100);
6369 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6370 genIfxJump (ifx, "c");
6374 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6375 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6376 if ((AOP_TYPE (right) == AOP_LIT) &&
6377 (AOP_TYPE (result) == AOP_CRY) &&
6378 (AOP_TYPE (left) != AOP_CRY))
6384 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6386 continueIfTrue (ifx);
6391 // lit = 0, result = boolean(left)
6393 emitcode ("setb", "c");
6397 symbol *tlbl = newiTempLabel (NULL);
6398 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6400 emitcode ("", "!tlabeldef", tlbl->key + 100);
6404 genIfxJump (ifx, "a");
6412 /* if left is same as result */
6413 if (sameRegs (AOP (result), AOP (left)))
6415 for (; size--; offset++)
6417 if (AOP_TYPE (right) == AOP_LIT)
6419 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6425 if (IS_AOP_PREG (left))
6427 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6428 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6429 aopPut (AOP (result), "a", offset);
6433 emitcode ("orl", "%s,%s",
6434 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6435 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6441 if (AOP_TYPE (left) == AOP_ACC)
6443 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6447 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6448 if (IS_AOP_PREG (left))
6450 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6451 aopPut (AOP (result), "a", offset);
6455 emitcode ("orl", "%s,a",
6456 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6464 // left & result in different registers
6465 if (AOP_TYPE (result) == AOP_CRY)
6468 // if(size), result in bit
6469 // if(!size && ifx), conditional oper: if(left | right)
6470 symbol *tlbl = newiTempLabel (NULL);
6471 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6473 emitcode ("setb", "c");
6476 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6477 emitcode ("orl", "a,%s",
6478 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6480 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6481 emitcode ("orl", "a,%s",
6482 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6484 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6490 emitcode ("", "!tlabeldef", tlbl->key + 100);
6494 jmpTrueOrFalse (ifx, tlbl);
6498 _startLazyDPSEvaluation();
6499 for (; (size--); offset++)
6502 // result = left & right
6503 if (AOP_TYPE (right) == AOP_LIT)
6505 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6507 aopPut (AOP (result),
6508 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6512 D (emitcode (";", "better literal OR."););
6513 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6514 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6515 FALSE, FALSE, FALSE));
6520 // faster than result <- left, anl result,right
6521 // and better if result is SFR
6522 if (AOP_TYPE (left) == AOP_ACC)
6524 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6525 FALSE, FALSE, FALSE));
6529 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6531 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6533 emitcode("mov", "b,a");
6537 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6538 emitcode ("orl", "a,%s", rOp);
6541 aopPut (AOP (result), "a", offset);
6543 _endLazyDPSEvaluation();
6548 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6549 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6550 freeAsmop (result, NULL, ic, TRUE);
6553 /*-----------------------------------------------------------------*/
6554 /* genXor - code for xclusive or */
6555 /*-----------------------------------------------------------------*/
6557 genXor (iCode * ic, iCode * ifx)
6559 operand *left, *right, *result;
6560 int size, offset = 0;
6561 unsigned long lit = 0L;
6564 D (emitcode (";", "genXor "););
6566 AOP_OP_3_NOFATAL (ic, pushResult);
6567 AOP_SET_LOCALS (ic);
6571 genFarFarLogicOp(ic, "xrl");
6576 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6578 AOP_TYPE (left), AOP_TYPE (right));
6579 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6581 AOP_SIZE (left), AOP_SIZE (right));
6584 /* if left is a literal & right is not ||
6585 if left needs acc & right does not */
6586 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6587 #ifdef LOGIC_OPS_BROKEN
6588 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6592 operand *tmp = right;
6597 /* if result = right then exchange them */
6598 if (sameRegs (AOP (result), AOP (right)))
6600 operand *tmp = right;
6605 /* if right is bit then exchange them */
6606 if (AOP_TYPE (right) == AOP_CRY &&
6607 AOP_TYPE (left) != AOP_CRY)
6609 operand *tmp = right;
6613 if (AOP_TYPE (right) == AOP_LIT)
6614 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6616 size = AOP_SIZE (result);
6620 if (AOP_TYPE (left) == AOP_CRY)
6622 if (AOP_TYPE (right) == AOP_LIT)
6624 // c = bit & literal;
6627 // lit>>1 != 0 => result = 1
6628 if (AOP_TYPE (result) == AOP_CRY)
6631 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6633 continueIfTrue (ifx);
6636 emitcode ("setb", "c");
6643 // lit == 0, result = left
6644 if (size && sameRegs (AOP (result), AOP (left)))
6646 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6650 // lit == 1, result = not(left)
6651 if (size && sameRegs (AOP (result), AOP (left)))
6653 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6658 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6659 emitcode ("cpl", "c");
6668 symbol *tlbl = newiTempLabel (NULL);
6669 if (AOP_TYPE (right) == AOP_CRY)
6672 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6676 int sizer = AOP_SIZE (right);
6678 // if val>>1 != 0, result = 1
6679 emitcode ("setb", "c");
6682 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6684 // test the msb of the lsb
6685 emitcode ("anl", "a,#!constbyte",0xfe);
6686 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6690 emitcode ("rrc", "a");
6692 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6693 emitcode ("cpl", "c");
6694 emitcode ("", "!tlabeldef", (tlbl->key + 100));
6701 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6702 genIfxJump (ifx, "c");
6706 if (sameRegs (AOP (result), AOP (left)))
6708 /* if left is same as result */
6709 for (; size--; offset++)
6711 if (AOP_TYPE (right) == AOP_LIT)
6713 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6715 else if (IS_AOP_PREG (left))
6717 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6718 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6719 aopPut (AOP (result), "a", offset);
6722 emitcode ("xrl", "%s,%s",
6723 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6724 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6728 if (AOP_TYPE (left) == AOP_ACC)
6729 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6732 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6733 if (IS_AOP_PREG (left))
6735 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6736 aopPut (AOP (result), "a", offset);
6739 emitcode ("xrl", "%s,a",
6740 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6747 // left & result in different registers
6748 if (AOP_TYPE (result) == AOP_CRY)
6751 // if(size), result in bit
6752 // if(!size && ifx), conditional oper: if(left ^ right)
6753 symbol *tlbl = newiTempLabel (NULL);
6754 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6757 emitcode ("setb", "c");
6760 if ((AOP_TYPE (right) == AOP_LIT) &&
6761 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6763 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6767 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6768 emitcode ("xrl", "a,%s",
6769 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6771 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6772 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6774 emitcode("mov", "b,a");
6778 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6779 emitcode ("xrl", "a,%s", rOp);
6782 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6788 emitcode ("", "!tlabeldef", tlbl->key + 100);
6792 jmpTrueOrFalse (ifx, tlbl);
6796 for (; (size--); offset++)
6799 // result = left & right
6800 if (AOP_TYPE (right) == AOP_LIT)
6802 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6804 aopPut (AOP (result),
6805 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6809 D (emitcode (";", "better literal XOR."););
6810 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6811 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6812 FALSE, FALSE, FALSE));
6816 // faster than result <- left, anl result,right
6817 // and better if result is SFR
6818 if (AOP_TYPE (left) == AOP_ACC)
6820 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6821 FALSE, FALSE, FALSE));
6825 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6826 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6828 emitcode("mov", "b,a");
6832 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6833 emitcode ("xrl", "a,%s", rOp);
6836 aopPut (AOP (result), "a", offset);
6843 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6844 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6845 freeAsmop (result, NULL, ic, TRUE);
6848 /*-----------------------------------------------------------------*/
6849 /* genInline - write the inline code out */
6850 /*-----------------------------------------------------------------*/
6852 genInline (iCode * ic)
6854 char *buffer, *bp, *bp1;
6856 D (emitcode (";", "genInline ");
6859 _G.inLine += (!options.asmpeep);
6861 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6862 strcpy (buffer, IC_INLINE (ic));
6864 /* emit each line as a code */
6889 /* emitcode("",buffer); */
6890 _G.inLine -= (!options.asmpeep);
6893 /*-----------------------------------------------------------------*/
6894 /* genRRC - rotate right with carry */
6895 /*-----------------------------------------------------------------*/
6899 operand *left, *result;
6900 int size, offset = 0;
6903 D (emitcode (";", "genRRC ");
6906 /* rotate right with carry */
6907 left = IC_LEFT (ic);
6908 result = IC_RESULT (ic);
6909 aopOp (left, ic, FALSE, FALSE);
6910 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6912 /* move it to the result */
6913 size = AOP_SIZE (result);
6917 _startLazyDPSEvaluation ();
6920 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6922 emitcode ("rrc", "a");
6923 if (AOP_SIZE (result) > 1)
6924 aopPut (AOP (result), "a", offset--);
6926 _endLazyDPSEvaluation ();
6928 /* now we need to put the carry into the
6929 highest order byte of the result */
6930 if (AOP_SIZE (result) > 1)
6932 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6935 emitcode ("mov", "acc.7,c");
6936 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6937 freeAsmop (left, NULL, ic, TRUE);
6938 freeAsmop (result, NULL, ic, TRUE);
6941 /*-----------------------------------------------------------------*/
6942 /* genRLC - generate code for rotate left with carry */
6943 /*-----------------------------------------------------------------*/
6947 operand *left, *result;
6948 int size, offset = 0;
6951 D (emitcode (";", "genRLC ");
6954 /* rotate right with carry */
6955 left = IC_LEFT (ic);
6956 result = IC_RESULT (ic);
6957 aopOp (left, ic, FALSE, FALSE);
6958 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6960 /* move it to the result */
6961 size = AOP_SIZE (result);
6965 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6967 emitcode ("add", "a,acc");
6968 if (AOP_SIZE (result) > 1)
6970 aopPut (AOP (result), "a", offset++);
6973 _startLazyDPSEvaluation ();
6976 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6978 emitcode ("rlc", "a");
6979 if (AOP_SIZE (result) > 1)
6980 aopPut (AOP (result), "a", offset++);
6982 _endLazyDPSEvaluation ();
6984 /* now we need to put the carry into the
6985 highest order byte of the result */
6986 if (AOP_SIZE (result) > 1)
6988 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6991 emitcode ("mov", "acc.0,c");
6992 aopPut (AOP (result), "a", 0);
6993 freeAsmop (left, NULL, ic, TRUE);
6994 freeAsmop (result, NULL, ic, TRUE);
6997 /*-----------------------------------------------------------------*/
6998 /* genGetHbit - generates code get highest order bit */
6999 /*-----------------------------------------------------------------*/
7001 genGetHbit (iCode * ic)
7003 operand *left, *result;
7004 left = IC_LEFT (ic);
7005 result = IC_RESULT (ic);
7006 aopOp (left, ic, FALSE, FALSE);
7007 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7009 D (emitcode (";", "genGetHbit ");
7012 /* get the highest order byte into a */
7013 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
7014 if (AOP_TYPE (result) == AOP_CRY)
7016 emitcode ("rlc", "a");
7021 emitcode ("rl", "a");
7022 emitcode ("anl", "a,#1");
7027 freeAsmop (left, NULL, ic, TRUE);
7028 freeAsmop (result, NULL, ic, TRUE);
7031 /*-----------------------------------------------------------------*/
7032 /* AccRol - rotate left accumulator by known count */
7033 /*-----------------------------------------------------------------*/
7035 AccRol (int shCount)
7037 shCount &= 0x0007; // shCount : 0..7
7044 emitcode ("rl", "a");
7047 emitcode ("rl", "a");
7048 emitcode ("rl", "a");
7051 emitcode ("swap", "a");
7052 emitcode ("rr", "a");
7055 emitcode ("swap", "a");
7058 emitcode ("swap", "a");
7059 emitcode ("rl", "a");
7062 emitcode ("rr", "a");
7063 emitcode ("rr", "a");
7066 emitcode ("rr", "a");
7071 /*-----------------------------------------------------------------*/
7072 /* AccLsh - left shift accumulator by known count */
7073 /*-----------------------------------------------------------------*/
7075 AccLsh (int shCount)
7080 emitcode ("add", "a,acc");
7081 else if (shCount == 2)
7083 emitcode ("add", "a,acc");
7084 emitcode ("add", "a,acc");
7088 /* rotate left accumulator */
7090 /* and kill the lower order bits */
7091 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7096 /*-----------------------------------------------------------------*/
7097 /* AccRsh - right shift accumulator by known count */
7098 /*-----------------------------------------------------------------*/
7100 AccRsh (int shCount)
7107 emitcode ("rrc", "a");
7111 /* rotate right accumulator */
7112 AccRol (8 - shCount);
7113 /* and kill the higher order bits */
7114 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7119 #ifdef BETTER_LITERAL_SHIFT
7120 /*-----------------------------------------------------------------*/
7121 /* AccSRsh - signed right shift accumulator by known count */
7122 /*-----------------------------------------------------------------*/
7124 AccSRsh (int shCount)
7131 emitcode ("mov", "c,acc.7");
7132 emitcode ("rrc", "a");
7134 else if (shCount == 2)
7136 emitcode ("mov", "c,acc.7");
7137 emitcode ("rrc", "a");
7138 emitcode ("mov", "c,acc.7");
7139 emitcode ("rrc", "a");
7143 tlbl = newiTempLabel (NULL);
7144 /* rotate right accumulator */
7145 AccRol (8 - shCount);
7146 /* and kill the higher order bits */
7147 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7148 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7149 emitcode ("orl", "a,#!constbyte",
7150 (unsigned char) ~SRMask[shCount]);
7151 emitcode ("", "!tlabeldef", tlbl->key + 100);
7157 #ifdef BETTER_LITERAL_SHIFT
7158 /*-----------------------------------------------------------------*/
7159 /* shiftR1Left2Result - shift right one byte from left to result */
7160 /*-----------------------------------------------------------------*/
7162 shiftR1Left2Result (operand * left, int offl,
7163 operand * result, int offr,
7164 int shCount, int sign)
7166 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7167 /* shift right accumulator */
7172 aopPut (AOP (result), "a", offr);
7176 #ifdef BETTER_LITERAL_SHIFT
7177 /*-----------------------------------------------------------------*/
7178 /* shiftL1Left2Result - shift left one byte from left to result */
7179 /*-----------------------------------------------------------------*/
7181 shiftL1Left2Result (operand * left, int offl,
7182 operand * result, int offr, int shCount)
7184 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7185 /* shift left accumulator */
7187 aopPut (AOP (result), "a", offr);
7191 #ifdef BETTER_LITERAL_SHIFT
7192 /*-----------------------------------------------------------------*/
7193 /* movLeft2Result - move byte from left to result */
7194 /*-----------------------------------------------------------------*/
7196 movLeft2Result (operand * left, int offl,
7197 operand * result, int offr, int sign)
7200 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7202 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
7204 if (*l == '@' && (IS_AOP_PREG (result)))
7206 emitcode ("mov", "a,%s", l);
7207 aopPut (AOP (result), "a", offr);
7213 aopPut (AOP (result), l, offr);
7217 /* MSB sign in acc.7 ! */
7218 if (getDataSize (left) == offl + 1)
7220 emitcode ("mov", "a,%s", l);
7221 aopPut (AOP (result), "a", offr);
7229 #ifdef BETTER_LITERAL_SHIFT
7230 /*-----------------------------------------------------------------*/
7231 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7232 /*-----------------------------------------------------------------*/
7236 emitcode ("rrc", "a");
7237 emitcode ("xch", "a,%s", x);
7238 emitcode ("rrc", "a");
7239 emitcode ("xch", "a,%s", x);
7243 #ifdef BETTER_LITERAL_SHIFT
7245 /*-----------------------------------------------------------------*/
7246 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7247 /*-----------------------------------------------------------------*/
7251 emitcode ("xch", "a,%s", x);
7252 emitcode ("rlc", "a");
7253 emitcode ("xch", "a,%s", x);
7254 emitcode ("rlc", "a");
7258 #ifdef BETTER_LITERAL_SHIFT
7259 /*-----------------------------------------------------------------*/
7260 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7261 /*-----------------------------------------------------------------*/
7265 emitcode ("xch", "a,%s", x);
7266 emitcode ("add", "a,acc");
7267 emitcode ("xch", "a,%s", x);
7268 emitcode ("rlc", "a");
7272 #ifdef BETTER_LITERAL_SHIFT
7273 /*-----------------------------------------------------------------*/
7274 /* AccAXLsh - left shift a:x by known count (0..7) */
7275 /*-----------------------------------------------------------------*/
7277 AccAXLsh (char *x, int shCount)
7292 case 5: // AAAAABBB:CCCCCDDD
7294 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7296 emitcode ("anl", "a,#!constbyte",
7297 SLMask[shCount]); // BBB00000:CCCCCDDD
7299 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7301 AccRol (shCount); // DDDCCCCC:BBB00000
7303 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7305 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7307 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7309 emitcode ("anl", "a,#!constbyte",
7310 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7312 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7314 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7317 case 6: // AAAAAABB:CCCCCCDD
7318 emitcode ("anl", "a,#!constbyte",
7319 SRMask[shCount]); // 000000BB:CCCCCCDD
7320 emitcode ("mov", "c,acc.0"); // c = B
7321 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7323 AccAXRrl1 (x); // BCCCCCCD:D000000B
7324 AccAXRrl1 (x); // BBCCCCCC:DD000000
7326 emitcode("rrc","a");
7327 emitcode("xch","a,%s", x);
7328 emitcode("rrc","a");
7329 emitcode("mov","c,acc.0"); //<< get correct bit
7330 emitcode("xch","a,%s", x);
7332 emitcode("rrc","a");
7333 emitcode("xch","a,%s", x);
7334 emitcode("rrc","a");
7335 emitcode("xch","a,%s", x);
7338 case 7: // a:x <<= 7
7340 emitcode ("anl", "a,#!constbyte",
7341 SRMask[shCount]); // 0000000B:CCCCCCCD
7343 emitcode ("mov", "c,acc.0"); // c = B
7345 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7347 AccAXRrl1 (x); // BCCCCCCC:D0000000
7356 #ifdef BETTER_LITERAL_SHIFT
7358 /*-----------------------------------------------------------------*/
7359 /* AccAXRsh - right shift a:x known count (0..7) */
7360 /*-----------------------------------------------------------------*/
7362 AccAXRsh (char *x, int shCount)
7370 AccAXRrl1 (x); // 0->a:x
7375 AccAXRrl1 (x); // 0->a:x
7378 AccAXRrl1 (x); // 0->a:x
7383 case 5: // AAAAABBB:CCCCCDDD = a:x
7385 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7387 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7389 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7391 emitcode ("anl", "a,#!constbyte",
7392 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7394 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7396 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7398 emitcode ("anl", "a,#!constbyte",
7399 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7401 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7403 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7405 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7408 case 6: // AABBBBBB:CCDDDDDD
7410 emitcode ("mov", "c,acc.7");
7411 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7413 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7415 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7417 emitcode ("anl", "a,#!constbyte",
7418 SRMask[shCount]); // 000000AA:BBBBBBCC
7421 case 7: // ABBBBBBB:CDDDDDDD
7423 emitcode ("mov", "c,acc.7"); // c = A
7425 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7427 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7429 emitcode ("anl", "a,#!constbyte",
7430 SRMask[shCount]); // 0000000A:BBBBBBBC
7439 #ifdef BETTER_LITERAL_SHIFT
7440 /*-----------------------------------------------------------------*/
7441 /* AccAXRshS - right shift signed a:x known count (0..7) */
7442 /*-----------------------------------------------------------------*/
7444 AccAXRshS (char *x, int shCount)
7452 emitcode ("mov", "c,acc.7");
7453 AccAXRrl1 (x); // s->a:x
7457 emitcode ("mov", "c,acc.7");
7458 AccAXRrl1 (x); // s->a:x
7460 emitcode ("mov", "c,acc.7");
7461 AccAXRrl1 (x); // s->a:x
7466 case 5: // AAAAABBB:CCCCCDDD = a:x
7468 tlbl = newiTempLabel (NULL);
7469 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7471 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7473 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7475 emitcode ("anl", "a,#!constbyte",
7476 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7478 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7480 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7482 emitcode ("anl", "a,#!constbyte",
7483 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7485 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7487 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7489 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7491 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7492 emitcode ("orl", "a,#!constbyte",
7493 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7495 emitcode ("", "!tlabeldef", tlbl->key + 100);
7496 break; // SSSSAAAA:BBBCCCCC
7498 case 6: // AABBBBBB:CCDDDDDD
7500 tlbl = newiTempLabel (NULL);
7501 emitcode ("mov", "c,acc.7");
7502 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7504 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7506 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7508 emitcode ("anl", "a,#!constbyte",
7509 SRMask[shCount]); // 000000AA:BBBBBBCC
7511 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7512 emitcode ("orl", "a,#!constbyte",
7513 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7515 emitcode ("", "!tlabeldef", tlbl->key + 100);
7517 case 7: // ABBBBBBB:CDDDDDDD
7519 tlbl = newiTempLabel (NULL);
7520 emitcode ("mov", "c,acc.7"); // c = A
7522 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7524 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7526 emitcode ("anl", "a,#!constbyte",
7527 SRMask[shCount]); // 0000000A:BBBBBBBC
7529 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7530 emitcode ("orl", "a,#!constbyte",
7531 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7533 emitcode ("", "!tlabeldef", tlbl->key + 100);
7541 #ifdef BETTER_LITERAL_SHIFT
7543 _loadLeftIntoAx(char **lsb,
7549 // Get the initial value from left into a pair of registers.
7550 // MSB must be in A, LSB can be any register.
7552 // If the result is held in registers, it is an optimization
7553 // if the LSB can be held in the register which will hold the,
7554 // result LSB since this saves us from having to copy it into
7555 // the result following AccAXLsh.
7557 // If the result is addressed indirectly, this is not a gain.
7558 if (AOP_NEEDSACC(result))
7562 _startLazyDPSEvaluation();
7563 if (AOP_TYPE(left) == AOP_DPTR2)
7566 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7567 // get LSB in DP2_RESULT_REG.
7568 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7569 assert(!strcmp(leftByte, DP2_RESULT_REG));
7573 // get LSB into DP2_RESULT_REG
7574 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7575 if (strcmp(leftByte, DP2_RESULT_REG))
7578 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7581 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7582 assert(strcmp(leftByte, DP2_RESULT_REG));
7585 _endLazyDPSEvaluation();
7586 *lsb = DP2_RESULT_REG;
7590 if (sameRegs (AOP (result), AOP (left)) &&
7591 ((offl + MSB16) == offr))
7593 /* don't crash result[offr] */
7594 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7595 emitcode ("xch", "a,%s",
7596 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7600 movLeft2Result (left, offl, result, offr, 0);
7601 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7603 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7604 assert(strcmp(*lsb,"a"));
7609 _storeAxResults(char *lsb,
7613 _startLazyDPSEvaluation();
7614 if (AOP_NEEDSACC(result))
7616 /* We have to explicitly update the result LSB.
7618 emitcode("xch","a,%s", lsb);
7619 aopPut(AOP(result), "a", offr);
7620 emitcode("mov","a,%s", lsb);
7622 if (getDataSize (result) > 1)
7624 aopPut (AOP (result), "a", offr + MSB16);
7626 _endLazyDPSEvaluation();
7629 /*-----------------------------------------------------------------*/
7630 /* shiftL2Left2Result - shift left two bytes from left to result */
7631 /*-----------------------------------------------------------------*/
7633 shiftL2Left2Result (operand * left, int offl,
7634 operand * result, int offr, int shCount)
7638 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7640 AccAXLsh (lsb, shCount);
7642 _storeAxResults(lsb, result, offr);
7646 #ifdef BETTER_LITERAL_SHIFT
7647 /*-----------------------------------------------------------------*/
7648 /* shiftR2Left2Result - shift right two bytes from left to result */
7649 /*-----------------------------------------------------------------*/
7651 shiftR2Left2Result (operand * left, int offl,
7652 operand * result, int offr,
7653 int shCount, int sign)
7657 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7659 /* a:x >> shCount (x = lsb(result)) */
7662 AccAXRshS(lsb, shCount);
7666 AccAXRsh(lsb, shCount);
7669 _storeAxResults(lsb, result, offr);
7675 /*-----------------------------------------------------------------*/
7676 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7677 /*-----------------------------------------------------------------*/
7679 shiftLLeftOrResult (operand * left, int offl,
7680 operand * result, int offr, int shCount)
7682 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7683 /* shift left accumulator */
7685 /* or with result */
7686 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7687 /* back to result */
7688 aopPut (AOP (result), "a", offr);
7694 /*-----------------------------------------------------------------*/
7695 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7696 /*-----------------------------------------------------------------*/
7698 shiftRLeftOrResult (operand * left, int offl,
7699 operand * result, int offr, int shCount)
7701 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7702 /* shift right accumulator */
7704 /* or with result */
7705 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7706 /* back to result */
7707 aopPut (AOP (result), "a", offr);
7711 #ifdef BETTER_LITERAL_SHIFT
7712 /*-----------------------------------------------------------------*/
7713 /* genlshOne - left shift a one byte quantity by known count */
7714 /*-----------------------------------------------------------------*/
7716 genlshOne (operand * result, operand * left, int shCount)
7718 D (emitcode (";", "genlshOne "););
7719 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7723 #ifdef BETTER_LITERAL_SHIFT
7724 /*-----------------------------------------------------------------*/
7725 /* genlshTwo - left shift two bytes by known amount != 0 */
7726 /*-----------------------------------------------------------------*/
7728 genlshTwo (operand * result, operand * left, int shCount)
7732 D (emitcode (";", "genlshTwo "););
7734 size = getDataSize (result);
7736 /* if shCount >= 8 */
7741 _startLazyDPSEvaluation();
7747 _endLazyDPSEvaluation();
7748 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7749 aopPut (AOP (result), zero, LSB);
7753 movLeft2Result (left, LSB, result, MSB16, 0);
7754 aopPut (AOP (result), zero, LSB);
7755 _endLazyDPSEvaluation();
7760 aopPut (AOP (result), zero, LSB);
7761 _endLazyDPSEvaluation();
7765 /* 1 <= shCount <= 7 */
7770 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7774 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7782 /*-----------------------------------------------------------------*/
7783 /* shiftLLong - shift left one long from left to result */
7784 /* offl = LSB or MSB16 */
7785 /*-----------------------------------------------------------------*/
7787 shiftLLong (operand * left, operand * result, int offr)
7790 int size = AOP_SIZE (result);
7792 if (size >= LSB + offr)
7794 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7796 emitcode ("add", "a,acc");
7797 if (sameRegs (AOP (left), AOP (result)) &&
7798 size >= MSB16 + offr && offr != LSB)
7799 emitcode ("xch", "a,%s",
7800 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7802 aopPut (AOP (result), "a", LSB + offr);
7805 if (size >= MSB16 + offr)
7807 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7809 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7812 emitcode ("rlc", "a");
7813 if (sameRegs (AOP (left), AOP (result)) &&
7814 size >= MSB24 + offr && offr != LSB)
7815 emitcode ("xch", "a,%s",
7816 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7818 aopPut (AOP (result), "a", MSB16 + offr);
7821 if (size >= MSB24 + offr)
7823 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7825 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7828 emitcode ("rlc", "a");
7829 if (sameRegs (AOP (left), AOP (result)) &&
7830 size >= MSB32 + offr && offr != LSB)
7831 emitcode ("xch", "a,%s",
7832 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7834 aopPut (AOP (result), "a", MSB24 + offr);
7837 if (size > MSB32 + offr)
7839 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7841 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7844 emitcode ("rlc", "a");
7845 aopPut (AOP (result), "a", MSB32 + offr);
7848 aopPut (AOP (result), zero, LSB);
7854 /*-----------------------------------------------------------------*/
7855 /* genlshFour - shift four byte by a known amount != 0 */
7856 /*-----------------------------------------------------------------*/
7858 genlshFour (operand * result, operand * left, int shCount)
7862 D (emitcode (";", "genlshFour ");
7865 size = AOP_SIZE (result);
7867 /* if shifting more that 3 bytes */
7872 /* lowest order of left goes to the highest
7873 order of the destination */
7874 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7876 movLeft2Result (left, LSB, result, MSB32, 0);
7877 aopPut (AOP (result), zero, LSB);
7878 aopPut (AOP (result), zero, MSB16);
7879 aopPut (AOP (result), zero, MSB24);
7883 /* more than two bytes */
7884 else if (shCount >= 16)
7886 /* lower order two bytes goes to higher order two bytes */
7888 /* if some more remaining */
7890 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7893 movLeft2Result (left, MSB16, result, MSB32, 0);
7894 movLeft2Result (left, LSB, result, MSB24, 0);
7896 aopPut (AOP (result), zero, MSB16);
7897 aopPut (AOP (result), zero, LSB);
7901 /* if more than 1 byte */
7902 else if (shCount >= 8)
7904 /* lower order three bytes goes to higher order three bytes */
7909 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7911 movLeft2Result (left, LSB, result, MSB16, 0);
7917 movLeft2Result (left, MSB24, result, MSB32, 0);
7918 movLeft2Result (left, MSB16, result, MSB24, 0);
7919 movLeft2Result (left, LSB, result, MSB16, 0);
7920 aopPut (AOP (result), zero, LSB);
7922 else if (shCount == 1)
7923 shiftLLong (left, result, MSB16);
7926 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7927 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7928 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7929 aopPut (AOP (result), zero, LSB);
7934 /* 1 <= shCount <= 7 */
7935 else if (shCount <= 2)
7937 shiftLLong (left, result, LSB);
7939 shiftLLong (result, result, LSB);
7941 /* 3 <= shCount <= 7, optimize */
7944 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7945 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7946 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7951 #ifdef BETTER_LITERAL_SHIFT
7952 /*-----------------------------------------------------------------*/
7953 /* genLeftShiftLiteral - left shifting by known count */
7954 /*-----------------------------------------------------------------*/
7956 genLeftShiftLiteral (operand * left,
7961 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7964 size = getSize (operandType (result));
7966 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7968 /* We only handle certain easy cases so far. */
7970 && (shCount < (size * 8))
7974 D(emitcode (";", "genLeftShiftLiteral wimping out"););
7978 freeAsmop (right, NULL, ic, TRUE);
7980 aopOp(left, ic, FALSE, FALSE);
7981 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7984 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7986 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7987 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7989 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7992 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7994 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7995 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7997 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8003 emitcode ("; shift left ", "result %d, left %d", size,
8007 /* I suppose that the left size >= result size */
8010 _startLazyDPSEvaluation();
8013 movLeft2Result (left, size, result, size, 0);
8015 _endLazyDPSEvaluation();
8017 else if (shCount >= (size * 8))
8019 _startLazyDPSEvaluation();
8022 aopPut (AOP (result), zero, size);
8024 _endLazyDPSEvaluation();
8031 genlshOne (result, left, shCount);
8035 genlshTwo (result, left, shCount);
8039 genlshFour (result, left, shCount);
8043 fprintf(stderr, "*** ack! mystery literal shift!\n");
8047 freeAsmop (left, NULL, ic, TRUE);
8048 freeAsmop (result, NULL, ic, TRUE);
8053 /*-----------------------------------------------------------------*/
8054 /* genLeftShift - generates code for left shifting */
8055 /*-----------------------------------------------------------------*/
8057 genLeftShift (iCode * ic)
8059 operand *left, *right, *result;
8062 symbol *tlbl, *tlbl1;
8064 D (emitcode (";", "genLeftShift "););
8066 right = IC_RIGHT (ic);
8067 left = IC_LEFT (ic);
8068 result = IC_RESULT (ic);
8070 aopOp (right, ic, FALSE, FALSE);
8073 #ifdef BETTER_LITERAL_SHIFT
8074 /* if the shift count is known then do it
8075 as efficiently as possible */
8076 if (AOP_TYPE (right) == AOP_LIT)
8078 if (genLeftShiftLiteral (left, right, result, ic))
8085 /* shift count is unknown then we have to form
8086 a loop get the loop count in B : Note: we take
8087 only the lower order byte since shifting
8088 more that 32 bits make no sense anyway, ( the
8089 largest size of an object can be only 32 bits ) */
8091 if (AOP_TYPE (right) == AOP_LIT)
8093 /* Really should be handled by genLeftShiftLiteral,
8094 * but since I'm too lazy to fix that today, at least we can make
8095 * some small improvement.
8097 emitcode("mov", "b,#!constbyte",
8098 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8102 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8103 emitcode ("inc", "b");
8105 freeAsmop (right, NULL, ic, TRUE);
8106 aopOp (left, ic, FALSE, FALSE);
8107 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8109 /* now move the left to the result if they are not the
8111 if (!sameRegs (AOP (left), AOP (result)) &&
8112 AOP_SIZE (result) > 1)
8115 size = AOP_SIZE (result);
8117 _startLazyDPSEvaluation ();
8120 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8121 if (*l == '@' && (IS_AOP_PREG (result)))
8124 emitcode ("mov", "a,%s", l);
8125 aopPut (AOP (result), "a", offset);
8128 aopPut (AOP (result), l, offset);
8131 _endLazyDPSEvaluation ();
8134 tlbl = newiTempLabel (NULL);
8135 size = AOP_SIZE (result);
8137 tlbl1 = newiTempLabel (NULL);
8139 /* if it is only one byte then */
8142 symbol *tlbl1 = newiTempLabel (NULL);
8144 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8146 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8147 emitcode ("", "!tlabeldef", tlbl->key + 100);
8148 emitcode ("add", "a,acc");
8149 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8150 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8151 aopPut (AOP (result), "a", 0);
8155 reAdjustPreg (AOP (result));
8157 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8158 emitcode ("", "!tlabeldef", tlbl->key + 100);
8159 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8161 emitcode ("add", "a,acc");
8162 aopPut (AOP (result), "a", offset++);
8163 _startLazyDPSEvaluation ();
8166 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8168 emitcode ("rlc", "a");
8169 aopPut (AOP (result), "a", offset++);
8171 _endLazyDPSEvaluation ();
8172 reAdjustPreg (AOP (result));
8174 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8175 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8177 freeAsmop (left, NULL, ic, TRUE);
8178 freeAsmop (result, NULL, ic, TRUE);
8181 #ifdef BETTER_LITERAL_SHIFT
8182 /*-----------------------------------------------------------------*/
8183 /* genrshOne - right shift a one byte quantity by known count */
8184 /*-----------------------------------------------------------------*/
8186 genrshOne (operand * result, operand * left,
8187 int shCount, int sign)
8189 D (emitcode (";", "genrshOne"););
8190 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8194 #ifdef BETTER_LITERAL_SHIFT
8195 /*-----------------------------------------------------------------*/
8196 /* genrshTwo - right shift two bytes by known amount != 0 */
8197 /*-----------------------------------------------------------------*/
8199 genrshTwo (operand * result, operand * left,
8200 int shCount, int sign)
8202 D (emitcode (";", "genrshTwo"););
8204 /* if shCount >= 8 */
8208 _startLazyDPSEvaluation();
8211 shiftR1Left2Result (left, MSB16, result, LSB,
8216 movLeft2Result (left, MSB16, result, LSB, sign);
8218 addSign (result, MSB16, sign);
8219 _endLazyDPSEvaluation();
8222 /* 1 <= shCount <= 7 */
8225 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8232 /*-----------------------------------------------------------------*/
8233 /* shiftRLong - shift right one long from left to result */
8234 /* offl = LSB or MSB16 */
8235 /*-----------------------------------------------------------------*/
8237 shiftRLong (operand * left, int offl,
8238 operand * result, int sign)
8240 int isSameRegs=sameRegs(AOP(left),AOP(result));
8242 if (isSameRegs && offl>1) {
8243 // we are in big trouble, but this shouldn't happen
8244 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8247 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
8252 emitcode ("rlc", "a");
8253 emitcode ("subb", "a,acc");
8254 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
8256 aopPut (AOP(result), zero, MSB32);
8261 emitcode ("clr", "c");
8263 emitcode ("mov", "c,acc.7");
8266 emitcode ("rrc", "a");
8268 if (isSameRegs && offl==MSB16) {
8269 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
8271 aopPut (AOP (result), "a", MSB32);
8272 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
8275 emitcode ("rrc", "a");
8276 if (isSameRegs && offl==1) {
8277 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
8279 aopPut (AOP (result), "a", MSB24);
8280 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
8282 emitcode ("rrc", "a");
8283 aopPut (AOP (result), "a", MSB16 - offl);
8287 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
8288 emitcode ("rrc", "a");
8289 aopPut (AOP (result), "a", LSB);
8296 /*-----------------------------------------------------------------*/
8297 /* genrshFour - shift four byte by a known amount != 0 */
8298 /*-----------------------------------------------------------------*/
8300 genrshFour (operand * result, operand * left,
8301 int shCount, int sign)
8303 D (emitcode (";", "genrshFour");
8306 /* if shifting more that 3 bytes */
8311 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8313 movLeft2Result (left, MSB32, result, LSB, sign);
8314 addSign (result, MSB16, sign);
8316 else if (shCount >= 16)
8320 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8323 movLeft2Result (left, MSB24, result, LSB, 0);
8324 movLeft2Result (left, MSB32, result, MSB16, sign);
8326 addSign (result, MSB24, sign);
8328 else if (shCount >= 8)
8332 shiftRLong (left, MSB16, result, sign);
8333 else if (shCount == 0)
8335 movLeft2Result (left, MSB16, result, LSB, 0);
8336 movLeft2Result (left, MSB24, result, MSB16, 0);
8337 movLeft2Result (left, MSB32, result, MSB24, sign);
8338 addSign (result, MSB32, sign);
8342 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8343 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8344 /* the last shift is signed */
8345 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8346 addSign (result, MSB32, sign);
8350 { /* 1 <= shCount <= 7 */
8353 shiftRLong (left, LSB, result, sign);
8355 shiftRLong (result, LSB, result, sign);
8359 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8360 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8361 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8367 #ifdef BETTER_LITERAL_SHIFT
8368 /*-----------------------------------------------------------------*/
8369 /* genRightShiftLiteral - right shifting by known count */
8370 /*-----------------------------------------------------------------*/
8372 genRightShiftLiteral (operand * left,
8378 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8381 size = getSize (operandType (result));
8383 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8385 /* We only handle certain easy cases so far. */
8387 && (shCount < (size * 8))
8391 D(emitcode (";", "genRightShiftLiteral wimping out"););
8395 freeAsmop (right, NULL, ic, TRUE);
8397 aopOp (left, ic, FALSE, FALSE);
8398 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8401 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8405 /* test the LEFT size !!! */
8407 /* I suppose that the left size >= result size */
8410 size = getDataSize (result);
8411 _startLazyDPSEvaluation();
8414 movLeft2Result (left, size, result, size, 0);
8416 _endLazyDPSEvaluation();
8418 else if (shCount >= (size * 8))
8422 /* get sign in acc.7 */
8423 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8425 addSign (result, LSB, sign);
8432 genrshOne (result, left, shCount, sign);
8436 genrshTwo (result, left, shCount, sign);
8440 genrshFour (result, left, shCount, sign);
8447 freeAsmop (left, NULL, ic, TRUE);
8448 freeAsmop (result, NULL, ic, TRUE);
8454 /*-----------------------------------------------------------------*/
8455 /* genSignedRightShift - right shift of signed number */
8456 /*-----------------------------------------------------------------*/
8458 genSignedRightShift (iCode * ic)
8460 operand *right, *left, *result;
8463 symbol *tlbl, *tlbl1;
8465 D (emitcode (";", "genSignedRightShift "););
8467 /* we do it the hard way put the shift count in b
8468 and loop thru preserving the sign */
8470 right = IC_RIGHT (ic);
8471 left = IC_LEFT (ic);
8472 result = IC_RESULT (ic);
8474 aopOp (right, ic, FALSE, FALSE);
8476 #ifdef BETTER_LITERAL_SHIFT
8477 if (AOP_TYPE (right) == AOP_LIT)
8479 if (genRightShiftLiteral (left, right, result, ic, 1))
8485 /* shift count is unknown then we have to form
8486 a loop get the loop count in B : Note: we take
8487 only the lower order byte since shifting
8488 more that 32 bits make no sense anyway, ( the
8489 largest size of an object can be only 32 bits ) */
8491 if (AOP_TYPE (right) == AOP_LIT)
8493 /* Really should be handled by genRightShiftLiteral,
8494 * but since I'm too lazy to fix that today, at least we can make
8495 * some small improvement.
8497 emitcode("mov", "b,#!constbyte",
8498 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8502 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8503 emitcode ("inc", "b");
8505 freeAsmop (right, NULL, ic, TRUE);
8506 aopOp (left, ic, FALSE, FALSE);
8507 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8509 /* now move the left to the result if they are not the
8511 if (!sameRegs (AOP (left), AOP (result)) &&
8512 AOP_SIZE (result) > 1)
8515 size = AOP_SIZE (result);
8517 _startLazyDPSEvaluation ();
8520 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8521 if (*l == '@' && IS_AOP_PREG (result))
8524 emitcode ("mov", "a,%s", l);
8525 aopPut (AOP (result), "a", offset);
8528 aopPut (AOP (result), l, offset);
8531 _endLazyDPSEvaluation ();
8534 /* mov the highest order bit to OVR */
8535 tlbl = newiTempLabel (NULL);
8536 tlbl1 = newiTempLabel (NULL);
8538 size = AOP_SIZE (result);
8540 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8541 emitcode ("rlc", "a");
8542 emitcode ("mov", "ov,c");
8543 /* if it is only one byte then */
8546 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8548 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8549 emitcode ("", "!tlabeldef", tlbl->key + 100);
8550 emitcode ("mov", "c,ov");
8551 emitcode ("rrc", "a");
8552 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8553 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8554 aopPut (AOP (result), "a", 0);
8558 reAdjustPreg (AOP (result));
8559 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8560 emitcode ("", "!tlabeldef", tlbl->key + 100);
8561 emitcode ("mov", "c,ov");
8562 _startLazyDPSEvaluation ();
8565 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8567 emitcode ("rrc", "a");
8568 aopPut (AOP (result), "a", offset--);
8570 _endLazyDPSEvaluation ();
8571 reAdjustPreg (AOP (result));
8572 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8573 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8576 freeAsmop (left, NULL, ic, TRUE);
8577 freeAsmop (result, NULL, ic, TRUE);
8580 /*-----------------------------------------------------------------*/
8581 /* genRightShift - generate code for right shifting */
8582 /*-----------------------------------------------------------------*/
8584 genRightShift (iCode * ic)
8586 operand *right, *left, *result;
8590 symbol *tlbl, *tlbl1;
8592 D (emitcode (";", "genRightShift "););
8594 /* if signed then we do it the hard way preserve the
8595 sign bit moving it inwards */
8596 retype = getSpec (operandType (IC_RESULT (ic)));
8598 if (!SPEC_USIGN (retype))
8600 genSignedRightShift (ic);
8604 /* signed & unsigned types are treated the same : i.e. the
8605 signed is NOT propagated inwards : quoting from the
8606 ANSI - standard : "for E1 >> E2, is equivalent to division
8607 by 2**E2 if unsigned or if it has a non-negative value,
8608 otherwise the result is implementation defined ", MY definition
8609 is that the sign does not get propagated */
8611 right = IC_RIGHT (ic);
8612 left = IC_LEFT (ic);
8613 result = IC_RESULT (ic);
8615 aopOp (right, ic, FALSE, FALSE);
8617 #ifdef BETTER_LITERAL_SHIFT
8618 /* if the shift count is known then do it
8619 as efficiently as possible */
8620 if (AOP_TYPE (right) == AOP_LIT)
8622 if (genRightShiftLiteral (left, right, result, ic, 0))
8629 /* shift count is unknown then we have to form
8630 a loop get the loop count in B : Note: we take
8631 only the lower order byte since shifting
8632 more that 32 bits make no sense anyway, ( the
8633 largest size of an object can be only 32 bits ) */
8635 if (AOP_TYPE (right) == AOP_LIT)
8637 /* Really should be handled by genRightShiftLiteral,
8638 * but since I'm too lazy to fix that today, at least we can make
8639 * some small improvement.
8641 emitcode("mov", "b,#!constbyte",
8642 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8646 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8647 emitcode ("inc", "b");
8649 freeAsmop (right, NULL, ic, TRUE);
8650 aopOp (left, ic, FALSE, FALSE);
8651 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8653 /* now move the left to the result if they are not the
8655 if (!sameRegs (AOP (left), AOP (result)) &&
8656 AOP_SIZE (result) > 1)
8659 size = AOP_SIZE (result);
8661 _startLazyDPSEvaluation ();
8664 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8665 if (*l == '@' && IS_AOP_PREG (result))
8668 emitcode ("mov", "a,%s", l);
8669 aopPut (AOP (result), "a", offset);
8672 aopPut (AOP (result), l, offset);
8675 _endLazyDPSEvaluation ();
8678 tlbl = newiTempLabel (NULL);
8679 tlbl1 = newiTempLabel (NULL);
8680 size = AOP_SIZE (result);
8683 /* if it is only one byte then */
8686 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8688 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8689 emitcode ("", "!tlabeldef", tlbl->key + 100);
8691 emitcode ("rrc", "a");
8692 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8693 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8694 aopPut (AOP (result), "a", 0);
8698 reAdjustPreg (AOP (result));
8699 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8700 emitcode ("", "!tlabeldef", tlbl->key + 100);
8702 _startLazyDPSEvaluation ();
8705 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8707 emitcode ("rrc", "a");
8708 aopPut (AOP (result), "a", offset--);
8710 _endLazyDPSEvaluation ();
8711 reAdjustPreg (AOP (result));
8713 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8714 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8717 freeAsmop (left, NULL, ic, TRUE);
8718 freeAsmop (result, NULL, ic, TRUE);
8721 /*-----------------------------------------------------------------*/
8722 /* genUnpackBits - generates code for unpacking bits */
8723 /*-----------------------------------------------------------------*/
8725 genUnpackBits (operand * result, char *rname, int ptype)
8732 D (emitcode (";", "genUnpackBits ");
8735 etype = getSpec (operandType (result));
8737 /* read the first byte */
8743 emitcode ("mov", "a,@%s", rname);
8747 emitcode ("movx", "a,@%s", rname);
8751 emitcode ("movx", "a,@dptr");
8755 emitcode ("clr", "a");
8756 emitcode ("movc", "a,@a+dptr");
8760 emitcode ("lcall", "__gptrget");
8764 /* if we have bitdisplacement then it fits */
8765 /* into this byte completely or if length is */
8766 /* less than a byte */
8767 if ((shCnt = SPEC_BSTR (etype)) ||
8768 (SPEC_BLEN (etype) <= 8))
8771 /* shift right acc */
8774 emitcode ("anl", "a,#!constbyte",
8775 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8776 aopPut (AOP (result), "a", offset);
8780 /* bit field did not fit in a byte */
8781 rlen = SPEC_BLEN (etype) - 8;
8782 aopPut (AOP (result), "a", offset++);
8791 emitcode ("inc", "%s", rname);
8792 emitcode ("mov", "a,@%s", rname);
8796 emitcode ("inc", "%s", rname);
8797 emitcode ("movx", "a,@%s", rname);
8801 emitcode ("inc", "dptr");
8802 emitcode ("movx", "a,@dptr");
8806 emitcode ("clr", "a");
8807 emitcode ("inc", "dptr");
8808 emitcode ("movc", "a,@a+dptr");
8812 emitcode ("inc", "dptr");
8813 emitcode ("lcall", "__gptrget");
8818 /* if we are done */
8822 aopPut (AOP (result), "a", offset++);
8828 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (rlen));
8829 aopPut (AOP (result), "a", offset);
8836 /*-----------------------------------------------------------------*/
8837 /* genDataPointerGet - generates code when ptr offset is known */
8838 /*-----------------------------------------------------------------*/
8840 genDataPointerGet (operand * left,
8846 int size, offset = 0;
8847 aopOp (result, ic, TRUE, FALSE);
8849 /* get the string representation of the name */
8850 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8851 size = AOP_SIZE (result);
8852 _startLazyDPSEvaluation ();
8856 sprintf (buffer, "(%s + %d)", l + 1, offset);
8858 sprintf (buffer, "%s", l + 1);
8859 aopPut (AOP (result), buffer, offset++);
8861 _endLazyDPSEvaluation ();
8863 freeAsmop (left, NULL, ic, TRUE);
8864 freeAsmop (result, NULL, ic, TRUE);
8867 /*-----------------------------------------------------------------*/
8868 /* genNearPointerGet - emitcode for near pointer fetch */
8869 /*-----------------------------------------------------------------*/
8871 genNearPointerGet (operand * left,
8879 sym_link *rtype, *retype, *letype;
8880 sym_link *ltype = operandType (left);
8883 rtype = operandType (result);
8884 retype = getSpec (rtype);
8885 letype = getSpec (ltype);
8887 aopOp (left, ic, FALSE, FALSE);
8889 /* if left is rematerialisable and
8890 result is not bit variable type and
8891 the left is pointer to data space i.e
8892 lower 128 bytes of space */
8893 if (AOP_TYPE (left) == AOP_IMMD &&
8894 !IS_BITVAR (retype) &&
8895 !IS_BITVAR (letype) &&
8896 DCL_TYPE (ltype) == POINTER)
8898 genDataPointerGet (left, result, ic);
8902 /* if the value is already in a pointer register
8903 then don't need anything more */
8904 if (!AOP_INPREG (AOP (left)))
8906 /* otherwise get a free pointer register */
8908 preg = getFreePtr (ic, &aop, FALSE);
8909 emitcode ("mov", "%s,%s",
8911 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8915 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8917 freeAsmop (left, NULL, ic, TRUE);
8918 aopOp (result, ic, FALSE, FALSE);
8920 /* if bitfield then unpack the bits */
8921 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8922 genUnpackBits (result, rname, POINTER);
8925 /* we have can just get the values */
8926 int size = AOP_SIZE (result);
8931 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8934 emitcode ("mov", "a,@%s", rname);
8935 aopPut (AOP (result), "a", offset);
8939 sprintf (buffer, "@%s", rname);
8940 aopPut (AOP (result), buffer, offset);
8944 emitcode ("inc", "%s", rname);
8948 /* now some housekeeping stuff */
8951 /* we had to allocate for this iCode */
8952 if (pi) { /* post increment present */
8953 aopPut(AOP ( left ),rname,0);
8955 freeAsmop (NULL, aop, ic, TRUE);
8959 /* we did not allocate which means left
8960 already in a pointer register, then
8961 if size > 0 && this could be used again
8962 we have to point it back to where it
8964 if (AOP_SIZE (result) > 1 &&
8965 !OP_SYMBOL (left)->remat &&
8966 (OP_SYMBOL (left)->liveTo > ic->seq ||
8970 int size = AOP_SIZE (result) - 1;
8972 emitcode ("dec", "%s", rname);
8977 freeAsmop (result, NULL, ic, TRUE);
8978 if (pi) pi->generated = 1;
8981 /*-----------------------------------------------------------------*/
8982 /* genPagedPointerGet - emitcode for paged pointer fetch */
8983 /*-----------------------------------------------------------------*/
8985 genPagedPointerGet (operand * left,
8993 sym_link *rtype, *retype, *letype;
8995 rtype = operandType (result);
8996 retype = getSpec (rtype);
8997 letype = getSpec (operandType (left));
8998 aopOp (left, ic, FALSE, FALSE);
9000 /* if the value is already in a pointer register
9001 then don't need anything more */
9002 if (!AOP_INPREG (AOP (left)))
9004 /* otherwise get a free pointer register */
9006 preg = getFreePtr (ic, &aop, FALSE);
9007 emitcode ("mov", "%s,%s",
9009 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
9013 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
9015 freeAsmop (left, NULL, ic, TRUE);
9016 aopOp (result, ic, FALSE, FALSE);
9018 /* if bitfield then unpack the bits */
9019 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9020 genUnpackBits (result, rname, PPOINTER);
9023 /* we have can just get the values */
9024 int size = AOP_SIZE (result);
9030 emitcode ("movx", "a,@%s", rname);
9031 aopPut (AOP (result), "a", offset);
9036 emitcode ("inc", "%s", rname);
9040 /* now some housekeeping stuff */
9043 /* we had to allocate for this iCode */
9044 if (pi) aopPut ( AOP (left), rname, 0);
9045 freeAsmop (NULL, aop, ic, TRUE);
9049 /* we did not allocate which means left
9050 already in a pointer register, then
9051 if size > 0 && this could be used again
9052 we have to point it back to where it
9054 if (AOP_SIZE (result) > 1 &&
9055 !OP_SYMBOL (left)->remat &&
9056 (OP_SYMBOL (left)->liveTo > ic->seq ||
9060 int size = AOP_SIZE (result) - 1;
9062 emitcode ("dec", "%s", rname);
9067 freeAsmop (result, NULL, ic, TRUE);
9068 if (pi) pi->generated = 1;
9071 /*-----------------------------------------------------------------*/
9072 /* genFarPointerGet - gget value from far space */
9073 /*-----------------------------------------------------------------*/
9075 genFarPointerGet (operand * left,
9076 operand * result, iCode * ic, iCode *pi)
9078 int size, offset, dopi=1;
9079 sym_link *retype = getSpec (operandType (result));
9080 sym_link *letype = getSpec (operandType (left));
9081 D (emitcode (";", "genFarPointerGet");
9084 aopOp (left, ic, FALSE, FALSE);
9086 /* if the operand is already in dptr
9087 then we do nothing else we move the value to dptr */
9088 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9090 /* if this is remateriazable */
9091 if (AOP_TYPE (left) == AOP_IMMD)
9093 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9097 /* we need to get it byte by byte */
9098 _startLazyDPSEvaluation ();
9099 if (AOP_TYPE (left) != AOP_DPTR)
9101 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9102 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9103 if (options.model == MODEL_FLAT24)
9104 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9108 /* We need to generate a load to DPTR indirect through DPTR. */
9109 D (emitcode (";", "genFarPointerGet -- indirection special case.");
9111 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9112 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9113 if (options.model == MODEL_FLAT24)
9114 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9115 emitcode ("pop", "dph");
9116 emitcode ("pop", "dpl");
9119 _endLazyDPSEvaluation ();
9122 /* so dptr know contains the address */
9123 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9125 /* if bit then unpack */
9126 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9127 if (AOP_INDPTRn(left)) {
9128 genSetDPTR(AOP(left)->aopu.dptr);
9130 genUnpackBits (result, "dptr", FPOINTER);
9131 if (AOP_INDPTRn(left)) {
9136 size = AOP_SIZE (result);
9139 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9141 genSetDPTR(AOP(left)->aopu.dptr);
9142 emitcode ("movx", "a,@dptr");
9143 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9144 emitcode ("inc", "dptr");
9146 aopPut (AOP (result), "a", offset++);
9149 _startLazyDPSEvaluation ();
9151 if (AOP_INDPTRn(left)) {
9152 genSetDPTR(AOP(left)->aopu.dptr);
9158 emitcode ("movx", "a,@dptr");
9159 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9160 emitcode ("inc", "dptr");
9162 aopPut (AOP (result), "a", offset++);
9164 _endLazyDPSEvaluation ();
9167 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9168 if (!AOP_INDPTRn(left)) {
9169 aopPut ( AOP (left), "dpl", 0);
9170 aopPut ( AOP (left), "dph", 1);
9171 if (options.model == MODEL_FLAT24)
9172 aopPut ( AOP (left), "dpx", 2);
9175 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
9176 AOP_SIZE(result) > 1 &&
9177 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9179 size = AOP_SIZE (result) - 1;
9180 if (AOP_INDPTRn(left)) {
9181 genSetDPTR(AOP(left)->aopu.dptr);
9183 while (size--) emitcode ("lcall","__decdptr");
9184 if (AOP_INDPTRn(left)) {
9189 freeAsmop (left, NULL, ic, TRUE);
9190 freeAsmop (result, NULL, ic, TRUE);
9193 /*-----------------------------------------------------------------*/
9194 /* emitcodePointerGet - gget value from code space */
9195 /*-----------------------------------------------------------------*/
9197 emitcodePointerGet (operand * left,
9198 operand * result, iCode * ic, iCode *pi)
9200 int size, offset, dopi=1;
9201 sym_link *retype = getSpec (operandType (result));
9203 aopOp (left, ic, FALSE, FALSE);
9205 /* if the operand is already in dptr
9206 then we do nothing else we move the value to dptr */
9207 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9209 /* if this is remateriazable */
9210 if (AOP_TYPE (left) == AOP_IMMD)
9212 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9215 { /* we need to get it byte by byte */
9216 _startLazyDPSEvaluation ();
9217 if (AOP_TYPE (left) != AOP_DPTR)
9219 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9220 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9221 if (options.model == MODEL_FLAT24)
9222 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9226 /* We need to generate a load to DPTR indirect through DPTR. */
9227 D (emitcode (";", "gencodePointerGet -- indirection special case.");
9229 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9230 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9231 if (options.model == MODEL_FLAT24)
9232 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9233 emitcode ("pop", "dph");
9234 emitcode ("pop", "dpl");
9237 _endLazyDPSEvaluation ();
9240 /* so dptr know contains the address */
9241 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9243 /* if bit then unpack */
9244 if (IS_BITVAR (retype)) {
9245 if (AOP_INDPTRn(left)) {
9246 genSetDPTR(AOP(left)->aopu.dptr);
9248 genUnpackBits (result, "dptr", CPOINTER);
9249 if (AOP_INDPTRn(left)) {
9254 size = AOP_SIZE (result);
9256 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9258 genSetDPTR(AOP(left)->aopu.dptr);
9259 emitcode ("clr", "a");
9260 emitcode ("movc", "a,@a+dptr");
9261 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9262 emitcode ("inc", "dptr");
9264 aopPut (AOP (result), "a", offset++);
9267 _startLazyDPSEvaluation ();
9270 if (AOP_INDPTRn(left)) {
9271 genSetDPTR(AOP(left)->aopu.dptr);
9277 emitcode ("clr", "a");
9278 emitcode ("movc", "a,@a+dptr");
9279 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9280 emitcode ("inc", "dptr");
9281 aopPut (AOP (result), "a", offset++);
9283 _endLazyDPSEvaluation ();
9286 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9287 if (!AOP_INDPTRn(left)) {
9288 aopPut ( AOP (left), "dpl", 0);
9289 aopPut ( AOP (left), "dph", 1);
9290 if (options.model == MODEL_FLAT24)
9291 aopPut ( AOP (left), "dpx", 2);
9294 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
9295 AOP_SIZE(result) > 1 &&
9296 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9298 size = AOP_SIZE (result) - 1;
9299 if (AOP_INDPTRn(left)) {
9300 genSetDPTR(AOP(left)->aopu.dptr);
9302 while (size--) emitcode ("lcall","__decdptr");
9303 if (AOP_INDPTRn(left)) {
9308 freeAsmop (left, NULL, ic, TRUE);
9309 freeAsmop (result, NULL, ic, TRUE);
9312 /*-----------------------------------------------------------------*/
9313 /* genGenPointerGet - gget value from generic pointer space */
9314 /*-----------------------------------------------------------------*/
9316 genGenPointerGet (operand * left,
9317 operand * result, iCode * ic, iCode * pi)
9320 sym_link *retype = getSpec (operandType (result));
9321 sym_link *letype = getSpec (operandType (left));
9323 D (emitcode (";", "genGenPointerGet "); );
9325 aopOp (left, ic, FALSE, (OP_SYMBOL(left)->ruonly ? FALSE : TRUE));
9327 /* if the operand is already in dptr
9328 then we do nothing else we move the value to dptr */
9329 if (AOP_TYPE (left) != AOP_STR)
9331 /* if this is remateriazable */
9332 if (AOP_TYPE (left) == AOP_IMMD)
9334 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9335 if (AOP(left)->aopu.aop_immd.from_cast_remat)
9336 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, FALSE));
9338 emitcode ("mov", "b,#%d", pointerCode (retype));
9341 { /* we need to get it byte by byte */
9342 _startLazyDPSEvaluation ();
9343 if (AOP(left)->type==AOP_DPTR2) {
9345 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
9348 emitcode ("mov", "dpl,%s", l);
9349 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
9352 emitcode ("mov", "dph,%s", l);
9353 if (options.model == MODEL_FLAT24) {
9354 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
9357 emitcode ("mov", "dpx,%s", l);
9358 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9360 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9363 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
9364 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
9365 if (options.model == MODEL_FLAT24) {
9366 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9367 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9369 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9372 _endLazyDPSEvaluation ();
9375 /* so dptr know contains the address */
9376 aopOp (result, ic, FALSE, TRUE);
9378 /* if bit then unpack */
9379 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9380 genUnpackBits (result, "dptr", GPOINTER);
9383 size = AOP_SIZE (result);
9388 emitcode ("lcall", "__gptrget");
9389 aopPut (AOP (result), "a", offset++);
9390 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9391 emitcode ("inc", "dptr");
9395 if (pi && AOP_TYPE (left) != AOP_IMMD) {
9396 aopPut ( AOP (left), "dpl", 0);
9397 aopPut ( AOP (left), "dph", 1);
9398 if (options.model == MODEL_FLAT24) {
9399 aopPut ( AOP (left), "dpx", 2);
9400 aopPut ( AOP (left), "b", 3);
9401 } else aopPut ( AOP (left), "b", 2);
9403 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9404 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9406 size = AOP_SIZE (result) - 1;
9407 while (size--) emitcode ("lcall","__decdptr");
9410 freeAsmop (left, NULL, ic, TRUE);
9411 freeAsmop (result, NULL, ic, TRUE);
9414 /*-----------------------------------------------------------------*/
9415 /* genPointerGet - generate code for pointer get */
9416 /*-----------------------------------------------------------------*/
9418 genPointerGet (iCode * ic, iCode *pi)
9420 operand *left, *result;
9421 sym_link *type, *etype;
9424 D (emitcode (";", "genPointerGet ");
9427 left = IC_LEFT (ic);
9428 result = IC_RESULT (ic);
9430 /* depending on the type of pointer we need to
9431 move it to the correct pointer register */
9432 type = operandType (left);
9433 etype = getSpec (type);
9434 /* if left is of type of pointer then it is simple */
9435 if (IS_PTR (type) && !IS_FUNC (type->next))
9436 p_type = DCL_TYPE (type);
9439 /* we have to go by the storage class */
9440 p_type = PTR_TYPE (SPEC_OCLS (etype));
9442 /* special case when cast remat */
9443 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9444 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9445 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9446 type = type = operandType (left);
9447 p_type = DCL_TYPE (type);
9449 /* now that we have the pointer type we assign
9450 the pointer values */
9456 genNearPointerGet (left, result, ic, pi);
9460 genPagedPointerGet (left, result, ic, pi);
9464 genFarPointerGet (left, result, ic, pi);
9468 emitcodePointerGet (left, result, ic, pi);
9472 genGenPointerGet (left, result, ic, pi);
9478 /*-----------------------------------------------------------------*/
9479 /* genPackBits - generates code for packed bit storage */
9480 /*-----------------------------------------------------------------*/
9482 genPackBits (sym_link * etype,
9484 char *rname, int p_type)
9492 blen = SPEC_BLEN (etype);
9493 bstr = SPEC_BSTR (etype);
9495 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9498 /* if the bit lenth is less than or */
9499 /* it exactly fits a byte then */
9500 if (SPEC_BLEN (etype) <= 8)
9502 shCount = SPEC_BSTR (etype);
9504 /* shift left acc */
9507 if (SPEC_BLEN (etype) < 8)
9508 { /* if smaller than a byte */
9514 emitcode ("mov", "b,a");
9515 emitcode ("mov", "a,@%s", rname);
9519 emitcode ("mov", "b,a");
9520 emitcode ("movx", "a,@dptr");
9524 emitcode ("push", "b");
9525 emitcode ("push", "acc");
9526 emitcode ("lcall", "__gptrget");
9527 emitcode ("pop", "b");
9531 emitcode ("anl", "a,#!constbyte", (unsigned char)
9532 ((unsigned char) (0xFF << (blen + bstr)) |
9533 (unsigned char) (0xFF >> (8 - bstr))));
9534 emitcode ("orl", "a,b");
9535 if (p_type == GPOINTER)
9536 emitcode ("pop", "b");
9543 emitcode ("mov", "@%s,a", rname);
9547 emitcode ("movx", "@dptr,a");
9551 emitcode ("lcall", "__gptrput");
9556 if (SPEC_BLEN (etype) <= 8)
9559 emitcode ("inc", "%s", rname);
9560 rLen = SPEC_BLEN (etype);
9562 /* now generate for lengths greater than one byte */
9566 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9578 emitcode ("mov", "@%s,a", rname);
9581 emitcode ("mov", "@%s,%s", rname, l);
9586 emitcode ("movx", "@dptr,a");
9591 emitcode ("lcall", "__gptrput");
9594 emitcode ("inc", "%s", rname);
9599 /* last last was not complete */
9602 /* save the byte & read byte */
9606 emitcode ("mov", "b,a");
9607 emitcode ("mov", "a,@%s", rname);
9611 emitcode ("mov", "b,a");
9612 emitcode ("movx", "a,@dptr");
9616 emitcode ("push", "b");
9617 emitcode ("push", "acc");
9618 emitcode ("lcall", "__gptrget");
9619 emitcode ("pop", "b");
9623 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1 << rLen));
9624 emitcode ("orl", "a,b");
9627 if (p_type == GPOINTER)
9628 emitcode ("pop", "b");
9634 emitcode ("mov", "@%s,a", rname);
9638 emitcode ("movx", "@dptr,a");
9642 emitcode ("lcall", "__gptrput");
9646 /*-----------------------------------------------------------------*/
9647 /* genDataPointerSet - remat pointer to data space */
9648 /*-----------------------------------------------------------------*/
9650 genDataPointerSet (operand * right,
9654 int size, offset = 0;
9655 char *l, buffer[256];
9657 aopOp (right, ic, FALSE, FALSE);
9659 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9660 size = AOP_SIZE (right);
9664 sprintf (buffer, "(%s + %d)", l + 1, offset);
9666 sprintf (buffer, "%s", l + 1);
9667 emitcode ("mov", "%s,%s", buffer,
9668 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9671 freeAsmop (right, NULL, ic, TRUE);
9672 freeAsmop (result, NULL, ic, TRUE);
9675 /*-----------------------------------------------------------------*/
9676 /* genNearPointerSet - emitcode for near pointer put */
9677 /*-----------------------------------------------------------------*/
9679 genNearPointerSet (operand * right,
9687 sym_link *retype, *letype;
9688 sym_link *ptype = operandType (result);
9690 retype = getSpec (operandType (right));
9691 letype = getSpec (ptype);
9693 aopOp (result, ic, FALSE, FALSE);
9695 /* if the result is rematerializable &
9696 in data space & not a bit variable */
9697 if (AOP_TYPE (result) == AOP_IMMD &&
9698 DCL_TYPE (ptype) == POINTER &&
9699 !IS_BITVAR (retype) &&
9700 !IS_BITVAR (letype))
9702 genDataPointerSet (right, result, ic);
9706 /* if the value is already in a pointer register
9707 then don't need anything more */
9708 if (!AOP_INPREG (AOP (result)))
9710 /* otherwise get a free pointer register */
9712 preg = getFreePtr (ic, &aop, FALSE);
9713 emitcode ("mov", "%s,%s",
9715 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9719 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9721 aopOp (right, ic, FALSE, FALSE);
9723 /* if bitfield then unpack the bits */
9724 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9725 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9728 /* we have can just get the values */
9729 int size = AOP_SIZE (right);
9734 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
9738 emitcode ("mov", "@%s,a", rname);
9741 emitcode ("mov", "@%s,%s", rname, l);
9743 emitcode ("inc", "%s", rname);
9748 /* now some housekeeping stuff */
9751 /* we had to allocate for this iCode */
9752 if (pi) aopPut (AOP (result),rname,0);
9753 freeAsmop (NULL, aop, ic, TRUE);
9757 /* we did not allocate which means left
9758 already in a pointer register, then
9759 if size > 0 && this could be used again
9760 we have to point it back to where it
9762 if (AOP_SIZE (right) > 1 &&
9763 !OP_SYMBOL (result)->remat &&
9764 (OP_SYMBOL (result)->liveTo > ic->seq ||
9768 int size = AOP_SIZE (right) - 1;
9770 emitcode ("dec", "%s", rname);
9775 if (pi) pi->generated = 1;
9776 freeAsmop (result, NULL, ic, TRUE);
9777 freeAsmop (right, NULL, ic, TRUE);
9782 /*-----------------------------------------------------------------*/
9783 /* genPagedPointerSet - emitcode for Paged pointer put */
9784 /*-----------------------------------------------------------------*/
9786 genPagedPointerSet (operand * right,
9794 sym_link *retype, *letype;
9796 retype = getSpec (operandType (right));
9797 letype = getSpec (operandType (result));
9799 aopOp (result, ic, FALSE, FALSE);
9801 /* if the value is already in a pointer register
9802 then don't need anything more */
9803 if (!AOP_INPREG (AOP (result)))
9805 /* otherwise get a free pointer register */
9807 preg = getFreePtr (ic, &aop, FALSE);
9808 emitcode ("mov", "%s,%s",
9810 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9814 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9816 aopOp (right, ic, FALSE, FALSE);
9818 /* if bitfield then unpack the bits */
9819 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9820 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
9823 /* we have can just get the values */
9824 int size = AOP_SIZE (right);
9829 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
9832 emitcode ("movx", "@%s,a", rname);
9835 emitcode ("inc", "%s", rname);
9841 /* now some housekeeping stuff */
9844 if (pi) aopPut (AOP (result),rname,0);
9845 /* we had to allocate for this iCode */
9846 freeAsmop (NULL, aop, ic, TRUE);
9850 /* we did not allocate which means left
9851 already in a pointer register, then
9852 if size > 0 && this could be used again
9853 we have to point it back to where it
9855 if (AOP_SIZE (right) > 1 &&
9856 !OP_SYMBOL (result)->remat &&
9857 (OP_SYMBOL (result)->liveTo > ic->seq ||
9861 int size = AOP_SIZE (right) - 1;
9863 emitcode ("dec", "%s", rname);
9868 if (pi) pi->generated = 1;
9869 freeAsmop (result, NULL, ic, TRUE);
9870 freeAsmop (right, NULL, ic, TRUE);
9875 /*-----------------------------------------------------------------*/
9876 /* genFarPointerSet - set value from far space */
9877 /*-----------------------------------------------------------------*/
9879 genFarPointerSet (operand * right,
9880 operand * result, iCode * ic, iCode *pi)
9882 int size, offset, dopi=1;
9883 sym_link *retype = getSpec (operandType (right));
9884 sym_link *letype = getSpec (operandType (result));
9886 aopOp (result, ic, FALSE, FALSE);
9888 /* if the operand is already in dptr
9889 then we do nothing else we move the value to dptr */
9890 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
9892 /* if this is remateriazable */
9893 if (AOP_TYPE (result) == AOP_IMMD)
9894 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9897 /* we need to get it byte by byte */
9898 _startLazyDPSEvaluation ();
9899 if (AOP_TYPE (result) != AOP_DPTR)
9901 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9902 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9903 if (options.model == MODEL_FLAT24)
9904 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9908 /* We need to generate a load to DPTR indirect through DPTR. */
9909 D (emitcode (";", "genFarPointerSet -- indirection special case.");
9911 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9912 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9913 if (options.model == MODEL_FLAT24)
9914 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9915 emitcode ("pop", "dph");
9916 emitcode ("pop", "dpl");
9919 _endLazyDPSEvaluation ();
9922 /* so dptr know contains the address */
9923 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
9925 /* if bit then unpack */
9926 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9927 if (AOP_INDPTRn(result)) {
9928 genSetDPTR(AOP(result)->aopu.dptr);
9930 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9931 if (AOP_INDPTRn(result)) {
9935 size = AOP_SIZE (right);
9937 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
9939 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9942 genSetDPTR(AOP(result)->aopu.dptr);
9943 emitcode ("movx", "@dptr,a");
9944 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
9945 emitcode ("inc", "dptr");
9949 _startLazyDPSEvaluation ();
9951 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9954 if (AOP_INDPTRn(result)) {
9955 genSetDPTR(AOP(result)->aopu.dptr);
9961 emitcode ("movx", "@dptr,a");
9962 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
9963 emitcode ("inc", "dptr");
9965 _endLazyDPSEvaluation ();
9969 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
9970 if (!AOP_INDPTRn(result)) {
9971 aopPut (AOP(result),"dpl",0);
9972 aopPut (AOP(result),"dph",1);
9973 if (options.model == MODEL_FLAT24)
9974 aopPut (AOP(result),"dpx",2);
9977 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
9978 AOP_SIZE(right) > 1 &&
9979 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9981 size = AOP_SIZE (right) - 1;
9982 if (AOP_INDPTRn(result)) {
9983 genSetDPTR(AOP(result)->aopu.dptr);
9985 while (size--) emitcode ("lcall","__decdptr");
9986 if (AOP_INDPTRn(result)) {
9990 freeAsmop (result, NULL, ic, TRUE);
9991 freeAsmop (right, NULL, ic, TRUE);
9994 /*-----------------------------------------------------------------*/
9995 /* genGenPointerSet - set value from generic pointer space */
9996 /*-----------------------------------------------------------------*/
9998 genGenPointerSet (operand * right,
9999 operand * result, iCode * ic, iCode *pi)
10002 sym_link *retype = getSpec (operandType (right));
10003 sym_link *letype = getSpec (operandType (result));
10005 aopOp (result, ic, FALSE, OP_SYMBOL(result)->ruonly ? FALSE : TRUE);
10007 /* if the operand is already in dptr
10008 then we do nothing else we move the value to dptr */
10009 if (AOP_TYPE (result) != AOP_STR)
10011 _startLazyDPSEvaluation ();
10012 /* if this is remateriazable */
10013 if (AOP_TYPE (result) == AOP_IMMD)
10015 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
10016 if (AOP(result)->aopu.aop_immd.from_cast_remat)
10017 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, FALSE));
10019 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
10022 { /* we need to get it byte by byte */
10023 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
10024 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
10025 if (options.model == MODEL_FLAT24) {
10026 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
10027 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
10029 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
10032 _endLazyDPSEvaluation ();
10034 /* so dptr know contains the address */
10035 aopOp (right, ic, FALSE, TRUE);
10037 /* if bit then unpack */
10038 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10039 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10042 size = AOP_SIZE (right);
10045 _startLazyDPSEvaluation ();
10048 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
10054 emitcode ("lcall", "__gptrput");
10055 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10056 emitcode ("inc", "dptr");
10058 _endLazyDPSEvaluation ();
10061 if (pi && AOP_TYPE (result) != AOP_IMMD) {
10062 aopPut (AOP(result),"dpl",0);
10063 aopPut (AOP(result),"dph",1);
10064 if (options.model == MODEL_FLAT24) {
10065 aopPut (AOP(result),"dpx",2);
10066 aopPut (AOP(result),"b",3);
10068 aopPut (AOP(result),"b",2);
10071 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10072 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10074 size = AOP_SIZE (right) - 1;
10075 while (size--) emitcode ("lcall","__decdptr");
10077 freeAsmop (result, NULL, ic, TRUE);
10078 freeAsmop (right, NULL, ic, TRUE);
10081 /*-----------------------------------------------------------------*/
10082 /* genPointerSet - stores the value into a pointer location */
10083 /*-----------------------------------------------------------------*/
10085 genPointerSet (iCode * ic, iCode *pi)
10087 operand *right, *result;
10088 sym_link *type, *etype;
10091 D (emitcode (";", "genPointerSet ");
10094 right = IC_RIGHT (ic);
10095 result = IC_RESULT (ic);
10097 /* depending on the type of pointer we need to
10098 move it to the correct pointer register */
10099 type = operandType (result);
10100 etype = getSpec (type);
10101 /* if left is of type of pointer then it is simple */
10102 if (IS_PTR (type) && !IS_FUNC (type->next))
10104 p_type = DCL_TYPE (type);
10108 /* we have to go by the storage class */
10109 p_type = PTR_TYPE (SPEC_OCLS (etype));
10111 /* special case when cast remat */
10112 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10113 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10114 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10115 type = type = operandType (result);
10116 p_type = DCL_TYPE (type);
10119 /* now that we have the pointer type we assign
10120 the pointer values */
10126 genNearPointerSet (right, result, ic, pi);
10130 genPagedPointerSet (right, result, ic, pi);
10134 genFarPointerSet (right, result, ic, pi);
10138 genGenPointerSet (right, result, ic, pi);
10144 /*-----------------------------------------------------------------*/
10145 /* genIfx - generate code for Ifx statement */
10146 /*-----------------------------------------------------------------*/
10148 genIfx (iCode * ic, iCode * popIc)
10150 operand *cond = IC_COND (ic);
10153 D (emitcode (";", "genIfx "););
10155 aopOp (cond, ic, FALSE, FALSE);
10157 /* get the value into acc */
10158 if (AOP_TYPE (cond) != AOP_CRY)
10162 /* the result is now in the accumulator */
10163 freeAsmop (cond, NULL, ic, TRUE);
10165 /* if there was something to be popped then do it */
10169 /* if the condition is a bit variable */
10170 if (isbit && IS_ITEMP (cond) &&
10172 genIfxJump (ic, SPIL_LOC (cond)->rname);
10173 else if (isbit && !IS_ITEMP (cond))
10174 genIfxJump (ic, OP_SYMBOL (cond)->rname);
10176 genIfxJump (ic, "a");
10181 /*-----------------------------------------------------------------*/
10182 /* genAddrOf - generates code for address of */
10183 /*-----------------------------------------------------------------*/
10185 genAddrOf (iCode * ic)
10187 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10190 D (emitcode (";", "genAddrOf ");
10193 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10195 /* if the operand is on the stack then we
10196 need to get the stack offset of this
10198 if (sym->onStack) {
10200 /* if 10 bit stack */
10201 if (options.stack10bit) {
10203 tsprintf(buff,"#!constbyte",(options.stack_loc >> 16) & 0xff);
10204 /* if it has an offset then we need to compute it */
10205 emitcode ("subb", "a,#!constbyte",
10206 -((sym->stack < 0) ?
10207 ((short) (sym->stack - _G.nRegsSaved)) :
10208 ((short) sym->stack)) & 0xff);
10209 emitcode ("mov","b,a");
10210 emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ?
10211 ((short) (sym->stack - _G.nRegsSaved)) :
10212 ((short) sym->stack)) >> 8) & 0xff);
10214 emitcode ("mov", "a,_bpx");
10215 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
10216 ((char) (sym->stack - _G.nRegsSaved)) :
10217 ((char) sym->stack )) & 0xff);
10218 emitcode ("mov", "b,a");
10219 emitcode ("mov", "a,_bpx+1");
10220 emitcode ("addc","a,#!constbyte", (((sym->stack < 0) ?
10221 ((short) (sym->stack - _G.nRegsSaved)) :
10222 ((short) sym->stack )) >> 8) & 0xff);
10223 aopPut (AOP (IC_RESULT (ic)), "b", 0);
10224 aopPut (AOP (IC_RESULT (ic)), "a", 1);
10225 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10227 /* we can just move _bp */
10228 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10229 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10230 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10233 /* if it has an offset then we need to compute it */
10235 emitcode ("mov", "a,_bp");
10236 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10237 aopPut (AOP (IC_RESULT (ic)), "a", 0);
10239 /* we can just move _bp */
10240 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10242 /* fill the result with zero */
10243 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10246 if (options.stack10bit && size < (FPTRSIZE - 1)) {
10248 "*** warning: pointer to stack var truncated.\n");
10253 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10259 /* object not on stack then we need the name */
10260 size = AOP_SIZE (IC_RESULT (ic));
10265 char s[SDCC_NAME_MAX];
10269 tsprintf(s,"!his",sym->rname);
10272 tsprintf(s,"!hihis",sym->rname);
10275 tsprintf(s,"!hihihis",sym->rname);
10277 default: /* should not need this (just in case) */
10278 sprintf (s, "#(%s >> %d)",
10283 sprintf (s, "#%s", sym->rname);
10284 aopPut (AOP (IC_RESULT (ic)), s, offset++);
10288 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10292 /*-----------------------------------------------------------------*/
10293 /* genArrayInit - generates code for address of */
10294 /*-----------------------------------------------------------------*/
10296 genArrayInit (iCode * ic)
10298 literalList *iLoop;
10300 int elementSize = 0, eIndex;
10301 unsigned val, lastVal;
10303 operand *left=IC_LEFT(ic);
10305 D (emitcode (";", "genArrayInit "););
10307 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10309 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10311 // Load immediate value into DPTR.
10312 emitcode("mov", "dptr, %s",
10313 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
10315 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10318 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10319 "Unexpected operand to genArrayInit.\n");
10322 // a regression because of SDCCcse.c:1.52
10323 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
10324 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
10325 if (options.model == MODEL_FLAT24)
10326 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
10330 type = operandType(IC_LEFT(ic));
10332 if (type && type->next)
10334 elementSize = getSize(type->next);
10338 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10339 "can't determine element size in genArrayInit.\n");
10343 iLoop = IC_ARRAYILIST(ic);
10348 bool firstpass = TRUE;
10350 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
10351 iLoop->count, (int)iLoop->literalValue, elementSize);
10357 symbol *tlbl = NULL;
10359 count = ix > 256 ? 256 : ix;
10363 tlbl = newiTempLabel (NULL);
10364 if (firstpass || (count & 0xff))
10366 emitcode("mov", "b, #!constbyte", count & 0xff);
10369 emitcode ("", "!tlabeldef", tlbl->key + 100);
10374 for (eIndex = 0; eIndex < elementSize; eIndex++)
10376 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10377 if (val != lastVal)
10379 emitcode("mov", "a, #!constbyte", val);
10383 emitcode("movx", "@dptr, a");
10384 emitcode("inc", "dptr");
10389 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10395 iLoop = iLoop->next;
10398 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10401 /*-----------------------------------------------------------------*/
10402 /* genFarFarAssign - assignment when both are in far space */
10403 /*-----------------------------------------------------------------*/
10405 genFarFarAssign (operand * result, operand * right, iCode * ic)
10407 int size = AOP_SIZE (right);
10409 symbol *rSym = NULL;
10413 /* quick & easy case. */
10414 D(emitcode(";","genFarFarAssign (1 byte case)"););
10415 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
10416 freeAsmop (right, NULL, ic, FALSE);
10417 /* now assign DPTR to result */
10419 aopOp(result, ic, FALSE, FALSE);
10421 aopPut(AOP(result), "a", 0);
10422 freeAsmop(result, NULL, ic, FALSE);
10426 /* See if we've got an underlying symbol to abuse. */
10427 if (IS_SYMOP(result) && OP_SYMBOL(result))
10429 if (IS_TRUE_SYMOP(result))
10431 rSym = OP_SYMBOL(result);
10433 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10435 rSym = OP_SYMBOL(result)->usl.spillLoc;
10439 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10441 /* We can use the '390 auto-toggle feature to good effect here. */
10443 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10444 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10445 emitcode ("mov", "dptr,#%s", rSym->rname);
10446 /* DP2 = result, DP1 = right, DP1 is current. */
10449 emitcode("movx", "a,@dptr");
10450 emitcode("movx", "@dptr,a");
10453 emitcode("inc", "dptr");
10454 emitcode("inc", "dptr");
10457 emitcode("mov", "dps,#0");
10458 freeAsmop (right, NULL, ic, FALSE);
10460 some alternative code for processors without auto-toggle
10461 no time to test now, so later well put in...kpb
10462 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10463 emitcode("mov", "dps,#1"); /* Select DPTR2. */
10464 emitcode ("mov", "dptr,#%s", rSym->rname);
10465 /* DP2 = result, DP1 = right, DP1 is current. */
10469 emitcode("movx", "a,@dptr");
10471 emitcode("inc", "dptr");
10472 emitcode("inc", "dps");
10473 emitcode("movx", "@dptr,a");
10475 emitcode("inc", "dptr");
10476 emitcode("inc", "dps");
10478 emitcode("mov", "dps,#0");
10479 freeAsmop (right, NULL, ic, FALSE);
10484 D (emitcode (";", "genFarFarAssign"););
10485 aopOp (result, ic, TRUE, TRUE);
10487 _startLazyDPSEvaluation ();
10491 aopPut (AOP (result),
10492 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
10495 _endLazyDPSEvaluation ();
10496 freeAsmop (result, NULL, ic, FALSE);
10497 freeAsmop (right, NULL, ic, FALSE);
10501 /*-----------------------------------------------------------------*/
10502 /* genAssign - generate code for assignment */
10503 /*-----------------------------------------------------------------*/
10505 genAssign (iCode * ic)
10507 operand *result, *right;
10509 unsigned long lit = 0L;
10511 D (emitcode (";", "genAssign ");
10514 result = IC_RESULT (ic);
10515 right = IC_RIGHT (ic);
10517 /* if they are the same */
10518 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10521 aopOp (right, ic, FALSE, FALSE);
10523 emitcode (";", "genAssign: resultIsFar = %s",
10524 isOperandInFarSpace (result) ?
10527 /* special case both in far space */
10528 if ((AOP_TYPE (right) == AOP_DPTR ||
10529 AOP_TYPE (right) == AOP_DPTR2) &&
10530 /* IS_TRUE_SYMOP(result) && */
10531 isOperandInFarSpace (result))
10533 genFarFarAssign (result, right, ic);
10537 aopOp (result, ic, TRUE, FALSE);
10539 /* if they are the same registers */
10540 if (sameRegs (AOP (right), AOP (result)))
10543 /* if the result is a bit */
10544 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10546 /* if the right size is a literal then
10547 we know what the value is */
10548 if (AOP_TYPE (right) == AOP_LIT)
10550 if (((int) operandLitValue (right)))
10551 aopPut (AOP (result), one, 0);
10553 aopPut (AOP (result), zero, 0);
10557 /* the right is also a bit variable */
10558 if (AOP_TYPE (right) == AOP_CRY)
10560 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10561 aopPut (AOP (result), "c", 0);
10565 /* we need to or */
10567 aopPut (AOP (result), "a", 0);
10571 /* bit variables done */
10573 size = AOP_SIZE (result);
10575 if (AOP_TYPE (right) == AOP_LIT)
10576 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10579 (AOP_TYPE (result) != AOP_REG) &&
10580 (AOP_TYPE (right) == AOP_LIT) &&
10581 !IS_FLOAT (operandType (right)))
10583 _startLazyDPSEvaluation ();
10584 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10586 aopPut (AOP (result),
10587 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
10592 /* And now fill the rest with zeros. */
10595 emitcode ("clr", "a");
10599 aopPut (AOP (result), "a", offset++);
10601 _endLazyDPSEvaluation ();
10605 _startLazyDPSEvaluation ();
10608 aopPut (AOP (result),
10609 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10613 _endLazyDPSEvaluation ();
10617 freeAsmop (right, NULL, ic, FALSE);
10618 freeAsmop (result, NULL, ic, TRUE);
10621 /*-----------------------------------------------------------------*/
10622 /* genJumpTab - generates code for jump table */
10623 /*-----------------------------------------------------------------*/
10625 genJumpTab (iCode * ic)
10630 D (emitcode (";", "genJumpTab ");
10633 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10634 /* get the condition into accumulator */
10635 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10637 /* multiply by four! */
10638 emitcode ("add", "a,acc");
10639 emitcode ("add", "a,acc");
10640 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10642 jtab = newiTempLabel (NULL);
10643 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10644 emitcode ("jmp", "@a+dptr");
10645 emitcode ("", "!tlabeldef", jtab->key + 100);
10646 /* now generate the jump labels */
10647 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10648 jtab = setNextItem (IC_JTLABELS (ic)))
10649 emitcode ("ljmp", "!tlabel", jtab->key + 100);
10653 /*-----------------------------------------------------------------*/
10654 /* genCast - gen code for casting */
10655 /*-----------------------------------------------------------------*/
10657 genCast (iCode * ic)
10659 operand *result = IC_RESULT (ic);
10660 sym_link *ctype = operandType (IC_LEFT (ic));
10661 sym_link *rtype = operandType (IC_RIGHT (ic));
10662 operand *right = IC_RIGHT (ic);
10665 D (emitcode (";", "genCast ");
10668 /* if they are equivalent then do nothing */
10669 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10672 aopOp (right, ic, FALSE, FALSE);
10673 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10675 /* if the result is a bit */
10676 // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10677 if (IS_BITVAR(OP_SYMBOL(result)->type))
10679 /* if the right size is a literal then
10680 we know what the value is */
10681 if (AOP_TYPE (right) == AOP_LIT)
10683 if (((int) operandLitValue (right)))
10684 aopPut (AOP (result), one, 0);
10686 aopPut (AOP (result), zero, 0);
10691 /* the right is also a bit variable */
10692 if (AOP_TYPE (right) == AOP_CRY)
10694 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10695 aopPut (AOP (result), "c", 0);
10699 /* we need to or */
10701 aopPut (AOP (result), "a", 0);
10705 /* if they are the same size : or less */
10706 if (AOP_SIZE (result) <= AOP_SIZE (right))
10709 /* if they are in the same place */
10710 if (sameRegs (AOP (right), AOP (result)))
10713 /* if they in different places then copy */
10714 size = AOP_SIZE (result);
10716 _startLazyDPSEvaluation ();
10719 aopPut (AOP (result),
10720 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10724 _endLazyDPSEvaluation ();
10729 /* if the result is of type pointer */
10730 if (IS_PTR (ctype))
10734 sym_link *type = operandType (right);
10736 /* pointer to generic pointer */
10737 if (IS_GENPTR (ctype))
10743 p_type = DCL_TYPE (type);
10747 #if OLD_CAST_BEHAVIOR
10748 /* KV: we are converting a non-pointer type to
10749 * a generic pointer. This (ifdef'd out) code
10750 * says that the resulting generic pointer
10751 * should have the same class as the storage
10752 * location of the non-pointer variable.
10754 * For example, converting an int (which happens
10755 * to be stored in DATA space) to a pointer results
10756 * in a DATA generic pointer; if the original int
10757 * in XDATA space, so will be the resulting pointer.
10759 * I don't like that behavior, and thus this change:
10760 * all such conversions will be forced to XDATA and
10761 * throw a warning. If you want some non-XDATA
10762 * type, or you want to suppress the warning, you
10763 * must go through an intermediate cast, like so:
10765 * char _generic *gp = (char _xdata *)(intVar);
10767 sym_link *etype = getSpec (type);
10769 /* we have to go by the storage class */
10770 if (SPEC_OCLS (etype) != generic)
10772 p_type = PTR_TYPE (SPEC_OCLS (etype));
10777 /* Converting unknown class (i.e. register variable)
10778 * to generic pointer. This is not good, but
10779 * we'll make a guess (and throw a warning).
10782 werror (W_INT_TO_GEN_PTR_CAST);
10786 /* the first two bytes are known */
10787 size = GPTRSIZE - 1;
10789 _startLazyDPSEvaluation ();
10792 aopPut (AOP (result),
10793 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10797 _endLazyDPSEvaluation ();
10799 /* the last byte depending on type */
10817 /* this should never happen */
10818 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10819 "got unknown pointer type");
10822 aopPut (AOP (result), l, GPTRSIZE - 1);
10826 /* just copy the pointers */
10827 size = AOP_SIZE (result);
10829 _startLazyDPSEvaluation ();
10832 aopPut (AOP (result),
10833 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10837 _endLazyDPSEvaluation ();
10841 /* so we now know that the size of destination is greater
10842 than the size of the source */
10843 /* we move to result for the size of source */
10844 size = AOP_SIZE (right);
10846 _startLazyDPSEvaluation ();
10849 aopPut (AOP (result),
10850 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10854 _endLazyDPSEvaluation ();
10856 /* now depending on the sign of the source && destination */
10857 size = AOP_SIZE (result) - AOP_SIZE (right);
10858 /* if unsigned or not an integral type */
10859 /* also, if the source is a bit, we don't need to sign extend, because
10860 * it can't possibly have set the sign bit.
10862 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
10866 aopPut (AOP (result), zero, offset++);
10871 /* we need to extend the sign :{ */
10872 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10873 FALSE, FALSE, TRUE);
10875 emitcode ("rlc", "a");
10876 emitcode ("subb", "a,acc");
10878 aopPut (AOP (result), "a", offset++);
10881 /* we are done hurray !!!! */
10884 freeAsmop (right, NULL, ic, TRUE);
10885 freeAsmop (result, NULL, ic, TRUE);
10889 /*-----------------------------------------------------------------*/
10890 /* genDjnz - generate decrement & jump if not zero instrucion */
10891 /*-----------------------------------------------------------------*/
10893 genDjnz (iCode * ic, iCode * ifx)
10895 symbol *lbl, *lbl1;
10899 /* if the if condition has a false label
10900 then we cannot save */
10901 if (IC_FALSE (ifx))
10904 /* if the minus is not of the form
10906 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10907 !IS_OP_LITERAL (IC_RIGHT (ic)))
10910 if (operandLitValue (IC_RIGHT (ic)) != 1)
10913 /* if the size of this greater than one then no
10915 if (getSize (operandType (IC_RESULT (ic))) > 1)
10918 /* otherwise we can save BIG */
10919 D(emitcode(";", "genDjnz"););
10921 lbl = newiTempLabel (NULL);
10922 lbl1 = newiTempLabel (NULL);
10924 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10926 if (AOP_NEEDSACC(IC_RESULT(ic)))
10928 /* If the result is accessed indirectly via
10929 * the accumulator, we must explicitly write
10930 * it back after the decrement.
10932 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
10934 if (strcmp(rByte, "a"))
10936 /* Something is hopelessly wrong */
10937 fprintf(stderr, "*** warning: internal error at %s:%d\n",
10938 __FILE__, __LINE__);
10939 /* We can just give up; the generated code will be inefficient,
10940 * but what the hey.
10942 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10945 emitcode ("dec", "%s", rByte);
10946 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
10947 emitcode ("jnz", "!tlabel", lbl->key + 100);
10949 else if (IS_AOP_PREG (IC_RESULT (ic)))
10951 emitcode ("dec", "%s",
10952 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10953 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10954 emitcode ("jnz", "!tlabel", lbl->key + 100);
10958 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
10961 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
10962 emitcode ("", "!tlabeldef", lbl->key + 100);
10963 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
10964 emitcode ("", "!tlabeldef", lbl1->key + 100);
10966 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10967 ifx->generated = 1;
10971 /*-----------------------------------------------------------------*/
10972 /* genReceive - generate code for a receive iCode */
10973 /*-----------------------------------------------------------------*/
10975 genReceive (iCode * ic)
10978 int size = getSize (operandType (IC_RESULT (ic)));
10982 D (emitcode (";", "genReceive ");
10985 if (ic->argreg == 1) { /* first parameter */
10986 if (isOperandInFarSpace (IC_RESULT (ic)) &&
10987 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10988 IS_TRUE_SYMOP (IC_RESULT (ic))))
10990 offset = fReturnSizeDS390 - size;
10993 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
10994 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
10997 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10998 size = AOP_SIZE (IC_RESULT (ic));
11002 emitcode ("pop", "acc");
11003 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
11008 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11010 assignResultValue (IC_RESULT (ic));
11012 } else { /* second receive onwards */
11013 /* this gets a little tricky since unused recevies will be
11014 eliminated, we have saved the reg in the type field . and
11015 we use that to figure out which register to use */
11016 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11017 rb1off = ic->argreg;
11019 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11023 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11026 /*-----------------------------------------------------------------*/
11027 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
11028 /*-----------------------------------------------------------------*/
11029 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11031 operand *from , *to , *count;
11036 /* we know it has to be 3 parameters */
11037 assert (nparms == 3);
11039 rsave = newBitVect(16);
11040 /* save DPTR if it needs to be saved */
11041 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11042 if (bitVectBitValue(ic->rMask,i))
11043 rsave = bitVectSetBit(rsave,i);
11045 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11046 ds390_rUmaskForOp (IC_RESULT(ic))));
11053 aopOp (from, ic->next, FALSE, FALSE);
11055 /* get from into DPTR1 */
11056 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
11057 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
11058 if (options.model == MODEL_FLAT24) {
11059 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
11062 freeAsmop (from, NULL, ic, FALSE);
11063 aopOp (to, ic, FALSE, FALSE);
11064 /* get "to" into DPTR */
11065 /* if the operand is already in dptr
11066 then we do nothing else we move the value to dptr */
11067 if (AOP_TYPE (to) != AOP_STR) {
11068 /* if already in DPTR then we need to push */
11069 if (AOP_TYPE(to) == AOP_DPTR) {
11070 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11071 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11072 if (options.model == MODEL_FLAT24)
11073 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11074 emitcode ("pop", "dph");
11075 emitcode ("pop", "dpl");
11077 _startLazyDPSEvaluation ();
11078 /* if this is remateriazable */
11079 if (AOP_TYPE (to) == AOP_IMMD) {
11080 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11081 } else { /* we need to get it byte by byte */
11082 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11083 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11084 if (options.model == MODEL_FLAT24) {
11085 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11088 _endLazyDPSEvaluation ();
11091 freeAsmop (to, NULL, ic, FALSE);
11093 aopOp (count, ic->next->next, FALSE,FALSE);
11094 lbl =newiTempLabel(NULL);
11096 /* now for the actual copy */
11097 if (AOP_TYPE(count) == AOP_LIT &&
11098 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11099 emitcode (";","OH JOY auto increment with djnz (very fast)");
11100 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11101 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11102 emitcode ("","!tlabeldef",lbl->key+100);
11104 emitcode ("clr","a");
11105 emitcode ("movc", "a,@a+dptr");
11107 emitcode ("movx", "a,@dptr");
11108 emitcode ("movx", "@dptr,a");
11109 emitcode ("inc", "dptr");
11110 emitcode ("inc", "dptr");
11111 emitcode ("djnz","b,!tlabel",lbl->key+100);
11113 symbol *lbl1 = newiTempLabel(NULL);
11115 emitcode (";"," Auto increment but no djnz");
11116 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11117 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11118 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11119 emitcode ("","!tlabeldef",lbl->key+100);
11121 emitcode ("clr","a");
11122 emitcode ("movc", "a,@a+dptr");
11124 emitcode ("movx", "a,@dptr");
11125 emitcode ("movx", "@dptr,a");
11126 emitcode ("inc", "dptr");
11127 emitcode ("inc", "dptr");
11128 emitcode ("mov","a,b");
11129 emitcode ("orl","a,_ap");
11130 emitcode ("jz","!tlabel",lbl1->key+100);
11131 emitcode ("mov","a,_ap");
11132 emitcode ("add","a,#!constbyte",0xFF);
11133 emitcode ("mov","_ap,a");
11134 emitcode ("mov","a,b");
11135 emitcode ("addc","a,#!constbyte",0xFF);
11136 emitcode ("mov","b,a");
11137 emitcode ("sjmp","!tlabel",lbl->key+100);
11138 emitcode ("","!tlabeldef",lbl1->key+100);
11140 emitcode ("mov", "dps,#0");
11141 freeAsmop (count, NULL, ic, FALSE);
11142 unsavermask(rsave);
11146 /*-----------------------------------------------------------------*/
11147 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
11148 /*-----------------------------------------------------------------*/
11149 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11151 operand *from , *to , *count;
11156 /* we know it has to be 3 parameters */
11157 assert (nparms == 3);
11159 rsave = newBitVect(16);
11160 /* save DPTR if it needs to be saved */
11161 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11162 if (bitVectBitValue(ic->rMask,i))
11163 rsave = bitVectSetBit(rsave,i);
11165 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11166 ds390_rUmaskForOp (IC_RESULT(ic))));
11173 aopOp (from, ic->next, FALSE, FALSE);
11175 /* get from into DPTR1 */
11176 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
11177 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
11178 if (options.model == MODEL_FLAT24) {
11179 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
11182 freeAsmop (from, NULL, ic, FALSE);
11183 aopOp (to, ic, FALSE, FALSE);
11184 /* get "to" into DPTR */
11185 /* if the operand is already in dptr
11186 then we do nothing else we move the value to dptr */
11187 if (AOP_TYPE (to) != AOP_STR) {
11188 /* if already in DPTR then we need to push */
11189 if (AOP_TYPE(to) == AOP_DPTR) {
11190 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11191 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11192 if (options.model == MODEL_FLAT24)
11193 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11194 emitcode ("pop", "dph");
11195 emitcode ("pop", "dpl");
11197 _startLazyDPSEvaluation ();
11198 /* if this is remateriazable */
11199 if (AOP_TYPE (to) == AOP_IMMD) {
11200 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11201 } else { /* we need to get it byte by byte */
11202 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11203 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11204 if (options.model == MODEL_FLAT24) {
11205 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11208 _endLazyDPSEvaluation ();
11211 freeAsmop (to, NULL, ic, FALSE);
11213 aopOp (count, ic->next->next, FALSE,FALSE);
11214 lbl =newiTempLabel(NULL);
11215 lbl2 =newiTempLabel(NULL);
11217 /* now for the actual compare */
11218 emitcode("push","ar0");
11219 if (AOP_TYPE(count) == AOP_LIT &&
11220 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11221 emitcode (";","OH JOY auto increment with djnz (very fast)");
11222 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11223 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11224 emitcode ("","!tlabeldef",lbl->key+100);
11226 emitcode ("clr","a");
11227 emitcode ("movc", "a,@a+dptr");
11229 emitcode ("movx", "a,@dptr");
11230 emitcode ("mov","r0,a");
11231 emitcode ("movx", "a,@dptr");
11232 emitcode ("clr","c");
11233 emitcode ("subb","a,r0");
11234 emitcode ("jnz","!tlabel",lbl2->key+100);
11235 emitcode ("inc", "dptr");
11236 emitcode ("inc", "dptr");
11237 emitcode ("djnz","b,!tlabel",lbl->key+100);
11238 emitcode ("clr","a");
11240 symbol *lbl1 = newiTempLabel(NULL);
11242 emitcode (";"," Auto increment but no djnz");
11243 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11244 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11245 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11246 emitcode ("","!tlabeldef",lbl->key+100);
11248 emitcode ("clr","a");
11249 emitcode ("movc", "a,@a+dptr");
11251 emitcode ("movx", "a,@dptr");
11252 emitcode ("mov","r0,a");
11253 emitcode ("movx", "a,@dptr");
11254 emitcode ("clr","c");
11255 emitcode ("subb","a,r0");
11256 emitcode ("jnz","!tlabel",lbl2->key+100);
11257 emitcode ("inc", "dptr");
11258 emitcode ("inc", "dptr");
11259 emitcode ("mov","a,b");
11260 emitcode ("orl","a,_ap");
11261 emitcode ("jz","!tlabel",lbl1->key+100);
11262 emitcode ("mov","a,_ap");
11263 emitcode ("add","a,#!constbyte",0xFF);
11264 emitcode ("mov","_ap,a");
11265 emitcode ("mov","a,b");
11266 emitcode ("addc","a,#!constbyte",0xFF);
11267 emitcode ("mov","b,a");
11268 emitcode ("sjmp","!tlabel",lbl->key+100);
11269 emitcode ("","!tlabeldef",lbl1->key+100);
11270 emitcode ("clr","a");
11272 freeAsmop (count, NULL, ic, FALSE);
11273 emitcode ("","!tlabeldef",lbl2->key+100);
11274 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11275 aopPut(AOP(IC_RESULT(ic)),"a",0);
11276 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11277 emitcode("pop","ar0");
11278 emitcode ("mov", "dps,#0");
11280 unsavermask(rsave);
11284 /*-----------------------------------------------------------------*/
11285 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11286 /* port, first parameter output area second parameter pointer to */
11287 /* port third parameter count */
11288 /*-----------------------------------------------------------------*/
11289 static void genInp( iCode *ic, int nparms, operand **parms)
11291 operand *from , *to , *count;
11296 /* we know it has to be 3 parameters */
11297 assert (nparms == 3);
11299 rsave = newBitVect(16);
11300 /* save DPTR if it needs to be saved */
11301 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11302 if (bitVectBitValue(ic->rMask,i))
11303 rsave = bitVectSetBit(rsave,i);
11305 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11306 ds390_rUmaskForOp (IC_RESULT(ic))));
11313 aopOp (from, ic->next, FALSE, FALSE);
11315 /* get from into DPTR1 */
11316 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
11317 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
11318 if (options.model == MODEL_FLAT24) {
11319 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
11322 freeAsmop (from, NULL, ic, FALSE);
11323 aopOp (to, ic, FALSE, FALSE);
11324 /* get "to" into DPTR */
11325 /* if the operand is already in dptr
11326 then we do nothing else we move the value to dptr */
11327 if (AOP_TYPE (to) != AOP_STR) {
11328 /* if already in DPTR then we need to push */
11329 if (AOP_TYPE(to) == AOP_DPTR) {
11330 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11331 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11332 if (options.model == MODEL_FLAT24)
11333 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11334 emitcode ("pop", "dph");
11335 emitcode ("pop", "dpl");
11337 _startLazyDPSEvaluation ();
11338 /* if this is remateriazable */
11339 if (AOP_TYPE (to) == AOP_IMMD) {
11340 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11341 } else { /* we need to get it byte by byte */
11342 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11343 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11344 if (options.model == MODEL_FLAT24) {
11345 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11348 _endLazyDPSEvaluation ();
11351 freeAsmop (to, NULL, ic, FALSE);
11353 aopOp (count, ic->next->next, FALSE,FALSE);
11354 lbl =newiTempLabel(NULL);
11356 /* now for the actual copy */
11357 if (AOP_TYPE(count) == AOP_LIT &&
11358 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11359 emitcode (";","OH JOY auto increment with djnz (very fast)");
11360 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11361 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11362 emitcode ("","!tlabeldef",lbl->key+100);
11363 emitcode ("movx", "a,@dptr"); /* read data from port */
11364 emitcode ("dec","dps"); /* switch to DPTR */
11365 emitcode ("movx", "@dptr,a"); /* save into location */
11366 emitcode ("inc", "dptr"); /* point to next area */
11367 emitcode ("inc","dps"); /* switch to DPTR2 */
11368 emitcode ("djnz","b,!tlabel",lbl->key+100);
11370 symbol *lbl1 = newiTempLabel(NULL);
11372 emitcode (";"," Auto increment but no djnz");
11373 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11374 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11375 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11376 emitcode ("","!tlabeldef",lbl->key+100);
11377 emitcode ("movx", "a,@dptr");
11378 emitcode ("dec","dps"); /* switch to DPTR */
11379 emitcode ("movx", "@dptr,a");
11380 emitcode ("inc", "dptr");
11381 emitcode ("inc","dps"); /* switch to DPTR2 */
11382 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
11383 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11384 emitcode ("mov","a,b");
11385 emitcode ("orl","a,_ap");
11386 emitcode ("jz","!tlabel",lbl1->key+100);
11387 emitcode ("mov","a,_ap");
11388 emitcode ("add","a,#!constbyte",0xFF);
11389 emitcode ("mov","_ap,a");
11390 emitcode ("mov","a,b");
11391 emitcode ("addc","a,#!constbyte",0xFF);
11392 emitcode ("mov","b,a");
11393 emitcode ("sjmp","!tlabel",lbl->key+100);
11394 emitcode ("","!tlabeldef",lbl1->key+100);
11396 emitcode ("mov", "dps,#0");
11397 freeAsmop (count, NULL, ic, FALSE);
11398 unsavermask(rsave);
11402 /*-----------------------------------------------------------------*/
11403 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11404 /* port, first parameter output area second parameter pointer to */
11405 /* port third parameter count */
11406 /*-----------------------------------------------------------------*/
11407 static void genOutp( iCode *ic, int nparms, operand **parms)
11409 operand *from , *to , *count;
11414 /* we know it has to be 3 parameters */
11415 assert (nparms == 3);
11417 rsave = newBitVect(16);
11418 /* save DPTR if it needs to be saved */
11419 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11420 if (bitVectBitValue(ic->rMask,i))
11421 rsave = bitVectSetBit(rsave,i);
11423 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11424 ds390_rUmaskForOp (IC_RESULT(ic))));
11431 aopOp (from, ic->next, FALSE, FALSE);
11433 /* get from into DPTR1 */
11434 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
11435 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
11436 if (options.model == MODEL_FLAT24) {
11437 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
11440 freeAsmop (from, NULL, ic, FALSE);
11441 aopOp (to, ic, FALSE, FALSE);
11442 /* get "to" into DPTR */
11443 /* if the operand is already in dptr
11444 then we do nothing else we move the value to dptr */
11445 if (AOP_TYPE (to) != AOP_STR) {
11446 /* if already in DPTR then we need to push */
11447 if (AOP_TYPE(to) == AOP_DPTR) {
11448 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11449 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11450 if (options.model == MODEL_FLAT24)
11451 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11452 emitcode ("pop", "dph");
11453 emitcode ("pop", "dpl");
11455 _startLazyDPSEvaluation ();
11456 /* if this is remateriazable */
11457 if (AOP_TYPE (to) == AOP_IMMD) {
11458 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11459 } else { /* we need to get it byte by byte */
11460 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11461 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11462 if (options.model == MODEL_FLAT24) {
11463 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11466 _endLazyDPSEvaluation ();
11469 freeAsmop (to, NULL, ic, FALSE);
11471 aopOp (count, ic->next->next, FALSE,FALSE);
11472 lbl =newiTempLabel(NULL);
11474 /* now for the actual copy */
11475 if (AOP_TYPE(count) == AOP_LIT &&
11476 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11477 emitcode (";","OH JOY auto increment with djnz (very fast)");
11478 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11479 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11480 emitcode ("","!tlabeldef",lbl->key+100);
11481 emitcode ("movx", "a,@dptr"); /* read data from port */
11482 emitcode ("inc","dps"); /* switch to DPTR2 */
11483 emitcode ("movx", "@dptr,a"); /* save into location */
11484 emitcode ("inc", "dptr"); /* point to next area */
11485 emitcode ("dec","dps"); /* switch to DPTR */
11486 emitcode ("djnz","b,!tlabel",lbl->key+100);
11488 symbol *lbl1 = newiTempLabel(NULL);
11490 emitcode (";"," Auto increment but no djnz");
11491 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11492 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11493 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11494 emitcode ("","!tlabeldef",lbl->key+100);
11495 /* emitcode ("push","acc"); */
11496 emitcode ("movx", "a,@dptr");
11497 emitcode ("inc", "dptr");
11498 emitcode ("inc","dps"); /* switch to DPTR2 */
11499 emitcode ("movx", "@dptr,a");
11500 emitcode ("dec","dps"); /* switch to DPTR */
11501 /* emitcode ("pop","acc"); */
11502 /* emitcode ("djnz","acc,!tlabel",lbl->key+100); */
11503 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
11504 emitcode ("mov","a,b");
11505 emitcode ("orl","a,_ap");
11506 emitcode ("jz","!tlabel",lbl1->key+100);
11507 emitcode ("mov","a,_ap");
11508 emitcode ("add","a,#!constbyte",0xFF);
11509 emitcode ("mov","_ap,a");
11510 emitcode ("mov","a,b");
11511 emitcode ("addc","a,#!constbyte",0xFF);
11512 emitcode ("mov","b,a");
11513 emitcode ("sjmp","!tlabel",lbl->key+100);
11514 emitcode ("","!tlabeldef",lbl1->key+100);
11516 emitcode ("mov", "dps,#0");
11517 freeAsmop (count, NULL, ic, FALSE);
11518 unsavermask(rsave);
11522 /*-----------------------------------------------------------------*/
11523 /* genSwapW - swap lower & high order bytes */
11524 /*-----------------------------------------------------------------*/
11525 static void genSwapW(iCode *ic, int nparms, operand **parms)
11529 assert (nparms==1);
11532 dest=IC_RESULT(ic);
11534 assert(getSize(operandType(src))==2);
11536 aopOp (src, ic, FALSE, FALSE);
11537 emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,TRUE));
11539 emitcode ("mov","b,%s",aopGet(AOP(src),1,FALSE,FALSE,FALSE));
11541 freeAsmop (src, NULL, ic, FALSE);
11543 aopOp (dest,ic, FALSE, FALSE);
11544 aopPut(AOP(dest),"b",0);
11545 aopPut(AOP(dest),"a",1);
11546 freeAsmop (dest, NULL, ic, FALSE);
11549 /*-----------------------------------------------------------------*/
11550 /* genMemsetX - gencode for memSetX data */
11551 /*-----------------------------------------------------------------*/
11552 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11554 operand *to , *val , *count;
11558 bitVect *rsave = NULL;
11560 /* we know it has to be 3 parameters */
11561 assert (nparms == 3);
11567 /* save DPTR if it needs to be saved */
11568 rsave = newBitVect(16);
11569 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11570 if (bitVectBitValue(ic->rMask,i))
11571 rsave = bitVectSetBit(rsave,i);
11573 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11574 ds390_rUmaskForOp (IC_RESULT(ic))));
11577 aopOp (to, ic, FALSE, FALSE);
11578 /* get "to" into DPTR */
11579 /* if the operand is already in dptr
11580 then we do nothing else we move the value to dptr */
11581 if (AOP_TYPE (to) != AOP_STR) {
11582 /* if already in DPTR then we need to push */
11583 if (AOP_TYPE(to) == AOP_DPTR) {
11584 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11585 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11586 if (options.model == MODEL_FLAT24)
11587 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11588 emitcode ("pop", "dph");
11589 emitcode ("pop", "dpl");
11591 _startLazyDPSEvaluation ();
11592 /* if this is remateriazable */
11593 if (AOP_TYPE (to) == AOP_IMMD) {
11594 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11595 } else { /* we need to get it byte by byte */
11596 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11597 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11598 if (options.model == MODEL_FLAT24) {
11599 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11602 _endLazyDPSEvaluation ();
11605 freeAsmop (to, NULL, ic, FALSE);
11607 aopOp (val, ic->next->next, FALSE,FALSE);
11608 aopOp (count, ic->next->next, FALSE,FALSE);
11609 lbl =newiTempLabel(NULL);
11610 /* now for the actual copy */
11611 if (AOP_TYPE(count) == AOP_LIT &&
11612 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11613 l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
11614 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11616 emitcode ("","!tlabeldef",lbl->key+100);
11617 emitcode ("movx", "@dptr,a");
11618 emitcode ("inc", "dptr");
11619 emitcode ("djnz","b,!tlabel",lbl->key+100);
11621 symbol *lbl1 = newiTempLabel(NULL);
11623 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11624 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11625 emitcode ("","!tlabeldef",lbl->key+100);
11626 l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
11628 emitcode ("movx", "@dptr,a");
11629 emitcode ("inc", "dptr");
11630 emitcode ("mov","a,b");
11631 emitcode ("orl","a,_ap");
11632 emitcode ("jz","!tlabel",lbl1->key+100);
11633 emitcode ("mov","a,_ap");
11634 emitcode ("add","a,#!constbyte",0xFF);
11635 emitcode ("mov","_ap,a");
11636 emitcode ("mov","a,b");
11637 emitcode ("addc","a,#!constbyte",0xFF);
11638 emitcode ("mov","b,a");
11639 emitcode ("sjmp","!tlabel",lbl->key+100);
11640 emitcode ("","!tlabeldef",lbl1->key+100);
11642 freeAsmop (count, NULL, ic, FALSE);
11643 unsavermask(rsave);
11646 /*-----------------------------------------------------------------*/
11647 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11648 /*-----------------------------------------------------------------*/
11649 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11652 operand *pnum, *result;
11655 assert (nparms==1);
11656 /* save registers that need to be saved */
11657 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11658 ds390_rUmaskForOp (IC_RESULT(ic))));
11661 aopOp (pnum, ic, FALSE, FALSE);
11662 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,FALSE));
11663 freeAsmop (pnum, NULL, ic, FALSE);
11664 emitcode ("lcall","NatLib_LoadPrimitive");
11665 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11666 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
11667 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
11668 for (i = (size-1) ; i >= 0 ; i-- ) {
11669 emitcode ("push","a%s",javaRet[i]);
11671 for (i=0; i < size ; i++ ) {
11672 emitcode ("pop","a%s",aopGet(AOP(result),i,FALSE,FALSE,FALSE));
11675 for (i = 0 ; i < size ; i++ ) {
11676 aopPut(AOP(result),javaRet[i],i);
11679 freeAsmop (result, NULL, ic, FALSE);
11680 unsavermask(rsave);
11683 /*-----------------------------------------------------------------*/
11684 /* genNatLibLoadPointer - calls TINI api function to load pointer */
11685 /*-----------------------------------------------------------------*/
11686 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
11689 operand *pnum, *result;
11693 assert (nparms==1);
11694 /* save registers that need to be saved */
11695 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11696 ds390_rUmaskForOp (IC_RESULT(ic))));
11699 aopOp (pnum, ic, FALSE, FALSE);
11700 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,FALSE));
11701 freeAsmop (pnum, NULL, ic, FALSE);
11702 emitcode ("lcall","NatLib_LoadPointer");
11703 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11704 if (AOP_TYPE(result)!=AOP_STR) {
11705 for (i = 0 ; i < size ; i++ ) {
11706 aopPut(AOP(result),fReturn[i],i);
11709 freeAsmop (result, NULL, ic, FALSE);
11710 unsavermask(rsave);
11713 /*-----------------------------------------------------------------*/
11714 /* genNatLibInstallStateBlock - */
11715 /*-----------------------------------------------------------------*/
11716 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
11717 operand **parms, const char *name)
11720 operand *psb, *handle;
11721 assert (nparms==2);
11723 /* save registers that need to be saved */
11724 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11725 ds390_rUmaskForOp (IC_RESULT(ic))));
11729 /* put pointer to state block into DPTR1 */
11730 aopOp (psb, ic, FALSE, FALSE);
11731 if (AOP_TYPE (psb) == AOP_IMMD) {
11732 emitcode ("mov","dps,#1");
11733 emitcode ("mov", "dptr,%s", aopGet (AOP (psb), 0, TRUE, FALSE, FALSE));
11734 emitcode ("mov","dps,#0");
11736 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,FALSE));
11737 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,FALSE));
11738 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,FALSE));
11740 freeAsmop (psb, NULL, ic, FALSE);
11742 /* put libraryID into DPTR */
11743 emitcode ("mov","dptr,#LibraryID");
11745 /* put handle into r3:r2 */
11746 aopOp (handle, ic, FALSE, FALSE);
11747 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11748 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11749 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11750 emitcode ("pop","ar3");
11751 emitcode ("pop","ar2");
11753 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11754 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11756 freeAsmop (psb, NULL, ic, FALSE);
11758 /* make the call */
11759 emitcode ("lcall","NatLib_Install%sStateBlock",name);
11761 /* put return value into place*/
11763 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
11765 aopPut(AOP(IC_RESULT(ic)),"a",0);
11766 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11767 unsavermask(rsave);
11770 /*-----------------------------------------------------------------*/
11771 /* genNatLibRemoveStateBlock - */
11772 /*-----------------------------------------------------------------*/
11773 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
11779 /* save registers that need to be saved */
11780 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11781 ds390_rUmaskForOp (IC_RESULT(ic))));
11783 /* put libraryID into DPTR */
11784 emitcode ("mov","dptr,#LibraryID");
11785 /* make the call */
11786 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
11787 unsavermask(rsave);
11790 /*-----------------------------------------------------------------*/
11791 /* genNatLibGetStateBlock - */
11792 /*-----------------------------------------------------------------*/
11793 static void genNatLibGetStateBlock(iCode *ic,int nparms,
11794 operand **parms,const char *name)
11797 symbol *lbl = newiTempLabel(NULL);
11800 /* save registers that need to be saved */
11801 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11802 ds390_rUmaskForOp (IC_RESULT(ic))));
11804 /* put libraryID into DPTR */
11805 emitcode ("mov","dptr,#LibraryID");
11806 /* make the call */
11807 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
11808 emitcode ("jnz","!tlabel",lbl->key+100);
11810 /* put return value into place */
11811 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
11812 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
11813 emitcode ("push","ar3");
11814 emitcode ("push","ar2");
11815 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,FALSE));
11816 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,FALSE));
11818 aopPut(AOP(IC_RESULT(ic)),"r2",0);
11819 aopPut(AOP(IC_RESULT(ic)),"r3",1);
11821 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11822 emitcode ("","!tlabeldef",lbl->key+100);
11823 unsavermask(rsave);
11826 /*-----------------------------------------------------------------*/
11827 /* genMMMalloc - */
11828 /*-----------------------------------------------------------------*/
11829 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
11830 int size, const char *name)
11835 symbol *lbl = newiTempLabel(NULL);
11837 assert (nparms == 1);
11838 /* save registers that need to be saved */
11839 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11840 ds390_rUmaskForOp (IC_RESULT(ic))));
11843 aopOp (bsize,ic,FALSE,FALSE);
11845 /* put the size in R4-R2 */
11846 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
11847 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,FALSE));
11848 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,FALSE));
11850 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,FALSE));
11851 emitcode("pop","ar4");
11853 emitcode("pop","ar3");
11854 emitcode("pop","ar2");
11856 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,FALSE));
11857 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,FALSE));
11859 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,FALSE));
11862 freeAsmop (bsize, NULL, ic, FALSE);
11864 /* make the call */
11865 emitcode ("lcall","MM_%s",name);
11866 emitcode ("jz","!tlabel",lbl->key+100);
11867 emitcode ("mov","r2,#!constbyte",0xff);
11868 emitcode ("mov","r3,#!constbyte",0xff);
11869 emitcode ("","!tlabeldef",lbl->key+100);
11870 /* we don't care about the pointer : we just save the handle */
11871 rsym = OP_SYMBOL(IC_RESULT(ic));
11872 if (rsym->liveFrom != rsym->liveTo) {
11873 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
11874 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
11875 emitcode ("push","ar3");
11876 emitcode ("push","ar2");
11877 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,FALSE));
11878 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,FALSE));
11880 aopPut(AOP(IC_RESULT(ic)),"r2",0);
11881 aopPut(AOP(IC_RESULT(ic)),"r3",1);
11883 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11885 unsavermask(rsave);
11888 /*-----------------------------------------------------------------*/
11890 /*-----------------------------------------------------------------*/
11891 static void genMMDeref (iCode *ic,int nparms, operand **parms)
11896 assert (nparms == 1);
11897 /* save registers that need to be saved */
11898 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11899 ds390_rUmaskForOp (IC_RESULT(ic))));
11902 aopOp (handle,ic,FALSE,FALSE);
11904 /* put the size in R4-R2 */
11905 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11906 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11907 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11908 emitcode("pop","ar3");
11909 emitcode("pop","ar2");
11911 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11912 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11914 freeAsmop (handle, NULL, ic, FALSE);
11916 /* make the call */
11917 emitcode ("lcall","MM_Deref");
11920 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11921 if (rsym->liveFrom != rsym->liveTo) {
11922 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11923 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
11924 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
11925 aopPut(AOP(IC_RESULT(ic)),"dph",1);
11926 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
11930 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11931 unsavermask(rsave);
11934 /*-----------------------------------------------------------------*/
11935 /* genMMUnrestrictedPersist - */
11936 /*-----------------------------------------------------------------*/
11937 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
11942 assert (nparms == 1);
11943 /* save registers that need to be saved */
11944 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11945 ds390_rUmaskForOp (IC_RESULT(ic))));
11948 aopOp (handle,ic,FALSE,FALSE);
11950 /* put the size in R3-R2 */
11951 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11952 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11953 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11954 emitcode("pop","ar3");
11955 emitcode("pop","ar2");
11957 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11958 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11960 freeAsmop (handle, NULL, ic, FALSE);
11962 /* make the call */
11963 emitcode ("lcall","MM_UnrestrictedPersist");
11966 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11967 if (rsym->liveFrom != rsym->liveTo) {
11968 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11969 aopPut(AOP(IC_RESULT(ic)),"a",0);
11970 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11973 unsavermask(rsave);
11976 /*-----------------------------------------------------------------*/
11977 /* genSystemExecJavaProcess - */
11978 /*-----------------------------------------------------------------*/
11979 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
11982 operand *handle, *pp;
11984 assert (nparms==2);
11985 /* save registers that need to be saved */
11986 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11987 ds390_rUmaskForOp (IC_RESULT(ic))));
11992 /* put the handle in R3-R2 */
11993 aopOp (handle,ic,FALSE,FALSE);
11994 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11995 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11996 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11997 emitcode("pop","ar3");
11998 emitcode("pop","ar2");
12000 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
12001 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
12003 freeAsmop (handle, NULL, ic, FALSE);
12005 /* put pointer in DPTR */
12006 aopOp (pp,ic,FALSE,FALSE);
12007 if (AOP_TYPE(pp) == AOP_IMMD) {
12008 emitcode ("mov", "dptr,%s", aopGet (AOP (pp), 0, TRUE, FALSE, FALSE));
12009 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12010 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,FALSE));
12011 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,FALSE));
12012 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,FALSE));
12014 freeAsmop (handle, NULL, ic, FALSE);
12016 /* make the call */
12017 emitcode ("lcall","System_ExecJavaProcess");
12019 /* put result in place */
12021 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12022 if (rsym->liveFrom != rsym->liveTo) {
12023 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12024 aopPut(AOP(IC_RESULT(ic)),"a",0);
12025 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12029 unsavermask(rsave);
12032 /*-----------------------------------------------------------------*/
12033 /* genSystemRTCRegisters - */
12034 /*-----------------------------------------------------------------*/
12035 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12041 assert (nparms==1);
12042 /* save registers that need to be saved */
12043 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12044 ds390_rUmaskForOp (IC_RESULT(ic))));
12047 /* put pointer in DPTR */
12048 aopOp (pp,ic,FALSE,FALSE);
12049 if (AOP_TYPE (pp) == AOP_IMMD) {
12050 emitcode ("mov","dps,#1");
12051 emitcode ("mov", "dptr,%s", aopGet (AOP (pp), 0, TRUE, FALSE, FALSE));
12052 emitcode ("mov","dps,#0");
12054 emitcode ("mov","dpl1,%s",aopGet(AOP(pp),0,FALSE,FALSE,FALSE));
12055 emitcode ("mov","dph1,%s",aopGet(AOP(pp),1,FALSE,FALSE,FALSE));
12056 emitcode ("mov","dpx1,%s",aopGet(AOP(pp),2,FALSE,FALSE,FALSE));
12058 freeAsmop (pp, NULL, ic, FALSE);
12060 /* make the call */
12061 emitcode ("lcall","System_%sRTCRegisters",name);
12063 unsavermask(rsave);
12066 /*-----------------------------------------------------------------*/
12067 /* genSystemThreadSleep - */
12068 /*-----------------------------------------------------------------*/
12069 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12074 assert (nparms==1);
12075 /* save registers that need to be saved */
12076 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12077 ds390_rUmaskForOp (IC_RESULT(ic))));
12080 aopOp(to,ic,FALSE,FALSE);
12081 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12082 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12083 emitcode ("push","%s",aopGet(AOP(to),0,FALSE,TRUE,FALSE));
12084 emitcode ("push","%s",aopGet(AOP(to),1,FALSE,TRUE,FALSE));
12085 emitcode ("push","%s",aopGet(AOP(to),2,FALSE,TRUE,FALSE));
12086 emitcode ("push","%s",aopGet(AOP(to),3,FALSE,TRUE,FALSE));
12087 emitcode ("pop","ar3");
12088 emitcode ("pop","ar2");
12089 emitcode ("pop","ar1");
12090 emitcode ("pop","ar0");
12092 emitcode ("mov","r0,%s",aopGet(AOP(to),0,FALSE,TRUE,FALSE));
12093 emitcode ("mov","r1,%s",aopGet(AOP(to),1,FALSE,TRUE,FALSE));
12094 emitcode ("mov","r2,%s",aopGet(AOP(to),2,FALSE,TRUE,FALSE));
12095 emitcode ("mov","r3,%s",aopGet(AOP(to),3,FALSE,TRUE,FALSE));
12097 freeAsmop (to, NULL, ic, FALSE);
12099 /* suspend in acc */
12101 aopOp(s,ic,FALSE,FALSE);
12102 emitcode ("mov","a,%s",aopGet(AOP(s),0,FALSE,TRUE,FALSE));
12103 freeAsmop (s, NULL, ic, FALSE);
12105 /* make the call */
12106 emitcode ("lcall","System_%s",name);
12108 unsavermask(rsave);
12111 /*-----------------------------------------------------------------*/
12112 /* genSystemThreadResume - */
12113 /*-----------------------------------------------------------------*/
12114 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12119 assert (nparms==2);
12120 /* save registers that need to be saved */
12121 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12122 ds390_rUmaskForOp (IC_RESULT(ic))));
12128 aopOp(pid,ic,FALSE,FALSE);
12129 emitcode ("mov","r0,%s",aopGet(AOP(pid),0,FALSE,TRUE,FALSE));
12130 freeAsmop (pid, NULL, ic, FALSE);
12133 aopOp(tid,ic,FALSE,FALSE);
12134 emitcode ("mov","a,%s",aopGet(AOP(tid),0,FALSE,TRUE,FALSE));
12135 freeAsmop (tid, NULL, ic, FALSE);
12137 emitcode ("lcall","System_ThreadResume");
12139 /* put result into place */
12141 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12142 if (rsym->liveFrom != rsym->liveTo) {
12143 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12144 aopPut(AOP(IC_RESULT(ic)),"a",0);
12145 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12148 unsavermask(rsave);
12151 /*-----------------------------------------------------------------*/
12152 /* genSystemProcessResume - */
12153 /*-----------------------------------------------------------------*/
12154 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12159 assert (nparms==1);
12160 /* save registers that need to be saved */
12161 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12162 ds390_rUmaskForOp (IC_RESULT(ic))));
12167 aopOp(pid,ic,FALSE,FALSE);
12168 emitcode ("mov","a,%s",aopGet(AOP(pid),0,FALSE,TRUE,FALSE));
12169 freeAsmop (pid, NULL, ic, FALSE);
12171 emitcode ("lcall","System_ProcessResume");
12173 unsavermask(rsave);
12176 /*-----------------------------------------------------------------*/
12178 /*-----------------------------------------------------------------*/
12179 static void genSystem (iCode *ic,int nparms,char *name)
12181 assert(nparms == 0);
12183 emitcode ("lcall","System_%s",name);
12186 /*-----------------------------------------------------------------*/
12187 /* genSystemPoll - */
12188 /*-----------------------------------------------------------------*/
12189 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12194 assert (nparms==1);
12195 /* save registers that need to be saved */
12196 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12197 ds390_rUmaskForOp (IC_RESULT(ic))));
12200 aopOp (fp,ic,FALSE,FALSE);
12201 if (AOP_TYPE (fp) == AOP_IMMD) {
12202 emitcode ("mov", "dptr,%s", aopGet (AOP (fp), 0, TRUE, FALSE, FALSE));
12203 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12204 emitcode ("mov","dpl,%s",aopGet(AOP(fp),0,FALSE,FALSE,FALSE));
12205 emitcode ("mov","dph,%s",aopGet(AOP(fp),1,FALSE,FALSE,FALSE));
12206 emitcode ("mov","dpx,%s",aopGet(AOP(fp),2,FALSE,FALSE,FALSE));
12208 freeAsmop (fp, NULL, ic, FALSE);
12210 emitcode ("lcall","System_%sPoll",name);
12212 /* put result into place */
12214 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12215 if (rsym->liveFrom != rsym->liveTo) {
12216 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12217 aopPut(AOP(IC_RESULT(ic)),"a",0);
12218 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12221 unsavermask(rsave);
12224 /*-----------------------------------------------------------------*/
12225 /* genSystemGetCurrentID - */
12226 /*-----------------------------------------------------------------*/
12227 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12229 assert (nparms==0);
12231 emitcode ("lcall","System_GetCurrent%sId",name);
12232 /* put result into place */
12234 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12235 if (rsym->liveFrom != rsym->liveTo) {
12236 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12237 aopPut(AOP(IC_RESULT(ic)),"a",0);
12238 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12243 /*-----------------------------------------------------------------*/
12244 /* genBuiltIn - calls the appropriate function to generating code */
12245 /* for a built in function */
12246 /*-----------------------------------------------------------------*/
12247 static void genBuiltIn (iCode *ic)
12249 operand *bi_parms[MAX_BUILTIN_ARGS];
12254 /* get all the arguments for a built in function */
12255 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12257 /* which function is it */
12258 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12259 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12260 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12261 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12262 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12263 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12264 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12265 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12266 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12267 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12268 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12269 } else if (strcmp(bif->name,"__builtin_inp")==0) {
12270 genInp(bi_iCode,nbi_parms,bi_parms);
12271 } else if (strcmp(bif->name,"__builtin_outp")==0) {
12272 genOutp(bi_iCode,nbi_parms,bi_parms);
12273 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12274 genSwapW(bi_iCode,nbi_parms,bi_parms);
12275 /* JavaNative builtIns */
12276 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12277 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12278 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12279 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12280 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12281 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12282 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12283 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12284 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12285 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12286 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12287 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12288 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12289 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12290 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12291 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12292 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12293 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12294 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12295 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12296 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12297 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12298 } else if (strcmp(bif->name,"MM_Malloc")==0) {
12299 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12300 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12301 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12302 } else if (strcmp(bif->name,"MM_Free")==0) {
12303 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12304 } else if (strcmp(bif->name,"MM_Deref")==0) {
12305 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12306 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12307 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12308 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12309 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12310 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12311 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12312 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12313 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12314 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12315 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12316 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12317 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12318 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12319 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12320 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12321 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12322 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12323 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12324 } else if (strcmp(bif->name,"System_SaveThread")==0) {
12325 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12326 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12327 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12328 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12329 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12330 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12331 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12332 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12333 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12334 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12335 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12336 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12337 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12338 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12339 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12340 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12341 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12342 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12343 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12344 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12345 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12347 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12353 /*-----------------------------------------------------------------*/
12354 /* gen390Code - generate code for Dallas 390 based controllers */
12355 /*-----------------------------------------------------------------*/
12357 gen390Code (iCode * lic)
12362 lineHead = lineCurr = NULL;
12363 dptrn[1][0] = "dpl1";
12364 dptrn[1][1] = "dph1";
12365 dptrn[1][2] = "dpx1";
12367 if (options.model == MODEL_FLAT24) {
12368 fReturnSizeDS390 = 5;
12369 fReturn = fReturn24;
12371 fReturnSizeDS390 = 4;
12372 fReturn = fReturn16;
12373 options.stack10bit=0;
12376 /* print the allocation information */
12378 printAllocInfo (currFunc, codeOutFile);
12380 /* if debug information required */
12381 if (options.debug && currFunc)
12383 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
12385 if (IS_STATIC (currFunc->etype))
12386 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12388 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12391 /* stack pointer name */
12392 if (options.useXstack)
12398 for (ic = lic; ic; ic = ic->next)
12401 if (ic->lineno && cln != ic->lineno)
12406 emitcode ("", "C$%s$%d$%d$%d ==.",
12407 FileBaseName (ic->filename), ic->lineno,
12408 ic->level, ic->block);
12411 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
12412 printCLine(ic->filename, ic->lineno));
12415 /* if the result is marked as
12416 spilt and rematerializable or code for
12417 this has already been generated then
12419 if (resultRemat (ic) || ic->generated)
12422 /* depending on the operation */
12442 /* IPOP happens only when trying to restore a
12443 spilt live range, if there is an ifx statement
12444 following this pop then the if statement might
12445 be using some of the registers being popped which
12446 would destory the contents of the register so
12447 we need to check for this condition and handle it */
12449 ic->next->op == IFX &&
12450 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
12451 genIfx (ic->next, ic);
12469 genEndFunction (ic);
12489 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12506 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
12510 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
12517 /* note these two are xlated by algebraic equivalence
12518 during parsing SDCC.y */
12519 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12520 "got '>=' or '<=' shouldn't have come here");
12524 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12536 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12540 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12544 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12568 genRightShift (ic);
12571 case GET_VALUE_AT_ADDRESS:
12572 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
12576 if (POINTER_SET (ic))
12577 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
12603 if (ic->builtinSEND) genBuiltIn(ic);
12604 else addSet (&_G.sendSet, ic);
12617 /* now we are ready to call the
12618 peep hole optimizer */
12619 if (!options.nopeep)
12620 peepHole (&lineHead);
12622 /* now do the actual printing */
12623 printLine (lineHead, codeOutFile);