1 /* jit/mips/codegen.c - machine code generator for mips
3 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4 Institut f. Computersprachen, TU Wien
5 R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser, M. Probst,
6 S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich,
9 This file is part of CACAO.
11 This program is free software; you can redistribute it and/or
12 modify it under the terms of the GNU General Public License as
13 published by the Free Software Foundation; either version 2, or (at
14 your option) any later version.
16 This program is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
26 Contact: cacao@complang.tuwien.ac.at
28 Authors: Andreas Krall
31 Contains the codegenerator for an MIPS (R4000 or higher) processor.
32 This module generates MIPS machine code for a sequence of
33 intermediate code commands (ICMDs).
35 $Id: codegen.c 597 2003-11-09 20:08:18Z twisti $
55 /* include independent code generation stuff */
56 #include "codegen.inc"
60 /* *****************************************************************************
62 Datatypes and Register Allocations:
63 -----------------------------------
65 On 64-bit-machines (like the MIPS) all operands are stored in the
66 registers in a 64-bit form, even when the correspondig JavaVM operands
67 only need 32 bits. This is done by a canonical representation:
69 32-bit integers are allways stored as sign-extended 64-bit values (this
70 approach is directly supported by the MIPS architecture and is very easy
73 32-bit-floats are stored in a 64-bit double precision register by simply
74 expanding the exponent and mantissa with zeroes. (also supported by the
80 The calling conventions and the layout of the stack is explained in detail
81 in the documention file: calling.doc
83 *******************************************************************************/
86 /* register descripton - array ************************************************/
88 /* #define REG_RES 0 reserved register for OS or code generator */
89 /* #define REG_RET 1 return value register */
90 /* #define REG_EXC 2 exception value register (only old jit) */
91 /* #define REG_SAV 3 (callee) saved register */
92 /* #define REG_TMP 4 scratch temporary register (caller saved) */
93 /* #define REG_ARG 5 argument register (caller saved) */
95 /* #define REG_END -1 last entry in tables */
98 REG_RES, REG_RES, REG_RET, REG_RES, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
99 REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
100 REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
101 REG_TMP, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES,
104 /* for use of reserved registers, see comment above */
106 int nregdescfloat[] = {
107 REG_RET, REG_RES, REG_RES, REG_RES, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
108 REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
109 REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
110 REG_SAV, REG_TMP, REG_SAV, REG_TMP, REG_SAV, REG_TMP, REG_SAV, REG_TMP,
113 /* for use of reserved registers, see comment above */
116 /* parameter allocation mode */
118 int nreg_parammode = PARAMMODE_NUMBERED;
120 /* parameter-registers will be allocated by assigning the
121 1. parameter: int/float-reg a0
122 2. parameter: int/float-reg a1
123 3. parameter: int/float-reg a2 ....
127 /* stackframe-infos ***********************************************************/
129 int parentargs_base; /* offset in stackframe for the parameter from the caller*/
131 /* -> see file 'calling.doc' */
134 /* additional functions and macros to generate code ***************************/
136 /* #define BlockPtrOfPC(pc) block+block_index[pc] */
137 #define BlockPtrOfPC(pc) ((basicblock *) iptr->target)
141 #define COUNT_SPILLS count_spills++
147 /* gen_nullptr_check(objreg) */
149 #ifdef SOFTNULLPTRCHECK
150 #define gen_nullptr_check(objreg) \
152 M_BEQZ((objreg), 0);\
153 codegen_addxnullrefs(mcodeptr);\
157 #define gen_nullptr_check(objreg)
161 /* MCODECHECK(icnt) */
163 #define MCODECHECK(icnt) \
164 if((mcodeptr+(icnt))>mcodeend)mcodeptr=codegen_increase((u1*)mcodeptr)
167 generates an integer-move from register a to b.
168 if a and b are the same int-register, no code will be generated.
171 #define M_INTMOVE(a,b) if(a!=b){M_MOV(a,b);}
175 generates a floating-point-move from register a to b.
176 if a and b are the same float-register, no code will be generated
179 #define M_FLTMOVE(a,b) {if(a!=b){M_DMOV(a,b);}}
181 #define M_TFLTMOVE(t,a,b) \
185 else {M_FMOV(a,b);} \
188 #define M_TFLD(t,a,b,disp) \
194 #define M_TFST(t,a,b,disp) \
200 #define M_CCFLTMOVE(t1,t2,a,b) \
202 {M_TFLTMOVE(t1,a,b);} \
204 if ((t1)==TYPE_DBL) \
209 #define M_CCFLD(t1,t2,a,b,disp) \
213 M_DLD(REG_FTMP1,b,disp); \
214 if ((t1)==TYPE_DBL) \
215 {M_CVTDF(REG_FTMP1,a);} \
217 {M_CVTFD(REG_FTMP1,a);} \
220 #define M_CCFST(t1,t2,a,b,disp) \
224 if ((t1)==TYPE_DBL) \
225 {M_CVTDF(a,REG_FTMP1);} \
227 {M_CVTFD(a,REG_FTMP1);} \
228 M_DST(REG_FTMP1,b,disp); \
233 this function generates code to fetch data from a pseudo-register
234 into a real register.
235 If the pseudo-register has actually been assigned to a real
236 register, no code will be emitted, since following operations
237 can use this register directly.
239 v: pseudoregister to be fetched from
240 tempregnum: temporary register to be used if v is actually spilled to ram
242 return: the register number, where the operand can be found after
243 fetching (this wil be either tempregnum or the register
244 number allready given to v)
247 #define var_to_reg_int(regnr,v,tempnr) { \
248 if ((v)->flags & INMEMORY) \
249 {COUNT_SPILLS;M_LLD(tempnr,REG_SP,8*(v)->regoff);regnr=tempnr;} \
250 else regnr=(v)->regoff; \
254 #define var_to_reg_flt(regnr,v,tempnr) { \
255 if ((v)->flags & INMEMORY) \
256 {COUNT_SPILLS;M_DLD(tempnr,REG_SP,8*(v)->regoff);regnr=tempnr;} \
257 else regnr=(v)->regoff; \
262 This function determines a register, to which the result of an operation
263 should go, when it is ultimatively intended to store the result in
265 If v is assigned to an actual register, this register will be returned.
266 Otherwise (when v is spilled) this function returns tempregnum.
267 If not already done, regoff and flags are set in the stack location.
270 static int reg_of_var(stackptr v, int tempregnum)
274 switch (v->varkind) {
276 if (!(v->flags & INMEMORY))
280 var = &(interfaces[v->varnum][v->type]);
281 v->regoff = var->regoff;
282 if (!(var->flags & INMEMORY))
286 var = &(locals[v->varnum][v->type]);
287 v->regoff = var->regoff;
288 if (!(var->flags & INMEMORY))
292 v->regoff = v->varnum;
293 if (IS_FLT_DBL_TYPE(v->type)) {
294 if (v->varnum < fltreg_argnum) {
295 v->regoff = argfltregs[v->varnum];
296 return(argfltregs[v->varnum]);
300 if (v->varnum < intreg_argnum) {
301 v->regoff = argintregs[v->varnum];
302 return(argintregs[v->varnum]);
304 v->regoff -= intreg_argnum;
307 v->flags |= INMEMORY;
312 /* store_reg_to_var_xxx:
313 This function generates the code to store the result of an operation
314 back into a spilled pseudo-variable.
315 If the pseudo-variable has not been spilled in the first place, this
316 function will generate nothing.
318 v ............ Pseudovariable
319 tempregnum ... Number of the temporary registers as returned by
323 #define store_reg_to_var_int(sptr, tempregnum) { \
324 if ((sptr)->flags & INMEMORY) { \
326 M_LST(tempregnum, REG_SP, 8 * (sptr)->regoff); \
330 #define store_reg_to_var_flt(sptr, tempregnum) { \
331 if ((sptr)->flags & INMEMORY) { \
333 M_DST(tempregnum, REG_SP, 8 * (sptr)->regoff); \
338 /* NullPointerException handlers and exception handling initialisation */
340 /* NullPointerException signal handler for hardware null pointer check */
342 void catch_NullPointerException(int sig, int code, struct sigcontext *sigctx)
348 /* Reset signal handler - necessary for SysV, does no harm for BSD */
350 instr = *((int*)(sigctx->sc_pc));
351 faultaddr = sigctx->sc_regs[(instr >> 21) & 0x1f];
353 if (faultaddr == 0) {
355 sigaddset(&nsig, sig);
356 sigprocmask(SIG_UNBLOCK, &nsig, NULL); /* unblock signal */
357 sigctx->sc_regs[REG_ITMP1_XPTR] =
358 (long) proto_java_lang_NullPointerException;
359 sigctx->sc_regs[REG_ITMP2_XPC] = sigctx->sc_pc;
360 sigctx->sc_pc = (long) asm_handle_exception;
363 faultaddr += (long) ((instr << 16) >> 16);
364 fprintf(stderr, "faulting address: 0x%lx at 0x%lx\n", (long) faultaddr, (long) sigctx->sc_pc);
365 panic("Stack overflow");
370 void init_exceptions(void)
373 sigset_t unblockmask;
377 /* The Boehm GC initialization blocks the SIGSEGV signal. So we do a
378 dummy allocation here to ensure that the GC is initialized.
380 heap_allocate(1, 0, NULL);
382 /* install signal handlers we need to convert to exceptions */
384 sigemptyset(&unblockmask);
386 sa.sa_sigaction = catch_NullPointerException;
387 sigemptyset(&sa.sa_mask);
392 sigaction(SIGSEGV, &sa, NULL);
393 sigaddset(&unblockmask, SIGSEGV);
397 sigaction(SIGBUS, &sa, NULL);
398 sigaddset(&unblockmask, SIGBUS);
402 sigprocmask(SIG_UNBLOCK, &unblockmask, NULL);
406 /* function gen_mcode **********************************************************
408 generates machine code
410 *******************************************************************************/
412 #define MethodPointer -8
413 #define FrameSize -12
418 #define ExTableSize -32
419 #define ExTableStart -32
422 #define ExEntrySize -32
425 #define ExHandlerPC -24
426 #define ExCatchType -32
428 #define ExEntrySize -16
431 #define ExHandlerPC -12
432 #define ExCatchType -16
437 int len, s1, s2, s3, d;
449 savedregs_num = (isleafmethod) ? 0 : 1; /* space to save the RA */
451 /* space to save used callee saved registers */
453 savedregs_num += (savintregcnt - maxsavintreguse);
454 savedregs_num += (savfltregcnt - maxsavfltreguse);
456 parentargs_base = maxmemuse + savedregs_num;
458 #ifdef USE_THREADS /* space to save argument of monitor_enter */
460 if (checksync && (method->flags & ACC_SYNCHRONIZED))
465 /* adjust frame size for 16 byte alignment */
467 if (parentargs_base & 1)
470 /* create method header */
473 (void) dseg_addaddress(method); /* Filler */
475 (void) dseg_addaddress(method); /* MethodPointer */
476 (void) dseg_adds4(parentargs_base * 8); /* FrameSize */
480 /* IsSync contains the offset relative to the stack pointer for the
481 argument of monitor_exit used in the exception handler. Since the
482 offset could be zero and give a wrong meaning of the flag it is
486 if (checksync && (method->flags & ACC_SYNCHRONIZED))
487 (void) dseg_adds4((maxmemuse + 1) * 8); /* IsSync */
492 (void) dseg_adds4(0); /* IsSync */
494 (void) dseg_adds4(isleafmethod); /* IsLeaf */
495 (void) dseg_adds4(savintregcnt - maxsavintreguse); /* IntSave */
496 (void) dseg_adds4(savfltregcnt - maxsavfltreguse); /* FltSave */
497 (void) dseg_adds4(exceptiontablelength); /* ExTableSize */
499 /* create exception table */
501 for (ex = extable; ex != NULL; ex = ex->down) {
504 if (ex->start != NULL)
505 printf("adding start - %d - ", ex->start->debug_nr);
507 printf("PANIC - start is NULL");
512 dseg_addtarget(ex->start);
516 printf("adding end - %d - ", ex->end->debug_nr);
518 printf("PANIC - end is NULL");
523 dseg_addtarget(ex->end);
526 if (ex->handler != NULL)
527 printf("adding handler - %d\n", ex->handler->debug_nr);
529 printf("PANIC - handler is NULL");
534 dseg_addtarget(ex->handler);
536 (void) dseg_addaddress(ex->catchtype);
539 /* initialize mcode variables */
541 mcodeptr = (s4*) mcodebase;
542 mcodeend = (s4*) (mcodebase + mcodesize);
543 MCODECHECK(128 + mparamcount);
545 /* create stack frame (if necessary) */
548 {M_LDA (REG_SP, REG_SP, -parentargs_base * 8);}
550 /* save return address and used callee saved registers */
554 {p--; M_LST (REG_RA, REG_SP, 8*p);}
555 for (r = savintregcnt - 1; r >= maxsavintreguse; r--)
556 {p--; M_LST (savintregs[r], REG_SP, 8 * p);}
557 for (r = savfltregcnt - 1; r >= maxsavfltreguse; r--)
558 {p--; M_DST (savfltregs[r], REG_SP, 8 * p);}
560 /* save monitorenter argument */
563 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
564 if (method->flags & ACC_STATIC) {
565 p = dseg_addaddress (class);
566 M_ALD(REG_ITMP1, REG_PV, p);
567 M_AST(REG_ITMP1, REG_SP, 8 * maxmemuse);
570 M_AST (argintregs[0], REG_SP, 8 * maxmemuse);
575 /* copy argument registers to stack and call trace function with pointer
576 to arguments on stack. ToDo: save floating point registers !!!!!!!!!
580 M_LDA (REG_SP, REG_SP, -(18*8));
582 M_LST(REG_RA, REG_SP, 1*8);
584 M_LST(argintregs[0], REG_SP, 2*8);
585 M_LST(argintregs[1], REG_SP, 3*8);
586 M_LST(argintregs[2], REG_SP, 4*8);
587 M_LST(argintregs[3], REG_SP, 5*8);
588 M_LST(argintregs[4], REG_SP, 6*8);
589 M_LST(argintregs[5], REG_SP, 7*8);
590 M_LST(argintregs[6], REG_SP, 8*8);
591 M_LST(argintregs[7], REG_SP, 9*8);
593 M_DST(argfltregs[0], REG_SP, 10*8);
594 M_DST(argfltregs[1], REG_SP, 11*8);
595 M_DST(argfltregs[2], REG_SP, 12*8);
596 M_DST(argfltregs[3], REG_SP, 13*8);
597 M_DST(argfltregs[4], REG_SP, 14*8);
598 M_DST(argfltregs[5], REG_SP, 15*8);
599 M_DST(argfltregs[6], REG_SP, 16*8);
600 M_DST(argfltregs[7], REG_SP, 17*8);
602 p = dseg_addaddress (method);
603 M_ALD(REG_ITMP1, REG_PV, p);
604 M_LST(REG_ITMP1, REG_SP, 0);
605 p = dseg_addaddress ((void*) (builtin_trace_args));
606 M_ALD(REG_ITMP3, REG_PV, p);
607 M_JSR(REG_RA, REG_ITMP3);
610 M_LLD(REG_RA, REG_SP, 1*8);
612 M_LLD(argintregs[0], REG_SP, 2*8);
613 M_LLD(argintregs[1], REG_SP, 3*8);
614 M_LLD(argintregs[2], REG_SP, 4*8);
615 M_LLD(argintregs[3], REG_SP, 5*8);
616 M_LLD(argintregs[4], REG_SP, 6*8);
617 M_LLD(argintregs[5], REG_SP, 7*8);
618 M_LLD(argintregs[6], REG_SP, 8*8);
619 M_LLD(argintregs[7], REG_SP, 9*8);
621 M_DLD(argfltregs[0], REG_SP, 10*8);
622 M_DLD(argfltregs[1], REG_SP, 11*8);
623 M_DLD(argfltregs[2], REG_SP, 12*8);
624 M_DLD(argfltregs[3], REG_SP, 13*8);
625 M_DLD(argfltregs[4], REG_SP, 14*8);
626 M_DLD(argfltregs[5], REG_SP, 15*8);
627 M_DLD(argfltregs[6], REG_SP, 16*8);
628 M_DLD(argfltregs[7], REG_SP, 17*8);
630 M_LDA (REG_SP, REG_SP, 18*8);
633 /* take arguments out of register or stack frame */
635 for (p = 0, l = 0; p < mparamcount; p++) {
637 var = &(locals[l][t]);
639 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
644 if (IS_INT_LNG_TYPE(t)) { /* integer args */
645 if (p < INT_ARG_CNT) { /* register arguments */
646 if (!(var->flags & INMEMORY)) /* reg arg -> register */
647 {M_INTMOVE (argintregs[p], r);}
648 else /* reg arg -> spilled */
649 M_LST (argintregs[p], REG_SP, 8 * r);
651 else { /* stack arguments */
652 pa = p - INT_ARG_CNT;
653 if (!(var->flags & INMEMORY)) /* stack arg -> register */
654 M_LLD (r, REG_SP, 8 * (parentargs_base + pa));
655 else { /* stack arg -> spilled */
656 M_LLD (REG_ITMP1, REG_SP, 8 * (parentargs_base + pa));
657 M_LST (REG_ITMP1, REG_SP, 8 * r);
661 else { /* floating args */
662 if (p < FLT_ARG_CNT) { /* register arguments */
663 if (!(var->flags & INMEMORY)) /* reg arg -> register */
664 {M_TFLTMOVE (var->type, argfltregs[p], r);}
665 else /* reg arg -> spilled */
666 M_DST (argfltregs[p], REG_SP, 8 * r);
668 else { /* stack arguments */
669 pa = p - FLT_ARG_CNT;
670 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
671 M_DLD (r, REG_SP, 8 * (parentargs_base + pa) );
672 } else { /* stack-arg -> spilled */
673 M_DLD (REG_FTMP1, REG_SP, 8 * (parentargs_base + pa));
674 M_DST (REG_FTMP1, REG_SP, 8 * r);
680 /* call trace function */
683 if (runverbose && !isleafmethod) {
684 M_LDA (REG_SP, REG_SP, -8);
685 p = dseg_addaddress (method);
686 M_ALD(REG_ITMP1, REG_PV, p);
687 M_AST(REG_ITMP1, REG_SP, 0);
688 p = dseg_addaddress ((void*) (builtin_trace_args));
689 M_ALD(REG_ITMP3, REG_PV, p);
690 M_JSR(REG_RA, REG_ITMP3);
692 M_LDA(REG_SP, REG_SP, 8);
696 /* call monitorenter function */
699 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
701 p = dseg_addaddress ((void*) (builtin_monitorenter));
702 M_ALD(REG_ITMP3, REG_PV, p);
703 M_JSR(REG_RA, REG_ITMP3);
704 M_ALD(argintregs[0], REG_SP, 8 * maxmemuse);
705 disp = -(int)((u1*) mcodeptr - mcodebase);
706 M_LDA(REG_PV, REG_RA, disp);
711 /* end of header generation */
713 /* walk through all basic blocks */
714 for (bptr = block; bptr != NULL; bptr = bptr->next) {
716 bptr -> mpc = (int)((u1*) mcodeptr - mcodebase);
718 if (bptr->flags >= BBREACHED) {
720 /* branch resolving */
724 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
725 gen_resolvebranch((u1*) mcodebase + brefs->branchpos,
726 brefs->branchpos, bptr->mpc);
730 /* copy interface registers to their destination */
735 while (src != NULL) {
737 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
738 d = reg_of_var(src, REG_ITMP1);
739 M_INTMOVE(REG_ITMP1, d);
740 store_reg_to_var_int(src, d);
743 d = reg_of_var(src, REG_IFTMP);
744 if ((src->varkind != STACKVAR)) {
746 if (IS_FLT_DBL_TYPE(s2)) {
747 if (!(interfaces[len][s2].flags & INMEMORY)) {
748 s1 = interfaces[len][s2].regoff;
752 M_DLD(d, REG_SP, 8 * interfaces[len][s2].regoff);
754 store_reg_to_var_flt(src, d);
757 if (!(interfaces[len][s2].flags & INMEMORY)) {
758 s1 = interfaces[len][s2].regoff;
762 M_LLD(d, REG_SP, 8 * interfaces[len][s2].regoff);
764 store_reg_to_var_int(src, d);
771 /* walk through all instructions */
775 for (iptr = bptr->iinstr;
777 src = iptr->dst, len--, iptr++) {
779 MCODECHECK(64); /* an instruction usually needs < 64 words */
782 case ICMD_NOP: /* ... ==> ... */
785 case ICMD_NULLCHECKPOP: /* ..., objectref ==> ... */
787 var_to_reg_int(s1, src, REG_ITMP1);
789 codegen_addxnullrefs(mcodeptr);
793 /* constant operations ************************************************/
795 #define ICONST(r,c) if(((c)>=-32768)&&((c)<= 32767)){M_IADD_IMM(REG_ZERO,c,r);} \
796 else if(((c)>=0)&&((c)<=0xffff)){M_OR_IMM(REG_ZERO,c,r);} \
797 else{a=dseg_adds4(c);M_ILD(r,REG_PV,a);}
799 #define LCONST(r,c) if(((c)>=-32768)&&((c)<= 32767)){M_LADD_IMM(REG_ZERO,c,r);} \
800 else if(((c)>=0)&&((c)<=0xffff)){M_OR_IMM(REG_ZERO,c,r);} \
801 else{a=dseg_adds8(c);M_LLD(r,REG_PV,a);}
803 case ICMD_ICONST: /* ... ==> ..., constant */
804 /* op1 = 0, val.i = constant */
806 d = reg_of_var(iptr->dst, REG_ITMP1);
807 ICONST(d, iptr->val.i);
808 store_reg_to_var_int(iptr->dst, d);
811 case ICMD_LCONST: /* ... ==> ..., constant */
812 /* op1 = 0, val.l = constant */
814 d = reg_of_var(iptr->dst, REG_ITMP1);
815 LCONST(d, iptr->val.l);
816 store_reg_to_var_int(iptr->dst, d);
819 case ICMD_FCONST: /* ... ==> ..., constant */
820 /* op1 = 0, val.f = constant */
822 d = reg_of_var (iptr->dst, REG_FTMP1);
823 a = dseg_addfloat (iptr->val.f);
825 store_reg_to_var_flt (iptr->dst, d);
828 case ICMD_DCONST: /* ... ==> ..., constant */
829 /* op1 = 0, val.d = constant */
831 d = reg_of_var (iptr->dst, REG_FTMP1);
832 a = dseg_adddouble (iptr->val.d);
834 store_reg_to_var_flt (iptr->dst, d);
837 case ICMD_ACONST: /* ... ==> ..., constant */
838 /* op1 = 0, val.a = constant */
840 d = reg_of_var(iptr->dst, REG_ITMP1);
842 a = dseg_addaddress (iptr->val.a);
846 M_INTMOVE(REG_ZERO, d);
848 store_reg_to_var_int(iptr->dst, d);
852 /* load/store operations **********************************************/
854 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
855 case ICMD_LLOAD: /* op1 = local variable */
858 d = reg_of_var(iptr->dst, REG_ITMP1);
859 if ((iptr->dst->varkind == LOCALVAR) &&
860 (iptr->dst->varnum == iptr->op1))
862 var = &(locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
863 if (var->flags & INMEMORY)
864 M_LLD(d, REG_SP, 8 * var->regoff);
866 {M_INTMOVE(var->regoff,d);}
867 store_reg_to_var_int(iptr->dst, d);
870 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
871 case ICMD_DLOAD: /* op1 = local variable */
873 d = reg_of_var(iptr->dst, REG_FTMP1);
874 if ((iptr->dst->varkind == LOCALVAR) &&
875 (iptr->dst->varnum == iptr->op1))
877 var = &(locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
879 int t2 = ((iptr->opc == ICMD_FLOAD) ? TYPE_FLT : TYPE_DBL);
880 if (var->flags & INMEMORY)
881 {M_CCFLD(var->type,t2,d, REG_SP, 8 * var->regoff);}
883 {M_CCFLTMOVE(var->type,t2,var->regoff,d);}
885 store_reg_to_var_flt(iptr->dst, d);
889 case ICMD_ISTORE: /* ..., value ==> ... */
890 case ICMD_LSTORE: /* op1 = local variable */
893 if ((src->varkind == LOCALVAR) &&
894 (src->varnum == iptr->op1))
896 var = &(locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
897 if (var->flags & INMEMORY) {
898 var_to_reg_int(s1, src, REG_ITMP1);
899 M_LST(s1, REG_SP, 8 * var->regoff);
902 var_to_reg_int(s1, src, var->regoff);
903 M_INTMOVE(s1, var->regoff);
907 case ICMD_FSTORE: /* ..., value ==> ... */
908 case ICMD_DSTORE: /* op1 = local variable */
910 if ((src->varkind == LOCALVAR) &&
911 (src->varnum == iptr->op1))
913 var = &(locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
915 int t1 = ((iptr->opc == ICMD_FSTORE) ? TYPE_FLT : TYPE_DBL);
916 if (var->flags & INMEMORY) {
917 var_to_reg_flt(s1, src, REG_FTMP1);
918 M_CCFST(t1,var->type,s1, REG_SP, 8 * var->regoff);
921 var_to_reg_flt(s1, src, var->regoff);
922 M_CCFLTMOVE(t1,var->type,s1, var->regoff);
928 /* pop/dup/swap operations ********************************************/
930 /* attention: double and longs are only one entry in CACAO ICMDs */
932 case ICMD_POP: /* ..., value ==> ... */
933 case ICMD_POP2: /* ..., value, value ==> ... */
936 #define M_COPY(from,to) \
937 d = reg_of_var(to, REG_IFTMP); \
938 if ((from->regoff != to->regoff) || \
939 ((from->flags ^ to->flags) & INMEMORY)) { \
940 if (IS_FLT_DBL_TYPE(from->type)) { \
941 var_to_reg_flt(s1, from, d); \
942 M_TFLTMOVE(from->type,s1,d); \
943 store_reg_to_var_flt(to, d); \
946 var_to_reg_int(s1, from, d); \
948 store_reg_to_var_int(to, d); \
952 case ICMD_DUP: /* ..., a ==> ..., a, a */
953 M_COPY(src, iptr->dst);
956 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
958 M_COPY(src, iptr->dst->prev->prev);
960 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
962 M_COPY(src, iptr->dst);
963 M_COPY(src->prev, iptr->dst->prev);
966 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
968 M_COPY(src->prev, iptr->dst->prev->prev->prev);
970 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
972 M_COPY(src, iptr->dst);
973 M_COPY(src->prev, iptr->dst->prev);
974 M_COPY(src->prev->prev, iptr->dst->prev->prev);
975 M_COPY(src, iptr->dst->prev->prev->prev);
978 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
980 M_COPY(src, iptr->dst);
981 M_COPY(src->prev, iptr->dst->prev);
982 M_COPY(src->prev->prev, iptr->dst->prev->prev);
983 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
984 M_COPY(src, iptr->dst->prev->prev->prev->prev);
985 M_COPY(src->prev, iptr->dst->prev->prev->prev->prev->prev);
988 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
990 M_COPY(src, iptr->dst->prev);
991 M_COPY(src->prev, iptr->dst);
995 /* integer operations *************************************************/
997 case ICMD_INEG: /* ..., value ==> ..., - value */
999 var_to_reg_int(s1, src, REG_ITMP1);
1000 d = reg_of_var(iptr->dst, REG_ITMP3);
1001 M_ISUB(REG_ZERO, s1, d);
1002 store_reg_to_var_int(iptr->dst, d);
1005 case ICMD_LNEG: /* ..., value ==> ..., - value */
1007 var_to_reg_int(s1, src, REG_ITMP1);
1008 d = reg_of_var(iptr->dst, REG_ITMP3);
1009 M_LSUB(REG_ZERO, s1, d);
1010 store_reg_to_var_int(iptr->dst, d);
1013 case ICMD_I2L: /* ..., value ==> ..., value */
1015 var_to_reg_int(s1, src, REG_ITMP1);
1016 d = reg_of_var(iptr->dst, REG_ITMP3);
1018 store_reg_to_var_int(iptr->dst, d);
1021 case ICMD_L2I: /* ..., value ==> ..., value */
1023 var_to_reg_int(s1, src, REG_ITMP1);
1024 d = reg_of_var(iptr->dst, REG_ITMP3);
1025 M_ISLL_IMM(s1, 0, d );
1026 store_reg_to_var_int(iptr->dst, d);
1029 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
1031 var_to_reg_int(s1, src, REG_ITMP1);
1032 d = reg_of_var(iptr->dst, REG_ITMP3);
1033 M_LSLL_IMM(s1, 56, d);
1034 M_LSRA_IMM( d, 56, d);
1035 store_reg_to_var_int(iptr->dst, d);
1038 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
1040 var_to_reg_int(s1, src, REG_ITMP1);
1041 d = reg_of_var(iptr->dst, REG_ITMP3);
1043 store_reg_to_var_int(iptr->dst, d);
1046 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
1048 var_to_reg_int(s1, src, REG_ITMP1);
1049 d = reg_of_var(iptr->dst, REG_ITMP3);
1050 M_LSLL_IMM(s1, 48, d);
1051 M_LSRA_IMM( d, 48, d);
1052 store_reg_to_var_int(iptr->dst, d);
1056 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1058 var_to_reg_int(s1, src->prev, REG_ITMP1);
1059 var_to_reg_int(s2, src, REG_ITMP2);
1060 d = reg_of_var(iptr->dst, REG_ITMP3);
1062 store_reg_to_var_int(iptr->dst, d);
1065 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
1066 /* val.i = constant */
1068 var_to_reg_int(s1, src, REG_ITMP1);
1069 d = reg_of_var(iptr->dst, REG_ITMP3);
1070 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
1071 M_IADD_IMM(s1, iptr->val.i, d);
1074 ICONST(REG_ITMP2, iptr->val.i);
1075 M_IADD(s1, REG_ITMP2, d);
1077 store_reg_to_var_int(iptr->dst, d);
1080 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1082 var_to_reg_int(s1, src->prev, REG_ITMP1);
1083 var_to_reg_int(s2, src, REG_ITMP2);
1084 d = reg_of_var(iptr->dst, REG_ITMP3);
1086 store_reg_to_var_int(iptr->dst, d);
1089 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
1090 /* val.l = constant */
1092 var_to_reg_int(s1, src, REG_ITMP1);
1093 d = reg_of_var(iptr->dst, REG_ITMP3);
1094 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
1095 M_LADD_IMM(s1, iptr->val.l, d);
1098 LCONST(REG_ITMP2, iptr->val.l);
1099 M_LADD(s1, REG_ITMP2, d);
1101 store_reg_to_var_int(iptr->dst, d);
1104 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1106 var_to_reg_int(s1, src->prev, REG_ITMP1);
1107 var_to_reg_int(s2, src, REG_ITMP2);
1108 d = reg_of_var(iptr->dst, REG_ITMP3);
1110 store_reg_to_var_int(iptr->dst, d);
1113 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
1114 /* val.i = constant */
1116 var_to_reg_int(s1, src, REG_ITMP1);
1117 d = reg_of_var(iptr->dst, REG_ITMP3);
1118 if ((iptr->val.i >= -32767) && (iptr->val.i <= 32768)) {
1119 M_IADD_IMM(s1, -iptr->val.i, d);
1122 ICONST(REG_ITMP2, iptr->val.i);
1123 M_ISUB(s1, REG_ITMP2, d);
1125 store_reg_to_var_int(iptr->dst, d);
1128 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1130 var_to_reg_int(s1, src->prev, REG_ITMP1);
1131 var_to_reg_int(s2, src, REG_ITMP2);
1132 d = reg_of_var(iptr->dst, REG_ITMP3);
1134 store_reg_to_var_int(iptr->dst, d);
1137 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
1138 /* val.l = constant */
1140 var_to_reg_int(s1, src, REG_ITMP1);
1141 d = reg_of_var(iptr->dst, REG_ITMP3);
1142 if ((iptr->val.l >= -32767) && (iptr->val.l <= 32768)) {
1143 M_LADD_IMM(s1, -iptr->val.l, d);
1146 LCONST(REG_ITMP2, iptr->val.l);
1147 M_LSUB(s1, REG_ITMP2, d);
1149 store_reg_to_var_int(iptr->dst, d);
1152 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1154 var_to_reg_int(s1, src->prev, REG_ITMP1);
1155 var_to_reg_int(s2, src, REG_ITMP2);
1156 d = reg_of_var(iptr->dst, REG_ITMP3);
1161 store_reg_to_var_int(iptr->dst, d);
1164 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
1165 /* val.i = constant */
1167 var_to_reg_int(s1, src, REG_ITMP1);
1168 d = reg_of_var(iptr->dst, REG_ITMP3);
1169 ICONST(REG_ITMP2, iptr->val.i);
1170 M_IMUL(s1, REG_ITMP2);
1174 store_reg_to_var_int(iptr->dst, d);
1177 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1179 var_to_reg_int(s1, src->prev, REG_ITMP1);
1180 var_to_reg_int(s2, src, REG_ITMP2);
1181 d = reg_of_var(iptr->dst, REG_ITMP3);
1186 store_reg_to_var_int(iptr->dst, d);
1189 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
1190 /* val.l = constant */
1192 var_to_reg_int(s1, src, REG_ITMP1);
1193 d = reg_of_var(iptr->dst, REG_ITMP3);
1194 LCONST(REG_ITMP2, iptr->val.l);
1195 M_LMUL(s1, REG_ITMP2);
1199 store_reg_to_var_int(iptr->dst, d);
1202 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1204 var_to_reg_int(s1, src->prev, REG_ITMP1);
1205 var_to_reg_int(s2, src, REG_ITMP2);
1206 d = reg_of_var(iptr->dst, REG_ITMP3);
1211 store_reg_to_var_int(iptr->dst, d);
1214 case ICMD_IDIVCONST: /* ..., value ==> ..., value / constant */
1215 /* val.i = constant */
1217 var_to_reg_int(s1, src, REG_ITMP1);
1218 d = reg_of_var(iptr->dst, REG_ITMP3);
1219 ICONST(REG_ITMP2, iptr->val.i);
1220 M_IDIV(s1, REG_ITMP2);
1224 store_reg_to_var_int(iptr->dst, d);
1227 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1229 var_to_reg_int(s1, src->prev, REG_ITMP1);
1230 var_to_reg_int(s2, src, REG_ITMP2);
1231 d = reg_of_var(iptr->dst, REG_ITMP3);
1236 store_reg_to_var_int(iptr->dst, d);
1239 case ICMD_LDIVCONST: /* ..., value ==> ..., value / constant */
1240 /* val.l = constant */
1242 var_to_reg_int(s1, src, REG_ITMP1);
1243 d = reg_of_var(iptr->dst, REG_ITMP3);
1244 LCONST(REG_ITMP2, iptr->val.l);
1245 M_LDIV(s1, REG_ITMP2);
1249 store_reg_to_var_int(iptr->dst, d);
1252 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1254 var_to_reg_int(s1, src->prev, REG_ITMP1);
1255 var_to_reg_int(s2, src, REG_ITMP2);
1256 d = reg_of_var(iptr->dst, REG_ITMP3);
1261 store_reg_to_var_int(iptr->dst, d);
1264 case ICMD_IREMCONST: /* ..., value ==> ..., value % constant */
1265 /* val.i = constant */
1267 var_to_reg_int(s1, src, REG_ITMP1);
1268 d = reg_of_var(iptr->dst, REG_ITMP3);
1269 ICONST(REG_ITMP2, iptr->val.i);
1270 M_IDIV(s1, REG_ITMP2);
1274 store_reg_to_var_int(iptr->dst, d);
1277 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1279 var_to_reg_int(s1, src->prev, REG_ITMP1);
1280 var_to_reg_int(s2, src, REG_ITMP2);
1281 d = reg_of_var(iptr->dst, REG_ITMP3);
1286 store_reg_to_var_int(iptr->dst, d);
1289 case ICMD_LREMCONST: /* ..., value ==> ..., value % constant */
1290 /* val.l = constant */
1292 var_to_reg_int(s1, src, REG_ITMP1);
1293 d = reg_of_var(iptr->dst, REG_ITMP3);
1294 LCONST(REG_ITMP2, iptr->val.l);
1295 M_LDIV(s1, REG_ITMP2);
1299 store_reg_to_var_int(iptr->dst, d);
1302 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
1303 case ICMD_LDIVPOW2: /* val.i = constant */
1305 var_to_reg_int(s1, src, REG_ITMP1);
1306 d = reg_of_var(iptr->dst, REG_ITMP3);
1307 M_LSRA_IMM(s1, 63, REG_ITMP2);
1308 M_LSRL_IMM(REG_ITMP2, 64 - iptr->val.i, REG_ITMP2);
1309 M_LADD(s1, REG_ITMP2, REG_ITMP2);
1310 M_LSRA_IMM(REG_ITMP2, iptr->val.i, d);
1311 store_reg_to_var_int(iptr->dst, d);
1314 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1316 var_to_reg_int(s1, src->prev, REG_ITMP1);
1317 var_to_reg_int(s2, src, REG_ITMP2);
1318 d = reg_of_var(iptr->dst, REG_ITMP3);
1320 store_reg_to_var_int(iptr->dst, d);
1323 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1324 /* val.i = constant */
1326 var_to_reg_int(s1, src, REG_ITMP1);
1327 d = reg_of_var(iptr->dst, REG_ITMP3);
1328 M_ISLL_IMM(s1, iptr->val.i, d);
1329 store_reg_to_var_int(iptr->dst, d);
1332 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1334 var_to_reg_int(s1, src->prev, REG_ITMP1);
1335 var_to_reg_int(s2, src, REG_ITMP2);
1336 d = reg_of_var(iptr->dst, REG_ITMP3);
1338 store_reg_to_var_int(iptr->dst, d);
1341 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1342 /* val.i = constant */
1344 var_to_reg_int(s1, src, REG_ITMP1);
1345 d = reg_of_var(iptr->dst, REG_ITMP3);
1346 M_ISRA_IMM(s1, iptr->val.i, d);
1347 store_reg_to_var_int(iptr->dst, d);
1350 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1352 var_to_reg_int(s1, src->prev, REG_ITMP1);
1353 var_to_reg_int(s2, src, REG_ITMP2);
1354 d = reg_of_var(iptr->dst, REG_ITMP3);
1356 store_reg_to_var_int(iptr->dst, d);
1359 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1360 /* val.i = constant */
1362 var_to_reg_int(s1, src, REG_ITMP1);
1363 d = reg_of_var(iptr->dst, REG_ITMP3);
1364 M_ISRL_IMM(s1, iptr->val.i, d);
1365 store_reg_to_var_int(iptr->dst, d);
1368 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1370 var_to_reg_int(s1, src->prev, REG_ITMP1);
1371 var_to_reg_int(s2, src, REG_ITMP2);
1372 d = reg_of_var(iptr->dst, REG_ITMP3);
1374 store_reg_to_var_int(iptr->dst, d);
1377 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1378 /* val.i = constant */
1380 var_to_reg_int(s1, src, REG_ITMP1);
1381 d = reg_of_var(iptr->dst, REG_ITMP3);
1382 M_LSLL_IMM(s1, iptr->val.i, d);
1383 store_reg_to_var_int(iptr->dst, d);
1386 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1388 var_to_reg_int(s1, src->prev, REG_ITMP1);
1389 var_to_reg_int(s2, src, REG_ITMP2);
1390 d = reg_of_var(iptr->dst, REG_ITMP3);
1392 store_reg_to_var_int(iptr->dst, d);
1395 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1396 /* val.i = constant */
1398 var_to_reg_int(s1, src, REG_ITMP1);
1399 d = reg_of_var(iptr->dst, REG_ITMP3);
1400 M_LSRA_IMM(s1, iptr->val.i, d);
1401 store_reg_to_var_int(iptr->dst, d);
1404 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1406 var_to_reg_int(s1, src->prev, REG_ITMP1);
1407 var_to_reg_int(s2, src, REG_ITMP2);
1408 d = reg_of_var(iptr->dst, REG_ITMP3);
1410 store_reg_to_var_int(iptr->dst, d);
1413 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1414 /* val.i = constant */
1416 var_to_reg_int(s1, src, REG_ITMP1);
1417 d = reg_of_var(iptr->dst, REG_ITMP3);
1418 M_LSRL_IMM(s1, iptr->val.i, d);
1419 store_reg_to_var_int(iptr->dst, d);
1422 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1425 var_to_reg_int(s1, src->prev, REG_ITMP1);
1426 var_to_reg_int(s2, src, REG_ITMP2);
1427 d = reg_of_var(iptr->dst, REG_ITMP3);
1429 store_reg_to_var_int(iptr->dst, d);
1432 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1433 /* val.i = constant */
1435 var_to_reg_int(s1, src, REG_ITMP1);
1436 d = reg_of_var(iptr->dst, REG_ITMP3);
1437 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1438 M_AND_IMM(s1, iptr->val.i, d);
1441 ICONST(REG_ITMP2, iptr->val.i);
1442 M_AND(s1, REG_ITMP2, d);
1444 store_reg_to_var_int(iptr->dst, d);
1447 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1448 /* val.i = constant */
1450 var_to_reg_int(s1, src, REG_ITMP1);
1451 d = reg_of_var(iptr->dst, REG_ITMP3);
1453 M_MOV(s1, REG_ITMP1);
1456 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1457 M_AND_IMM(s1, iptr->val.i, d);
1460 M_ISUB(REG_ZERO, s1, d);
1461 M_AND_IMM(d, iptr->val.i, d);
1464 ICONST(REG_ITMP2, iptr->val.i);
1465 M_AND(s1, REG_ITMP2, d);
1468 M_ISUB(REG_ZERO, s1, d);
1469 M_AND(d, REG_ITMP2, d);
1471 M_ISUB(REG_ZERO, d, d);
1472 store_reg_to_var_int(iptr->dst, d);
1475 case ICMD_IREM0X10001: /* ..., value ==> ..., value % 0x100001 */
1477 /* b = value & 0xffff;
1479 a = ((b - a) & 0xffff) + (b < a);
1481 var_to_reg_int(s1, src, REG_ITMP1);
1482 d = reg_of_var(iptr->dst, REG_ITMP3);
1484 M_MOV(s1, REG_ITMP3);
1488 M_CZEXT(s1, REG_ITMP2); /* delay slot */
1489 M_ISRA_IMM(s1, 16, d);
1490 M_CMPLT(REG_ITMP2, d, REG_ITMP1);
1491 M_ISUB(REG_ITMP2, d, d);
1494 M_IADD(d, REG_ITMP1, d); /* delay slot */
1496 M_LUI(REG_ITMP2, 1);
1497 M_IADD_IMM(REG_ITMP2, 1, REG_ITMP2);
1498 M_IDIV(s1, REG_ITMP2);
1502 store_reg_to_var_int(iptr->dst, d);
1505 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1506 /* val.l = constant */
1508 var_to_reg_int(s1, src, REG_ITMP1);
1509 d = reg_of_var(iptr->dst, REG_ITMP3);
1510 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1511 M_AND_IMM(s1, iptr->val.l, d);
1514 LCONST(REG_ITMP2, iptr->val.l);
1515 M_AND(s1, REG_ITMP2, d);
1517 store_reg_to_var_int(iptr->dst, d);
1520 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1521 /* val.l = constant */
1523 var_to_reg_int(s1, src, REG_ITMP1);
1524 d = reg_of_var(iptr->dst, REG_ITMP3);
1526 M_MOV(s1, REG_ITMP1);
1529 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1530 M_AND_IMM(s1, iptr->val.l, d);
1533 M_LSUB(REG_ZERO, s1, d);
1534 M_AND_IMM(d, iptr->val.l, d);
1537 LCONST(REG_ITMP2, iptr->val.l);
1538 M_AND(s1, REG_ITMP2, d);
1541 M_LSUB(REG_ZERO, s1, d);
1542 M_AND(d, REG_ITMP2, d);
1544 M_LSUB(REG_ZERO, d, d);
1545 store_reg_to_var_int(iptr->dst, d);
1548 case ICMD_LREM0X10001:/* ..., value ==> ..., value % 0x10001 */
1550 var_to_reg_int(s1, src, REG_ITMP1);
1551 d = reg_of_var(iptr->dst, REG_ITMP3);
1552 M_LUI(REG_ITMP2, 1);
1553 M_LADD_IMM(REG_ITMP2, 1, REG_ITMP2);
1554 M_LDIV(s1, REG_ITMP2);
1558 store_reg_to_var_int(iptr->dst, d);
1561 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1564 var_to_reg_int(s1, src->prev, REG_ITMP1);
1565 var_to_reg_int(s2, src, REG_ITMP2);
1566 d = reg_of_var(iptr->dst, REG_ITMP3);
1568 store_reg_to_var_int(iptr->dst, d);
1571 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1572 /* val.i = constant */
1574 var_to_reg_int(s1, src, REG_ITMP1);
1575 d = reg_of_var(iptr->dst, REG_ITMP3);
1576 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1577 M_OR_IMM(s1, iptr->val.i, d);
1580 ICONST(REG_ITMP2, iptr->val.i);
1581 M_OR(s1, REG_ITMP2, d);
1583 store_reg_to_var_int(iptr->dst, d);
1586 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1587 /* val.l = constant */
1589 var_to_reg_int(s1, src, REG_ITMP1);
1590 d = reg_of_var(iptr->dst, REG_ITMP3);
1591 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1592 M_OR_IMM(s1, iptr->val.l, d);
1595 LCONST(REG_ITMP2, iptr->val.l);
1596 M_OR(s1, REG_ITMP2, d);
1598 store_reg_to_var_int(iptr->dst, d);
1601 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1604 var_to_reg_int(s1, src->prev, REG_ITMP1);
1605 var_to_reg_int(s2, src, REG_ITMP2);
1606 d = reg_of_var(iptr->dst, REG_ITMP3);
1608 store_reg_to_var_int(iptr->dst, d);
1611 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1612 /* val.i = constant */
1614 var_to_reg_int(s1, src, REG_ITMP1);
1615 d = reg_of_var(iptr->dst, REG_ITMP3);
1616 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1617 M_XOR_IMM(s1, iptr->val.i, d);
1620 ICONST(REG_ITMP2, iptr->val.i);
1621 M_XOR(s1, REG_ITMP2, d);
1623 store_reg_to_var_int(iptr->dst, d);
1626 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1627 /* val.l = constant */
1629 var_to_reg_int(s1, src, REG_ITMP1);
1630 d = reg_of_var(iptr->dst, REG_ITMP3);
1631 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1632 M_XOR_IMM(s1, iptr->val.l, d);
1635 LCONST(REG_ITMP2, iptr->val.l);
1636 M_XOR(s1, REG_ITMP2, d);
1638 store_reg_to_var_int(iptr->dst, d);
1642 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
1644 var_to_reg_int(s1, src->prev, REG_ITMP1);
1645 var_to_reg_int(s2, src, REG_ITMP2);
1646 d = reg_of_var(iptr->dst, REG_ITMP3);
1647 M_CMPLT(s1, s2, REG_ITMP3);
1648 M_CMPLT(s2, s1, REG_ITMP1);
1649 M_LSUB (REG_ITMP1, REG_ITMP3, d);
1650 store_reg_to_var_int(iptr->dst, d);
1654 case ICMD_IINC: /* ..., value ==> ..., value + constant */
1655 /* op1 = variable, val.i = constant */
1657 var = &(locals[iptr->op1][TYPE_INT]);
1658 if (var->flags & INMEMORY) {
1660 M_LLD(s1, REG_SP, 8 * var->regoff);
1664 M_IADD_IMM(s1, iptr->val.i, s1);
1665 if (var->flags & INMEMORY)
1666 M_LST(s1, REG_SP, 8 * var->regoff);
1670 /* floating operations ************************************************/
1672 case ICMD_FNEG: /* ..., value ==> ..., - value */
1674 var_to_reg_flt(s1, src, REG_FTMP1);
1675 d = reg_of_var(iptr->dst, REG_FTMP3);
1677 store_reg_to_var_flt(iptr->dst, d);
1680 case ICMD_DNEG: /* ..., value ==> ..., - value */
1682 var_to_reg_flt(s1, src, REG_FTMP1);
1683 d = reg_of_var(iptr->dst, REG_FTMP3);
1685 store_reg_to_var_flt(iptr->dst, d);
1688 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1690 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1691 var_to_reg_flt(s2, src, REG_FTMP2);
1692 d = reg_of_var(iptr->dst, REG_FTMP3);
1694 store_reg_to_var_flt(iptr->dst, d);
1697 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1699 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1700 var_to_reg_flt(s2, src, REG_FTMP2);
1701 d = reg_of_var(iptr->dst, REG_FTMP3);
1703 store_reg_to_var_flt(iptr->dst, d);
1706 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1708 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1709 var_to_reg_flt(s2, src, REG_FTMP2);
1710 d = reg_of_var(iptr->dst, REG_FTMP3);
1712 store_reg_to_var_flt(iptr->dst, d);
1715 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1717 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1718 var_to_reg_flt(s2, src, REG_FTMP2);
1719 d = reg_of_var(iptr->dst, REG_FTMP3);
1721 store_reg_to_var_flt(iptr->dst, d);
1724 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1726 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1727 var_to_reg_flt(s2, src, REG_FTMP2);
1728 d = reg_of_var(iptr->dst, REG_FTMP3);
1730 store_reg_to_var_flt(iptr->dst, d);
1733 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 *** val2 */
1735 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1736 var_to_reg_flt(s2, src, REG_FTMP2);
1737 d = reg_of_var(iptr->dst, REG_FTMP3);
1739 store_reg_to_var_flt(iptr->dst, d);
1742 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1744 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1745 var_to_reg_flt(s2, src, REG_FTMP2);
1746 d = reg_of_var(iptr->dst, REG_FTMP3);
1748 store_reg_to_var_flt(iptr->dst, d);
1751 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1753 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1754 var_to_reg_flt(s2, src, REG_FTMP2);
1755 d = reg_of_var(iptr->dst, REG_FTMP3);
1757 store_reg_to_var_flt(iptr->dst, d);
1760 case ICMD_FREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1763 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1764 var_to_reg_flt(s2, src, REG_FTMP2);
1765 d = reg_of_var(iptr->dst, REG_FTMP3);
1766 M_FDIV(s1,s2, REG_FTMP3);
1767 M_FLOORFL(REG_FTMP3, REG_FTMP3);
1768 M_CVTLF(REG_FTMP3, REG_FTMP3);
1769 M_FMUL(REG_FTMP3, s2, REG_FTMP3);
1770 M_FSUB(s1, REG_FTMP3, d);
1771 store_reg_to_var_flt(iptr->dst, d);
1774 case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1776 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1777 var_to_reg_flt(s2, src, REG_FTMP2);
1778 d = reg_of_var(iptr->dst, REG_FTMP3);
1779 M_DDIV(s1,s2, REG_FTMP3);
1780 M_FLOORDL(REG_FTMP3, REG_FTMP3);
1781 M_CVTLD(REG_FTMP3, REG_FTMP3);
1782 M_DMUL(REG_FTMP3, s2, REG_FTMP3);
1783 M_DSUB(s1, REG_FTMP3, d);
1784 store_reg_to_var_flt(iptr->dst, d);
1787 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1789 var_to_reg_int(s1, src, REG_ITMP1);
1790 d = reg_of_var(iptr->dst, REG_FTMP3);
1793 store_reg_to_var_flt(iptr->dst, d);
1796 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1798 var_to_reg_int(s1, src, REG_ITMP1);
1799 d = reg_of_var(iptr->dst, REG_FTMP3);
1802 store_reg_to_var_flt(iptr->dst, d);
1805 case ICMD_F2I: /* ..., (float) value ==> ..., (int) value */
1807 var_to_reg_flt(s1, src, REG_FTMP1);
1808 d = reg_of_var(iptr->dst, REG_ITMP3);
1809 M_TRUNCFI(s1, REG_FTMP1);
1810 M_MOVDI(REG_FTMP1, d);
1812 store_reg_to_var_int(iptr->dst, d);
1815 case ICMD_D2I: /* ..., (double) value ==> ..., (int) value */
1817 var_to_reg_flt(s1, src, REG_FTMP1);
1818 d = reg_of_var(iptr->dst, REG_ITMP3);
1819 M_TRUNCDI(s1, REG_FTMP1);
1820 M_MOVDI(REG_FTMP1, d);
1822 store_reg_to_var_int(iptr->dst, d);
1825 case ICMD_F2L: /* ..., (float) value ==> ..., (long) value */
1827 var_to_reg_flt(s1, src, REG_FTMP1);
1828 d = reg_of_var(iptr->dst, REG_ITMP3);
1829 M_TRUNCFL(s1, REG_FTMP1);
1830 M_MOVDL(REG_FTMP1, d);
1832 store_reg_to_var_int(iptr->dst, d);
1835 case ICMD_D2L: /* ..., (double) value ==> ..., (long) value */
1837 var_to_reg_flt(s1, src, REG_FTMP1);
1838 d = reg_of_var(iptr->dst, REG_ITMP3);
1839 M_TRUNCDL(s1, REG_FTMP1);
1840 M_MOVDL(REG_FTMP1, d);
1842 store_reg_to_var_int(iptr->dst, d);
1845 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1847 var_to_reg_flt(s1, src, REG_FTMP1);
1848 d = reg_of_var(iptr->dst, REG_FTMP3);
1850 store_reg_to_var_flt(iptr->dst, d);
1853 case ICMD_D2F: /* ..., value ==> ..., (double) value */
1855 var_to_reg_flt(s1, src, REG_FTMP1);
1856 d = reg_of_var(iptr->dst, REG_FTMP3);
1858 store_reg_to_var_flt(iptr->dst, d);
1861 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1863 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1864 var_to_reg_flt(s2, src, REG_FTMP2);
1865 d = reg_of_var(iptr->dst, REG_ITMP3);
1867 M_NOP; /* compare delay */
1868 M_FBF(2); /* jump over next instructions */
1869 M_LSUB_IMM(REG_ZERO, 1, d); /* delay slot */
1872 M_NOP; /* compare delay */
1873 M_FBF(2); /* jump over next instruction */
1875 M_LADD_IMM(REG_ZERO, 1, d);
1876 store_reg_to_var_int(iptr->dst, d);
1879 case ICMD_DCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1881 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1882 var_to_reg_flt(s2, src, REG_FTMP2);
1883 d = reg_of_var(iptr->dst, REG_ITMP3);
1885 M_NOP; /* compare delay */
1886 M_FBF(2); /* jump over next instructions */
1887 M_LSUB_IMM(REG_ZERO, 1, d); /* delay slot */
1890 M_NOP; /* compare delay */
1891 M_FBF(2); /* jump over next instruction */
1893 M_LADD_IMM(REG_ZERO, 1, d);
1894 store_reg_to_var_int(iptr->dst, d);
1897 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1899 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1900 var_to_reg_flt(s2, src, REG_FTMP2);
1901 d = reg_of_var(iptr->dst, REG_ITMP3);
1903 M_NOP; /* compare delay */
1904 M_FBF(2); /* jump over next instruction */
1905 M_LADD_IMM(REG_ZERO, 1, d); /* delay slot */
1908 M_NOP; /* compare delay */
1909 M_FBF(2); /* jump over next instruction */
1911 M_LSUB_IMM(REG_ZERO, 1, d);
1912 store_reg_to_var_int(iptr->dst, d);
1915 case ICMD_DCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1917 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1918 var_to_reg_flt(s2, src, REG_FTMP2);
1919 d = reg_of_var(iptr->dst, REG_ITMP3);
1921 M_NOP; /* compare delay */
1922 M_FBF(2); /* jump over next instruction */
1923 M_LADD_IMM(REG_ZERO, 1, d); /* delay slot */
1926 M_NOP; /* compare delay */
1927 M_FBF(2); /* jump over next instruction */
1929 M_LSUB_IMM(REG_ZERO, 1, d);
1930 store_reg_to_var_int(iptr->dst, d);
1934 /* memory operations **************************************************/
1936 #define gen_bound_check \
1938 M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size));\
1939 M_CMPULT(s2, REG_ITMP3, REG_ITMP3);\
1940 M_BEQZ(REG_ITMP3, 0);\
1941 codegen_addxboundrefs(mcodeptr);\
1945 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1947 var_to_reg_int(s1, src, REG_ITMP1);
1948 d = reg_of_var(iptr->dst, REG_ITMP3);
1949 gen_nullptr_check(s1);
1950 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1951 store_reg_to_var_int(iptr->dst, d);
1954 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1956 var_to_reg_int(s1, src->prev, REG_ITMP1);
1957 var_to_reg_int(s2, src, REG_ITMP2);
1958 d = reg_of_var(iptr->dst, REG_ITMP3);
1959 if (iptr->op1 == 0) {
1960 gen_nullptr_check(s1);
1963 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
1964 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1965 M_ALD(d, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1966 store_reg_to_var_int(iptr->dst, d);
1969 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1971 var_to_reg_int(s1, src->prev, REG_ITMP1);
1972 var_to_reg_int(s2, src, REG_ITMP2);
1973 d = reg_of_var(iptr->dst, REG_ITMP3);
1974 if (iptr->op1 == 0) {
1975 gen_nullptr_check(s1);
1978 M_ASLL_IMM(s2, 2, REG_ITMP2);
1979 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1980 M_ILD(d, REG_ITMP1, OFFSET(java_intarray, data[0]));
1981 store_reg_to_var_int(iptr->dst, d);
1984 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1986 var_to_reg_int(s1, src->prev, REG_ITMP1);
1987 var_to_reg_int(s2, src, REG_ITMP2);
1988 d = reg_of_var(iptr->dst, REG_ITMP3);
1989 if (iptr->op1 == 0) {
1990 gen_nullptr_check(s1);
1993 M_ASLL_IMM(s2, 3, REG_ITMP2);
1994 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1995 M_LLD(d, REG_ITMP1, OFFSET(java_longarray, data[0]));
1996 store_reg_to_var_int(iptr->dst, d);
1999 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
2001 var_to_reg_int(s1, src->prev, REG_ITMP1);
2002 var_to_reg_int(s2, src, REG_ITMP2);
2003 d = reg_of_var(iptr->dst, REG_FTMP3);
2004 if (iptr->op1 == 0) {
2005 gen_nullptr_check(s1);
2008 M_ASLL_IMM(s2, 2, REG_ITMP2);
2009 M_AADD(REG_ITMP2, s1, REG_ITMP1);
2010 M_FLD(d, REG_ITMP1, OFFSET(java_floatarray, data[0]));
2011 store_reg_to_var_flt(iptr->dst, d);
2014 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
2016 var_to_reg_int(s1, src->prev, REG_ITMP1);
2017 var_to_reg_int(s2, src, REG_ITMP2);
2018 d = reg_of_var(iptr->dst, REG_FTMP3);
2019 if (iptr->op1 == 0) {
2020 gen_nullptr_check(s1);
2023 M_ASLL_IMM(s2, 3, REG_ITMP2);
2024 M_AADD(REG_ITMP2, s1, REG_ITMP1);
2025 M_DLD(d, REG_ITMP1, OFFSET(java_doublearray, data[0]));
2026 store_reg_to_var_flt(iptr->dst, d);
2029 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
2031 var_to_reg_int(s1, src->prev, REG_ITMP1);
2032 var_to_reg_int(s2, src, REG_ITMP2);
2033 d = reg_of_var(iptr->dst, REG_ITMP3);
2034 if (iptr->op1 == 0) {
2035 gen_nullptr_check(s1);
2038 M_AADD(s2, s1, REG_ITMP1);
2039 M_AADD(s2, REG_ITMP1, REG_ITMP1);
2040 M_SLDU(d, REG_ITMP1, OFFSET(java_chararray, data[0]));
2041 store_reg_to_var_int(iptr->dst, d);
2044 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
2046 var_to_reg_int(s1, src->prev, REG_ITMP1);
2047 var_to_reg_int(s2, src, REG_ITMP2);
2048 d = reg_of_var(iptr->dst, REG_ITMP3);
2049 if (iptr->op1 == 0) {
2050 gen_nullptr_check(s1);
2053 M_AADD(s2, s1, REG_ITMP1);
2054 M_AADD(s2, REG_ITMP1, REG_ITMP1);
2055 M_SLDS(d, REG_ITMP1, OFFSET(java_chararray, data[0]));
2056 store_reg_to_var_int(iptr->dst, d);
2059 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
2061 var_to_reg_int(s1, src->prev, REG_ITMP1);
2062 var_to_reg_int(s2, src, REG_ITMP2);
2063 d = reg_of_var(iptr->dst, REG_ITMP3);
2064 if (iptr->op1 == 0) {
2065 gen_nullptr_check(s1);
2068 M_AADD(s2, s1, REG_ITMP1);
2069 M_BLDS(d, REG_ITMP1, OFFSET(java_chararray, data[0]));
2070 store_reg_to_var_int(iptr->dst, d);
2074 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
2076 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2077 var_to_reg_int(s2, src->prev, REG_ITMP2);
2078 if (iptr->op1 == 0) {
2079 gen_nullptr_check(s1);
2082 var_to_reg_int(s3, src, REG_ITMP3);
2083 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
2084 M_AADD(REG_ITMP2, s1, REG_ITMP1);
2085 M_AST(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
2088 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
2090 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2091 var_to_reg_int(s2, src->prev, REG_ITMP2);
2092 if (iptr->op1 == 0) {
2093 gen_nullptr_check(s1);
2096 var_to_reg_int(s3, src, REG_ITMP3);
2097 M_ASLL_IMM(s2, 2, REG_ITMP2);
2098 M_AADD(REG_ITMP2, s1, REG_ITMP1);
2099 M_IST(s3, REG_ITMP1, OFFSET(java_intarray, data[0]));
2102 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
2104 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2105 var_to_reg_int(s2, src->prev, REG_ITMP2);
2106 if (iptr->op1 == 0) {
2107 gen_nullptr_check(s1);
2110 var_to_reg_int(s3, src, REG_ITMP3);
2111 M_ASLL_IMM(s2, 3, REG_ITMP2);
2112 M_AADD(REG_ITMP2, s1, REG_ITMP1);
2113 M_LST(s3, REG_ITMP1, OFFSET(java_longarray, data[0]));
2116 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
2118 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2119 var_to_reg_int(s2, src->prev, REG_ITMP2);
2120 if (iptr->op1 == 0) {
2121 gen_nullptr_check(s1);
2124 var_to_reg_flt(s3, src, REG_FTMP3);
2125 M_ASLL_IMM(s2, 2, REG_ITMP2);
2126 M_AADD(REG_ITMP2, s1, REG_ITMP1);
2127 M_FST(s3, REG_ITMP1, OFFSET(java_floatarray, data[0]));
2130 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
2132 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2133 var_to_reg_int(s2, src->prev, REG_ITMP2);
2134 if (iptr->op1 == 0) {
2135 gen_nullptr_check(s1);
2138 var_to_reg_flt(s3, src, REG_FTMP3);
2139 M_ASLL_IMM(s2, 3, REG_ITMP2);
2140 M_AADD(REG_ITMP2, s1, REG_ITMP1);
2141 M_DST(s3, REG_ITMP1, OFFSET(java_doublearray, data[0]));
2144 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
2145 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
2147 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2148 var_to_reg_int(s2, src->prev, REG_ITMP2);
2149 if (iptr->op1 == 0) {
2150 gen_nullptr_check(s1);
2153 var_to_reg_int(s3, src, REG_ITMP3);
2154 M_AADD(s2, s1, REG_ITMP1);
2155 M_AADD(s2, REG_ITMP1, REG_ITMP1);
2156 M_SST(s3, REG_ITMP1, OFFSET(java_chararray, data[0]));
2159 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
2161 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2162 var_to_reg_int(s2, src->prev, REG_ITMP2);
2163 if (iptr->op1 == 0) {
2164 gen_nullptr_check(s1);
2167 var_to_reg_int(s3, src, REG_ITMP3);
2168 M_AADD(s2, s1, REG_ITMP1);
2169 M_BST(s3, REG_ITMP1, OFFSET(java_bytearray, data[0]));
2173 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2174 /* op1 = type, val.a = field address */
2176 a = dseg_addaddress (&(((fieldinfo *)(iptr->val.a))->value));
2177 M_ALD(REG_ITMP1, REG_PV, a);
2178 switch (iptr->op1) {
2180 var_to_reg_int(s2, src, REG_ITMP2);
2181 M_IST(s2, REG_ITMP1, 0);
2184 var_to_reg_int(s2, src, REG_ITMP2);
2185 M_LST(s2, REG_ITMP1, 0);
2188 var_to_reg_int(s2, src, REG_ITMP2);
2189 M_AST(s2, REG_ITMP1, 0);
2192 var_to_reg_flt(s2, src, REG_FTMP2);
2193 M_FST(s2, REG_ITMP1, 0);
2196 var_to_reg_flt(s2, src, REG_FTMP2);
2197 M_DST(s2, REG_ITMP1, 0);
2199 default: panic ("internal error");
2203 case ICMD_GETSTATIC: /* ... ==> ..., value */
2204 /* op1 = type, val.a = field address */
2206 a = dseg_addaddress (&(((fieldinfo *)(iptr->val.a))->value));
2207 M_ALD(REG_ITMP1, REG_PV, a);
2208 switch (iptr->op1) {
2210 d = reg_of_var(iptr->dst, REG_ITMP3);
2211 M_ILD(d, REG_ITMP1, 0);
2212 store_reg_to_var_int(iptr->dst, d);
2215 d = reg_of_var(iptr->dst, REG_ITMP3);
2216 M_LLD(d, REG_ITMP1, 0);
2217 store_reg_to_var_int(iptr->dst, d);
2220 d = reg_of_var(iptr->dst, REG_ITMP3);
2221 M_ALD(d, REG_ITMP1, 0);
2222 store_reg_to_var_int(iptr->dst, d);
2225 d = reg_of_var(iptr->dst, REG_FTMP1);
2226 M_FLD(d, REG_ITMP1, 0);
2227 store_reg_to_var_flt(iptr->dst, d);
2230 d = reg_of_var(iptr->dst, REG_FTMP1);
2231 M_DLD(d, REG_ITMP1, 0);
2232 store_reg_to_var_flt(iptr->dst, d);
2234 default: panic ("internal error");
2239 case ICMD_PUTFIELD: /* ..., value ==> ... */
2240 /* op1 = type, val.i = field offset */
2242 a = ((fieldinfo *)(iptr->val.a))->offset;
2243 switch (iptr->op1) {
2245 var_to_reg_int(s1, src->prev, REG_ITMP1);
2246 var_to_reg_int(s2, src, REG_ITMP2);
2247 gen_nullptr_check(s1);
2251 var_to_reg_int(s1, src->prev, REG_ITMP1);
2252 var_to_reg_int(s2, src, REG_ITMP2);
2253 gen_nullptr_check(s1);
2257 var_to_reg_int(s1, src->prev, REG_ITMP1);
2258 var_to_reg_int(s2, src, REG_ITMP2);
2259 gen_nullptr_check(s1);
2263 var_to_reg_int(s1, src->prev, REG_ITMP1);
2264 var_to_reg_flt(s2, src, REG_FTMP2);
2265 gen_nullptr_check(s1);
2269 var_to_reg_int(s1, src->prev, REG_ITMP1);
2270 var_to_reg_flt(s2, src, REG_FTMP2);
2271 gen_nullptr_check(s1);
2274 default: panic ("internal error");
2278 case ICMD_GETFIELD: /* ... ==> ..., value */
2279 /* op1 = type, val.i = field offset */
2281 a = ((fieldinfo *)(iptr->val.a))->offset;
2282 switch (iptr->op1) {
2284 var_to_reg_int(s1, src, REG_ITMP1);
2285 d = reg_of_var(iptr->dst, REG_ITMP3);
2286 gen_nullptr_check(s1);
2288 store_reg_to_var_int(iptr->dst, d);
2291 var_to_reg_int(s1, src, REG_ITMP1);
2292 d = reg_of_var(iptr->dst, REG_ITMP3);
2293 gen_nullptr_check(s1);
2295 store_reg_to_var_int(iptr->dst, d);
2298 var_to_reg_int(s1, src, REG_ITMP1);
2299 d = reg_of_var(iptr->dst, REG_ITMP3);
2300 gen_nullptr_check(s1);
2302 store_reg_to_var_int(iptr->dst, d);
2305 var_to_reg_int(s1, src, REG_ITMP1);
2306 d = reg_of_var(iptr->dst, REG_FTMP1);
2307 gen_nullptr_check(s1);
2309 store_reg_to_var_flt(iptr->dst, d);
2312 var_to_reg_int(s1, src, REG_ITMP1);
2313 d = reg_of_var(iptr->dst, REG_FTMP1);
2314 gen_nullptr_check(s1);
2316 store_reg_to_var_flt(iptr->dst, d);
2318 default: panic ("internal error");
2323 /* branch operations **************************************************/
2325 #define ALIGNCODENOP {if((int)((long)mcodeptr&7)){M_NOP;}}
2327 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2329 var_to_reg_int(s1, src, REG_ITMP1);
2330 M_INTMOVE(s1, REG_ITMP1_XPTR);
2331 a = dseg_addaddress(asm_handle_exception);
2332 M_ALD(REG_ITMP2, REG_PV, a);
2333 M_JSR(REG_ITMP2_XPC, REG_ITMP2);
2335 M_NOP; /* nop ensures that XPC is less than the end */
2336 /* of basic block */
2340 case ICMD_GOTO: /* ... ==> ... */
2341 /* op1 = target JavaVM pc */
2343 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2348 case ICMD_JSR: /* ... ==> ... */
2349 /* op1 = target JavaVM pc */
2351 dseg_addtarget(BlockPtrOfPC(iptr->op1));
2352 M_ALD(REG_ITMP1, REG_PV, -dseglen);
2353 M_JSR(REG_ITMP1, REG_ITMP1); /* REG_ITMP1 = return address */
2357 case ICMD_RET: /* ... ==> ... */
2358 /* op1 = local variable */
2359 var = &(locals[iptr->op1][TYPE_ADR]);
2360 if (var->flags & INMEMORY) {
2361 M_ALD(REG_ITMP1, REG_SP, 8 * var->regoff);
2370 case ICMD_IFNULL: /* ..., value ==> ... */
2371 /* op1 = target JavaVM pc */
2373 var_to_reg_int(s1, src, REG_ITMP1);
2375 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2379 case ICMD_IFNONNULL: /* ..., value ==> ... */
2380 /* op1 = target JavaVM pc */
2382 var_to_reg_int(s1, src, REG_ITMP1);
2384 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2388 case ICMD_IFEQ: /* ..., value ==> ... */
2389 /* op1 = target JavaVM pc, val.i = constant */
2391 var_to_reg_int(s1, src, REG_ITMP1);
2392 if (iptr->val.i == 0) {
2396 ICONST(REG_ITMP2, iptr->val.i);
2397 M_BEQ(s1, REG_ITMP2, 0);
2399 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2403 case ICMD_IFLT: /* ..., value ==> ... */
2404 /* op1 = target JavaVM pc, val.i = constant */
2406 var_to_reg_int(s1, src, REG_ITMP1);
2407 if (iptr->val.i == 0) {
2411 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2412 M_CMPLT_IMM(s1, iptr->val.i, REG_ITMP1);
2415 ICONST(REG_ITMP2, iptr->val.i);
2416 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2418 M_BNEZ(REG_ITMP1, 0);
2420 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2424 case ICMD_IFLE: /* ..., value ==> ... */
2425 /* op1 = target JavaVM pc, val.i = constant */
2427 var_to_reg_int(s1, src, REG_ITMP1);
2428 if (iptr->val.i == 0) {
2432 if ((iptr->val.i >= -32769) && (iptr->val.i <= 32766)) {
2433 M_CMPLT_IMM(s1, iptr->val.i + 1, REG_ITMP1);
2434 M_BNEZ(REG_ITMP1, 0);
2437 ICONST(REG_ITMP2, iptr->val.i);
2438 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2439 M_BEQZ(REG_ITMP1, 0);
2442 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2446 case ICMD_IFNE: /* ..., value ==> ... */
2447 /* op1 = target JavaVM pc, val.i = constant */
2449 var_to_reg_int(s1, src, REG_ITMP1);
2450 if (iptr->val.i == 0) {
2454 ICONST(REG_ITMP2, iptr->val.i);
2455 M_BNE(s1, REG_ITMP2, 0);
2457 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2461 case ICMD_IFGT: /* ..., value ==> ... */
2462 /* op1 = target JavaVM pc, val.i = constant */
2464 var_to_reg_int(s1, src, REG_ITMP1);
2465 if (iptr->val.i == 0) {
2469 if ((iptr->val.i >= -32769) && (iptr->val.i <= 32766)) {
2470 M_CMPLT_IMM(s1, iptr->val.i + 1, REG_ITMP1);
2471 M_BEQZ(REG_ITMP1, 0);
2474 ICONST(REG_ITMP2, iptr->val.i);
2475 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2476 M_BNEZ(REG_ITMP1, 0);
2479 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2483 case ICMD_IFGE: /* ..., value ==> ... */
2484 /* op1 = target JavaVM pc, val.i = constant */
2486 var_to_reg_int(s1, src, REG_ITMP1);
2487 if (iptr->val.i == 0) {
2491 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2492 M_CMPLT_IMM(s1, iptr->val.i, REG_ITMP1);
2495 ICONST(REG_ITMP2, iptr->val.i);
2496 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2498 M_BEQZ(REG_ITMP1, 0);
2500 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2504 case ICMD_IF_LEQ: /* ..., value ==> ... */
2505 /* op1 = target JavaVM pc, val.l = constant */
2507 var_to_reg_int(s1, src, REG_ITMP1);
2508 if (iptr->val.l == 0) {
2512 LCONST(REG_ITMP2, iptr->val.l);
2513 M_BEQ(s1, REG_ITMP2, 0);
2515 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2519 case ICMD_IF_LLT: /* ..., value ==> ... */
2520 /* op1 = target JavaVM pc, val.l = constant */
2522 var_to_reg_int(s1, src, REG_ITMP1);
2523 if (iptr->val.l == 0) {
2527 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2528 M_CMPLT_IMM(s1, iptr->val.l, REG_ITMP1);
2531 LCONST(REG_ITMP2, iptr->val.l);
2532 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2534 M_BNEZ(REG_ITMP1, 0);
2536 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2540 case ICMD_IF_LLE: /* ..., value ==> ... */
2541 /* op1 = target JavaVM pc, val.l = constant */
2543 var_to_reg_int(s1, src, REG_ITMP1);
2544 if (iptr->val.l == 0) {
2548 if ((iptr->val.l >= -32769) && (iptr->val.l <= 32766)) {
2549 M_CMPLT_IMM(s1, iptr->val.l + 1, REG_ITMP1);
2550 M_BNEZ(REG_ITMP1, 0);
2553 LCONST(REG_ITMP2, iptr->val.l);
2554 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2555 M_BEQZ(REG_ITMP1, 0);
2558 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2562 case ICMD_IF_LNE: /* ..., value ==> ... */
2563 /* op1 = target JavaVM pc, val.l = constant */
2565 var_to_reg_int(s1, src, REG_ITMP1);
2566 if (iptr->val.l == 0) {
2570 LCONST(REG_ITMP2, iptr->val.l);
2571 M_BNE(s1, REG_ITMP2, 0);
2573 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2577 case ICMD_IF_LGT: /* ..., value ==> ... */
2578 /* op1 = target JavaVM pc, val.l = constant */
2580 var_to_reg_int(s1, src, REG_ITMP1);
2581 if (iptr->val.l == 0) {
2585 if ((iptr->val.l >= -32769) && (iptr->val.l <= 32766)) {
2586 M_CMPLT_IMM(s1, iptr->val.l + 1, REG_ITMP1);
2587 M_BEQZ(REG_ITMP1, 0);
2590 LCONST(REG_ITMP2, iptr->val.l);
2591 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2592 M_BNEZ(REG_ITMP1, 0);
2595 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2599 case ICMD_IF_LGE: /* ..., value ==> ... */
2600 /* op1 = target JavaVM pc, val.l = constant */
2602 var_to_reg_int(s1, src, REG_ITMP1);
2603 if (iptr->val.l == 0) {
2607 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2608 M_CMPLT_IMM(s1, iptr->val.l, REG_ITMP1);
2611 LCONST(REG_ITMP2, iptr->val.l);
2612 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2614 M_BEQZ(REG_ITMP1, 0);
2616 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2620 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2621 case ICMD_IF_LCMPEQ: /* op1 = target JavaVM pc */
2622 case ICMD_IF_ACMPEQ:
2624 var_to_reg_int(s1, src->prev, REG_ITMP1);
2625 var_to_reg_int(s2, src, REG_ITMP2);
2627 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2631 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2632 case ICMD_IF_LCMPNE: /* op1 = target JavaVM pc */
2633 case ICMD_IF_ACMPNE:
2635 var_to_reg_int(s1, src->prev, REG_ITMP1);
2636 var_to_reg_int(s2, src, REG_ITMP2);
2638 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2642 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2643 case ICMD_IF_LCMPLT: /* op1 = target JavaVM pc */
2645 var_to_reg_int(s1, src->prev, REG_ITMP1);
2646 var_to_reg_int(s2, src, REG_ITMP2);
2647 M_CMPLT(s1, s2, REG_ITMP1);
2648 M_BNEZ(REG_ITMP1, 0);
2649 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2653 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2654 case ICMD_IF_LCMPGT: /* op1 = target JavaVM pc */
2656 var_to_reg_int(s1, src->prev, REG_ITMP1);
2657 var_to_reg_int(s2, src, REG_ITMP2);
2658 M_CMPGT(s1, s2, REG_ITMP1);
2659 M_BNEZ(REG_ITMP1, 0);
2660 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2664 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2665 case ICMD_IF_LCMPLE: /* op1 = target JavaVM pc */
2667 var_to_reg_int(s1, src->prev, REG_ITMP1);
2668 var_to_reg_int(s2, src, REG_ITMP2);
2669 M_CMPGT(s1, s2, REG_ITMP1);
2670 M_BEQZ(REG_ITMP1, 0);
2671 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2675 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2676 case ICMD_IF_LCMPGE: /* op1 = target JavaVM pc */
2678 var_to_reg_int(s1, src->prev, REG_ITMP1);
2679 var_to_reg_int(s2, src, REG_ITMP2);
2680 M_CMPLT(s1, s2, REG_ITMP1);
2681 M_BEQZ(REG_ITMP1, 0);
2682 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
2686 #ifdef CONDITIONAL_LOADCONST
2687 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST */
2689 case ICMD_ELSE_ICONST: /* handled by IFxx_ICONST */
2692 case ICMD_IFEQ_ICONST: /* ..., value ==> ..., constant */
2693 /* val.i = constant */
2695 var_to_reg_int(s1, src, REG_ITMP1);
2696 d = reg_of_var(iptr->dst, REG_ITMP3);
2698 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2699 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2700 M_CMPEQ(s1, REG_ZERO, d);
2701 store_reg_to_var_int(iptr->dst, d);
2704 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2705 M_CMPEQ(s1, REG_ZERO, d);
2707 store_reg_to_var_int(iptr->dst, d);
2711 M_MOV(s1, REG_ITMP1);
2714 ICONST(d, iptr[1].val.i);
2716 if ((s3 >= 0) && (s3 <= 255)) {
2717 M_CMOVEQ_IMM(s1, s3, d);
2720 ICONST(REG_ITMP2, s3);
2721 M_CMOVEQ(s1, REG_ITMP2, d);
2723 store_reg_to_var_int(iptr->dst, d);
2726 case ICMD_IFNE_ICONST: /* ..., value ==> ..., constant */
2727 /* val.i = constant */
2729 var_to_reg_int(s1, src, REG_ITMP1);
2730 d = reg_of_var(iptr->dst, REG_ITMP3);
2732 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2733 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2734 M_CMPEQ(s1, REG_ZERO, d);
2735 store_reg_to_var_int(iptr->dst, d);
2738 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2739 M_CMPEQ(s1, REG_ZERO, d);
2741 store_reg_to_var_int(iptr->dst, d);
2745 M_MOV(s1, REG_ITMP1);
2748 ICONST(d, iptr[1].val.i);
2750 if ((s3 >= 0) && (s3 <= 255)) {
2751 M_CMOVNE_IMM(s1, s3, d);
2754 ICONST(REG_ITMP2, s3);
2755 M_CMOVNE(s1, REG_ITMP2, d);
2757 store_reg_to_var_int(iptr->dst, d);
2760 case ICMD_IFLT_ICONST: /* ..., value ==> ..., constant */
2761 /* val.i = constant */
2763 var_to_reg_int(s1, src, REG_ITMP1);
2764 d = reg_of_var(iptr->dst, REG_ITMP3);
2766 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2767 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2768 M_CMPLT(s1, REG_ZERO, d);
2769 store_reg_to_var_int(iptr->dst, d);
2772 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2773 M_CMPLE(REG_ZERO, s1, d);
2774 store_reg_to_var_int(iptr->dst, d);
2778 M_MOV(s1, REG_ITMP1);
2781 ICONST(d, iptr[1].val.i);
2783 if ((s3 >= 0) && (s3 <= 255)) {
2784 M_CMOVLT_IMM(s1, s3, d);
2787 ICONST(REG_ITMP2, s3);
2788 M_CMOVLT(s1, REG_ITMP2, d);
2790 store_reg_to_var_int(iptr->dst, d);
2793 case ICMD_IFGE_ICONST: /* ..., value ==> ..., constant */
2794 /* val.i = constant */
2796 var_to_reg_int(s1, src, REG_ITMP1);
2797 d = reg_of_var(iptr->dst, REG_ITMP3);
2799 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2800 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2801 M_CMPLE(REG_ZERO, s1, d);
2802 store_reg_to_var_int(iptr->dst, d);
2805 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2806 M_CMPLT(s1, REG_ZERO, d);
2807 store_reg_to_var_int(iptr->dst, d);
2811 M_MOV(s1, REG_ITMP1);
2814 ICONST(d, iptr[1].val.i);
2816 if ((s3 >= 0) && (s3 <= 255)) {
2817 M_CMOVGE_IMM(s1, s3, d);
2820 ICONST(REG_ITMP2, s3);
2821 M_CMOVGE(s1, REG_ITMP2, d);
2823 store_reg_to_var_int(iptr->dst, d);
2826 case ICMD_IFGT_ICONST: /* ..., value ==> ..., constant */
2827 /* val.i = constant */
2829 var_to_reg_int(s1, src, REG_ITMP1);
2830 d = reg_of_var(iptr->dst, REG_ITMP3);
2832 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2833 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2834 M_CMPLT(REG_ZERO, s1, d);
2835 store_reg_to_var_int(iptr->dst, d);
2838 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2839 M_CMPLE(s1, REG_ZERO, d);
2840 store_reg_to_var_int(iptr->dst, d);
2844 M_MOV(s1, REG_ITMP1);
2847 ICONST(d, iptr[1].val.i);
2849 if ((s3 >= 0) && (s3 <= 255)) {
2850 M_CMOVGT_IMM(s1, s3, d);
2853 ICONST(REG_ITMP2, s3);
2854 M_CMOVGT(s1, REG_ITMP2, d);
2856 store_reg_to_var_int(iptr->dst, d);
2859 case ICMD_IFLE_ICONST: /* ..., value ==> ..., constant */
2860 /* val.i = constant */
2862 var_to_reg_int(s1, src, REG_ITMP1);
2863 d = reg_of_var(iptr->dst, REG_ITMP3);
2865 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2866 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2867 M_CMPLE(s1, REG_ZERO, d);
2868 store_reg_to_var_int(iptr->dst, d);
2871 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2872 M_CMPLT(REG_ZERO, s1, d);
2873 store_reg_to_var_int(iptr->dst, d);
2877 M_MOV(s1, REG_ITMP1);
2880 ICONST(d, iptr[1].val.i);
2882 if ((s3 >= 0) && (s3 <= 255)) {
2883 M_CMOVLE_IMM(s1, s3, d);
2886 ICONST(REG_ITMP2, s3);
2887 M_CMOVLE(s1, REG_ITMP2, d);
2889 store_reg_to_var_int(iptr->dst, d);
2894 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2899 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
2901 a = dseg_addaddress ((void*) (builtin_monitorexit));
2902 M_ALD(REG_ITMP3, REG_PV, a);
2903 M_JSR(REG_RA, REG_ITMP3);
2904 M_ALD(argintregs[0], REG_SP, 8 * maxmemuse); /* delay slot */
2905 disp = -(int)((u1*) mcodeptr - mcodebase);
2906 M_LDA(REG_PV, REG_RA, disp);
2909 var_to_reg_int(s1, src, REG_RESULT);
2910 M_INTMOVE(s1, REG_RESULT);
2911 goto nowperformreturn;
2913 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2917 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
2919 a = dseg_addaddress ((void*) (builtin_monitorexit));
2920 M_ALD(REG_ITMP3, REG_PV, a);
2921 M_JSR(REG_RA, REG_ITMP3);
2922 M_ALD(argintregs[0], REG_SP, 8 * maxmemuse); /* delay slot */
2923 disp = -(int)((u1*) mcodeptr - mcodebase);
2924 M_LDA(REG_PV, REG_RA, disp);
2927 var_to_reg_flt(s1, src, REG_FRESULT);
2929 int t = ((iptr->opc == ICMD_FRETURN) ? TYPE_FLT : TYPE_DBL);
2930 M_TFLTMOVE(t, s1, REG_FRESULT);
2932 goto nowperformreturn;
2934 case ICMD_RETURN: /* ... ==> ... */
2937 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
2939 a = dseg_addaddress ((void*) (builtin_monitorexit));
2940 M_ALD(REG_ITMP3, REG_PV, a);
2941 M_JSR(REG_RA, REG_ITMP3);
2942 M_ALD(argintregs[0], REG_SP, 8 * maxmemuse); /* delay slot */
2943 disp = -(int)((u1*) mcodeptr - mcodebase);
2944 M_LDA(REG_PV, REG_RA, disp);
2952 p = parentargs_base;
2954 /* restore return address */
2957 {p--; M_LLD (REG_RA, REG_SP, 8 * p);}
2959 /* restore saved registers */
2961 for (r = savintregcnt - 1; r >= maxsavintreguse; r--)
2962 {p--; M_LLD(savintregs[r], REG_SP, 8 * p);}
2963 for (r = savfltregcnt - 1; r >= maxsavfltreguse; r--)
2964 {p--; M_DLD(savfltregs[r], REG_SP, 8 * p);}
2966 /* call trace function */
2969 M_LDA (REG_SP, REG_SP, -24);
2970 M_LST(REG_RA, REG_SP, 0);
2971 M_LST(REG_RESULT, REG_SP, 8);
2972 M_DST(REG_FRESULT, REG_SP,16);
2973 a = dseg_addaddress (method);
2974 M_ALD(argintregs[0], REG_PV, a);
2975 M_MOV(REG_RESULT, argintregs[1]);
2976 M_FLTMOVE(REG_FRESULT, argfltregs[2]);
2977 M_FMOV(REG_FRESULT, argfltregs[3]);
2978 a = dseg_addaddress ((void*) (builtin_displaymethodstop));
2979 M_ALD(REG_ITMP3, REG_PV, a);
2980 M_JSR (REG_RA, REG_ITMP3);
2982 M_DLD(REG_FRESULT, REG_SP,16);
2983 M_LLD(REG_RESULT, REG_SP, 8);
2984 M_LLD(REG_RA, REG_SP, 0);
2985 M_LDA (REG_SP, REG_SP, 24);
2990 /* deallocate stack */
2992 if (parentargs_base)
2993 {M_LDA(REG_SP, REG_SP, parentargs_base*8);}
3001 case ICMD_TABLESWITCH: /* ..., index ==> ... */
3006 tptr = (void **) iptr->target;
3008 s4ptr = iptr->val.a;
3009 l = s4ptr[1]; /* low */
3010 i = s4ptr[2]; /* high */
3012 var_to_reg_int(s1, src, REG_ITMP1);
3014 {M_INTMOVE(s1, REG_ITMP1);}
3015 else if (l <= 32768) {
3016 M_IADD_IMM(s1, -l, REG_ITMP1);
3019 ICONST(REG_ITMP2, l);
3020 M_ISUB(s1, REG_ITMP2, REG_ITMP1);
3026 M_CMPULT_IMM(REG_ITMP1, i, REG_ITMP2);
3027 M_BEQZ(REG_ITMP2, 0);
3028 codegen_addreference((basicblock *) tptr[0], mcodeptr);
3029 M_ASLL_IMM(REG_ITMP1, POINTERSHIFT, REG_ITMP1); /* delay slot*/
3031 /* build jump table top down and use address of lowest entry */
3033 /* s4ptr += 3 + i; */
3037 /* dseg_addtarget(BlockPtrOfPC(*--s4ptr)); */
3038 dseg_addtarget((basicblock *) tptr[0]);
3043 /* length of dataseg after last dseg_addtarget is used by load */
3045 M_AADD(REG_ITMP1, REG_PV, REG_ITMP2);
3046 M_ALD(REG_ITMP2, REG_ITMP2, -dseglen);
3053 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
3055 s4 i, l, val, *s4ptr;
3058 tptr = (void **) iptr->target;
3060 s4ptr = iptr->val.a;
3061 l = s4ptr[0]; /* default */
3062 i = s4ptr[1]; /* count */
3064 MCODECHECK((i<<2)+8);
3065 var_to_reg_int(s1, src, REG_ITMP1);
3071 ICONST(REG_ITMP2, val);
3072 M_BEQ(s1, REG_ITMP2, 0);
3073 codegen_addreference((basicblock *) tptr[0], mcodeptr);
3078 tptr = (void **) iptr->target;
3079 codegen_addreference((basicblock *) tptr[0], mcodeptr);
3086 case ICMD_BUILTIN3: /* ..., arg1, arg2, arg3 ==> ... */
3087 /* op1 = return type, val.a = function pointer*/
3091 case ICMD_BUILTIN2: /* ..., arg1, arg2 ==> ... */
3092 /* op1 = return type, val.a = function pointer*/
3096 case ICMD_BUILTIN1: /* ..., arg1 ==> ... */
3097 /* op1 = return type, val.a = function pointer*/
3101 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
3102 /* op1 = arg count, val.a = method pointer */
3104 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3105 /* op1 = arg count, val.a = method pointer */
3107 case ICMD_INVOKEVIRTUAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3108 /* op1 = arg count, val.a = method pointer */
3110 case ICMD_INVOKEINTERFACE:/*.., objectref, [arg1, [arg2 ...]] ==> ... */
3111 /* op1 = arg count, val.a = method pointer */
3119 MCODECHECK((s3 << 1) + 64);
3121 /* copy arguments to registers or stack location */
3123 for (; --s3 >= 0; src = src->prev) {
3124 if (src->varkind == ARGVAR)
3126 if (IS_INT_LNG_TYPE(src->type)) {
3127 if (s3 < INT_ARG_CNT) {
3128 s1 = argintregs[s3];
3129 var_to_reg_int(d, src, s1);
3133 var_to_reg_int(d, src, REG_ITMP1);
3134 M_LST(d, REG_SP, 8 * (s3 - INT_ARG_CNT));
3138 if (s3 < FLT_ARG_CNT) {
3139 s1 = argfltregs[s3];
3140 var_to_reg_flt(d, src, s1);
3141 M_TFLTMOVE(src->type,d, s1);
3144 var_to_reg_flt(d, src, REG_FTMP1);
3145 M_DST(d, REG_SP, 8 * (s3 - FLT_ARG_CNT));
3150 switch (iptr->opc) {
3154 a = dseg_addaddress ((void*) (m));
3155 M_ALD(REG_ITMP3, REG_PV, a); /* built-in-function pointer */
3156 M_JSR (REG_RA, REG_ITMP3);
3158 d = iptr->op1; /* return type */
3159 goto afteractualcall;
3161 case ICMD_INVOKESTATIC:
3162 case ICMD_INVOKESPECIAL:
3163 a = dseg_addaddress (m->stubroutine);
3165 M_ALD(REG_PV, REG_PV, a ); /* method pointer in pv */
3168 goto makeactualcall;
3170 case ICMD_INVOKEVIRTUAL:
3172 gen_nullptr_check(argintregs[0]);
3173 M_ALD(REG_METHODPTR, argintregs[0],
3174 OFFSET(java_objectheader, vftbl));
3175 M_ALD(REG_PV, REG_METHODPTR, OFFSET(vftbl, table[0]) +
3176 sizeof(methodptr) * m->vftblindex);
3179 goto makeactualcall;
3181 case ICMD_INVOKEINTERFACE:
3184 gen_nullptr_check(argintregs[0]);
3185 M_ALD(REG_METHODPTR, argintregs[0],
3186 OFFSET(java_objectheader, vftbl));
3187 M_ALD(REG_METHODPTR, REG_METHODPTR,
3188 OFFSET(vftbl, interfacetable[0]) -
3189 sizeof(methodptr*) * ci->index);
3190 M_ALD(REG_PV, REG_METHODPTR,
3191 sizeof(methodptr) * (m - ci->methods));
3194 goto makeactualcall;
3198 sprintf (logtext, "Unkown ICMD-Command: %d", iptr->opc);
3204 M_JSR (REG_RA, REG_PV);
3211 s1 = (int)((u1*) mcodeptr - mcodebase);
3212 if (s1<=32768) M_LDA (REG_PV, REG_RA, -s1);
3215 while (ml<-32768) { ml+=65536; mh--; }
3217 M_IADD_IMM(REG_PV, ml, REG_PV);
3218 M_LADD(REG_PV, REG_RA, REG_PV);
3221 /* d contains return type */
3223 if (d != TYPE_VOID) {
3224 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
3225 s1 = reg_of_var(iptr->dst, REG_RESULT);
3226 M_INTMOVE(REG_RESULT, s1);
3227 store_reg_to_var_int(iptr->dst, s1);
3230 s1 = reg_of_var(iptr->dst, REG_FRESULT);
3231 M_TFLTMOVE(iptr->dst->type, REG_FRESULT, s1);
3232 store_reg_to_var_flt(iptr->dst, s1);
3239 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3241 /* op1: 0 == array, 1 == class */
3242 /* val.a: (classinfo*) superclass */
3244 /* superclass is an interface:
3246 * return (sub != NULL) &&
3247 * (sub->vftbl->interfacetablelength > super->index) &&
3248 * (sub->vftbl->interfacetable[-super->index] != NULL);
3250 * superclass is a class:
3252 * return ((sub != NULL) && (0
3253 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3254 * super->vftbl->diffvall));
3258 classinfo *super = (classinfo*) iptr->val.a;
3260 var_to_reg_int(s1, src, REG_ITMP1);
3261 d = reg_of_var(iptr->dst, REG_ITMP3);
3263 M_MOV(s1, REG_ITMP1);
3267 if (iptr->op1) { /* class/interface */
3268 if (super->flags & ACC_INTERFACE) { /* interface */
3271 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3272 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(vftbl, interfacetablelength));
3273 M_IADD_IMM(REG_ITMP2, - super->index, REG_ITMP2);
3274 M_BLEZ(REG_ITMP2, 3);
3276 M_ALD(REG_ITMP1, REG_ITMP1,
3277 OFFSET(vftbl, interfacetable[0]) -
3278 super->index * sizeof(methodptr*));
3279 M_CMPULT(REG_ZERO, REG_ITMP1, d); /* REG_ITMP1 != 0 */
3283 s2 = super->vftbl->diffval;
3286 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3287 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl, baseval));
3288 M_IADD_IMM(REG_ITMP1, - super->vftbl->baseval, REG_ITMP1);
3289 M_CMPULT_IMM(REG_ITMP1, s2 + 1, d);
3294 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3295 a = dseg_addaddress ((void*) super->vftbl);
3296 M_ALD(REG_ITMP2, REG_PV, a);
3297 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl, baseval));
3298 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl, baseval));
3299 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl, diffval));
3300 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
3301 M_CMPULT(REG_ITMP2, REG_ITMP1, d);
3307 panic ("internal error: no inlined array instanceof");
3309 store_reg_to_var_int(iptr->dst, d);
3312 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
3314 /* op1: 0 == array, 1 == class */
3315 /* val.a: (classinfo*) superclass */
3317 /* superclass is an interface:
3319 * OK if ((sub == NULL) ||
3320 * (sub->vftbl->interfacetablelength > super->index) &&
3321 * (sub->vftbl->interfacetable[-super->index] != NULL));
3323 * superclass is a class:
3325 * OK if ((sub == NULL) || (0
3326 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3327 * super->vftbl->diffvall));
3331 classinfo *super = (classinfo*) iptr->val.a;
3333 d = reg_of_var(iptr->dst, REG_ITMP3);
3334 var_to_reg_int(s1, src, d);
3335 if (iptr->op1) { /* class/interface */
3336 if (super->flags & ACC_INTERFACE) { /* interface */
3339 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3340 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(vftbl, interfacetablelength));
3341 M_IADD_IMM(REG_ITMP2, - super->index, REG_ITMP2);
3342 M_BLEZ(REG_ITMP2, 0);
3343 codegen_addxcastrefs(mcodeptr);
3345 M_ALD(REG_ITMP2, REG_ITMP1,
3346 OFFSET(vftbl, interfacetable[0]) -
3347 super->index * sizeof(methodptr*));
3348 M_BEQZ(REG_ITMP2, 0);
3349 codegen_addxcastrefs(mcodeptr);
3355 s2 = super->vftbl->diffval;
3356 M_BEQZ(s1, 6 + (s2 != 0));
3358 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3359 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl, baseval));
3360 M_IADD_IMM(REG_ITMP1, - super->vftbl->baseval, REG_ITMP1);
3362 M_BNEZ(REG_ITMP1, 0);
3365 M_CMPULT_IMM(REG_ITMP1, s2 + 1, REG_ITMP2);
3366 M_BEQZ(REG_ITMP2, 0);
3370 M_BEQZ(s1, 10 + (d == REG_ITMP3));
3372 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3373 a = dseg_addaddress ((void*) super->vftbl);
3374 M_ALD(REG_ITMP2, REG_PV, a);
3375 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl, baseval));
3376 if (d != REG_ITMP3) {
3377 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl, baseval));
3378 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl, diffval));
3379 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
3381 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl, baseval));
3382 M_ISUB(REG_ITMP1, REG_ITMP2, REG_ITMP1);
3383 M_ALD(REG_ITMP2, REG_PV, a);
3384 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl, diffval));
3386 M_CMPULT(REG_ITMP2, REG_ITMP1, REG_ITMP2);
3387 M_BNEZ(REG_ITMP2, 0);
3389 codegen_addxcastrefs(mcodeptr);
3394 panic ("internal error: no inlined array checkcast");
3397 store_reg_to_var_int(iptr->dst, d);
3400 case ICMD_CHECKASIZE: /* ..., size ==> ..., size */
3402 var_to_reg_int(s1, src, REG_ITMP1);
3404 codegen_addxcheckarefs(mcodeptr);
3408 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3409 /* op1 = dimension, val.a = array descriptor */
3411 /* check for negative sizes and copy sizes to stack if necessary */
3413 MCODECHECK((iptr->op1 << 1) + 64);
3415 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
3416 var_to_reg_int(s2, src, REG_ITMP1);
3418 codegen_addxcheckarefs(mcodeptr);
3421 /* copy sizes to stack (argument numbers >= INT_ARG_CNT) */
3423 if (src->varkind != ARGVAR) {
3424 M_LST(s2, REG_SP, 8 * (s1 + INT_ARG_CNT));
3428 /* a0 = dimension count */
3430 ICONST(argintregs[0], iptr->op1);
3432 /* a1 = arraydescriptor */
3434 a = dseg_addaddress(iptr->val.a);
3435 M_ALD(argintregs[1], REG_PV, a);
3437 /* a2 = pointer to dimensions = stack pointer */
3439 M_INTMOVE(REG_SP, argintregs[2]);
3441 a = dseg_addaddress((void*) (builtin_nmultianewarray));
3442 M_ALD(REG_ITMP3, REG_PV, a);
3443 M_JSR(REG_RA, REG_ITMP3);
3445 s1 = (int)((u1*) mcodeptr - mcodebase);
3447 M_LDA (REG_PV, REG_RA, -s1);
3451 s1 = reg_of_var(iptr->dst, REG_RESULT);
3452 M_INTMOVE(REG_RESULT, s1);
3453 store_reg_to_var_int(iptr->dst, s1);
3457 default: sprintf (logtext, "Unknown pseudo command: %d", iptr->opc);
3464 } /* for instruction */
3466 /* copy values to interface registers */
3468 src = bptr->outstack;
3469 len = bptr->outdepth;
3473 if ((src->varkind != STACKVAR)) {
3475 if (IS_FLT_DBL_TYPE(s2)) {
3476 var_to_reg_flt(s1, src, REG_FTMP1);
3477 if (!(interfaces[len][s2].flags & INMEMORY)) {
3478 M_TFLTMOVE(s2,s1,interfaces[len][s2].regoff);
3481 M_DST(s1, REG_SP, 8 * interfaces[len][s2].regoff);
3485 var_to_reg_int(s1, src, REG_ITMP1);
3486 if (!(interfaces[len][s2].flags & INMEMORY)) {
3487 M_INTMOVE(s1,interfaces[len][s2].regoff);
3490 M_LST(s1, REG_SP, 8 * interfaces[len][s2].regoff);
3496 } /* if (bptr -> flags >= BBREACHED) */
3497 } /* for basic block */
3499 /* bptr -> mpc = (int)((u1*) mcodeptr - mcodebase); */
3502 /* generate bound check stubs */
3504 s4 *xcodeptr = NULL;
3506 for (; xboundrefs != NULL; xboundrefs = xboundrefs->next) {
3507 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
3508 gen_resolvebranch((u1*) mcodebase + xboundrefs->branchpos,
3509 xboundrefs->branchpos, (u1*) xcodeptr - (u1*) mcodebase - 4);
3514 gen_resolvebranch((u1*) mcodebase + xboundrefs->branchpos,
3515 xboundrefs->branchpos, (u1*) mcodeptr - mcodebase);
3519 M_LDA(REG_ITMP2_XPC, REG_PV, xboundrefs->branchpos - 4);
3521 if (xcodeptr != NULL) {
3522 int disp = xcodeptr-mcodeptr;
3527 xcodeptr = mcodeptr;
3529 a = dseg_addaddress(asm_handle_exception);
3530 M_ALD(REG_ITMP3, REG_PV, a);
3533 a = dseg_addaddress(proto_java_lang_ArrayIndexOutOfBoundsException);
3534 M_ALD(REG_ITMP1_XPTR, REG_PV, a);
3538 /* generate negative array size check stubs */
3542 for (; xcheckarefs != NULL; xcheckarefs = xcheckarefs->next) {
3543 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
3544 gen_resolvebranch((u1*) mcodebase + xcheckarefs->branchpos,
3545 xcheckarefs->branchpos, (u1*) xcodeptr - (u1*) mcodebase - 4);
3549 gen_resolvebranch((u1*) mcodebase + xcheckarefs->branchpos,
3550 xcheckarefs->branchpos, (u1*) mcodeptr - mcodebase);
3554 M_LDA(REG_ITMP2_XPC, REG_PV, xcheckarefs->branchpos - 4);
3556 if (xcodeptr != NULL) {
3557 int disp = xcodeptr-mcodeptr;
3562 xcodeptr = mcodeptr;
3564 a = dseg_addaddress(asm_handle_exception);
3565 M_ALD(REG_ITMP3, REG_PV, a);
3568 a = dseg_addaddress(proto_java_lang_NegativeArraySizeException);
3569 M_ALD(REG_ITMP1_XPTR, REG_PV, a);
3573 /* generate cast check stubs */
3577 for (; xcastrefs != NULL; xcastrefs = xcastrefs->next) {
3578 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
3579 gen_resolvebranch((u1*) mcodebase + xcastrefs->branchpos,
3580 xcastrefs->branchpos, (u1*) xcodeptr - (u1*) mcodebase - 4);
3584 gen_resolvebranch((u1*) mcodebase + xcastrefs->branchpos,
3585 xcastrefs->branchpos, (u1*) mcodeptr - mcodebase);
3589 M_LDA(REG_ITMP2_XPC, REG_PV, xcastrefs->branchpos - 4);
3591 if (xcodeptr != NULL) {
3592 int disp = xcodeptr-mcodeptr;
3597 xcodeptr = mcodeptr;
3599 a = dseg_addaddress(asm_handle_exception);
3600 M_ALD(REG_ITMP3, REG_PV, a);
3603 a = dseg_addaddress(proto_java_lang_ClassCastException);
3604 M_ALD(REG_ITMP1_XPTR, REG_PV, a);
3609 #ifdef SOFTNULLPTRCHECK
3611 /* generate null pointer check stubs */
3615 for (; xnullrefs != NULL; xnullrefs = xnullrefs->next) {
3616 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
3617 gen_resolvebranch((u1*) mcodebase + xnullrefs->branchpos,
3618 xnullrefs->branchpos, (u1*) xcodeptr - (u1*) mcodebase - 4);
3622 gen_resolvebranch((u1*) mcodebase + xnullrefs->branchpos,
3623 xnullrefs->branchpos, (u1*) mcodeptr - mcodebase);
3627 M_LDA(REG_ITMP2_XPC, REG_PV, xnullrefs->branchpos - 4);
3629 if (xcodeptr != NULL) {
3630 int disp = xcodeptr-mcodeptr;
3635 xcodeptr = mcodeptr;
3637 a = dseg_addaddress(asm_handle_exception);
3638 M_ALD(REG_ITMP3, REG_PV, a);
3641 a = dseg_addaddress(proto_java_lang_NullPointerException);
3642 M_ALD(REG_ITMP1_XPTR, REG_PV, a);
3649 codegen_finish((int)((u1*) mcodeptr - mcodebase));
3651 docacheflush((void*) method->entrypoint,
3652 ((u1*) mcodeptr - mcodebase));
3656 /* redefinition of code generation macros (compiling into array) **************/
3659 These macros are newly defined to allow code generation into an array.
3660 This is necessary, because the original M_.. macros generate code by
3661 calling 'codegen_adds4' that uses an additional data structure to
3664 For a faster (but less flexible) version to generate code, these
3665 macros directly use the (s4* p) - pointer to put the code directly
3666 in a locally defined array.
3667 This makes sense only for the stub-generation-routines below.
3671 #define M_ITYPE(op, rs, rt, imm)\
3672 *(p++) = (((op)<<26)|((rs)<<21)|((rt)<<16)|((imm)&0xffff))
3675 #define M_JTYPE(op, imm)\
3676 *(p++) = (((op)<<26)|((off)&0x3ffffff))
3679 #define M_RTYPE(op, rs, rt, rd, sa, fu)\
3680 *(p++) = (((op)<<26)|((rs)<<21)|((rt)<<16)|((rd)<<11)|((sa)<<6)|(fu))
3683 /* function createcompilerstub *************************************************
3685 creates a stub routine which calls the compiler
3687 *******************************************************************************/
3689 #define COMPSTUBSIZE 4
3691 u1 *createcompilerstub (methodinfo *m)
3693 u8 *s = CNEW(u8, COMPSTUBSIZE); /* memory to hold the stub */
3694 s4 *p = (s4*) s; /* code generation pointer */
3696 /* code for the stub */
3697 M_ALD(REG_PV, REG_PV, 24); /* load pointer to the compiler */
3699 M_JSR(REG_ITMP1, REG_PV); /* jump to the compiler, return address
3700 in itmp1 is used as method pointer */
3703 s[2] = (u8) m; /* literals to be adressed */
3704 s[3] = (u8) asm_call_jit_compiler; /* jump directly via PV from above */
3706 (void) docacheflush((void*) s, (char*) p - (char*) s);
3709 count_cstub_len += COMPSTUBSIZE * 8;
3716 /* function removecompilerstub *************************************************
3718 deletes a compilerstub from memory (simply by freeing it)
3720 *******************************************************************************/
3722 void removecompilerstub (u1 *stub)
3724 CFREE(stub, COMPSTUBSIZE * 8);
3727 /* function: createnativestub **************************************************
3729 creates a stub routine which calls a native method
3731 *******************************************************************************/
3733 #define NATIVESTUBSIZE 20
3735 u1 *createnativestub (functionptr f, methodinfo *m)
3737 u8 *s = CNEW(u8, NATIVESTUBSIZE); /* memory to hold the stub */
3738 s4 *p = (s4*) s; /* code generation pointer */
3742 M_MOV (argintregs[4], argintregs[5]);
3743 M_DMFC1 (REG_ITMP1, argfltregs[4]);
3745 M_MOV (argintregs[3], argintregs[4]);
3746 M_DMTC1 (REG_ITMP1, argfltregs[5]);
3748 M_MOV (argintregs[2], argintregs[3]);
3749 M_DMFC1 (REG_ITMP1, argfltregs[3]);
3751 M_MOV (argintregs[1], argintregs[2]);
3752 M_DMTC1 (REG_ITMP1, argfltregs[4]);
3754 M_MOV (argintregs[0], argintregs[1]);
3755 M_DMFC1 (REG_ITMP1, argfltregs[2]);
3757 M_ALD (argintregs[0], REG_PV, 19*8); /* load adress of jni_environement */
3758 M_DMTC1 (REG_ITMP1, argfltregs[3]);
3760 M_DMFC1 (REG_ITMP1, argfltregs[1]);
3761 M_DMFC1 (REG_ITMP2, argfltregs[0]);
3763 M_DMTC1 (REG_ITMP1, argfltregs[2]);
3764 M_DMTC1 (REG_ITMP2, argfltregs[1]);
3766 M_ALD (REG_ITMP3, REG_PV, 16*8); /* load adress of native method */
3767 M_LDA (REG_SP, REG_SP, -8); /* build up stackframe */
3769 M_LST (REG_RA, REG_SP, 0); /* store return address */
3770 M_JSR (REG_RA, REG_ITMP3); /* call native method */
3772 M_NOP; /* delay slot */
3773 M_ALD (REG_ITMP3, REG_PV, 17*8); /* get address of exceptionptr */
3775 M_LLD (REG_RA, REG_SP, 0); /* load return address */
3776 M_ALD (REG_ITMP1, REG_ITMP3, 0); /* load exception into reg. itmp1 */
3778 M_BNEZ (REG_ITMP1, 2); /* if no exception then return */
3779 M_LDA (REG_SP, REG_SP, 8); /* remove stackframe, delay slot */
3781 M_RET (REG_RA); /* return to caller */
3782 M_NOP; /* delay slot */
3784 M_AST (REG_ZERO, REG_ITMP3, 0); /* store NULL into exceptionptr */
3785 M_ALD (REG_ITMP3, REG_PV,18*8); /* load asm exception handler address */
3787 M_JMP (REG_ITMP3); /* jump to asm exception handler */
3788 M_LDA (REG_ITMP2, REG_RA, -4); /* move fault address into reg. itmp2 */
3791 s[16] = (u8) f; /* address of native method */
3792 s[17] = (u8) (&exceptionptr); /* address of exceptionptr */
3793 s[18]= (u8) (asm_handle_nat_exception); /* addr of asm exception handler */
3794 s[19] = (u8) (&env); /* addr of jni_environement */
3796 (void) docacheflush((void*) s, (char*) p - (char*) s);
3799 count_nstub_len += NATIVESTUBSIZE * 8;
3805 /* function: removenativestub **************************************************
3807 removes a previously created native-stub from memory
3809 *******************************************************************************/
3811 void removenativestub (u1 *stub)
3813 CFREE(stub, NATIVESTUBSIZE * 8);
3817 /* function: createcalljava ****************************************************
3819 creates the asm_calljavamethod (MIPS assembler does not like data in the
3820 text segment). Documentation can be found in asmpart.c.
3822 *******************************************************************************/
3831 #define CALL_JAVA_MEM_SIZE 60
3832 #define CALL_JAVA_ENTRY 20
3833 #define CALL_JAVA_XHANDLER 55
3835 static s4 calljavamem[CALL_JAVA_MEM_SIZE];
3837 void createcalljava ()
3841 *((void**)(calljavamem + 0)) = (void*) asm_call_jit_compiler;
3842 *((void**)(calljavamem + 2)) = (void*) builtin_throw_exception;
3844 *((void**)(calljavamem + 4)) = NULL;
3845 *((void**)(calljavamem + 6)) = (void*) (calljavamem + CALL_JAVA_XHANDLER);
3846 *((void**)(calljavamem + 8)) = (void*) (calljavamem + CALL_JAVA_XHANDLER);
3847 *((void**)(calljavamem +10)) = (void*) (calljavamem + CALL_JAVA_ENTRY);
3849 *((void**)(calljavamem + 8)) = NULL;
3850 *((void**)(calljavamem + 9)) = (void*) (calljavamem + CALL_JAVA_XHANDLER);
3851 *((void**)(calljavamem +10)) = (void*) (calljavamem + CALL_JAVA_XHANDLER);
3852 *((void**)(calljavamem +11)) = (void*) (calljavamem + CALL_JAVA_ENTRY);
3855 calljavamem[12] = 1; /* extable size */
3856 calljavamem[13] = 0; /* fltsave */
3857 calljavamem[14] = 0; /* intsave */
3858 calljavamem[15] = 0; /* isleaf */
3859 calljavamem[16] = 0; /* IsSync */
3860 calljavamem[17] = 80; /* frame size */
3861 calljavamem[18] = 0; /* method pointer (NULL) */
3862 calljavamem[19] = 0; /* method pointer (NULL) */
3864 p = calljavamem + CALL_JAVA_ENTRY; /* code generation pointer */
3867 M_LDA (REG_SP, REG_SP, -10*8); /* allocate stackframe */
3868 M_LST (REG_RA, REG_SP, 0); /* save return address */
3870 M_BRS(1); /* compute current program counter */
3871 M_LST (REG_PV, REG_SP, 3*8); /* save procedure vector */
3873 M_LDA (REG_PV, REG_RA, -4*4); /* compute procedure vector */
3874 M_DST (REG_FSS0, REG_SP, 4*8); /* save non JavaABI saved flt regs */
3876 M_DST (REG_FSS1, REG_SP, 5*8);
3877 M_DST (REG_FSS2, REG_SP, 6*8);
3879 M_DST (REG_FSS3, REG_SP, 7*8);
3880 M_DST (REG_FSS4, REG_SP, 8*8);
3882 M_DST (REG_FSS5, REG_SP, 9*8);
3883 M_LST (REG_ARG_0, REG_SP, 2*8); /* save method pointer for compiler */
3885 M_LDA (REG_ITMP1, REG_SP, 2*8); /* pass pointer to methodptr via itmp1*/
3886 M_MOV (REG_ARG_1, REG_ARG_0); /* pass the remaining parameters */
3888 M_MOV (REG_ARG_2, REG_ARG_1);
3889 M_MOV (REG_ARG_3, REG_ARG_2);
3891 M_MOV (REG_ARG_4, REG_ARG_3);
3892 M_ALD (REG_METHODPTR, REG_PV, -80); /* address of asm_call_jit_compiler */
3894 M_AST (REG_METHODPTR, REG_SP, 8); /* store function address */
3895 M_MOV (REG_SP, REG_METHODPTR); /* set method pointer */
3897 M_ALD (REG_PV, REG_METHODPTR, 8); /* method call as in Java */
3898 M_JSR (REG_RA, REG_PV); /* call JIT compiler */
3900 M_NOP; /* delay slot */
3901 M_LDA (REG_PV, REG_RA, -23*4); /* recompute procedure vector */
3905 M_CLR (REG_RESULT); /* clear return value (exception ptr) */
3909 /* calljava_return: */
3910 M_LLD (REG_RA, REG_SP, 0); /* restore return address */
3912 M_LLD (REG_PV, REG_SP, 3*8); /* restore procedure vector */
3913 M_DLD (REG_FSS0, REG_SP, 4*8); /* restore non JavaABI saved flt regs */
3915 M_DLD (REG_FSS1, REG_SP, 5*8);
3916 M_DLD (REG_FSS2, REG_SP, 6*8);
3918 M_DLD (REG_FSS3, REG_SP, 7*8);
3919 M_DLD (REG_FSS4, REG_SP, 8*8);
3921 M_DLD (REG_FSS5, REG_SP, 9*8);
3922 M_RET(REG_RA); /* return */
3924 M_LDA (REG_SP, REG_SP, 10*8); /* deallocate stackframe (delay slot) */
3927 /* calljava_xhandler: */
3929 M_ALD (REG_ITMP3, REG_PV, -72); /* address of builtin_throw_exception */
3931 M_JSR (REG_RA, REG_ITMP3); /* call builtin */
3932 M_MOV (REG_ITMP1, REG_ARG_0); /* pass parameter (delay slot) */
3934 M_BR(-14); /* branch calljava_return */
3935 M_NOP; /* delay slot */
3937 (void) docacheflush((void*)(calljavamem + CALL_JAVA_ENTRY),
3938 (CALL_JAVA_MEM_SIZE - CALL_JAVA_ENTRY) * (int) sizeof(s4));
3942 typedef java_objectheader* (*asm_fptr)(methodinfo*, void*, void*, void*, void*);
3945 java_objectheader *asm_calljavamethod (methodinfo *m, void *arg1, void *arg2,
3946 void *arg3, void *arg4)
3948 java_objectheader *r = ((asm_fptr)(calljavamem + 20))(m, arg1, arg2, arg3, arg4);
3949 return (exceptionptr ? r : NULL);
3953 java_objectheader *asm_calljavafunction (methodinfo *m, void *arg1, void *arg2,
3954 void *arg3, void *arg4)
3956 return ((asm_fptr)(calljavamem + 20))(m, arg1, arg2, arg3, arg4);
3960 void docacheflush(u1 *p, long bytelen)
3962 u1 *e = p + bytelen;
3963 long psize = sysconf(_SC_PAGESIZE);
3964 p -= (long) p & (psize-1);
3965 e += psize - ((((long) e - 1) & (psize-1)) + 1);
3967 mprotect(p, bytelen, PROT_READ|PROT_WRITE|PROT_EXEC);
3972 * These are local overrides for various environment variables in Emacs.
3973 * Please do not remove this and leave it at the end of the file, where
3974 * Emacs will automagically detect them.
3975 * ---------------------------------------------------------------------
3978 * indent-tabs-mode: t