X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fvm%2Fjit%2Fsparc64%2Fcodegen.c;h=87e3084cd7129e77932d72dd1a93b7f164b0ec50;hb=5d22373538ae0e6903b8d3c3be1c1643135d856f;hp=16ddd5c94bffb07f030c2055b578a32c4e7c3153;hpb=746594beeacf27fd1f0357cf23b1a2c091af8ed6;p=cacao.git diff --git a/src/vm/jit/sparc64/codegen.c b/src/vm/jit/sparc64/codegen.c index 16ddd5c94..87e3084cd 100644 --- a/src/vm/jit/sparc64/codegen.c +++ b/src/vm/jit/sparc64/codegen.c @@ -1,9 +1,7 @@ /* src/vm/jit/sparc64/codegen.c - machine code generator for Sparc - Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel, - C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring, - E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, - J. Wenninger, Institut f. Computersprachen - TU Wien + Copyright (C) 1996-2005, 2006, 2007, 2008 + CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO This file is part of CACAO. @@ -22,24 +20,14 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - Contact: cacao@cacaojvm.org - - Authors: Andreas Krall - Reinhard Grafl - Alexander Jordan - - Changes: Edwin Steiner - - $Id: codegen.c 4644 2006-03-16 18:44:46Z edwin $ - */ #include "config.h" -#include #include - +#include +#include #include "vm/types.h" @@ -47,49 +35,100 @@ /* #include "vm/jit/sparc64/arch.h" */ #include "vm/jit/sparc64/codegen.h" +#include "vm/jit/sparc64/emit.h" #include "mm/memory.h" -#include "native/jni.h" +#include "native/localref.h" #include "native/native.h" -#include "vm/builtin.h" -#include "vm/exceptions.h" + +#include "vm/jit/builtin.hpp" +#include "vm/exceptions.hpp" #include "vm/global.h" -#include "vm/loader.h" +#include "vm/loader.hpp" #include "vm/options.h" -#include "vm/stringlocal.h" + +#include "vm/jit/abi.h" #include "vm/jit/asmpart.h" -#include "vm/jit/codegen-common.h" +#include "vm/jit/codegen-common.hpp" #include "vm/jit/dseg.h" -#include "vm/jit/emit-common.h" -#include "vm/jit/jit.h" +#include "vm/jit/emit-common.hpp" +#include "vm/jit/jit.hpp" +#include "vm/jit/linenumbertable.h" #include "vm/jit/parse.h" #include "vm/jit/patcher.h" #include "vm/jit/reg.h" +#include "vm/jit/replace.hpp" +#include "vm/jit/stacktrace.hpp" + +#include "vm/jit/sparc64/solaris/macro_rename.h" + +#define BUILTIN_FLOAT_ARGS 1 /* XXX use something like this for window control ? * #define REG_PV (own_window?REG_PV_CALLEE:REG_PV_CALLER) */ #define REG_PV REG_PV_CALLEE +bool fits_13(s4 disp) +{ + /* + if ((disp < -4096) || (disp > 4095)) + printf("disp %d\n", disp); + */ + + return (disp >= -4096) && (disp <= 4095); +} + +s4 get_lopart_disp(disp) +{ + s4 lodisp; + + if (disp > 0) + lodisp = setlo_part(disp); + else { + if (setlo_part(disp) == 0) + lodisp = 0; + else + lodisp = setlo_part(disp) | 0x1c00; + } + + return lodisp; +} + +#ifndef NDEBUG +bool check_13bit_imm(s8 imm) +{ + s4 sign = (imm >> 12) & 0x1; -/* codegen ********************************************************************* + if (sign == 0) { + if ((imm & ~0xfff) == 0) return true; /* pos imm. */ + } + else + if ((imm & ~0xfff) + 0xfff == -1) return true; /* neg imm. */ + + printf("immediate out-of-bounds: %ld\n", imm); + return false; +} +#endif + + +/* codegen_emit **************************************************************** Generates machine code. *******************************************************************************/ -bool codegen(jitdata *jd) +bool codegen_emit(jitdata *jd) { methodinfo *m; codeinfo *code; codegendata *cd; registerdata *rd; - s4 len, s1, s2, s3, d, disp; + s4 len, s1, s2, s3, d, disp, slots; varinfo *var; basicblock *bptr; instruction *iptr; - exception_entry *ex; u2 currentline; constant_classref *cr; methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */ @@ -98,7 +137,6 @@ bool codegen(jitdata *jd) methoddesc *md; fieldinfo *fi; unresolved_field *uf; - rplpoint *replacementpoint; s4 fieldtype; s4 varindex; @@ -118,12 +156,13 @@ bool codegen(jitdata *jd) { s4 i, p, t, l; - s4 savedregs_num, localbase; + s4 savedregs_num; + s4 framesize_disp; #if 0 /* no leaf optimization yet */ - savedregs_num = (jd->isleafmethod) ? 0 : 1; /* space to save the RA */ + savedregs_num = (code_is_leafmethod(code)) ? 0 : 1; /* space to save the RA */ #endif - savedregs_num = 16; /* register-window save area */ + savedregs_num = WINSAVE_CNT + ABIPARAMS_CNT; /* register-window save area */ /* space to save used callee saved registers */ @@ -134,48 +173,43 @@ bool codegen(jitdata *jd) cd->stackframesize = rd->memuse + savedregs_num; #if defined(ENABLE_THREADS) /* space to save argument of monitor_enter */ - if (checksync && (m->flags & ACC_SYNCHRONIZED)) + if (checksync && code_is_synchronized(code)) cd->stackframesize++; #endif + /* keep stack 16-byte aligned (ABI requirement) */ + + if (cd->stackframesize & 1) + cd->stackframesize++; + /* create method header */ (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */ - (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */ + framesize_disp = dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */ -#if defined(ENABLE_THREADS) - /* IsSync contains the offset relative to the stack pointer for the - argument of monitor_exit used in the exception handler. Since the - offset could be zero and give a wrong meaning of the flag it is - offset by one. - */ + code->synchronizedoffset = JITSTACK + rd->memuse * 8; + + /* REMOVEME: We still need it for exception handling in assembler. */ - if (checksync && (m->flags & ACC_SYNCHRONIZED)) - (void) dseg_add_unique_s4(cd, (rd->memuse + 1) * 8); /* IsSync */ + if (code_is_leafmethod(code)) + (void) dseg_add_unique_s4(cd, 1); else -#endif - (void) dseg_add_unique_s4(cd, 0); /* IsSync */ - - (void) dseg_add_unique_s4(cd, jd->isleafmethod); /* IsLeaf */ + (void) dseg_add_unique_s4(cd, 0); + (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */ (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */ - dseg_addlinenumbertablesize(cd); - (void) dseg_add_unique_s4(cd, jd->exceptiontablelength); /* ExTableSize */ - - /* create exception table */ - - for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) { - dseg_add_target(cd, ex->start); - dseg_add_target(cd, ex->end); - dseg_add_target(cd, ex->handler); - (void) dseg_add_unique_address(cd, ex->catchtype.any); - } /* save register window and create stack frame (if necessary) */ - if (cd->stackframesize) - M_SAVE(REG_SP, -cd->stackframesize * 8, REG_SP); - + if (cd->stackframesize) { + if (cd->stackframesize <= 4095) + M_SAVE(REG_SP, -cd->stackframesize * 8, REG_SP); + else { + M_ILD_INTERN(REG_ITMP3, REG_PV_CALLER, framesize_disp); + M_SUB(REG_ZERO, REG_ITMP3, REG_ITMP3); + M_SAVE_REG(REG_SP, REG_ITMP3, REG_SP); + } + } /* save callee saved float registers (none right now) */ #if 0 @@ -191,27 +225,58 @@ bool codegen(jitdata *jd) #endif - - /* take arguments out of register or stack frame */ - - md = m->parseddesc; + /* call monitorenter function */ +#if defined(ENABLE_THREADS) + if (checksync && code_is_synchronized(code)) { + /* stack offset for monitor argument */ - /* when storing locals, use this as base */ - localbase = USESTACK; - - /* since the register allocator does not know about the shifting window - * arg regs need to be copied via the stack - */ - if (md->argintreguse > 0) { - /* allocate scratch space for copying in to save(i&l) regs */ - M_SUB_IMM(REG_SP, INT_ARG_CNT * 8, REG_SP); - - localbase += INT_ARG_CNT * 8; - - for (p = 0; p < INT_ARG_CNT; p++) - M_STX(REG_WINDOW_TRANSPOSE(rd->argintregs[p]), REG_SP, USESTACK + (p * 8)); + s1 = rd->memuse; + + /* save float argument registers */ + + /* XXX jit-c-call */ + slots = FLT_ARG_CNT; + ALIGN_STACK_SLOTS(slots); + + M_LDA(REG_SP, REG_SP, -(slots * 8)); + for (i = 0; i < FLT_ARG_CNT; i++) + M_DST(abi_registers_float_argument[i], REG_SP, CSTACK + i * 8); + + s1 += slots; + + /* get correct lock object */ + + if (m->flags & ACC_STATIC) { + disp = dseg_add_address(cd, &m->clazz->object.header); + M_ALD(REG_OUT0, REG_PV, disp); + disp = dseg_add_functionptr(cd, LOCK_monitor_enter); + M_ALD(REG_ITMP3, REG_PV, disp); + } + else { + /* copy class pointer: $i0 -> $o0 */ + M_MOV(REG_RESULT_CALLEE, REG_OUT0); + M_BNEZ(REG_OUT0, 3); + disp = dseg_add_functionptr(cd, LOCK_monitor_enter); + M_ALD(REG_ITMP3, REG_PV, disp); /* branch delay */ + M_ALD_INTERN(REG_ZERO, REG_ZERO, TRAP_NullPointerException); + } + + M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO); + M_AST(REG_OUT0, REG_SP, CSTACK + s1 * 8); /* branch delay */ + + /* restore float argument registers */ + + for (i = 0; i < FLT_ARG_CNT; i++) + M_DLD(abi_registers_float_argument[i], REG_SP, CSTACK + i * 8); + + M_LDA(REG_SP, REG_SP, slots * 8); } +#endif + + + /* take arguments out of register or stack frame */ + md = m->parseddesc; for (p = 0, l = 0; p < md->paramcount; p++) { t = md->paramtypes[p].type; @@ -226,71 +291,96 @@ bool codegen(jitdata *jd) continue; var = VAR(varindex); + s1 = md->params[p].regoff; + + if (IS_INT_LNG_TYPE(t)) { /* integer args */ - s1 = md->params[p].regoff; - if (IS_INT_LNG_TYPE(t)) { /* integer args */ + s2 = var->vv.regoff; + if (!md->params[p].inmemory) { /* register arguments */ - /*s2 = rd->argintregs[s1];*/ - /*s2 = REG_WINDOW_TRANSPOSE(s2);*/ + s1 = REG_WINDOW_TRANSPOSE(s1); + if (!(var->flags & INMEMORY)) { /* reg arg -> register */ - /*M_INTMOVE(s2, var->vv.regoff);*/ - M_LDX(var->vv.regoff, REG_SP, USESTACK + (s1 * 8)); - } else { /* reg arg -> spilled */ - /*M_STX(s2, REG_SP, (WINSAVE_CNT + var->vv.regoff) * 8);*/ - - M_LDX(REG_ITMP1, REG_SP, USESTACK + (s1 * 8)); - M_STX(REG_ITMP1, REG_SP, localbase + (var->vv.regoff * 8)); + /* the register allocator does not know about the window. */ + /* avoid copying the locals from save to save regs by */ + /* swapping variables. */ + + { + int old_dest = var->vv.regoff; + int new_dest = p + 24; + + /* run through all variables */ + + for (i = 0; i < jd->varcount; i++) { + varinfo* uvar = VAR(i); + + if (IS_FLT_DBL_TYPE(uvar->type) || IS_INMEMORY(uvar->flags)) + continue; + + s2 = uvar->vv.regoff; + + /* free the in reg by moving all other references */ + + if (s2 == new_dest) { + uvar->vv.regoff = old_dest; + /*printf("p%d-var[%d]: moved %d -> %d (to free save reg)\n", p, i, s2, old_dest);*/ + } + + /* move all variables to the in reg */ + + if (s2 == old_dest) { + uvar->vv.regoff = new_dest; + /*printf("p%d-var[%d]: moved %d -> %d (to avoid copy)\n", p, i, s2, new_dest);*/ + } + } + } + + + + } + else { /* reg arg -> spilled */ + M_STX(s1, REG_SP, JITSTACK + var->vv.regoff); } } else { /* stack arguments */ if (!(var->flags & INMEMORY)) { /* stack arg -> register */ - M_LDX(var->vv.regoff, REG_FP, (WINSAVE_CNT + s1) * 8); + M_LDX(var->vv.regoff, REG_FP, JITSTACK + s1); } else { /* stack arg -> spilled */ - assert(0); /* XXX winsave area in between */ - var->vv.regoff = cd->stackframesize + s1; + /* add the callers window save registers */ + var->vv.regoff = cd->stackframesize * 8 + s1; } } } else { /* floating args */ if (!md->params[p].inmemory) { /* register arguments */ - s2 = rd->argfltregs[s1]; if (!(var->flags & INMEMORY)) { /* reg arg -> register */ - M_FLTMOVE(s2, var->vv.regoff); + M_FLTMOVE(s1, var->vv.regoff); } else { /* reg arg -> spilled */ - M_DST(s2, REG_SP, localbase + (var->vv.regoff) * 8); + M_DST(s1, REG_SP, JITSTACK + var->vv.regoff); } } else { /* stack arguments */ if (!(var->flags & INMEMORY)) { /* stack-arg -> register */ - M_DLD(var->vv.regoff, REG_FP, (WINSAVE_CNT + s1) * 8); + M_DLD(var->vv.regoff, REG_FP, JITSTACK + s1); } else { /* stack-arg -> spilled */ - assert(0); /* XXX winsave area in between */ - var->vv.regoff = cd->stackframesize + s1; + var->vv.regoff = cd->stackframesize * 8 + s1; } } } } /* end for */ - if (md->argintreguse > 0) { - /* release scratch space */ - M_ADD_IMM(REG_SP, INT_ARG_CNT * 8, REG_SP); - } - - - /* XXX monitor enter */ - - - } /* end of header generation */ - replacementpoint = jd->code->rplpoints; + /* create replacement points */ + + REPLACEMENT_POINTS_INIT(cd, jd); /* walk through all basic blocks */ @@ -306,13 +396,8 @@ bool codegen(jitdata *jd) /* handle replacement points */ -#if 0 - if (bptr->bitflags & BBFLAG_REPLACEMENT) { - replacementpoint->pc = (u1*)(ptrint)bptr->mpc; /* will be resolved later */ - - replacementpoint++; - } -#endif + REPLACEMENT_POINT_BLOCK_START(cd, bptr); + /* copy interface registers to their destination */ @@ -320,6 +405,7 @@ bool codegen(jitdata *jd) MCODECHECK(64+len); #if defined(ENABLE_LSRA) +#error XXX LSRA not tested yet if (opt_lsra) { while (len) { len--; @@ -337,17 +423,17 @@ bool codegen(jitdata *jd) } else { #endif while (len) { - len--; + len--; var = VAR(bptr->invars[len]); if ((len == bptr->indepth-1) && (bptr->type == BBTYPE_EXH)) { d = codegen_reg_of_var(0, var, REG_ITMP1); - M_INTMOVE(REG_ITMP1, d); + M_INTMOVE(REG_ITMP2_XPTR, d); emit_store(jd, NULL, var, d); - } + } else { assert((var->flags & INOUT)); - } - } + } + } #if defined(ENABLE_LSRA) } #endif @@ -357,11 +443,12 @@ bool codegen(jitdata *jd) for (iptr = bptr->iinstr; len > 0; len--, iptr++) { if (iptr->line != currentline) { - dseg_addlinenumber(cd, iptr->line); + linenumbertable_list_entry_add(cd, iptr->line); currentline = iptr->line; } MCODECHECK(64); /* an instruction usually needs < 64 words */ + switch (iptr->opc) { case ICMD_INLINE_START: @@ -370,6 +457,12 @@ bool codegen(jitdata *jd) case ICMD_NOP: /* ... ==> ... */ break; + + case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + emit_nullpointer_check(cd, iptr, s1); + break; /* constant operations ************************************************/ @@ -432,23 +525,23 @@ bool codegen(jitdata *jd) /* load/store/copy/move operations ************************************/ case ICMD_ILOAD: /* ... ==> ..., content of local variable */ - case ICMD_LLOAD: /* ... ==> ..., content of local variable */ - case ICMD_ALOAD: /* ... ==> ..., content of local variable */ - case ICMD_FLOAD: /* ... ==> ..., content of local variable */ - case ICMD_DLOAD: /* ... ==> ..., content of local variable */ + case ICMD_LLOAD: + case ICMD_ALOAD: + case ICMD_FLOAD: + case ICMD_DLOAD: case ICMD_ISTORE: /* ..., value ==> ... */ - case ICMD_LSTORE: /* ..., value ==> ... */ - case ICMD_FSTORE: /* ..., value ==> ... */ - case ICMD_DSTORE: /* ..., value ==> ... */ + case ICMD_LSTORE: + case ICMD_FSTORE: + case ICMD_DSTORE: case ICMD_COPY: case ICMD_MOVE: - emit_copy(jd, iptr, VAROP(iptr->s1), VAROP(iptr->dst)); + emit_copy(jd, iptr); break; case ICMD_ASTORE: if (!(iptr->flags.bits & INS_FLAG_RETADDR)) - emit_copy(jd, iptr, VAROP(iptr->s1), VAROP(iptr->dst)); + emit_copy(jd, iptr); break; @@ -498,7 +591,15 @@ bool codegen(jitdata *jd) break; case ICMD_INT2CHAR: /* ..., value ==> ..., value */ - case ICMD_INT2SHORT: + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); + M_SLLX_IMM(s1, 48, d); + M_SRLX_IMM( d, 48, d); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_INT2SHORT: /* ..., value ==> ..., value */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); @@ -627,7 +728,7 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); - gen_div_check(s2); + emit_arithmetic_check(cd, iptr, s2); M_ISEXT(s1, s1); /* XXX trim s2 like s1 ? */ M_DIVX(s1, s2, d); @@ -639,7 +740,7 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); - gen_div_check(s2); + emit_arithmetic_check(cd, iptr, s2); M_DIVX(s1, s2, d); emit_store_dst(jd, iptr, d); break; @@ -649,12 +750,12 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); d = codegen_reg_of_dst(jd, iptr, REG_ITMP3); - gen_div_check(s2); + emit_arithmetic_check(cd, iptr, s2); M_ISEXT(s1, s1); /* XXX trim s2 like s1 ? */ - M_DIVX(s1, s2, d); - M_MULX(s2, d, d); - M_SUB(s1, d, d); + M_DIVX(s1, s2, REG_ITMP3); + M_MULX(s2, REG_ITMP3, REG_ITMP3); + M_SUB(s1, REG_ITMP3, d); emit_store_dst(jd, iptr, d); break; @@ -663,10 +764,10 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); d = codegen_reg_of_dst(jd, iptr, REG_ITMP3); - gen_div_check(s2); - M_DIVX(s1, s2, d); - M_MULX(s2, d, d); - M_SUB(s1, d, d); + emit_arithmetic_check(cd, iptr, s2); + M_DIVX(s1, s2, REG_ITMP3); + M_MULX(s2, REG_ITMP3, REG_ITMP3); + M_SUB(s1, REG_ITMP3, d); emit_store_dst(jd, iptr, d); break; @@ -683,7 +784,15 @@ bool codegen(jitdata *jd) break; case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */ - case ICMD_LSHL: + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s2 = emit_load_s2(jd, iptr, REG_ITMP2); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); + M_SLL(s1, s2, d); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); @@ -693,7 +802,16 @@ bool codegen(jitdata *jd) break; case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */ - case ICMD_LSHLCONST: /* val.i = constant */ + /* val.i = constant */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); + M_SLL_IMM(s1, iptr->sx.val.i, d); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */ + /* val.i = constant */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); @@ -797,26 +915,27 @@ bool codegen(jitdata *jd) emit_store_dst(jd, iptr, d); break; - case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */ + case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */ /* sx.val.i = constant */ + /* constant is actually constant - 1 */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); - M_ISEXT(s1, s1); /* trim for 32-bit compare (BGEZ) */ if (s1 == d) { M_MOV(s1, REG_ITMP1); s1 = REG_ITMP1; } - if ((iptr->sx.val.i >= 0) && (iptr->sx.val.i <= 0xffff)) { + M_ISEXT(s1, s1); /* trim for 32-bit compare (BGEZ) */ + if ((iptr->sx.val.i >= 0) && (iptr->sx.val.i <= 4095)) { M_AND_IMM(s1, iptr->sx.val.i, d); - M_BGEZ(s1, 4); + M_BGEZ(s1, 5); M_NOP; M_SUB(REG_ZERO, s1, d); M_AND_IMM(d, iptr->sx.val.i, d); } else { ICONST(REG_ITMP2, iptr->sx.val.i); M_AND(s1, REG_ITMP2, d); - M_BGEZ(s1, 4); + M_BGEZ(s1, 5); M_NOP; M_SUB(REG_ZERO, s1, d); M_AND(d, REG_ITMP2, d); @@ -1049,7 +1168,7 @@ bool codegen(jitdata *jd) case ICMD_I2F: s1 = emit_load_s1(jd, iptr, REG_ITMP1); d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); - disp = dseg_add_float(cd, 0.0); + disp = dseg_add_unique_float(cd, 0.0); M_IST (s1, REG_PV_CALLEE, disp); M_FLD (d, REG_PV_CALLEE, disp); M_CVTIF (d, d); /* rd gets translated to double target register */ @@ -1059,17 +1178,43 @@ bool codegen(jitdata *jd) case ICMD_I2D: s1 = emit_load_s1(jd, iptr, REG_ITMP1); d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); - disp = dseg_add_float(cd, 0.0); - M_IST (s1, REG_PV_CALLEE, disp); - M_FLD (REG_FTMP2, REG_PV_CALLEE, disp); /* REG_FTMP2 needs to be a double temp */ + disp = dseg_add_unique_float(cd, 0.0); + M_IST(s1, REG_PV_CALLEE, disp); + M_FLD(REG_FTMP2, REG_PV_CALLEE, disp); /* REG_FTMP2 needs to be a double temp */ M_CVTID (REG_FTMP2, d); /* rd gets translated to double target register */ emit_store_dst(jd, iptr, d); break; + + case ICMD_L2F: + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); + disp = dseg_add_unique_double(cd, 0.0); + M_STX(s1, REG_PV_CALLEE, disp); + M_DLD(REG_FTMP3, REG_PV_CALLEE, disp); + M_CVTLF(REG_FTMP3, d); + emit_store_dst(jd, iptr, d); + break; + + case ICMD_L2D: + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); + disp = dseg_add_unique_double(cd, 0.0); + M_STX(s1, REG_PV_CALLEE, disp); + M_DLD(d, REG_PV_CALLEE, disp); + M_CVTLD(d, d); + emit_store_dst(jd, iptr, d); + break; case ICMD_F2I: /* ..., value ==> ..., (int) value */ s1 = emit_load_s1(jd, iptr, REG_FTMP1); d = codegen_reg_of_dst(jd, iptr, REG_ITMP3); - disp = dseg_add_float(cd, 0.0); + disp = dseg_add_unique_float(cd, 0.0); + + /* check for NaN, SPARC overflow is noncompliant (see V9 spec B.5) */ + M_FCMP(s1, s1); + M_FBU(5); + M_MOV(REG_ZERO, d); /* delay slot */ + M_CVTFI(s1, REG_FTMP2); M_FST(REG_FTMP2, REG_PV_CALLEE, disp); M_ILD(d, REG_PV, disp); @@ -1080,7 +1225,13 @@ bool codegen(jitdata *jd) case ICMD_D2I: /* ..., value ==> ..., (int) value */ s1 = emit_load_s1(jd, iptr, REG_FTMP1); d = codegen_reg_of_dst(jd, iptr, REG_ITMP3); - disp = dseg_add_float(cd, 0.0); + disp = dseg_add_unique_float(cd, 0.0); + + /* check for NaN, SPARC overflow is noncompliant (see V9 spec B.5) */ + M_DCMP(s1, s1); + M_FBU(5); + M_MOV(REG_ZERO, d); /* delay slot */ + M_CVTDI(s1, REG_FTMP2); M_FST(REG_FTMP2, REG_PV, disp); M_ILD(d, REG_PV, disp); @@ -1090,7 +1241,13 @@ bool codegen(jitdata *jd) case ICMD_F2L: /* ..., value ==> ..., (long) value */ s1 = emit_load_s1(jd, iptr, REG_FTMP1); d = codegen_reg_of_dst(jd, iptr, REG_ITMP3); - disp = dseg_add_double(cd, 0.0); + disp = dseg_add_unique_double(cd, 0.0); + + /* check for NaN, SPARC overflow is noncompliant (see V9 spec B.5) */ + M_FCMP(s1, s1); + M_FBU(5); + M_MOV(REG_ZERO, d); /* delay slot */ + M_CVTFL(s1, REG_FTMP2); /* FTMP2 needs to be double reg */ M_DST(REG_FTMP2, REG_PV, disp); M_LDX(d, REG_PV, disp); @@ -1100,7 +1257,13 @@ bool codegen(jitdata *jd) case ICMD_D2L: /* ..., value ==> ..., (long) value */ s1 = emit_load_s1(jd, iptr, REG_FTMP1); d = codegen_reg_of_dst(jd, iptr, REG_ITMP3); - disp = dseg_add_double(cd, 0.0); + disp = dseg_add_unique_double(cd, 0.0); + + /* check for NaN, SPARC overflow is noncompliant (see V9 spec B.5) */ + M_DCMP(s1, s1); + M_FBU(5); + M_MOV(REG_ZERO, d); /* delay slot */ + M_CVTDL(s1, REG_FTMP2); /* FTMP2 needs to be double reg */ M_DST(REG_FTMP2, REG_PV, disp); M_LDX(d, REG_PV, disp); @@ -1130,9 +1293,9 @@ bool codegen(jitdata *jd) s2 = emit_load_s2(jd, iptr, REG_FTMP2); d = codegen_reg_of_dst(jd, iptr, REG_ITMP3); M_FCMP(s1,s2); - M_OR_IMM(REG_ZERO, -1, REG_ITMP3); /* less by default (less or unordered) */ - M_CMOVFEQ_IMM(0, REG_ITMP3); /* 0 if equal */ - M_CMOVFGT_IMM(1, REG_ITMP3); /* 1 if greater */ + M_OR_IMM(REG_ZERO, -1, d); /* less by default (less or unordered) */ + M_CMOVFEQ_IMM(0, d); /* 0 if equal */ + M_CMOVFGT_IMM(1, d); /* 1 if greater */ emit_store_dst(jd, iptr, d); break; @@ -1142,9 +1305,9 @@ bool codegen(jitdata *jd) s2 = emit_load_s2(jd, iptr, REG_FTMP2); d = codegen_reg_of_dst(jd, iptr, REG_ITMP3); M_DCMP(s1,s2); - M_OR_IMM(REG_ZERO, -1, REG_ITMP3); /* less by default (less or unordered) */ - M_CMOVFEQ_IMM(0, REG_ITMP3); /* 0 if equal */ - M_CMOVFGT_IMM(1, REG_ITMP3); /* 1 if greater */ + M_OR_IMM(REG_ZERO, -1, d); /* less by default (less or unordered) */ + M_CMOVFEQ_IMM(0, d); /* 0 if equal */ + M_CMOVFGT_IMM(1, d); /* 1 if greater */ emit_store_dst(jd, iptr, d); break; @@ -1154,9 +1317,9 @@ bool codegen(jitdata *jd) s2 = emit_load_s2(jd, iptr, REG_FTMP2); d = codegen_reg_of_dst(jd, iptr, REG_ITMP3); M_FCMP(s1,s2); - M_OR_IMM(REG_ZERO, 1, REG_ITMP3); /* greater by default (greater or unordered) */ - M_CMOVFEQ_IMM(0, REG_ITMP3); /* 0 if equal */ - M_CMOVFLT_IMM(-1, REG_ITMP3); /* -1 if less */ + M_OR_IMM(REG_ZERO, 1, d); /* greater by default (greater or unordered) */ + M_CMOVFEQ_IMM(0, d); /* 0 if equal */ + M_CMOVFLT_IMM(-1, d); /* -1 if less */ emit_store_dst(jd, iptr, d); break; @@ -1166,9 +1329,9 @@ bool codegen(jitdata *jd) s2 = emit_load_s2(jd, iptr, REG_FTMP2); d = codegen_reg_of_dst(jd, iptr, REG_ITMP3); M_DCMP(s1,s2); - M_OR_IMM(REG_ZERO, 1, REG_ITMP3); /* greater by default (greater or unordered) */ - M_CMOVFEQ_IMM(0, REG_ITMP3); /* 0 if equal */ - M_CMOVFLT_IMM(-1, REG_ITMP3); /* -1 if less */ + M_OR_IMM(REG_ZERO, 1, d); /* greater by default (greater or unordered) */ + M_CMOVFEQ_IMM(0, d); /* 0 if equal */ + M_CMOVFLT_IMM(-1, d); /* -1 if less */ emit_store_dst(jd, iptr, d); break; @@ -1179,8 +1342,8 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); - gen_nullptr_check(s1); - M_ILD(d, s1, OFFSET(java_arrayheader, size)); + emit_nullpointer_check(cd, iptr, s1); + M_ILD(d, s1, OFFSET(java_array_t, size)); emit_store_dst(jd, iptr, d); break; @@ -1189,12 +1352,10 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); - if (INSTRUCTION_MUST_CHECK(iptr)) { - gen_nullptr_check(s1); - gen_bound_check; - } + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); M_AADD(s2, s1, REG_ITMP3); - M_BLDS(d, REG_ITMP3, OFFSET(java_chararray, data[0])); + M_BLDS(d, REG_ITMP3, OFFSET(java_bytearray_t, data[0])); emit_store_dst(jd, iptr, d); break; @@ -1203,13 +1364,11 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); - if (INSTRUCTION_MUST_CHECK(iptr)) { - gen_nullptr_check(s1); - gen_bound_check; - } + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); M_AADD(s2, s1, REG_ITMP3); M_AADD(s2, REG_ITMP3, REG_ITMP3); - M_SLDU(d, REG_ITMP3, OFFSET(java_chararray, data[0])); + M_SLDU(d, REG_ITMP3, OFFSET(java_chararray_t, data[0])); emit_store_dst(jd, iptr, d); break; @@ -1218,13 +1377,11 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); - if (INSTRUCTION_MUST_CHECK(iptr)) { - gen_nullptr_check(s1); - gen_bound_check; - } + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); M_AADD(s2, s1, REG_ITMP3); M_AADD(s2, REG_ITMP3, REG_ITMP3); - M_SLDS(d, REG_ITMP3, OFFSET(java_chararray, data[0])); + M_SLDS(d, REG_ITMP3, OFFSET(java_shortarray_t, data[0])); emit_store_dst(jd, iptr, d); break; @@ -1233,13 +1390,11 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); - if (INSTRUCTION_MUST_CHECK(iptr)) { - gen_nullptr_check(s1); - gen_bound_check; - } + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); M_ASLL_IMM(s2, 2, REG_ITMP3); M_AADD(REG_ITMP3, s1, REG_ITMP3); - M_ILD(d, REG_ITMP3, OFFSET(java_intarray, data[0])); + M_ILD(d, REG_ITMP3, OFFSET(java_intarray_t, data[0])); emit_store_dst(jd, iptr, d); break; @@ -1248,13 +1403,11 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); - if (INSTRUCTION_MUST_CHECK(iptr)) { - gen_nullptr_check(s1); - gen_bound_check; - } + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); M_ASLL_IMM(s2, 3, REG_ITMP3); M_AADD(REG_ITMP3, s1, REG_ITMP3); - M_LDX(d, REG_ITMP3, OFFSET(java_longarray, data[0])); + M_LDX(d, REG_ITMP3, OFFSET(java_longarray_t, data[0])); emit_store_dst(jd, iptr, d); break; @@ -1263,13 +1416,11 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); - if (INSTRUCTION_MUST_CHECK(iptr)) { - gen_nullptr_check(s1); - gen_bound_check; - } + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); M_ASLL_IMM(s2, 2, REG_ITMP3); M_AADD(REG_ITMP3, s1, REG_ITMP3); - M_FLD(d, REG_ITMP3, OFFSET(java_floatarray, data[0])); + M_FLD(d, REG_ITMP3, OFFSET(java_floatarray_t, data[0])); emit_store_dst(jd, iptr, d); break; @@ -1278,13 +1429,11 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); - if (INSTRUCTION_MUST_CHECK(iptr)) { - gen_nullptr_check(s1); - gen_bound_check; - } + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); M_ASLL_IMM(s2, 3, REG_ITMP3); M_AADD(REG_ITMP3, s1, REG_ITMP3); - M_DLD(d, REG_ITMP3, OFFSET(java_doublearray, data[0])); + M_DLD(d, REG_ITMP3, OFFSET(java_doublearray_t, data[0])); emit_store_dst(jd, iptr, d); break; @@ -1293,13 +1442,11 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); - if (INSTRUCTION_MUST_CHECK(iptr)) { - gen_nullptr_check(s1); - gen_bound_check; - } + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP3); M_AADD(REG_ITMP3, s1, REG_ITMP3); - M_ALD(d, REG_ITMP3, OFFSET(java_objectarray, data[0])); + M_ALD(d, REG_ITMP3, OFFSET(java_objectarray_t, data[0])); emit_store_dst(jd, iptr, d); break; @@ -1308,13 +1455,11 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); - if (INSTRUCTION_MUST_CHECK(iptr)) { - gen_nullptr_check(s1); - gen_bound_check; - } + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); M_AADD(s2, s1, REG_ITMP1); s3 = emit_load_s3(jd, iptr, REG_ITMP3); - M_BST(s3, REG_ITMP1, OFFSET(java_bytearray, data[0])); + M_BST(s3, REG_ITMP1, OFFSET(java_bytearray_t, data[0])); break; case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */ @@ -1322,70 +1467,60 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); - if (INSTRUCTION_MUST_CHECK(iptr)) { - gen_nullptr_check(s1); - gen_bound_check; - } + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); M_AADD(s2, s1, REG_ITMP1); M_AADD(s2, REG_ITMP1, REG_ITMP1); s3 = emit_load_s3(jd, iptr, REG_ITMP3); - M_SST(s3, REG_ITMP1, OFFSET(java_chararray, data[0])); + M_SST(s3, REG_ITMP1, OFFSET(java_chararray_t, data[0])); break; case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); - if (INSTRUCTION_MUST_CHECK(iptr)) { - gen_nullptr_check(s1); - gen_bound_check; - } + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); M_ASLL_IMM(s2, 2, REG_ITMP2); M_AADD(REG_ITMP2, s1, REG_ITMP1); s3 = emit_load_s3(jd, iptr, REG_ITMP3); - M_IST_INTERN(s3, REG_ITMP1, OFFSET(java_intarray, data[0])); + M_IST_INTERN(s3, REG_ITMP1, OFFSET(java_intarray_t, data[0])); break; case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); - if (INSTRUCTION_MUST_CHECK(iptr)) { - gen_nullptr_check(s1); - gen_bound_check; - } + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); M_ASLL_IMM(s2, 3, REG_ITMP2); M_AADD(REG_ITMP2, s1, REG_ITMP1); s3 = emit_load_s3(jd, iptr, REG_ITMP3); - M_STX_INTERN(s3, REG_ITMP1, OFFSET(java_longarray, data[0])); + M_STX_INTERN(s3, REG_ITMP1, OFFSET(java_longarray_t, data[0])); break; case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); - if (INSTRUCTION_MUST_CHECK(iptr)) { - gen_nullptr_check(s1); - gen_bound_check; - } + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); M_ASLL_IMM(s2, 2, REG_ITMP2); M_AADD(REG_ITMP2, s1, REG_ITMP1); s3 = emit_load_s3(jd, iptr, REG_FTMP1); - M_FST_INTERN(s3, REG_ITMP1, OFFSET(java_floatarray, data[0])); + M_FST_INTERN(s3, REG_ITMP1, OFFSET(java_floatarray_t, data[0])); break; case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); - if (INSTRUCTION_MUST_CHECK(iptr)) { - gen_nullptr_check(s1); - gen_bound_check; - } + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); M_ASLL_IMM(s2, 3, REG_ITMP2); M_AADD(REG_ITMP2, s1, REG_ITMP1); s3 = emit_load_s3(jd, iptr, REG_FTMP1); - M_DST_INTERN(s3, REG_ITMP1, OFFSET(java_doublearray, data[0])); + M_DST_INTERN(s3, REG_ITMP1, OFFSET(java_doublearray_t, data[0])); break; @@ -1393,29 +1528,25 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); - if (INSTRUCTION_MUST_CHECK(iptr)) { - gen_nullptr_check(s1); - gen_bound_check; - } + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); s3 = emit_load_s3(jd, iptr, REG_ITMP3); - M_MOV(s1, rd->argintregs[0]); - M_MOV(s3, rd->argintregs[1]); - disp = dseg_add_functionptr(cd, BUILTIN_canstore); + M_MOV(s1, REG_OUT0); + M_MOV(s3, REG_OUT1); + disp = dseg_add_functionptr(cd, BUILTIN_FAST_canstore); M_ALD(REG_ITMP3, REG_PV, disp); M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO); M_NOP; - - M_BEQZ(REG_RESULT_CALLER, 0); - codegen_add_arraystoreexception_ref(cd); - M_NOP; + emit_arraystore_check(cd, iptr); s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2); M_AADD(REG_ITMP2, s1, REG_ITMP1); s3 = emit_load_s3(jd, iptr, REG_ITMP3); - M_AST_INTERN(s3, REG_ITMP1, OFFSET(java_objectarray, data[0])); + /* implicit null-pointer check */ + M_AST_INTERN(s3, REG_ITMP1, OFFSET(java_objectarray_t, data[0])); break; @@ -1423,12 +1554,10 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); - if (INSTRUCTION_MUST_CHECK(iptr)) { - gen_nullptr_check(s1); - gen_bound_check; - } + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); M_AADD(s2, s1, REG_ITMP1); - M_BST(REG_ZERO, REG_ITMP1, OFFSET(java_bytearray, data[0])); + M_BST(REG_ZERO, REG_ITMP1, OFFSET(java_bytearray_t, data[0])); break; case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */ @@ -1436,71 +1565,63 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); - if (INSTRUCTION_MUST_CHECK(iptr)) { - gen_nullptr_check(s1); - gen_bound_check; - } + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); M_AADD(s2, s1, REG_ITMP1); M_AADD(s2, REG_ITMP1, REG_ITMP1); - M_SST(REG_ZERO, REG_ITMP1, OFFSET(java_chararray, data[0])); + M_SST(REG_ZERO, REG_ITMP1, OFFSET(java_chararray_t, data[0])); break; case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); - if (INSTRUCTION_MUST_CHECK(iptr)) { - gen_nullptr_check(s1); - gen_bound_check; - } + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); M_ASLL_IMM(s2, 2, REG_ITMP2); M_AADD(REG_ITMP2, s1, REG_ITMP1); - M_IST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_intarray, data[0])); + M_IST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_intarray_t, data[0])); break; case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); - if (INSTRUCTION_MUST_CHECK(iptr)) { - gen_nullptr_check(s1); - gen_bound_check; - } + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); M_ASLL_IMM(s2, 3, REG_ITMP2); M_AADD(REG_ITMP2, s1, REG_ITMP1); - M_STX_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_longarray, data[0])); + M_STX_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_longarray_t, data[0])); break; case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); - if (INSTRUCTION_MUST_CHECK(iptr)) { - gen_nullptr_check(s1); - gen_bound_check; - } + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2); M_AADD(REG_ITMP2, s1, REG_ITMP1); - M_AST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_objectarray, data[0])); + M_AST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_objectarray_t, data[0])); break; case ICMD_GETSTATIC: /* ... ==> ..., value */ if (INSTRUCTION_IS_UNRESOLVED(iptr)) { - uf = iptr->sx.s23.s3.uf; + uf = iptr->sx.s23.s3.uf; fieldtype = uf->fieldref->parseddesc.fd->type; disp = dseg_add_unique_address(cd, uf); codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp); } else { - fi = iptr->sx.s23.s3.fmiref->p.field; + fi = iptr->sx.s23.s3.fmiref->p.field; fieldtype = fi->type; - disp = dseg_add_address(cd, &(fi->value)); + disp = dseg_add_address(cd, fi->value); - if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) - codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, disp); + if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz)) + codegen_add_patch_ref(cd, PATCHER_clinit, fi->clazz, disp); } M_ALD(REG_ITMP1, REG_PV, disp); @@ -1533,19 +1654,19 @@ bool codegen(jitdata *jd) case ICMD_PUTSTATIC: /* ..., value ==> ... */ if (INSTRUCTION_IS_UNRESOLVED(iptr)) { - uf = iptr->sx.s23.s3.uf; + uf = iptr->sx.s23.s3.uf; fieldtype = uf->fieldref->parseddesc.fd->type; disp = dseg_add_unique_address(cd, uf); codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp); } else { - fi = iptr->sx.s23.s3.fmiref->p.field; + fi = iptr->sx.s23.s3.fmiref->p.field; fieldtype = fi->type; - disp = dseg_add_address(cd, &(fi->value)); + disp = dseg_add_address(cd, fi->value); - if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) - codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, disp); + if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz)) + codegen_add_patch_ref(cd, PATCHER_clinit, fi->clazz, disp); } M_ALD(REG_ITMP1, REG_PV, disp); @@ -1581,17 +1702,17 @@ bool codegen(jitdata *jd) if (INSTRUCTION_IS_UNRESOLVED(iptr)) { uf = iptr->sx.s23.s3.uf; fieldtype = uf->fieldref->parseddesc.fd->type; - disp = dseg_add_unique_address(cd, uf); + disp = dseg_add_unique_address(cd, uf); codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp); } else { fi = iptr->sx.s23.s3.fmiref->p.field; fieldtype = fi->type; - disp = dseg_add_address(cd, &(fi->value)); + disp = dseg_add_address(cd, fi->value); - if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) - codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, disp); + if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz)) + codegen_add_patch_ref(cd, PATCHER_clinit, fi->clazz, disp); } M_ALD(REG_ITMP1, REG_PV, disp); @@ -1619,7 +1740,7 @@ bool codegen(jitdata *jd) case ICMD_GETFIELD: /* ... ==> ..., value */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); - gen_nullptr_check(s1); + emit_nullpointer_check(cd, iptr, s1); if (INSTRUCTION_IS_UNRESOLVED(iptr)) { uf = iptr->sx.s23.s3.uf; @@ -1666,7 +1787,7 @@ bool codegen(jitdata *jd) case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); - gen_nullptr_check(s1); + emit_nullpointer_check(cd, iptr, s1); if (INSTRUCTION_IS_UNRESOLVED(iptr)) { uf = iptr->sx.s23.s3.uf; @@ -1715,7 +1836,7 @@ bool codegen(jitdata *jd) /* following NOP) */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); - gen_nullptr_check(s1); + emit_nullpointer_check(cd, iptr, s1); if (INSTRUCTION_IS_UNRESOLVED(iptr)) { unresolved_field *uf = iptr->sx.s23.s3.uf; @@ -1770,18 +1891,15 @@ bool codegen(jitdata *jd) #ifdef ENABLE_VERIFIER if (INSTRUCTION_IS_UNRESOLVED(iptr)) { - codegen_addpatchref(cd, PATCHER_athrow_areturn, - iptr->sx.s23.s2.uc, 0); + unresolved_class *uc = iptr->sx.s23.s2.uc; - if (opt_showdisassemble) { - M_NOP; M_NOP; - } + codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0); } #endif /* ENABLE_VERIFIER */ disp = dseg_add_functionptr(cd, asm_handle_exception); - M_ALD(REG_ITMP2, REG_PV, disp); - M_JMP(REG_ITMP3_XPC, REG_ITMP2, REG_ZERO); + M_ALD(REG_ITMP1, REG_PV, disp); + M_JMP(REG_ITMP3_XPC, REG_ITMP1, REG_ZERO); M_NOP; M_NOP; /* nop ensures that XPC is less than the end */ /* of basic block */ @@ -1791,158 +1909,115 @@ bool codegen(jitdata *jd) case ICMD_GOTO: /* ... ==> ... */ case ICMD_RET: /* ... ==> ... */ - M_BR(0); - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; + emit_br(cd, iptr->dst.block); ALIGNCODENOP; break; case ICMD_JSR: /* ... ==> ... */ - M_BR(0); - codegen_add_branch_ref(cd, iptr->sx.s23.s3.jsrtarget.block); - M_NOP; + emit_br(cd, iptr->sx.s23.s3.jsrtarget.block); ALIGNCODENOP; break; case ICMD_IFNULL: /* ..., value ==> ... */ + case ICMD_IFNONNULL: s1 = emit_load_s1(jd, iptr, REG_ITMP1); - M_BEQZ(s1, 0); - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; - break; - - case ICMD_IFNONNULL: /* ..., value ==> ... */ - - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - M_BNEZ(s1, 0); - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; + emit_bccz(cd, iptr->dst.block, iptr->opc - ICMD_IFNULL, s1, BRANCH_OPT_NONE); break; + + /* Note: int compares must not branch on the register directly. */ + /* Reason is, that register content is not 32-bit clean. */ case ICMD_IFEQ: /* ..., value ==> ... */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); - if (iptr->sx.val.i == 0) { - M_BEQZ(s1, 0); - } else { - if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) { - M_CMP_IMM(s1, iptr->sx.val.i); - } - else { - ICONST(REG_ITMP2, iptr->sx.val.i); - M_CMP(s1, REG_ITMP2); - } - M_BEQ(0); - } - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; + + if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) { + M_CMP_IMM(s1, iptr->sx.val.i); + } + else { + ICONST(REG_ITMP2, iptr->sx.val.i); + M_CMP(s1, REG_ITMP2); + } + emit_beq(cd, iptr->dst.block); break; case ICMD_IFLT: /* ..., value ==> ... */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); - if (iptr->sx.val.i == 0) { - M_BLTZ(s1, 0); - } else { - if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) { - M_CMP_IMM(s1, iptr->sx.val.i); - } else { - ICONST(REG_ITMP2, iptr->sx.val.i); - M_CMP(s1, REG_ITMP2); - } - M_BLT(0); + + if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) { + M_CMP_IMM(s1, iptr->sx.val.i); + } + else { + ICONST(REG_ITMP2, iptr->sx.val.i); + M_CMP(s1, REG_ITMP2); } - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; + emit_blt(cd, iptr->dst.block); break; case ICMD_IFLE: /* ..., value ==> ... */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); - if (iptr->sx.val.i == 0) { - M_BLEZ(s1, 0); - } + + if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) { + M_CMP_IMM(s1, iptr->sx.val.i); + } else { - if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) { - M_CMP_IMM(s1, iptr->sx.val.i); - } - else { - ICONST(REG_ITMP2, iptr->sx.val.i); - M_CMP(s1, REG_ITMP2); - } - M_BLE(0); + ICONST(REG_ITMP2, iptr->sx.val.i); + M_CMP(s1, REG_ITMP2); } - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; + emit_ble(cd, iptr->dst.block); break; case ICMD_IFNE: /* ..., value ==> ... */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); - if (iptr->sx.val.i == 0) { - M_BNEZ(s1, 0); - } + + if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) { + M_CMP_IMM(s1, iptr->sx.val.i); + } else { - if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) { - M_CMP_IMM(s1, iptr->sx.val.i); - } - else { - ICONST(REG_ITMP2, iptr->sx.val.i); - M_CMP(s1, REG_ITMP2); - } - M_BNE(0); + ICONST(REG_ITMP2, iptr->sx.val.i); + M_CMP(s1, REG_ITMP2); } - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; + emit_bne(cd, iptr->dst.block); break; case ICMD_IFGT: /* ..., value ==> ... */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); - if (iptr->sx.val.i == 0) { - M_BGTZ(s1, 0); + + if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) { + M_CMP_IMM(s1, iptr->sx.val.i); } else { - if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) { - M_CMP_IMM(s1, iptr->sx.val.i); - } else { - ICONST(REG_ITMP2, iptr->sx.val.i); - M_CMP(s1, REG_ITMP2); - } - M_BGT(0); + ICONST(REG_ITMP2, iptr->sx.val.i); + M_CMP(s1, REG_ITMP2); } - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; + emit_bgt(cd, iptr->dst.block); break; case ICMD_IFGE: /* ..., value ==> ... */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); - if (iptr->sx.val.i == 0) { - M_BGEZ(s1, 0); - } - else { - if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) { - M_CMP_IMM(s1, iptr->sx.val.i); - } - else { - ICONST(REG_ITMP2, iptr->sx.val.i); - M_CMP(s1, REG_ITMP2); - } - M_BGE(0); + + if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) { + M_CMP_IMM(s1, iptr->sx.val.i); } - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; + else { + ICONST(REG_ITMP2, iptr->sx.val.i); + M_CMP(s1, REG_ITMP2); + } + emit_bge(cd, iptr->dst.block); break; case ICMD_IF_LEQ: /* ..., value ==> ... */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); - if (iptr->sx.val.l == 0) { - M_BEQZ(s1, 0); - } + if (iptr->sx.val.l == 0) + emit_beqz(cd, iptr->dst.block, s1); else { if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) { M_CMP_IMM(s1, iptr->sx.val.l); @@ -1951,108 +2026,93 @@ bool codegen(jitdata *jd) LCONST(REG_ITMP2, iptr->sx.val.l); M_CMP(s1, REG_ITMP2); } - M_XBEQ(0); + emit_beq_xcc(cd, iptr->dst.block); } - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; break; case ICMD_IF_LLT: /* ..., value ==> ... */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); - if (iptr->sx.val.l == 0) { - M_BLTZ(s1, 0); - } + if (iptr->sx.val.l == 0) + emit_bltz(cd, iptr->dst.block, s1); else { if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) { M_CMP_IMM(s1, iptr->sx.val.l); } else { - ICONST(REG_ITMP2, iptr->sx.val.l); + LCONST(REG_ITMP2, iptr->sx.val.l); M_CMP(s1, REG_ITMP2); } - M_XBLT(0); + emit_blt_xcc(cd, iptr->dst.block); } - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; break; case ICMD_IF_LLE: /* ..., value ==> ... */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); - if (iptr->sx.val.l == 0) { - M_BLEZ(s1, 0); - } + if (iptr->sx.val.l == 0) + emit_blez(cd, iptr->dst.block, s1); else { if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) { M_CMP_IMM(s1, iptr->sx.val.l); - } + } else { - ICONST(REG_ITMP2, iptr->sx.val.l); + LCONST(REG_ITMP2, iptr->sx.val.l); M_CMP(s1, REG_ITMP2); } - M_XBLE(0); + emit_ble_xcc(cd, iptr->dst.block); } - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; break; case ICMD_IF_LNE: /* ..., value ==> ... */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); - if (iptr->sx.val.l == 0) { - M_BNEZ(s1, 0); - } + if (iptr->sx.val.l == 0) + emit_bnez(cd, iptr->dst.block, s1); else { if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) { - M_CMP_IMM(s1, iptr->sx.val.i); + M_CMP_IMM(s1, iptr->sx.val.l); } else { - ICONST(REG_ITMP2, iptr->sx.val.l); + LCONST(REG_ITMP2, iptr->sx.val.l); M_CMP(s1, REG_ITMP2); } - M_XBNE(0); + emit_bne_xcc(cd, iptr->dst.block); } - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; break; case ICMD_IF_LGT: /* ..., value ==> ... */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); - if (iptr->sx.val.l == 0) { - M_BLTZ(s1, 0); - } else { + if (iptr->sx.val.l == 0) + emit_bgtz(cd, iptr->dst.block, s1); + else { if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) { M_CMP_IMM(s1, iptr->sx.val.l); - } else { - ICONST(REG_ITMP2, iptr->sx.val.l); + } + else { + LCONST(REG_ITMP2, iptr->sx.val.l); M_CMP(s1, REG_ITMP2); } - M_XBGT(0); + emit_bgt_xcc(cd, iptr->dst.block); } - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; break; case ICMD_IF_LGE: /* ..., value ==> ... */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); - if (iptr->sx.val.l == 0) { - M_BLEZ(s1, 0); - } + if (iptr->sx.val.l == 0) + emit_bgez(cd, iptr->dst.block, s1); else { if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) { M_CMP_IMM(s1, iptr->sx.val.l); - } + } else { - ICONST(REG_ITMP2, iptr->sx.val.l); + LCONST(REG_ITMP2, iptr->sx.val.l); M_CMP(s1, REG_ITMP2); } - M_XBGE(0); + emit_bge_xcc(cd, iptr->dst.block); } - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; break; @@ -2062,9 +2122,7 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); M_CMP(s1, s2); - M_XBEQ(0); - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; + emit_beq_xcc(cd, iptr->dst.block); break; case ICMD_IF_ICMPEQ: /* 32-bit compare */ @@ -2072,9 +2130,7 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); M_CMP(s1, s2); - M_BEQ(0); - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; + emit_beq(cd, iptr->dst.block); break; case ICMD_IF_ACMPNE: /* ..., value, value ==> ... */ @@ -2083,9 +2139,7 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); M_CMP(s1, s2); - M_XBNE(0); - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; + emit_bne_xcc(cd, iptr->dst.block); break; case ICMD_IF_ICMPNE: /* 32-bit compare */ @@ -2093,9 +2147,7 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); M_CMP(s1, s2); - M_BNE(0); - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; + emit_bne(cd, iptr->dst.block); break; case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */ @@ -2103,9 +2155,7 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); M_CMP(s1, s2); - M_XBLT(0); - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; + emit_blt_xcc(cd, iptr->dst.block); break; case ICMD_IF_ICMPLT: /* 32-bit compare */ @@ -2113,9 +2163,7 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); M_CMP(s1, s2); - M_BLT(0); - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; + emit_blt(cd, iptr->dst.block); break; case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */ @@ -2123,9 +2171,7 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); M_CMP(s1, s2); - M_XBGT(0); - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; + emit_bgt_xcc(cd, iptr->dst.block); break; case ICMD_IF_ICMPGT: /* 32-bit compare */ @@ -2133,9 +2179,7 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); M_CMP(s1, s2); - M_BGT(0); - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; + emit_bgt(cd, iptr->dst.block); break; case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */ @@ -2143,9 +2187,7 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); M_CMP(s1, s2); - M_BLE(0); - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; + emit_ble_xcc(cd, iptr->dst.block); break; case ICMD_IF_ICMPLE: /* 32-bit compare */ @@ -2153,9 +2195,7 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); M_CMP(s1, s2); - M_BLE(0); - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; + emit_ble(cd, iptr->dst.block); break; @@ -2164,9 +2204,7 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); M_CMP(s1, s2); - M_BGE(0); - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; + emit_bge_xcc(cd, iptr->dst.block); break; case ICMD_IF_ICMPGE: /* 32-bit compare */ @@ -2174,32 +2212,31 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); M_CMP(s1, s2); - M_BGE(0); - codegen_add_branch_ref(cd, iptr->dst.block); - M_NOP; + emit_bge(cd, iptr->dst.block); break; case ICMD_IRETURN: /* ..., retvalue ==> ... */ case ICMD_LRETURN: + REPLACEMENT_POINT_RETURN(cd, iptr); + s1 = emit_load_s1(jd, iptr, REG_RESULT_CALLEE); M_INTMOVE(s1, REG_RESULT_CALLEE); goto nowperformreturn; case ICMD_ARETURN: /* ..., retvalue ==> ... */ + REPLACEMENT_POINT_RETURN(cd, iptr); + s1 = emit_load_s1(jd, iptr, REG_RESULT_CALLEE); M_INTMOVE(s1, REG_RESULT_CALLEE); #ifdef ENABLE_VERIFIER if (INSTRUCTION_IS_UNRESOLVED(iptr)) { - codegen_addpatchref(cd, PATCHER_athrow_areturn, - iptr->sx.s23.s2.uc, 0); + unresolved_class *uc = iptr->sx.s23.s2.uc; - if (opt_showdisassemble) { - M_NOP; M_NOP; - } + codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0); } #endif /* ENABLE_VERIFIER */ goto nowperformreturn; @@ -2207,11 +2244,15 @@ bool codegen(jitdata *jd) case ICMD_FRETURN: /* ..., retvalue ==> ... */ case ICMD_DRETURN: + REPLACEMENT_POINT_RETURN(cd, iptr); + s1 = emit_load_s1(jd, iptr, REG_FRESULT); - M_FLTMOVE(s1, REG_FRESULT); + M_DBLMOVE(s1, REG_FRESULT); goto nowperformreturn; case ICMD_RETURN: /* ... ==> ... */ + + REPLACEMENT_POINT_RETURN(cd, iptr); nowperformreturn: { @@ -2225,25 +2266,33 @@ nowperformreturn: #endif #if defined(ENABLE_THREADS) - if (checksync && (m->flags & ACC_SYNCHRONIZED)) { -/* XXX: REG_RESULT is save, but what about FRESULT? */ - M_ALD(rd->argintregs[0], REG_SP, rd->memuse * 8); /* XXX: what for ? */ + if (checksync && code_is_synchronized(code)) { + /* XXX jit-c-call */ + disp = dseg_add_functionptr(cd, LOCK_monitor_exit); + M_ALD(REG_ITMP3, REG_PV, disp); + + /* we need to save fp return value (int saved by window) */ switch (iptr->opc) { case ICMD_FRETURN: case ICMD_DRETURN: - M_DST(REG_FRESULT, REG_SP, rd->memuse * 8); - break; - } + M_ALD(REG_OUT0, REG_SP, CSTACK + rd->memuse * 8); + M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO); + M_DST(REG_FRESULT, REG_SP, CSTACK + rd->memuse * 8); /* delay */ - disp = dseg_add_functionptr(cd, BUILTIN_monitorexit); - M_ALD(REG_ITMP3, REG_PV, disp); - M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO); /*REG_RA_CALLER */ + /* restore the fp return value */ - switch (iptr->opc) { - case ICMD_FRETURN: - case ICMD_DRETURN: - M_DLD(REG_FRESULT, REG_SP, rd->memuse * 8); + M_DLD(REG_FRESULT, REG_SP, CSTACK + rd->memuse * 8); + break; + case ICMD_IRETURN: + case ICMD_LRETURN: + case ICMD_ARETURN: + case ICMD_RETURN: + M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO); + M_ALD(REG_OUT0, REG_SP, CSTACK + rd->memuse * 8); /* delay */ + break; + default: + assert(false); break; } } @@ -2271,29 +2320,27 @@ nowperformreturn: if (l == 0) { M_INTMOVE(s1, REG_ITMP1); } - else if (l <= 4095) { + else if (-l >= 4096 && -l <= 4095) { M_ADD_IMM(s1, -l, REG_ITMP1); } else { ICONST(REG_ITMP2, l); - /* XXX: do I need to truncate s1 to 32-bit ? */ M_SUB(s1, REG_ITMP2, REG_ITMP1); } - i = i - l + 1; + + i = i - l + 1; /* number of targets (>0) */ /* range check */ if (i <= 4095) { - M_CMP_IMM(REG_ITMP1, i); + M_CMP_IMM(REG_ITMP1, i - 1); } else { - ICONST(REG_ITMP2, i); + ICONST(REG_ITMP2, i - 1); M_CMP(REG_ITMP1, REG_ITMP2); } - M_XBULT(0); - codegen_add_branch_ref(cd, table[0].block); /* default target */ - M_ASLL_IMM(REG_ITMP1, POINTERSHIFT, REG_ITMP1); /* delay slot*/ + emit_bugt(cd, table[0].block); /* default target */ /* build jump table top down and use address of lowest entry */ @@ -2307,6 +2354,7 @@ nowperformreturn: /* length of dataseg after last dseg_addtarget is used by load */ + M_ASLL_IMM(REG_ITMP1, POINTERSHIFT, REG_ITMP1); M_AADD(REG_ITMP1, REG_PV, REG_ITMP2); M_ALD(REG_ITMP2, REG_ITMP2, -(cd->dseglen)); M_JMP(REG_ZERO, REG_ITMP2, REG_ZERO); @@ -2333,15 +2381,11 @@ nowperformreturn: ICONST(REG_ITMP2, lookup->value); M_CMP(s1, REG_ITMP2); } - M_BEQ(0); - codegen_add_branch_ref(cd, lookup->target.block); - M_NOP; + emit_beq(cd, lookup->target.block); ++lookup; } - M_BR(0); - codegen_add_branch_ref(cd, iptr->sx.s23.s3.lookupdefault.block); - M_NOP; + emit_br(cd, iptr->sx.s23.s3.lookupdefault.block); ALIGNCODENOP; break; } @@ -2349,20 +2393,65 @@ nowperformreturn: case ICMD_BUILTIN: /* ..., arg1, arg2, arg3 ==> ... */ + REPLACEMENT_POINT_FORGC_BUILTIN(cd, iptr); + bte = iptr->sx.s23.s3.bte; md = bte->md; - /* XXX: proper builtin calling and float args are so not implemented */ - assert(md->paramcount <= 5 && md->argfltreguse < 1); + /* XXX: builtin calling with stack arguments not implemented */ + assert(md->paramcount <= 5 && md->argfltreguse <= 16); + + s3 = md->paramcount; + + MCODECHECK((s3 << 1) + 64); + +#ifdef BUILTIN_FLOAT_ARGS /* float args for builtins disabled */ + + /* copy float arguments according to ABI convention */ + + int num_fltregargs = 0; + int fltregarg_inswap[16]; + + for (s3 = s3 - 1; s3 >= 0; s3--) { + var = VAR(iptr->sx.s23.s2.args[s3]); + + if (IS_FLT_DBL_TYPE(var->type)) { + if (!md->params[s3].inmemory) { + s1 = s3; /*native flt args use argument index directly*/ + d = emit_load(jd, iptr, var, REG_FTMP1); + + M_DMOV(d, s1 + 16); + fltregarg_inswap[num_fltregargs] = s1; + num_fltregargs++; + /*printf("builtin: flt arg swap to %d\n", s1 + 16);*/ + } + else { + assert(0); + } + } + } + + int i; + /* move swapped float args to target regs */ + for (i = 0; i < num_fltregargs; i++) { + s1 = fltregarg_inswap[i]; + M_DMOV(s1 + 16, s1); + /*printf("builtin float arg to target reg: %d ==> %d\n", s1+16, s1);*/ + } + +#else + assert(md->argfltreguse == 0); +#endif goto gen_method; case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */ - case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */ case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */ case ICMD_INVOKEINTERFACE: + REPLACEMENT_POINT_INVOKE(cd, iptr); + if (INSTRUCTION_IS_UNRESOLVED(iptr)) { lm = NULL; um = iptr->sx.s23.s3.um; @@ -2383,57 +2472,72 @@ gen_method: for (s3 = s3 - 1; s3 >= 0; s3--) { var = VAR(iptr->sx.s23.s2.args[s3]); + d = md->params[s3].regoff; if (var->flags & PREALLOC) continue; if (IS_INT_LNG_TYPE(var->type)) { if (!md->params[s3].inmemory) { - s1 = rd->argintregs[md->params[s3].regoff]; - d = emit_load(jd, iptr, var, s1); - M_INTMOVE(d, s1); + s1 = emit_load(jd, iptr, var, d); + M_INTMOVE(s1, d); } else { - d = emit_load(jd, iptr, var, REG_ITMP1); - M_STX(d, REG_SP, md->params[s3].regoff * 8); + s1 = emit_load(jd, iptr, var, REG_ITMP1); + M_STX(s1, REG_SP, JITSTACK + d); } } else { +#ifdef BUILTIN_FLOAT_ARGS + if (iptr->opc == ICMD_BUILTIN) + continue; +#endif + if (!md->params[s3].inmemory) { - s1 = rd->argfltregs[md->params[s3].regoff]; - d = emit_load(jd, iptr, var, s1); + s1 = emit_load(jd, iptr, var, d); if (IS_2_WORD_TYPE(var->type)) - M_DMOV(d, s1); + M_DMOV(s1, d); else - M_FMOV(d, s1); + M_FMOV(s1, d); } else { - d = emit_load(jd, iptr, var, REG_FTMP1); - if (IS_2_WORD_TYPE(var->type)) - M_DST(d, REG_SP, md->params[s3].regoff * 8); - else - M_FST(d, REG_SP, md->params[s3].regoff * 8); + s1 = emit_load(jd, iptr, var, REG_FTMP1); + M_DST(s1, REG_SP, JITSTACK + d); } } } switch (iptr->opc) { case ICMD_BUILTIN: - disp = dseg_add_functionptr(cd, bte->fp); + if (bte->stub == NULL) { + disp = dseg_add_functionptr(cd, bte->fp); + } + else { + disp = dseg_add_functionptr(cd, bte->stub); + } M_ALD(REG_PV_CALLER, REG_PV, disp); /* built-in-function pointer */ - s1 = REG_PV_CALLER; - - /* c call, allocate parameter array */ - M_LDA(REG_SP, REG_SP, -(ABI_PARAMARRAY_SLOTS) * 8); + /* XXX jit-c-call */ + /* generate the actual call */ + + M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO); + M_NOP; + REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr); + REPLACEMENT_POINT_FORGC_BUILTIN_RETURN(cd, iptr); + disp = (s4) (cd->mcodeptr - cd->mcodebase); + /* REG_RA holds the value of the jmp instruction, therefore +8 */ + M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8); + + if (md->returntype.type == TYPE_FLT) { + /* special handling for float return value in %f0 */ + M_FMOV_INTERN(0,1); + } break; case ICMD_INVOKESPECIAL: - M_BEQZ(REG_OUT0, 0); - codegen_add_nullpointerexception_ref(cd); - M_NOP; - /* fall through */ + emit_nullpointer_check(cd, iptr, REG_OUT0); + /* fall-through */ case ICMD_INVOKESTATIC: if (lm == NULL) { @@ -2446,11 +2550,19 @@ gen_method: disp = dseg_add_address(cd, lm->stubroutine); M_ALD(REG_PV_CALLER, REG_PV, disp); /* method pointer in pv */ - s1 = REG_PV_CALLER; + + /* generate the actual call */ + + M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO); + M_NOP; + REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr); + disp = (s4) (cd->mcodeptr - cd->mcodebase); + /* REG_RA holds the value of the jmp instruction, therefore +8 */ + M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8); break; case ICMD_INVOKEVIRTUAL: - gen_nullptr_check(REG_OUT0); + emit_nullpointer_check(cd, iptr, REG_OUT0); if (lm == NULL) { codegen_add_patch_ref(cd, PATCHER_invokevirtual, um, 0); @@ -2461,60 +2573,50 @@ gen_method: s1 = OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * lm->vftblindex; - M_ALD(REG_METHODPTR, REG_OUT0, - OFFSET(java_objectheader, vftbl)); + /* implicit null-pointer check */ + M_ALD(REG_METHODPTR, REG_OUT0,OFFSET(java_object_t, vftbl)); M_ALD(REG_PV_CALLER, REG_METHODPTR, s1); - s1 = REG_PV_CALLER; + + /* generate the actual call */ + + M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO); + M_NOP; + REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr); + disp = (s4) (cd->mcodeptr - cd->mcodebase); + /* REG_RA holds the value of the jmp instruction, therefore +8 */ + M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8); break; case ICMD_INVOKEINTERFACE: - gen_nullptr_check(rd->argintregs[0]); + emit_nullpointer_check(cd, iptr, REG_OUT0); if (lm == NULL) { - codegen_addpatchref(cd, PATCHER_invokeinterface, um, 0); - - if (opt_showdisassemble) { - M_NOP; M_NOP; - } + codegen_add_patch_ref(cd, PATCHER_invokeinterface, um, 0); s1 = 0; s2 = 0; } else { s1 = OFFSET(vftbl_t, interfacetable[0]) - - sizeof(methodptr*) * lm->class->index; + sizeof(methodptr*) * lm->clazz->index; - s2 = sizeof(methodptr) * (lm - lm->class->methods); + s2 = sizeof(methodptr) * (lm - lm->clazz->methods); } - M_ALD(REG_METHODPTR, REG_OUT0, - OFFSET(java_objectheader, vftbl)); + /* implicit null-pointer check */ + M_ALD(REG_METHODPTR, REG_OUT0, OFFSET(java_object_t, vftbl)); M_ALD(REG_METHODPTR, REG_METHODPTR, s1); M_ALD(REG_PV_CALLER, REG_METHODPTR, s2); - s1 = REG_PV_CALLER; - break; - } - - /* generate the actual call */ - - M_JMP(REG_RA_CALLER, s1, REG_ZERO); - M_NOP; - disp = (s4) (cd->mcodeptr - cd->mcodebase); - /* REG_RA holds the value of the jmp instruction, therefore +8 */ - M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8); - - if (iptr->opc == ICMD_BUILTIN) { - /* remove param slots */ - M_LDA(REG_SP, REG_SP, (ABI_PARAMARRAY_SLOTS) * 8); - } - - - /* actually only used for ICMD_BUILTIN */ - if (INSTRUCTION_MUST_CHECK(iptr)) { - M_BEQZ(REG_RESULT_CALLER, 0); - codegen_add_fillinstacktrace_ref(cd); - M_NOP; + /* generate the actual call */ + + M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO); + M_NOP; + REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr); + disp = (s4) (cd->mcodeptr - cd->mcodebase); + /* REG_RA holds the value of the jmp instruction, therefore +8 */ + M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8); + break; } /* store return value */ @@ -2540,7 +2642,6 @@ gen_method: case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */ - /* XXX needs manual attention! */ /* val.a: (classinfo*) superclass */ /* superclass is an interface: @@ -2558,146 +2659,104 @@ gen_method: if (!(iptr->flags.bits & INS_FLAG_ARRAY)) { classinfo *super; - vftbl_t *supervftbl; s4 superindex; - super = iptr->sx.s23.s3.c.cls; - - if (super == NULL) { + if (INSTRUCTION_IS_UNRESOLVED(iptr)) { + super = NULL; superindex = 0; - supervftbl = NULL; } else { + super = iptr->sx.s23.s3.c.cls; superindex = super->index; - supervftbl = super->vftbl; } -#if defined(ENABLE_THREADS) - codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase); -#endif - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - /* calculate interface checkcast code size */ - - s2 = 8; - if (super == NULL) - s2 += (opt_showdisassemble ? 2 : 0); - - /* calculate class checkcast code size */ - - s3 = 10 /* 10 + (s1 == REG_ITMP1) */; - if (super == NULL) - s3 += (opt_showdisassemble ? 2 : 0); - /* if class is not resolved, check which code to call */ if (super == NULL) { - M_BEQZ(s1, 5 + (opt_showdisassemble ? 2 : 0) + s2 + 2 + s3); - M_NOP; + emit_label_beqz(cd, BRANCH_LABEL_1, s1); + cr = iptr->sx.s23.s3.c.ref; disp = dseg_add_unique_s4(cd, 0); /* super->flags */ - codegen_addpatchref(cd, PATCHER_checkcast_instanceof_flags, - iptr->sx.s23.s3.c.ref, - disp); - - if (opt_showdisassemble) { - M_NOP; M_NOP; - } + codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_flags, + cr, disp); M_ILD(REG_ITMP2, REG_PV, disp); M_AND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2); - M_BEQZ(REG_ITMP2, 1 + s2 + 2); - M_NOP; + emit_label_beqz(cd, BRANCH_LABEL_2, REG_ITMP2); } /* interface checkcast code */ if ((super == NULL) || (super->flags & ACC_INTERFACE)) { if (super == NULL) { - codegen_addpatchref(cd, - PATCHER_checkcast_instanceof_interface, - iptr->sx.s23.s3.c.ref, - 0); + cr = iptr->sx.s23.s3.c.ref; - if (opt_showdisassemble) { - M_NOP; M_NOP; - } + codegen_add_patch_ref(cd, PATCHER_checkcast_interface, + cr, 0); } else { - M_BEQZ(s1, 1 + s2); - M_NOP; + emit_label_beqz(cd, BRANCH_LABEL_3, s1); } - M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl)); - M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength)); - M_LDA(REG_ITMP3, REG_ITMP3, -superindex); - M_BLEZ(REG_ITMP3, 0); - codegen_add_classcastexception_ref(cd, s1); - M_NOP; + M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl)); + M_ILD(REG_ITMP3, REG_ITMP2, + OFFSET(vftbl_t, interfacetablelength)); + M_ADD_IMM(REG_ITMP3, -superindex, REG_ITMP3); + emit_classcast_check(cd, iptr, ICMD_IFLE, REG_ITMP3, s1); + M_ALD(REG_ITMP3, REG_ITMP2, - (s4) (OFFSET(vftbl_t, interfacetable[0]) - - superindex * sizeof(methodptr*))); - M_BEQZ(REG_ITMP3, 0); - codegen_add_classcastexception_ref(cd, s1); - M_NOP; + OFFSET(vftbl_t, interfacetable[0]) - + superindex * sizeof(methodptr*)); + emit_classcast_check(cd, iptr, ICMD_IFEQ, REG_ITMP3, s1); - if (super == NULL) { - M_BR(1 + s3); - M_NOP; - } + if (super == NULL) + emit_label_br(cd, BRANCH_LABEL_4); + else + emit_label(cd, BRANCH_LABEL_3); } /* class checkcast code */ if ((super == NULL) || !(super->flags & ACC_INTERFACE)) { if (super == NULL) { + emit_label(cd, BRANCH_LABEL_2); + + cr = iptr->sx.s23.s3.c.ref; disp = dseg_add_unique_address(cd, NULL); - codegen_addpatchref(cd, + codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_class, - iptr->sx.s23.s3.c.ref, - disp); - - if (opt_showdisassemble) { - M_NOP; M_NOP; - } + cr, disp); } else { - disp = dseg_add_address(cd, supervftbl); + disp = dseg_add_address(cd, super->vftbl); - M_BEQZ(s1, 1 + s3); - M_NOP; + emit_label_beqz(cd, BRANCH_LABEL_5, s1); } - M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl)); + M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl)); M_ALD(REG_ITMP3, REG_PV, disp); -#if defined(ENABLE_THREADS) - codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase); -#endif + M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval)); - /* if (s1 != REG_ITMP1) { */ - /* M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, baseval)); */ - /* M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval)); */ - /* #if defined(ENABLE_THREADS) */ - /* codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase); */ - /* #endif */ - /* M_ISUB(REG_ITMP2, REG_ITMP1, REG_ITMP2); */ - - /* } else { */ M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval)); M_SUB(REG_ITMP2, REG_ITMP3, REG_ITMP2); M_ALD(REG_ITMP3, REG_PV, disp); M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval)); -#if defined(ENABLE_THREADS) - codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase); -#endif + /* } */ M_CMP(REG_ITMP3, REG_ITMP2); - M_BULT(0); /* branch if ITMP3 < ITMP2 */ - codegen_add_classcastexception_ref(cd, s1); - M_NOP; + emit_classcast_check(cd, iptr, BRANCH_ULT, REG_ITMP3, s1); + + if (super != NULL) + emit_label(cd, BRANCH_LABEL_5); + } + + if (super == NULL) { + emit_label(cd, BRANCH_LABEL_1); + emit_label(cd, BRANCH_LABEL_4); } d = codegen_reg_of_dst(jd, iptr, s1); @@ -2705,31 +2764,30 @@ gen_method: else { /* array type cast-check */ - s1 = emit_load_s1(jd, iptr, rd->argintregs[0]); - M_INTMOVE(s1, rd->argintregs[0]); + s1 = emit_load_s1(jd, iptr, REG_OUT0); + M_INTMOVE(s1, REG_OUT0); disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls); if (INSTRUCTION_IS_UNRESOLVED(iptr)) { - codegen_addpatchref(cd, PATCHER_builtin_arraycheckcast, - iptr->sx.s23.s3.c.ref, - disp); + cr = iptr->sx.s23.s3.c.ref; + disp = dseg_add_unique_address(cd, NULL); - if (opt_showdisassemble) { - M_NOP; M_NOP; - } + codegen_add_patch_ref(cd, PATCHER_builtin_arraycheckcast, + cr, disp); } + else + disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls); - M_ALD(rd->argintregs[1], REG_PV, disp); + M_ALD(REG_OUT1, REG_PV, disp); disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast); M_ALD(REG_ITMP3, REG_PV, disp); + /* XXX jit-c-call */ M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO); M_NOP; s1 = emit_load_s1(jd, iptr, REG_ITMP1); - M_BEQZ(REG_RESULT_CALLER, 0); - codegen_add_classcastexception_ref(cd, s1); - M_NOP; + emit_classcast_check(cd, iptr, ICMD_IFEQ, REG_RESULT_CALLER, s1); d = codegen_reg_of_dst(jd, iptr, s1); } @@ -2738,30 +2796,221 @@ gen_method: emit_store_dst(jd, iptr, d); break; + case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */ + /* val.a: (classinfo*) superclass */ + + /* superclass is an interface: + * + * return (sub != NULL) && + * (sub->vftbl->interfacetablelength > super->index) && + * (sub->vftbl->interfacetable[-super->index] != NULL); + * + * superclass is a class: + * + * return ((sub != NULL) && (0 + * <= (sub->vftbl->baseval - super->vftbl->baseval) <= + * super->vftbl->diffvall)); + */ + + { + classinfo *super; + vftbl_t *supervftbl; + s4 superindex; + + if (INSTRUCTION_IS_UNRESOLVED(iptr)) { + super = NULL; + superindex = 0; + supervftbl = NULL; + + } else { + super = iptr->sx.s23.s3.c.cls; + superindex = super->index; + supervftbl = super->vftbl; + } + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); + if (s1 == d) { + M_MOV(s1, REG_ITMP1); + s1 = REG_ITMP1; + } + + M_CLR(d); + + /* if class is not resolved, check which code to call */ + + if (super == NULL) { + emit_label_beqz(cd, BRANCH_LABEL_1, s1); + + cr = iptr->sx.s23.s3.c.ref; + disp = dseg_add_unique_s4(cd, 0); /* super->flags */ + + codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_flags, + cr, disp); + + M_ILD(REG_ITMP3, REG_PV, disp); + M_AND_IMM(REG_ITMP3, ACC_INTERFACE, REG_ITMP3); + emit_label_beqz(cd, BRANCH_LABEL_2, REG_ITMP3); + } + + /* interface instanceof code */ + + if ((super == NULL) || (super->flags & ACC_INTERFACE)) { + if (super == NULL) { + cr = iptr->sx.s23.s3.c.ref; + + codegen_add_patch_ref(cd, PATCHER_instanceof_interface, + cr, 0); + } + else { + emit_label_beqz(cd, BRANCH_LABEL_3, s1); + } + + M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl)); + M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength)); + M_CMP_IMM(REG_ITMP3, superindex); + M_BLE(4); + M_NOP; + M_ALD(REG_ITMP1, REG_ITMP1, + (s4) (OFFSET(vftbl_t, interfacetable[0]) - + superindex * sizeof(methodptr*))); + M_CMOVRNE_IMM(REG_ITMP1, 1, d); /* REG_ITMP1 != 0 */ + + if (super == NULL) + emit_label_br(cd, BRANCH_LABEL_4); + else + emit_label(cd, BRANCH_LABEL_3); + } + + /* class instanceof code */ + + if ((super == NULL) || !(super->flags & ACC_INTERFACE)) { + if (super == NULL) { + emit_label(cd, BRANCH_LABEL_2); + + cr = iptr->sx.s23.s3.c.ref; + disp = dseg_add_unique_address(cd, NULL); + + codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_class, + cr, disp); + } + else { + disp = dseg_add_address(cd, supervftbl); + + emit_label_beqz(cd, BRANCH_LABEL_5, s1); + } + M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl)); + M_ALD(REG_ITMP2, REG_PV, disp); + + M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval)); + M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval)); + M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval)); + + M_SUB(REG_ITMP1, REG_ITMP3, REG_ITMP1); + M_CMP(REG_ITMP1, REG_ITMP2); + M_XCMOVULE_IMM(1, d); + + if (super != NULL) + emit_label(cd, BRANCH_LABEL_5); + } + + if (super == NULL) { + emit_label(cd, BRANCH_LABEL_1); + emit_label(cd, BRANCH_LABEL_4); + } + + emit_store_dst(jd, iptr, d); + } + break; + + case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */ + + /* check for negative sizes and copy sizes to stack if necessary */ + + MCODECHECK((iptr->s1.argcount << 1) + 64); + + for (s1 = iptr->s1.argcount; --s1 >= 0; ) { + + var = VAR(iptr->sx.s23.s2.args[s1]); + + /* copy SAVEDVAR sizes to stack */ + + /* Already Preallocated? */ + + if (!(var->flags & PREALLOC)) { + s2 = emit_load(jd, iptr, var, REG_ITMP1); + M_STX(s2, REG_SP, CSTACK + (s1 * 8)); + } + } + + /* arg 0 = dimension count */ + + ICONST(REG_OUT0, iptr->s1.argcount); + + /* is patcher function set? */ + + if (INSTRUCTION_IS_UNRESOLVED(iptr)) { + disp = dseg_add_unique_address(cd, 0); + + codegen_add_patch_ref(cd, PATCHER_builtin_multianewarray, + iptr->sx.s23.s3.c.ref, + disp); + } + else + disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls); + + /* arg 1 = arraydescriptor */ + + M_ALD(REG_OUT1, REG_PV, disp); + + /* arg 2 = pointer to dimensions = stack pointer (absolute) */ + + M_ADD_IMM(REG_SP, CSTACK, REG_OUT2); + + /* XXX c abi call */ + disp = dseg_add_functionptr(cd, BUILTIN_multianewarray); + M_ALD(REG_ITMP3, REG_PV, disp); + M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO); + M_NOP; + + /* check for exception before result assignment */ + + emit_exception_check(cd, iptr); + + d = codegen_reg_of_dst(jd, iptr, REG_RESULT_CALLER); + M_INTMOVE(REG_RESULT_CALLER, d); + emit_store_dst(jd, iptr, d); + break; default: - *exceptionptr = new_internalerror("Unknown ICMD %d", iptr->opc); + exceptions_throw_internalerror("Unknown ICMD %d during code generation", + iptr->opc); return false; } /* switch */ } /* for instruction */ + + MCODECHECK(64); + /* At the end of a basic block we may have to append some nops, + because the patcher stub calling code might be longer than the + actual instruction. So codepatching does not change the + following block unintentionally. */ + if (cd->mcodeptr < cd->lastmcodeptr) { + while (cd->mcodeptr < cd->lastmcodeptr) { + M_NOP; + } + } } /* if (bptr -> flags >= BBREACHED) */ } /* for basic block */ - dseg_createlinenumbertable(cd); - - /* generate exception and patcher stubs */ + /* generate stubs */ - emit_exception_stubs(jd); emit_patcher_stubs(jd); - emit_replacement_stubs(jd); - - codegen_finish(jd); /* everything's ok */ @@ -2769,102 +3018,223 @@ gen_method: } +/* codegen_emit_stub_compiler ************************************************** + Emits a stub routine which calls the compiler. + +*******************************************************************************/ +void codegen_emit_stub_compiler(jitdata *jd) +{ + methodinfo *m; + codegendata *cd; -/* createcompilerstub ********************************************************** + /* get required compiler data */ - Creates a stub routine which calls the compiler. - -*******************************************************************************/ + m = jd->m; + cd = jd->cd; + + /* code for the stub */ + + /* no window save yet, user caller's PV */ + M_ALD_INTERN(REG_ITMP1, REG_PV_CALLER, -2 * SIZEOF_VOID_P); /* codeinfo pointer */ + M_ALD_INTERN(REG_PV_CALLER, REG_PV_CALLER, -3 * SIZEOF_VOID_P); /* pointer to compiler */ + M_JMP(REG_ZERO, REG_PV_CALLER, REG_ZERO); /* jump to the compiler, RA is wasted */ + M_NOP; +} -#define COMPILERSTUB_DATASIZE 3 * SIZEOF_VOID_P -#define COMPILERSTUB_CODESIZE 4 * 4 -#define COMPILERSTUB_SIZE COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE +/* codegen_emit_stub_builtin *************************************************** + Creates a stub routine which calls a builtin function. + +*******************************************************************************/ -u1 *createcompilerstub(methodinfo *m) +void codegen_emit_stub_builtin(jitdata *jd, builtintable_entry *bte) { - u1 *s; /* memory to hold the stub */ - ptrint *d; codeinfo *code; codegendata *cd; - s4 dumpsize; - - s = CNEW(u1, COMPILERSTUB_SIZE); + methoddesc *md; + s4 i; + s4 disp; + s4 s1, s2; - /* set data pointer and code pointer */ + /* get required compiler data */ + code = jd->code; + cd = jd->cd; - d = (ptrint *) s; - s = s + COMPILERSTUB_DATASIZE; + /* set some variables */ + md = bte->md; - /* mark start of dump memory area */ + /* calculate stack frame size */ + cd->stackframesize = + WINSAVE_CNT + + ABIPARAMS_CNT + + FLT_ARG_CNT + + sizeof(stackframeinfo_t) / SIZEOF_VOID_P + + 4; /* 4 arguments or return value */ - dumpsize = dump_size(); - cd = DNEW(codegendata); - cd->mcodeptr = s; - - /* Store the codeinfo pointer in the same place as in the - methodheader for compiled methods. */ + /* keep stack 16-byte aligned (ABI requirement) */ - code = code_codeinfo_new(m); + if (cd->stackframesize & 1) + cd->stackframesize++; - d[0] = (ptrint) asm_call_jit_compiler; - d[1] = (ptrint) m; - d[2] = (ptrint) code; + /* create method header */ + (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */ + (void) dseg_add_unique_s4(cd, cd->stackframesize * 4); /* FrameSize */ + (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */ + (void) dseg_add_unique_s4(cd, 0); /* IntSave */ + (void) dseg_add_unique_s4(cd, 0); /* FltSave */ - /* code for the stub */ - /* no window save yet, user caller's PV */ - M_ALD_INTERN(REG_ITMP1, REG_PV_CALLER, -2 * SIZEOF_VOID_P); /* codeinfo pointer */ - M_ALD_INTERN(REG_PV_CALLER, REG_PV_CALLER, -3 * SIZEOF_VOID_P); /* pointer to compiler */ - M_JMP(REG_ZERO, REG_PV_CALLER, REG_ZERO); /* jump to the compiler, RA is wasted */ - M_NOP; + /* generate stub code */ + M_SAVE(REG_SP, -cd->stackframesize * 8, REG_SP); /* build up stackframe */ + +#if defined(ENABLE_GC_CACAO) + /* Save callee saved integer registers in stackframeinfo (GC may + need to recover them during a collection). */ + + disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) + + OFFSET(stackframeinfo_t, intregs) + BIAS; -#if defined(ENABLE_STATISTICS) - if (opt_stat) - count_cstub_len += COMPILERSTUB_SIZE; + for (i = 0; i < INT_SAV_CNT; i++) + M_AST(abi_registers_integer_saved[i], REG_SP, disp + i * 8); #endif - /* release dump area */ + for (i = 0; i < md->paramcount; i++) { + s1 = md->params[i].regoff; - dump_release(dumpsize); + switch (md->paramtypes[i].type) { + case TYPE_INT: + case TYPE_LNG: + case TYPE_ADR: + break; + case TYPE_FLT: + case TYPE_DBL: + M_DST(s1, REG_SP, JITSTACK + i * 8); + break; + } + } + + /* create dynamic stack info */ + + M_AADD_IMM(REG_SP, BIAS + cd->stackframesize * 8, REG_OUT0); /* data sp*/ + M_MOV(REG_PV_CALLEE, REG_OUT1); /* PV */ + M_MOV(REG_FP, REG_OUT2); /* java sp */ + M_MOV(REG_RA_CALLEE, REG_OUT3); /* ra */ + + disp = dseg_add_functionptr(cd, codegen_stub_builtin_enter); + M_ALD(REG_ITMP3, REG_PV_CALLEE, disp); + M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO); + M_NOP; /* XXX fill me! */ - return s; -} + /* builtins are allowed to have 5 arguments max */ + assert(md->paramcount <= 5); -/* createnativestub ************************************************************ + /* copy arguments into position */ - Creates a stub routine which calls a native method. + for (i = 0; i < md->paramcount; i++) { + assert(!md->params[i].inmemory); + + s1 = md->params[i].regoff; + + switch (md->paramtypes[i].type) { + case TYPE_INT: + case TYPE_LNG: + case TYPE_ADR: + M_MOV(REG_WINDOW_TRANSPOSE(abi_registers_integer_argument[i]), s1); + break; + case TYPE_FLT: + case TYPE_DBL: + M_DLD(s1, REG_SP, JITSTACK + i * 8); + break; + } + + } + + /* call the builtin function */ + + disp = dseg_add_functionptr(cd, bte->fp); + M_ALD(REG_ITMP3, REG_PV_CALLEE, disp); /* load adress of builtin */ + M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO); /* call builtin */ + M_NOP; /* delay slot */ + + + /* save return value */ + + if (md->returntype.type != TYPE_VOID) { + if (IS_INT_LNG_TYPE(md->returntype.type)) + M_MOV(REG_RESULT_CALLER, REG_RESULT_CALLEE); + else + M_DST(REG_FRESULT, REG_SP, CSTACK); + } + + + /* remove native stackframe info */ + + M_ADD_IMM(REG_FP, BIAS, REG_OUT0); /* datasp, like above */ + disp = dseg_add_functionptr(cd, codegen_stub_builtin_exit); + M_ALD(REG_ITMP3, REG_PV_CALLEE, disp); + M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO); + M_NOP; + + /* restore float return value, int return value already in our return reg */ + + if (md->returntype.type != TYPE_VOID) { + if (IS_FLT_DBL_TYPE(md->returntype.type)) { + if (IS_2_WORD_TYPE(md->returntype.type)) + M_DLD(REG_FRESULT, REG_SP, CSTACK); + else + M_FLD(REG_FRESULT, REG_SP, CSTACK); + } + } + + +#if defined(ENABLE_GC_CACAO) + /* Restore callee saved integer registers from stackframeinfo (GC + might have modified them during a collection). */ + + disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) + + OFFSET(stackframeinfo_t, intregs) + BIAS; + + for (i = 0; i < INT_SAV_CNT; i++) + M_ALD(abi_registers_integer_saved[i], REG_SP, disp + i * 8); +#endif + + /* return */ + M_RETURN(REG_RA_CALLEE, 8); /* implicit window restore */ + M_NOP; + + /* assert(0); */ +} + + +/* codegen_emit_stub_native **************************************************** + + Emits a stub routine which calls a native method. *******************************************************************************/ -u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd) +void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f) { methodinfo *m; codeinfo *code; codegendata *cd; - registerdata *rd; methoddesc *md; s4 nativeparams; s4 i, j; /* count variables */ s4 t; s4 s1, s2, disp; s4 funcdisp; /* displacement of the function */ + s4 fltregarg_offset[FLT_ARG_CNT]; /* get required compiler data */ m = jd->m; code = jd->code; cd = jd->cd; - rd = jd->rd; - - /* rewrite registers and params */ - md_native_reg_setup(jd); - md_native_param_alloc(nmd); /* initialize variables */ @@ -2877,19 +3247,22 @@ u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd) sizeof(stackframeinfo) / SIZEOF_VOID_P + sizeof(localref_table) / SIZEOF_VOID_P + md->paramcount + /* for saving arguments over calls */ - nmd->memuse + /* nmd knows about the native stackframe layout */ + nmd->memuse + /* nmd->memuse includes the (6) abi params */ WINSAVE_CNT; + + /* keep stack 16-byte aligned (ABI requirement) */ + + if (cd->stackframesize & 1) + cd->stackframesize++; + /* create method header */ (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */ (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */ - (void) dseg_add_unique_s4(cd, 0); /* IsSync */ (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */ (void) dseg_add_unique_s4(cd, 0); /* IntSave */ (void) dseg_add_unique_s4(cd, 0); /* FltSave */ - (void) dseg_addlinenumbertablesize(cd); - (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */ /* generate stub code */ @@ -2904,28 +3277,25 @@ u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd) funcdisp = dseg_add_functionptr(cd, f); -#if !defined(WITH_STATIC_CLASSPATH) - if (f == NULL) { - codegen_addpatchref(cd, PATCHER_resolve_native, m, funcdisp); - - if (opt_showdisassemble) { - M_NOP; M_NOP; - } - } -#endif + if (f == NULL) + codegen_add_patch_ref(cd, PATCHER_resolve_native, m, funcdisp); /* save float argument registers */ + assert(ABIPARAMS_CNT >= FLT_ARG_CNT); + for (i = 0, j = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) { if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) { - M_DST(rd->argfltregs[i], REG_SP, j * 8); + s1 = WINSAVE_CNT + nmd->memuse + j; + M_DST(abi_registers_float_argument[i], REG_SP, BIAS + (s1*8)); + fltregarg_offset[i] = s1; /* remember stack offset */ j++; } } /* prepare data structures for native function call */ - M_ADD_IMM(REG_FP, BIAS, REG_OUT0); /* datasp == top of the stack frame (absolute == +BIAS) */ + M_ADD_IMM(REG_FP, BIAS, REG_OUT0); /* datasp == top of the stack frame (absolute, ie. + BIAS) */ M_MOV(REG_PV_CALLEE, REG_OUT1); M_MOV(REG_FP, REG_OUT2); /* java sp */ M_MOV(REG_RA_CALLEE, REG_OUT3); @@ -2934,96 +3304,122 @@ u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd) M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO); M_NOP; /* XXX fill me! */ - /* restore float argument registers */ + /* remember class argument */ + + if (m->flags & ACC_STATIC) + M_MOV(REG_RESULT_CALLER, REG_ITMP3); + /* keep float arguments on stack */ +#if 0 for (i = 0, j = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) { if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) { - M_DLD(rd->argfltregs[i], REG_SP, j * 8); + M_DLD(abi_registers_float_argument[i], REG_SP, CSTACK + (j * 8)); j++; } } +#endif /* copy or spill arguments to new locations */ - int num_fltregargs = 0; - int fltregarg_inswap[16]; + for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) { t = md->paramtypes[i].type; if (IS_INT_LNG_TYPE(t)) { + + /* integral types */ + if (!md->params[i].inmemory) { - s1 = rd->argintregs[md->params[i].regoff]; + s1 = md->params[i].regoff; /* s1 refers to the old window, transpose */ s1 = REG_WINDOW_TRANSPOSE(s1); if (!nmd->params[j].inmemory) { - s2 = nat_argintregs[nmd->params[j].regoff]; + s2 = nmd->params[j].regoff; M_INTMOVE(s1, s2); } else { - s2 = nmd->params[j].regoff; - M_AST(s1, REG_SP, USESTACK_PARAMS + s2 * 8); + /* nmd's regoff is relative to the start of the param array */ + s2 = BIAS + WINSAVE_CNT * 8 + nmd->params[j].regoff; + M_AST(s1, REG_SP, s2); } } else { - s1 = md->params[i].regoff + cd->stackframesize; - s2 = nmd->params[j].regoff; - M_ALD(REG_ITMP1, REG_SP, USESTACK_PARAMS + s1 * 8); - M_AST(REG_ITMP1, REG_SP, USESTACK_PARAMS + s2 * 8); + if (!nmd->params[j].inmemory) { + /* JIT stack arg -> NAT reg arg */ + + /* Due to the Env pointer that is always passed, the 6th JIT arg */ + /* is the 7th (or 8th w/ class ptr) NAT arg, and goes to the stack */ + + assert(false); /* path never taken */ + } + + s1 = md->params[i].regoff + cd->stackframesize * 8; + s2 = BIAS + WINSAVE_CNT * 8 + nmd->params[j].regoff; + M_ALD(REG_ITMP1, REG_SP, CSTACK + s1); + M_AST(REG_ITMP1, REG_SP, s2); } } else { + + /* floating point types */ + if (!md->params[i].inmemory) { - s1 = rd->argfltregs[md->params[i].regoff]; + s1 = md->params[i].regoff; if (!nmd->params[j].inmemory) { + /* no mapping to regs needed, native flt args use regoff */ s2 = nmd->params[j].regoff; - - /* we cannot move flt regs to their native arg locations directly */ - M_DMOV(s1, s2 + 16); - fltregarg_inswap[num_fltregargs] = s2; - num_fltregargs++; - printf("flt arg swap to %d\n", s2 + 16); - } else { + /* JIT float regs are still on the stack */ + M_DLD(s2, REG_SP, BIAS + (fltregarg_offset[i] * 8)); + } + else { + /* not supposed to happen with 16 NAT flt args */ + assert(false); + /* s2 = nmd->params[j].regoff; if (IS_2_WORD_TYPE(t)) - M_DST(s1, REG_SP, USESTACK_PARAMS + s2 * 8); + M_DST(s1, REG_SP, CSTACK + (s2 * 8)); else - M_FST(s1, REG_SP, USESTACK_PARAMS + s2 * 8); + M_FST(s1, REG_SP, CSTACK + (s2 * 8)); + */ } - } else { - s1 = md->params[i].regoff + cd->stackframesize; - s2 = nmd->params[j].regoff; - if (IS_2_WORD_TYPE(t)) { - M_DLD(REG_FTMP1, REG_SP, USESTACK_PARAMS + s1 * 8); - M_DST(REG_FTMP1, REG_SP, USESTACK_PARAMS + s2 * 8); - } else { - M_FLD(REG_FTMP1, REG_SP, USESTACK_PARAMS + s1 * 8); - M_FST(REG_FTMP1, REG_SP, USESTACK_PARAMS + s2 * 8); + } + else { + s1 = md->params[i].regoff; + + if (!nmd->params[j].inmemory) { + + /* JIT stack -> NAT reg */ + + s2 = nmd->params[j].regoff; + M_DLD(s2, REG_FP, JITSTACK + s1); + } + else { + + /* JIT stack -> NAT stack */ + + s2 = WINSAVE_CNT * 8 + nmd->params[j].regoff; + + /* The FTMP register may already be loaded with args */ + /* we know $f0 is unused because of the env pointer */ + M_DLD(REG_F0, REG_FP, JITSTACK + s1); + M_DST(REG_F0, REG_SP, BIAS + s2); } } } } - /* move swapped float args to target regs */ - for (i = 0; i < num_fltregargs; i++) { - s1 = fltregarg_inswap[i]; - M_DMOV(s1 + 16, s1); - printf("float arg to target reg: %d ==> %d\n", s1+16, s1); - } - /* put class into second argument register */ - if (m->flags & ACC_STATIC) { - disp = dseg_add_address(cd, m->class); - M_ALD(REG_OUT1, REG_PV_CALLEE, disp); - } + if (m->flags & ACC_STATIC) + M_MOV(REG_ITMP3, REG_OUT1); /* put env into first argument register */ - disp = dseg_add_address(cd, _Jv_env); + disp = dseg_add_address(cd, VM_get_jnienv()); M_ALD(REG_OUT0, REG_PV_CALLEE, disp); /* do the native function call */ @@ -3038,7 +3434,7 @@ u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd) if (IS_INT_LNG_TYPE(md->returntype.type)) M_MOV(REG_RESULT_CALLER, REG_RESULT_CALLEE); else - M_DST(REG_FRESULT, REG_SP, USESTACK_PARAMS); + M_DST(REG_FRESULT, REG_SP, CSTACK); } /* Note: native functions return float values in %f0 (see ABI) */ @@ -3048,7 +3444,7 @@ u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd) /* But for the trace function we need to put a flt result into %f1 */ if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) { if (!IS_2_WORD_TYPE(md->returntype.type)) - M_FLD(REG_FRESULT, REG_SP, USESTACK_PARAMS); + M_FLD(REG_FRESULT, REG_SP, CSTACK); emit_verbosecall_exit(jd); } #endif @@ -3067,34 +3463,30 @@ u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd) if (md->returntype.type != TYPE_VOID) { if (IS_FLT_DBL_TYPE(md->returntype.type)) { if (IS_2_WORD_TYPE(md->returntype.type)) - M_DLD(REG_FRESULT, REG_SP, USESTACK_PARAMS); + M_DLD(REG_FRESULT, REG_SP, CSTACK); else - M_FLD(REG_FRESULT, REG_SP, USESTACK_PARAMS); + M_FLD(REG_FRESULT, REG_SP, CSTACK); } } /* check for exception */ - M_BNEZ(REG_ITMP2_XPTR, 4); /* if no exception then return */ - M_RESTORE(REG_ZERO, 0, REG_ZERO); /* restore callers window (DELAY) */ + M_NOP; - M_RET(REG_RA_CALLER, 8); /* return to caller */ - M_NOP; /* DELAY SLOT */ + M_RETURN(REG_RA_CALLEE, 8); /* implicit window restore */ + M_NOP; /* handle exception */ disp = dseg_add_functionptr(cd, asm_handle_nat_exception); - M_ALD(REG_ITMP3, REG_PV, disp); /* load asm exception handler address */ - M_JMP(REG_ZERO, REG_ITMP3, REG_ZERO);/* jump to asm exception handler */ - M_MOV(REG_RA_CALLER, REG_ITMP3_XPC); /* get exception address (DELAY) */ - + M_ALD(REG_ITMP1, REG_PV, disp); /* load asm exception handler address */ + M_MOV(REG_RA_CALLEE, REG_ITMP3_XPC); /* get exception address */ + M_JMP(REG_ZERO, REG_ITMP1, REG_ZERO);/* jump to asm exception handler */ + M_RESTORE(REG_ZERO, 0, REG_ZERO); /* restore callers window (DELAY) */ + /* generate patcher stubs */ emit_patcher_stubs(jd); - - codegen_finish(jd); - - return code->entrypoint; } /*