X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fvm%2Fjit%2Fs390%2Fcodegen.c;h=25e2c1983dee70e721a61d59ab206535e1e59f24;hb=ebb448e2a77afa30d719a056c58e548bf9985b7f;hp=5051fb075be0a3a2938a96917d6064ad6f0e12d5;hpb=8841cf7f8ae89d6f5bbc607d8cd83c843191471e;p=cacao.git diff --git a/src/vm/jit/s390/codegen.c b/src/vm/jit/s390/codegen.c index 5051fb075..25e2c1983 100644 --- a/src/vm/jit/s390/codegen.c +++ b/src/vm/jit/s390/codegen.c @@ -1,9 +1,7 @@ -/* src/vm/jit/x86_64/codegen.c - machine code generator for x86_64 +/* src/vm/jit/s390/codegen.c - machine code generator for s390 - 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,82 +20,77 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - Contact: cacao@cacaojvm.org - - Authors: Andreas Krall - Christian Thalinger - Christian Ullrich - Edwin Steiner - - $Id: codegen.c 7367 2007-02-16 07:17:01Z pm $ - */ #include "config.h" #include +#include #include -#include "vm/types.h" - -#include "md-abi.h" - -#include "vm/jit/s390/arch.h" -#include "vm/jit/s390/codegen.h" -#include "vm/jit/s390/emit.h" - -#include "mm/memory.h" #include "native/jni.h" +#include "native/localref.h" #include "native/native.h" -#if defined(ENABLE_THREADS) -# include "threads/native/lock.h" -#endif +#include "mm/memory.h" + +#include "threads/lock-common.h" -#include "vm/builtin.h" -#include "vm/exceptions.h" -#include "vm/global.h" #include "vmcore/loader.h" #include "vmcore/options.h" #include "vmcore/statistics.h" -#include "vm/stringlocal.h" -#include "vm/vm.h" +#include "vm/builtin.h" +#include "vm/exceptions.h" +#include "vm/global.h" +#include "vm/jit/abi.h" +#if defined(ENABLE_LSRA) +# include "vm/jit/allocator/lsra.h" +#endif #include "vm/jit/asmpart.h" #include "vm/jit/codegen-common.h" #include "vm/jit/dseg.h" #include "vm/jit/emit-common.h" #include "vm/jit/jit.h" +#include "vm/jit/linenumbertable.h" #include "vm/jit/methodheader.h" #include "vm/jit/parse.h" -#include "vm/jit/patcher.h" +#include "vm/jit/patcher-common.h" #include "vm/jit/reg.h" #include "vm/jit/replace.h" +#include "vm/jit/s390/arch.h" +#include "vm/jit/s390/codegen.h" +#include "vm/jit/s390/emit.h" +#include "vm/jit/s390/md-abi.h" #include "vm/jit/stacktrace.h" +#include "vm/types.h" +#include "vm/stringlocal.h" +#include "vm/vm.h" -#if defined(ENABLE_LSRA) -# include "vm/jit/allocator/lsra.h" -#endif - -#define OOPS() assert(0); - -#if 0 -u1 *createcompilerstub(methodinfo *m) { - OOPS(); - u1 *stub = malloc(8); - bzero(stub, 8); - return stub; -} -#endif +/* DO__LOG generates a call to do__log. No registers are destroyed, + * so you may use it anywhere. regs is an array containing all general + * purpose registers. + */ -#if 0 -u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd) { - OOPS(); - return createcompilerstub(NULL); +/* +static void do__log(u4 *regs) { } -#endif +*/ +#define DO__LOG \ + N_AHI(REG_SP, -200); \ + N_STM(R0, R15, 96, REG_SP); \ + M_ALD_DSEG(R14, dseg_add_address(cd, &do__log)); \ + N_LA(R2, 96, RN, REG_SP); \ + N_BASR(R14, R14); \ + N_LM(R0, R15, 96, REG_SP); \ + N_AHI(REG_SP, 200); + +/* If the following macro is defined, workaround code for hercules quirks + * is generated + */ +/* #define SUPPORT_HERCULES 1 */ /* codegen ********************************************************************* @@ -105,20 +98,42 @@ u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd) { *******************************************************************************/ +/* + +Layout of stackframe: + +Meaning Offset +=============================================================================== +return_address (stackframesize - 1) * 8 +saved_int_reg[INT_SAV_CNT - 1] (stackframseize - 2) * 8 +... +saved_int_reg[rd->savintreguse] +saved_flt_reg[FLT_SAV_CNT - 1] +... +saved_flt_reg[rd->savfltreguse] (stackframesize - 1 - savedregs_num) * 8 + +return_value_tmp (rd->memuse + 1) * 8 +monitorenter_argument (rd->memuse) * 8 +??? +local[rd->memuse - 1] (rd->memuse - 1) * 8 +.... +local[2] 2 * 8 +local[1] 1 * 8 +local[0] 0 * 8 -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, dd, disp; u2 currentline; - ptrint a; - varinfo *var, *var1, *var2, *dst; + varinfo *var; basicblock *bptr; instruction *iptr; - exception_entry *ex; constant_classref *cr; unresolved_class *uc; methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */ @@ -156,102 +171,89 @@ bool codegen(jitdata *jd) /* space to save used callee saved registers */ savedregs_num += (INT_SAV_CNT - rd->savintreguse); - savedregs_num += (FLT_SAV_CNT - rd->savfltreguse) * 2; + savedregs_num += (FLT_SAV_CNT - rd->savfltreguse); cd->stackframesize = rd->memuse + savedregs_num + 1 /* space to save RA */; /* CAUTION: - * As REG_ITMP3 == REG_RA, do not touch REG_ITMP3, until it has been saved. + * As REG_ITMP2 == REG_RA, do not touch REG_ITMP2, until it has been saved. */ #if defined(ENABLE_THREADS) - /* space to save argument of monitor_enter */ - OOPS(); /* see powerpc */ -#if 0 - if (checksync && (m->flags & ACC_SYNCHRONIZED)) - cd->stackframesize++; -#endif + /* Space to save argument of monitor_enter and Return Values to + survive monitor_exit. The stack position for the argument can + not be shared with place to save the return register + since both values reside in R2. */ + + if (checksync && code_is_synchronized(code)) { + /* 1 slot space to save argument of monitor_enter */ + /* 1 slot to temporary store return value before monitor_exit */ + cd->stackframesize += 2; + } #endif /* Keep stack of non-leaf functions 16-byte aligned for calls into native code e.g. libc or jni (alignment problems with movaps). */ - if (!jd->isleafmethod || opt_verbosecall) + if (!code_is_leafmethod(code) || opt_verbosecall ) /* TODO really 16 bytes ? */ - cd->stackframesize = (cd->stackframesize + 3) & ~3; + cd->stackframesize = (cd->stackframesize + 2) & ~2; /* 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, 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. - */ - - if (checksync && (m->flags & ACC_SYNCHRONIZED)) - (void) dseg_add_unique_s4(cd, (rd->memuse + 1) * 4); /* IsSync */ - else -#endif -/* - (void) dseg_add_unique_s4(cd, 0);*/ /* IsSync */ + code->synchronizedoffset = rd->memuse * 8; + + /* REMOVEME: We still need it for exception handling in assembler. */ - disp = dseg_add_unique_address(cd, 0); + if (code_is_leafmethod(code)) + (void) dseg_add_unique_s4(cd, 1); + else + (void) dseg_add_unique_s4(cd, 0); - (void) dseg_add_unique_s4(cd, jd->isleafmethod); /* IsLeaf */ (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */ (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */ - (void) dseg_addlinenumbertablesize(cd); + /* Offset PV */ - (void) dseg_add_unique_s4(cd, jd->exceptiontablelength); /* ExTableSize */ + M_AADD_IMM(N_PV_OFFSET, REG_PV); - /* create exception table */ + /* create stack frame (if necessary) */ - 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); + if (cd->stackframesize) { + M_ASUB_IMM(cd->stackframesize * 8, REG_SP); } - + + /* store return address */ + + M_AST(REG_RA, REG_SP, (cd->stackframesize - 1) * 8); + /* generate method profiling code */ #if defined(ENABLE_PROFILING) if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) { /* count frequency */ - - M_ALD(REG_ITMP1, REG_PV, CodeinfoPointer); - M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency)); - M_IADD_IMM(1, REG_ITMP2); + M_ALD_DSEG(REG_ITMP1, CodeinfoPointer); + ICONST(REG_ITMP2, 1); + N_AL(REG_ITMP2, OFFSET(codeinfo, frequency), RN, REG_ITMP1); M_IST(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency)); -/* PROFILE_CYCLE_START; */ + PROFILE_CYCLE_START; } #endif - /* create stack frame (if necessary) */ - - if (cd->stackframesize) - M_ASUB_IMM(cd->stackframesize * 4, REG_SP); - - N_LHI(REG_ITMP2, disp); - N_ST(REG_SP, 0, REG_ITMP2, REG_PV); - /* save used callee saved registers and return address */ - p = cd->stackframesize; - p--; M_AST(REG_RA, REG_SP, p * 4); + p = cd->stackframesize - 1; for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) { - p--; M_IST(rd->savintregs[i], REG_SP, p * 4); + p--; M_IST(rd->savintregs[i], REG_SP, p * 8); } for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) { - p -= 2; M_DST(rd->savfltregs[i], REG_SP, p * 4); + p--; M_DST(rd->savfltregs[i], REG_SP, p * 8); } /* take arguments out of register or stack frame */ @@ -263,8 +265,9 @@ bool codegen(jitdata *jd) varindex = jd->local_map[l * 5 + t]; l++; - if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */ - l++; + + if (IS_2_WORD_TYPE(t)) + l++; if (varindex == UNUSED) continue; @@ -272,74 +275,67 @@ bool codegen(jitdata *jd) var = VAR(varindex); s1 = md->params[p].regoff; + if (IS_INT_LNG_TYPE(t)) { /* integer args */ - if (IS_2_WORD_TYPE(t)) - s2 = PACK_REGS(rd->argintregs[GET_LOW_REG(s1)], - rd->argintregs[GET_HIGH_REG(s1)]); - else - s2 = rd->argintregs[s1]; + if (IS_2_WORD_TYPE(t)) { + s2 = PACK_REGS( + GET_LOW_REG(s1), + GET_HIGH_REG(s1) + ); + } else { + s2 = s1; + } if (!md->params[p].inmemory) { /* register arguments */ if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */ - if (IS_2_WORD_TYPE(t)) + if (IS_2_WORD_TYPE(t)) { M_LNGMOVE(s2, var->vv.regoff); - else + } else { M_INTMOVE(s2, var->vv.regoff); - + } } else { /* reg arg -> spilled */ - if (IS_2_WORD_TYPE(t)) - M_LST(s2, REG_SP, var->vv.regoff * 4); - else - M_IST(s2, REG_SP, var->vv.regoff * 4); + if (IS_2_WORD_TYPE(t)) { + M_LST(s2, REG_SP, var->vv.regoff); + } else { + M_IST(s2, REG_SP, var->vv.regoff); + } } } else { /* stack arguments */ if (!IS_INMEMORY(var->flags)) { /* stack arg -> register */ - if (IS_2_WORD_TYPE(t)) - M_LLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 4); - else - M_ILD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 4); - - } else { /* stack arg -> spilled */ - M_ILD(REG_ITMP1, REG_SP, (cd->stackframesize + s1) * 4); - M_IST(REG_ITMP1, REG_SP, var->vv.regoff * 4); if (IS_2_WORD_TYPE(t)) { - M_ILD(REG_ITMP1, REG_SP, (cd->stackframesize + s1) * 4 +4); - M_IST(REG_ITMP1, REG_SP, var->vv.regoff * 4 + 4); + M_LLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1); + } else { + M_ILD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1); } + } else { /* stack arg -> spilled */ + N_MVC(var->vv.regoff, 8, REG_SP, cd->stackframesize * 8 + s1, REG_SP); } } } else { /* floating args */ if (!md->params[p].inmemory) { /* register arguments */ - s2 = rd->argfltregs[s1]; + s2 = s1; if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */ M_FLTMOVE(s2, var->vv.regoff); } else { /* reg arg -> spilled */ if (IS_2_WORD_TYPE(t)) - M_DST(s2, REG_SP, var->vv.regoff * 4); + M_DST(s2, REG_SP, var->vv.regoff); else - M_FST(s2, REG_SP, var->vv.regoff * 4); + M_FST(s2, REG_SP, var->vv.regoff); } } else { /* stack arguments */ if (!IS_INMEMORY(var->flags)) { /* stack-arg -> register */ if (IS_2_WORD_TYPE(t)) - M_DLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 4); + M_DLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1); else - M_FLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 4); + M_FLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1); } else { /* stack-arg -> spilled */ - if (IS_2_WORD_TYPE(t)) { - M_DLD(REG_FTMP1, REG_SP, (cd->stackframesize + s1) * 4); - M_DST(REG_FTMP1, REG_SP, var->vv.regoff * 4); - var->vv.regoff = cd->stackframesize + s1; - - } else { - M_FLD(REG_FTMP1, REG_SP, (cd->stackframesize + s1) * 4); - M_FST(REG_FTMP1, REG_SP, var->vv.regoff * 4); - } + N_MVC(var->vv.regoff, 8, REG_SP, cd->stackframesize * 8 + s1, REG_SP); + var->vv.regoff = cd->stackframesize * 8 + s1; } } } @@ -348,47 +344,57 @@ bool codegen(jitdata *jd) /* save monitorenter argument */ #if defined(ENABLE_THREADS) - if (checksync && (m->flags & ACC_SYNCHRONIZED)) { + if (checksync && code_is_synchronized(code)) { /* stack offset for monitor argument */ s1 = rd->memuse; +#if !defined(NDEBUG) if (opt_verbosecall) { - M_LSUB_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP); + M_ASUB_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP); for (p = 0; p < INT_ARG_CNT; p++) - M_LST(rd->argintregs[p], REG_SP, p * 8); + M_IST(abi_registers_integer_argument[p], REG_SP, p * 8); for (p = 0; p < FLT_ARG_CNT; p++) - M_DST(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 8); + M_DST(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8); - s1 += INT_ARG_CNT + FLT_ARG_CNT; + s1 += ((INT_ARG_CNT + FLT_ARG_CNT)); } +#endif /* decide which monitor enter function to call */ if (m->flags & ACC_STATIC) { - M_MOV_IMM(&m->class->object.header, REG_A0); + disp = dseg_add_address(cd, &m->clazz->object.header); + M_ALD_DSEG(REG_A0, disp); } else { M_TEST(REG_A0); - M_BEQ(0); - codegen_add_nullpointerexception_ref(cd); + M_BNE(SZ_BRC + SZ_ILL); + M_ILL(EXCEPTION_HARDWARE_NULLPOINTER); } + disp = dseg_add_functionptr(cd, LOCK_monitor_enter); + M_ALD_DSEG(REG_ITMP2, disp); + M_AST(REG_A0, REG_SP, s1 * 8); - M_MOV_IMM(LOCK_monitor_enter, REG_ITMP1); - M_CALL(REG_ITMP1); + M_ASUB_IMM(96, REG_SP); + M_CALL(REG_ITMP2); + M_AADD_IMM(96, REG_SP); + +#if !defined(NDEBUG) if (opt_verbosecall) { for (p = 0; p < INT_ARG_CNT; p++) - M_LLD(rd->argintregs[p], REG_SP, p * 8); + M_ILD(abi_registers_integer_argument[p], REG_SP, p * 8); for (p = 0; p < FLT_ARG_CNT; p++) - M_DLD(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 8); + M_DLD(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8); - M_LADD_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP); + M_AADD_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP); } +#endif } #endif @@ -400,9 +406,10 @@ bool codegen(jitdata *jd) } /* end of header generation */ -#if 0 - replacementpoint = jd->code->rplpoints; -#endif + + /* create replacement points */ + + REPLACEMENT_POINTS_INIT(cd, jd); /* walk through all basic blocks */ @@ -418,35 +425,31 @@ 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++; - - assert(cd->lastmcodeptr <= cd->mcodeptr); - cd->lastmcodeptr = cd->mcodeptr + 5; /* 5 byte jmp patch */ - } -#endif + REPLACEMENT_POINT_BLOCK_START(cd, bptr); /* copy interface registers to their destination */ len = bptr->indepth; MCODECHECK(512); +#if defined(ENABLE_PROFILING) /* generate basicblock profiling code */ if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) { /* count frequency */ - M_MOV_IMM(code->bbfrequency, REG_ITMP3); - M_IINC_MEMBASE(REG_ITMP3, bptr->nr * 4); + M_ALD_DSEG(REG_ITMP1, CodeinfoPointer); + M_ALD(REG_ITMP1, REG_ITMP1, OFFSET(codeinfo, bbfrequency)); + ICONST(REG_ITMP2, 1); + N_AL(REG_ITMP2, bptr->nr * 4, RN, REG_ITMP1); + M_IST(REG_ITMP2, REG_ITMP1, bptr->nr * 4); /* if this is an exception handler, start profiling again */ if (bptr->type == BBTYPE_EXH) PROFILE_CYCLE_START; } +#endif #if defined(ENABLE_LSRA) if (opt_lsra) { @@ -457,10 +460,10 @@ bool codegen(jitdata *jd) if (bptr->type == BBTYPE_EXH) { /* d = reg_of_var(rd, src, REG_ITMP1); */ if (!IS_INMEMORY(src->flags)) - d= src->vv.regoff; + d = src->vv.regoff; else - d=REG_ITMP1; - M_INTMOVE(REG_ITMP1, d); + d = REG_ITMP3_XPTR; + M_INTMOVE(REG_ITMP3_XPTR, d); emit_store(jd, NULL, src, d); } } @@ -474,8 +477,8 @@ bool codegen(jitdata *jd) var = VAR(bptr->invars[len]); if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) { if (bptr->type == BBTYPE_EXH) { - d = codegen_reg_of_var(0, var, REG_ITMP1); - M_INTMOVE(REG_ITMP1, d); + d = codegen_reg_of_var(0, var, REG_ITMP3_XPTR); + M_INTMOVE(REG_ITMP3_XPTR, d); emit_store(jd, NULL, var, d); } } @@ -493,7 +496,7 @@ 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; } @@ -503,18 +506,29 @@ bool codegen(jitdata *jd) case ICMD_NOP: /* ... ==> ... */ case ICMD_POP: /* ..., value ==> ... */ case ICMD_POP2: /* ..., value, value ==> ... */ - case ICMD_INLINE_START: /* internal ICMDs */ + break; + + case ICMD_INLINE_START: + + REPLACEMENT_POINT_INLINE_START(cd, iptr); + break; + + case ICMD_INLINE_BODY: + + REPLACEMENT_POINT_INLINE_BODY(cd, iptr); + linenumbertable_list_entry_add_inline_start(cd, iptr); + linenumbertable_list_entry_add(cd, iptr->line); + break; + case ICMD_INLINE_END: + + linenumbertable_list_entry_add_inline_end(cd, iptr); + linenumbertable_list_entry_add(cd, iptr->line); break; case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */ - OOPS(); -#if 0 s1 = emit_load_s1(jd, iptr, REG_ITMP1); - M_TEST(s1); - M_BEQ(0); - codegen_add_nullpointerexception_ref(cd); -#endif + emit_nullpointer_check(cd, iptr, s1); break; /* constant operations ************************************************/ @@ -526,29 +540,24 @@ bool codegen(jitdata *jd) break; case ICMD_LCONST: /* ... ==> ..., constant */ - OOPS(); -#if 0 - d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); + + d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED); LCONST(d, iptr->sx.val.l); emit_store_dst(jd, iptr, d); -#endif break; case ICMD_FCONST: /* ... ==> ..., constant */ d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); disp = dseg_add_float(cd, iptr->sx.val.f); - M_FLDN(d, REG_PV, disp, REG_ITMP1); + M_FLD_DSEG(d, disp, REG_ITMP1); emit_store_dst(jd, iptr, d); break; case ICMD_DCONST: /* ... ==> ..., constant */ - OOPS(); -#if 0 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); disp = dseg_add_double(cd, iptr->sx.val.d); - emit_movd_membase_reg(cd, RIP, -((cd->mcodeptr + 9) - cd->mcodebase) + disp, d); + M_DLD_DSEG(d, disp, REG_ITMP1); emit_store_dst(jd, iptr, d); -#endif break; case ICMD_ACONST: /* ... ==> ..., constant */ @@ -560,18 +569,28 @@ bool codegen(jitdata *jd) /* PROFILE_CYCLE_STOP; */ - codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_classinfo, + patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo, cr, disp); /* PROFILE_CYCLE_START; */ - M_ALD(d, REG_PV, disp); + M_ALD_DSEG(d, disp); } else { if (iptr->sx.val.anyptr == 0) { M_CLR(d); } else { disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr); - M_ALD(d, REG_PV, disp); + M_ALD_DSEG(d, disp); + /* + if (((u4)(iptr->sx.val.anyptr) & 0x00008000) == 0) { + N_LHI(d, ((u4)(iptr->sx.val.anyptr) >> 16) & 0xFFFF); + M_SLL_IMM(16, d); + N_AHI(d, (u4)(iptr->sx.val.anyptr) & 0xFFFF); + } else { + disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr); + M_ALD_DSEG(d, disp); + } + */ } } emit_store_dst(jd, iptr, d); @@ -591,89 +610,89 @@ bool codegen(jitdata *jd) 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; /* integer operations *************************************************/ case ICMD_INEG: /* ..., value ==> ..., - value */ - OOPS(); -#if 0 + s1 = emit_load_s1(jd, iptr, REG_ITMP1); - d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); - M_INTMOVE(s1, d); - M_INEG(d); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); + M_INEG(s1, d); emit_store_dst(jd, iptr, d); -#endif + break; case ICMD_LNEG: /* ..., value ==> ..., - value */ - OOPS(); -#if 0 - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); - M_INTMOVE(s1, d); - M_LNEG(d); + + s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED); + M_INEG(GET_HIGH_REG(s1), GET_HIGH_REG(d)); + M_INEG(GET_LOW_REG(s1), GET_LOW_REG(d)); + N_BRC(8 /* result zero, no overflow */, SZ_BRC + SZ_AHI); + N_AHI(GET_HIGH_REG(d), -1); emit_store_dst(jd, iptr, d); -#endif break; case ICMD_I2L: /* ..., value ==> ..., value */ - OOPS(); -#if 0 - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - d = codegen_reg_of_dst(jd, iptr, REG_ITMP3); - M_ISEXT(s1, d); + + d = codegen_reg_of_dst(jd, iptr, REG_ITMP31_PACKED); /* even-odd */ + if (! N_IS_EVEN_ODD(d)) { + d = REG_ITMP31_PACKED; + } + assert(N_IS_EVEN_ODD(d)); + + s1 = emit_load_s1(jd, iptr, REG_ITMP2); + + M_INTMOVE(s1, GET_HIGH_REG(d)); + M_SRDA_IMM(32, GET_HIGH_REG(d)); + + emit_copy_dst(jd, iptr, d); emit_store_dst(jd, iptr, d); -#endif break; case ICMD_L2I: /* ..., value ==> ..., value */ - OOPS(); -#if 0 - s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s1 = emit_load_s1_low(jd, iptr, REG_ITMP1); d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); - M_IMOV(s1, d); + M_INTMOVE(GET_LOW_REG(s1), d); emit_store_dst(jd, iptr, d); -#endif break; case ICMD_INT2BYTE: /* ..., value ==> ..., value */ - OOPS(); -#if 0 s1 = emit_load_s1(jd, iptr, REG_ITMP1); - d = codegen_reg_of_dst(jd, iptr, REG_ITMP3); - M_BSEXT(s1, d); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); + M_INTMOVE(s1, d); + M_SLL_IMM(24, d); + M_SRA_IMM(24, d); emit_store_dst(jd, iptr, d); -#endif break; case ICMD_INT2CHAR: /* ..., value ==> ..., value */ - OOPS(); -#if 0 s1 = emit_load_s1(jd, iptr, REG_ITMP1); - d = codegen_reg_of_dst(jd, iptr, REG_ITMP3); - M_CZEXT(s1, d); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); + M_INTMOVE(s1, d); + M_SLL_IMM(16, d); + M_SRL_IMM(16, d); emit_store_dst(jd, iptr, d); -#endif break; case ICMD_INT2SHORT: /* ..., value ==> ..., value */ - OOPS(); -#if 0 + s1 = emit_load_s1(jd, iptr, REG_ITMP1); - d = codegen_reg_of_dst(jd, iptr, REG_ITMP3); - M_SSEXT(s1, d); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); + M_INTMOVE(s1, d); + M_SLL_IMM(16, d); + M_SRA_IMM(16, d); emit_store_dst(jd, iptr, d); -#endif break; - case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); @@ -694,47 +713,85 @@ bool codegen(jitdata *jd) /* sx.val.i = constant */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); - M_INTMOVE(s1, d); - M_IADD_IMM(iptr->sx.val.i, d); + + if (N_VALID_IMM(iptr->sx.val.i)) { + M_IADD_IMM(iptr->sx.val.i, d); + } else { + ICONST(REG_ITMP2, iptr->sx.val.i); + M_IADD(REG_ITMP2, d); + } emit_store_dst(jd, iptr, d); break; case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */ - OOPS(); -#if 0 - 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 (s2 == d) - M_LADD(s1, d); - else { - M_INTMOVE(s1, d); - M_LADD(s2, d); + + /* M, (r, q) -> (r, q) */ + + d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED); + + s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED)); + s2 = emit_load_s2_high(jd, iptr, REG_ITMP3); + dd = GET_HIGH_REG(d); + + if (s2 == dd) { + M_IADD(s1, dd); + } else { + M_INTMOVE(s1, dd); + M_IADD(s2, dd); + } + + s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED)); + s2 = emit_load_s2_low(jd, iptr, REG_ITMP3); + dd = GET_LOW_REG(d); + + if (s2 == dd) { + N_ALR(dd, s1); + } else { + M_INTMOVE(s1, dd); + N_ALR(dd, s2); } + + N_BRC(8 | 4, SZ_BRC + SZ_AHI); + N_AHI(GET_HIGH_REG(d), 1); + emit_store_dst(jd, iptr, d); -#endif break; case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */ /* sx.val.l = constant */ - OOPS(); -#if 0 - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); - M_INTMOVE(s1, d); - if (IS_IMM32(iptr->sx.val.l)) - M_LADD_IMM(iptr->sx.val.l, d); - else { - M_MOV_IMM(iptr->sx.val.l, REG_ITMP2); - M_LADD(REG_ITMP2, d); + + d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED); + dd = GET_HIGH_REG(d); + + s1 = emit_load_s1_high(jd, iptr, dd); + s3 = iptr->sx.val.l >> 32; + + M_INTMOVE(s1, dd); + + if (N_VALID_IMM(s3)) { + M_IADD_IMM(s3, dd); + } else { + ICONST(REG_ITMP3, s3); + M_IADD(REG_ITMP3, dd); } + + dd = GET_LOW_REG(d); + s1 = emit_load_s1_low(jd, iptr, dd); + s3 = iptr->sx.val.l & 0xffffffff; + ICONST(REG_ITMP3, s3); + + M_INTMOVE(s1, dd); + N_ALR(dd, REG_ITMP3); + + N_BRC(8 | 4, SZ_BRC + SZ_AHI); + N_AHI(GET_HIGH_REG(d), 1); + emit_store_dst(jd, iptr, d); -#endif break; case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */ - + 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); @@ -752,636 +809,438 @@ bool codegen(jitdata *jd) case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */ /* sx.val.i = constant */ - OOPS(); -#if 0 + s1 = emit_load_s1(jd, iptr, REG_ITMP1); d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); M_INTMOVE(s1, d); - M_ISUB_IMM(iptr->sx.val.i, d); + + if (N_VALID_IMM(-iptr->sx.val.i)) { + M_ISUB_IMM(iptr->sx.val.i, d); + } else { + ICONST(REG_ITMP2, iptr->sx.val.i); + M_ISUB(REG_ITMP2, d); + } emit_store_dst(jd, iptr, d); -#endif + break; case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */ - OOPS(); -#if 0 - 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 (s2 == d) { - M_INTMOVE(s1, REG_ITMP1); - M_LSUB(s2, REG_ITMP1); - M_INTMOVE(REG_ITMP1, d); - } else { - M_INTMOVE(s1, d); - M_LSUB(s2, d); + + d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED); + + s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED)); + s2 = emit_load_s2_high(jd, iptr, REG_ITMP3); + dd = GET_HIGH_REG(d); + + if (s2 == dd) { + M_INTMOVE(s2, REG_ITMP3); + s2 = REG_ITMP3; } + + M_INTMOVE(s1, dd); + M_ISUB(s2, dd); + + s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED)); + s2 = emit_load_s2_low(jd, iptr, REG_ITMP3); + dd = GET_LOW_REG(d); + + if (s2 == dd) { + M_INTMOVE(s2, REG_ITMP3); + s2 = REG_ITMP3; + } + + M_INTMOVE(s1, dd); + N_SLR(dd, s2); + + N_BRC(1 | 2, SZ_BRC + SZ_AHI); + N_AHI(GET_HIGH_REG(d), -1); + emit_store_dst(jd, iptr, d); -#endif break; case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */ /* sx.val.l = constant */ - OOPS(); -#if 0 - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); - M_INTMOVE(s1, d); - if (IS_IMM32(iptr->sx.val.l)) - M_LSUB_IMM(iptr->sx.val.l, d); - else { - M_MOV_IMM(iptr->sx.val.l, REG_ITMP2); - M_LSUB(REG_ITMP2, d); - } - emit_store_dst(jd, iptr, d); -#endif - break; - case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */ - OOPS(); -#if 0 - 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 (s2 == d) - M_IMUL(s1, d); - else { - M_INTMOVE(s1, d); - M_IMUL(s2, d); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED); + + dd = GET_HIGH_REG(d); + s1 = emit_load_s1_high(jd, iptr, dd); + s3 = iptr->sx.val.l >> 32; + + M_INTMOVE(s1, dd); + + if (N_VALID_IMM(-s3)) { + M_IADD_IMM(-s3, dd); + } else { + ICONST(REG_ITMP3, s3); + M_ISUB(REG_ITMP3, dd); } - emit_store_dst(jd, iptr, d); -#endif - break; - case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */ - /* sx.val.i = constant */ - OOPS(); -#if 0 - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); - if (iptr->sx.val.i == 2) { - M_INTMOVE(s1, d); - M_ISLL_IMM(1, d); - } else - M_IMUL_IMM(s1, iptr->sx.val.i, d); + dd = GET_LOW_REG(d); + s1 = emit_load_s1_low(jd, iptr, dd); + s3 = iptr->sx.val.l & 0xffffffff; + ICONST(REG_ITMP3, s3); + + M_INTMOVE(s1, dd); + N_SLR(dd, REG_ITMP3); + + N_BRC(1 | 2, SZ_BRC + SZ_AHI); + N_AHI(GET_HIGH_REG(d), -1); + emit_store_dst(jd, iptr, d); -#endif break; - case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */ - OOPS(); -#if 0 + case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */ + 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 (s2 == d) - M_LMUL(s1, d); + M_IMUL(s1, d); else { M_INTMOVE(s1, d); - M_LMUL(s2, d); + M_IMUL(s2, d); } emit_store_dst(jd, iptr, d); -#endif + break; - case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */ - /* sx.val.l = constant */ - OOPS(); -#if 0 + case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */ + /* sx.val.i = constant */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); - if (IS_IMM32(iptr->sx.val.l)) - M_LMUL_IMM(s1, iptr->sx.val.l, d); - else { - M_MOV_IMM(iptr->sx.val.l, REG_ITMP2); - M_INTMOVE(s1, d); - M_LMUL(REG_ITMP2, d); + M_INTMOVE(s1, d); + if (iptr->sx.val.i == 2) { + M_SLL_IMM(1, d); + } else if (N_VALID_IMM(iptr->sx.val.i)) { + M_IMUL_IMM(iptr->sx.val.i, d); + } else { + disp = dseg_add_s4(cd, iptr->sx.val.i); + M_ILD_DSEG(REG_ITMP2, disp); + M_IMUL(REG_ITMP2, d); } emit_store_dst(jd, iptr, d); -#endif break; case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */ - OOPS(); -#if 0 - var1 = VAROP(iptr->s1); - var2 = VAROP(iptr->sx.s23.s2); - dst = VAROP(iptr->dst); + case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */ - d = codegen_reg_of_dst(jd, iptr, REG_NULL); - if (IS_INMEMORY(var1->flags)) - M_ILD(RAX, REG_SP, var1->vv.regoff * 8); - else - M_INTMOVE(var1->vv.regoff, RAX); - - if (IS_INMEMORY(var2->flags)) - M_ILD(REG_ITMP3, REG_SP, var2->vv.regoff * 8); - else - M_INTMOVE(var2->vv.regoff, REG_ITMP3); - - if (checknull) { - M_ITEST(REG_ITMP3); - M_BEQ(0); - codegen_add_arithmeticexception_ref(cd); - } + /* load s1 into r0 */ - emit_alul_imm_reg(cd, ALU_CMP, 0x80000000, RAX); /* check as described in jvm spec */ - emit_jcc(cd, CC_NE, 4 + 6); - emit_alul_imm_reg(cd, ALU_CMP, -1, REG_ITMP3); /* 4 bytes */ - emit_jcc(cd, CC_E, 3 + 1 + 3); /* 6 bytes */ + s1 = emit_load_s1(jd, iptr, GET_HIGH_REG(REG_ITMP31_PACKED)); + M_INTMOVE(s1, GET_HIGH_REG(REG_ITMP31_PACKED)); + s1 = GET_HIGH_REG(REG_ITMP31_PACKED); - emit_mov_reg_reg(cd, RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */ - emit_cltd(cd); - emit_idivl_reg(cd, REG_ITMP3); + s2 = emit_load_s2(jd, iptr, REG_ITMP2); - if (IS_INMEMORY(dst->flags)) { - emit_mov_reg_membase(cd, RAX, REG_SP, dst->vv.regoff * 8); - emit_mov_reg_reg(cd, REG_ITMP2, RDX); /* restore %rdx */ + /* extend s1 to long */ - } else { - M_INTMOVE(RAX, dst->vv.regoff); + M_SRDA_IMM(32, GET_HIGH_REG(REG_ITMP31_PACKED)); - if (dst->vv.regoff != RDX) { - emit_mov_reg_reg(cd, REG_ITMP2, RDX); /* restore %rdx */ - } - } -#endif - break; + /* divide */ - case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */ - OOPS(); -#if 0 - var1 = VAROP(iptr->s1); - var2 = VAROP(iptr->sx.s23.s2); - dst = VAROP(iptr->dst); + N_DR(GET_HIGH_REG(REG_ITMP31_PACKED), s2); - d = codegen_reg_of_dst(jd, iptr, REG_NULL); - if (IS_INMEMORY(var1->flags)) - M_ILD(RAX, REG_SP, var1->vv.regoff * 8); - else - M_INTMOVE(var1->vv.regoff, RAX); - - if (IS_INMEMORY(var2->flags)) - M_ILD(REG_ITMP3, REG_SP, var2->vv.regoff * 8); - else - M_INTMOVE(var2->vv.regoff, REG_ITMP3); + /* take result */ - if (checknull) { - M_ITEST(REG_ITMP3); - M_BEQ(0); - codegen_add_arithmeticexception_ref(cd); + switch (iptr->opc) { + case ICMD_IREM: + d = codegen_reg_of_dst(jd, iptr, GET_HIGH_REG(REG_ITMP31_PACKED)); + M_INTMOVE(GET_HIGH_REG(REG_ITMP31_PACKED), d); + break; + case ICMD_IDIV: + d = codegen_reg_of_dst(jd, iptr, GET_LOW_REG(REG_ITMP31_PACKED)); + M_INTMOVE(GET_LOW_REG(REG_ITMP31_PACKED), d); + break; } - emit_mov_reg_reg(cd, RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */ + emit_store_dst(jd, iptr, d); - emit_alul_imm_reg(cd, ALU_CMP, 0x80000000, RAX); /* check as described in jvm spec */ - emit_jcc(cd, CC_NE, 2 + 4 + 6); + break; + case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */ + case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */ - emit_alul_reg_reg(cd, ALU_XOR, RDX, RDX); /* 2 bytes */ - emit_alul_imm_reg(cd, ALU_CMP, -1, REG_ITMP3); /* 4 bytes */ - emit_jcc(cd, CC_E, 1 + 3); /* 6 bytes */ + bte = iptr->sx.s23.s3.bte; + md = bte->md; - emit_cltd(cd); - emit_idivl_reg(cd, REG_ITMP3); + /* test s2 for zero */ - if (IS_INMEMORY(dst->flags)) { - emit_mov_reg_membase(cd, RDX, REG_SP, dst->vv.regoff * 8); - emit_mov_reg_reg(cd, REG_ITMP2, RDX); /* restore %rdx */ + s2 = emit_load_s2(jd, iptr, REG_ITMP12_PACKED); + M_INTMOVE(GET_LOW_REG(s2), REG_ITMP3); + M_IOR(GET_HIGH_REG(s2), REG_ITMP3); + emit_arithmetic_check(cd, iptr, REG_ITMP3); - } else { - M_INTMOVE(RDX, dst->vv.regoff); + /* TODO SIGFPE? */ - if (dst->vv.regoff != RDX) { - emit_mov_reg_reg(cd, REG_ITMP2, RDX); /* restore %rdx */ - } - } -#endif - break; + disp = dseg_add_functionptr(cd, bte->fp); - case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */ - /* sx.val.i = constant */ - OOPS(); -#if 0 - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - d = codegen_reg_of_dst(jd, iptr, REG_ITMP3); - M_INTMOVE(s1, REG_ITMP1); - emit_alul_imm_reg(cd, ALU_CMP, -1, REG_ITMP1); - emit_leal_membase_reg(cd, REG_ITMP1, (1 << iptr->sx.val.i) - 1, REG_ITMP2); - emit_cmovccl_reg_reg(cd, CC_LE, REG_ITMP2, REG_ITMP1); - emit_shiftl_imm_reg(cd, SHIFT_SAR, iptr->sx.val.i, REG_ITMP1); - emit_mov_reg_reg(cd, REG_ITMP1, d); - emit_store_dst(jd, iptr, d); -#endif - break; + /* load arguments */ - case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */ - /* sx.val.i = constant */ - OOPS(); -#if 0 - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - d = codegen_reg_of_dst(jd, iptr, REG_ITMP3); - M_INTMOVE(s1, REG_ITMP1); - emit_alul_imm_reg(cd, ALU_CMP, -1, REG_ITMP1); - emit_leal_membase_reg(cd, REG_ITMP1, iptr->sx.val.i, REG_ITMP2); - emit_cmovccl_reg_reg(cd, CC_G, REG_ITMP1, REG_ITMP2); - emit_alul_imm_reg(cd, ALU_AND, -1 - (iptr->sx.val.i), REG_ITMP2); - emit_alul_reg_reg(cd, ALU_SUB, REG_ITMP2, REG_ITMP1); - emit_mov_reg_reg(cd, REG_ITMP1, d); - emit_store_dst(jd, iptr, d); -#endif - break; + M_LNGMOVE(s2, PACK_REGS(REG_A3, REG_A2)); + s1 = emit_load_s1(jd, iptr, PACK_REGS(REG_A1, REG_A0)); + M_LNGMOVE(s1, PACK_REGS(REG_A1, REG_A0)); - case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */ - OOPS(); -#if 0 - var1 = VAROP(iptr->s1); - var2 = VAROP(iptr->sx.s23.s2); - dst = VAROP(iptr->dst); + /* call builtin */ - d = codegen_reg_of_dst(jd, iptr, REG_NULL); + M_ASUB_IMM(96, REG_SP); + M_ALD_DSEG(REG_ITMP2, disp); + M_JSR(REG_RA, REG_ITMP2); + M_AADD_IMM(96, REG_SP); - if (IS_INMEMORY(var1->flags)) - M_LLD(RAX, REG_SP, var1->vv.regoff * 8); - else - M_INTMOVE(var1->vv.regoff, RAX); - - if (IS_INMEMORY(var2->flags)) - M_LLD(REG_ITMP3, REG_SP, var2->vv.regoff * 8); - else - M_INTMOVE(var2->vv.regoff, REG_ITMP3); + /* store result */ - if (checknull) { - M_TEST(REG_ITMP3); - M_BEQ(0); - codegen_add_arithmeticexception_ref(cd); - } + d = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED); + M_LNGMOVE(REG_RESULT_PACKED, d); + emit_store_dst(jd, iptr, d); - /* check as described in jvm spec */ - disp = dseg_add_s8(cd, 0x8000000000000000LL); - M_LCMP_MEMBASE(RIP, -((cd->mcodeptr + 7) - cd->mcodebase) + disp, RAX); - M_BNE(4 + 6); - M_LCMP_IMM(-1, REG_ITMP3); /* 4 bytes */ - M_BEQ(3 + 2 + 3); /* 6 bytes */ + break; - M_MOV(RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */ - emit_cqto(cd); - emit_idiv_reg(cd, REG_ITMP3); + case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */ + case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */ + case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */ - if (IS_INMEMORY(dst->flags)) { - M_LST(RAX, REG_SP, dst->vv.regoff * 8); - M_MOV(REG_ITMP2, RDX); /* restore %rdx */ + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); + s2 = emit_load_s2(jd, iptr, REG_ITMP2); - } else { - M_INTMOVE(RAX, dst->vv.regoff); + /* Use only 5 bits of sencond operand. */ - if (dst->vv.regoff != RDX) { - M_MOV(REG_ITMP2, RDX); /* restore %rdx */ - } + M_INTMOVE(s2, REG_ITMP2); + s2 = REG_ITMP2; + ICONST(REG_ITMP3, 0x1F); + M_IAND(REG_ITMP3, s2); + + M_INTMOVE(s1, d); + + switch (iptr->opc) { + case ICMD_ISHL: + M_SLL(s2, d); + break; + case ICMD_ISHR: + M_SRA(s2, d); + break; + case ICMD_IUSHR: + M_SRL(s2, d); + break; + default: + assert(0); } -#endif + emit_store_dst(jd, iptr, d); break; - case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */ - OOPS(); -#if 0 - var1 = VAROP(iptr->s1); - var2 = VAROP(iptr->sx.s23.s2); - dst = VAROP(iptr->dst); + case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */ + /* sx.val.i = constant */ + { + u1 *ref; - d = codegen_reg_of_dst(jd, iptr, REG_NULL); - - if (IS_INMEMORY(var1->flags)) - M_LLD(REG_ITMP1, REG_SP, var1->vv.regoff * 8); - else - M_INTMOVE(var1->vv.regoff, REG_ITMP1); - - if (IS_INMEMORY(var2->flags)) - M_LLD(REG_ITMP3, REG_SP, var2->vv.regoff * 8); - else - M_INTMOVE(var2->vv.regoff, REG_ITMP3); - /* - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - M_INTMOVE(s1, REG_ITMP1); - s2 = emit_load_s2(jd, iptr, REG_ITMP3); - M_INTMOVE(s2, REG_ITMP3); - */ - if (checknull) { - M_ITEST(REG_ITMP3); - M_BEQ(0); - codegen_add_arithmeticexception_ref(cd); - } + assert(iptr->sx.val.i <= 32); - M_MOV(RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */ + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); - /* check as described in jvm spec */ - disp = dseg_add_s8(cd, 0x8000000000000000LL); - M_LCMP_MEMBASE(RIP, -((cd->mcodeptr + 7) - cd->mcodebase) + disp, REG_ITMP1); - M_BNE(3 + 4 + 6); + M_INTMOVE(s1, d); + M_TEST(d); + ref = cd->mcodeptr; + M_BGE(0); -#if 0 - emit_alul_reg_reg(cd, ALU_XOR, RDX, RDX); /* 2 bytes */ -#endif - M_LXOR(RDX, RDX); /* 3 bytes */ - M_LCMP_IMM(-1, REG_ITMP3); /* 4 bytes */ - M_BEQ(2 + 3); /* 6 bytes */ + s3 = (1 << iptr->sx.val.i) - 1; - emit_cqto(cd); - emit_idiv_reg(cd, REG_ITMP3); + if (N_VALID_IMM(s3)) { + M_IADD_IMM(s3, d); + } else { + ICONST(REG_ITMP1, -1); + M_SRL_IMM(32 - iptr->sx.val.i, REG_ITMP1); + M_IADD(REG_ITMP1, d); + } - if (IS_INMEMORY(dst->flags)) { - M_LST(RDX, REG_SP, dst->vv.regoff * 8); - M_MOV(REG_ITMP2, RDX); /* restore %rdx */ + N_BRC_BACK_PATCH(ref); - } else { - M_INTMOVE(RDX, dst->vv.regoff); + M_SRA_IMM(iptr->sx.val.i, d); - if (dst->vv.regoff != RDX) { - M_MOV(REG_ITMP2, RDX); /* restore %rdx */ - } + emit_store_dst(jd, iptr, d); } -#endif - break; - case ICMD_LDIVPOW2: /* ..., value ==> ..., value >> constant */ - /* sx.val.i = constant */ - OOPS(); -#if 0 - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - d = codegen_reg_of_dst(jd, iptr, REG_ITMP3); - M_INTMOVE(s1, REG_ITMP1); - emit_alu_imm_reg(cd, ALU_CMP, -1, REG_ITMP1); - emit_lea_membase_reg(cd, REG_ITMP1, (1 << iptr->sx.val.i) - 1, REG_ITMP2); - emit_cmovcc_reg_reg(cd, CC_LE, REG_ITMP2, REG_ITMP1); - emit_shift_imm_reg(cd, SHIFT_SAR, iptr->sx.val.i, REG_ITMP1); - emit_mov_reg_reg(cd, REG_ITMP1, d); - emit_store_dst(jd, iptr, d); -#endif break; + + case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */ + /* sx.val.i = constant */ - case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */ - /* sx.val.l = constant */ - OOPS(); -#if 0 s1 = emit_load_s1(jd, iptr, REG_ITMP1); - d = codegen_reg_of_dst(jd, iptr, REG_ITMP3); - M_INTMOVE(s1, REG_ITMP1); - emit_alu_imm_reg(cd, ALU_CMP, -1, REG_ITMP1); - emit_lea_membase_reg(cd, REG_ITMP1, iptr->sx.val.i, REG_ITMP2); - emit_cmovcc_reg_reg(cd, CC_G, REG_ITMP1, REG_ITMP2); - emit_alu_imm_reg(cd, ALU_AND, -1 - (iptr->sx.val.i), REG_ITMP2); - emit_alu_reg_reg(cd, ALU_SUB, REG_ITMP2, REG_ITMP1); - emit_mov_reg_reg(cd, REG_ITMP1, d); - emit_store_dst(jd, iptr, d); -#endif - break; + d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); - case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */ - OOPS(); -#if 0 - d = codegen_reg_of_dst(jd, iptr, REG_NULL); - emit_ishift(jd, SHIFT_SHL, iptr); -#endif - break; + if (s1 == d) { + M_MOV(s1, REG_ITMP1); + s1 = REG_ITMP1; + } + + ICONST(REG_ITMP3, iptr->sx.val.i); - case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */ - /* sx.val.i = constant */ - OOPS(); -#if 0 - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); M_INTMOVE(s1, d); - M_ISLL_IMM(iptr->sx.val.i, d); - emit_store_dst(jd, iptr, d); -#endif - break; + M_IAND(REG_ITMP3, d); - case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */ - OOPS(); -#if 0 - d = codegen_reg_of_dst(jd, iptr, REG_NULL); - emit_ishift(jd, SHIFT_SAR, iptr); -#endif - break; + M_TEST(s1); + M_BGE(SZ_BRC + SZ_LCR + SZ_NR + SZ_LCR); + + N_LCR(d, s1); + N_NR(d, REG_ITMP3); + N_LCR(d, d); - case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */ - /* sx.val.i = constant */ - OOPS(); -#if 0 - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); - M_INTMOVE(s1, d); - M_ISRA_IMM(iptr->sx.val.i, d); emit_store_dst(jd, iptr, d); -#endif - break; - case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */ - OOPS(); -#if 0 - d = codegen_reg_of_dst(jd, iptr, REG_NULL); - emit_ishift(jd, SHIFT_SHR, iptr); -#endif break; + case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */ + /* sx.val.i = constant */ + case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */ + /* sx.val.i = constant */ case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */ /* sx.val.i = constant */ - OOPS(); -#if 0 s1 = emit_load_s1(jd, iptr, REG_ITMP1); - d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); + M_INTMOVE(s1, d); - M_ISRL_IMM(iptr->sx.val.i, d); - emit_store_dst(jd, iptr, d); -#endif - break; - case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */ - OOPS(); -#if 0 - d = codegen_reg_of_dst(jd, iptr, REG_NULL); - emit_lshift(jd, SHIFT_SHL, iptr); -#endif - break; + disp = iptr->sx.val.i & 0x1F; /* Use only 5 bits of value */ + + switch (iptr->opc) { + case ICMD_ISHLCONST: + N_SLL(d, disp, RN); + break; + case ICMD_ISHRCONST: + N_SRA(d, disp, RN); + break; + case ICMD_IUSHRCONST: + N_SRL(d, disp, RN); + break; + default: + assert(0); + } - case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */ - /* sx.val.i = constant */ - OOPS(); -#if 0 - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); - M_INTMOVE(s1, d); - M_LSLL_IMM(iptr->sx.val.i, d); emit_store_dst(jd, iptr, d); -#endif break; - case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */ - OOPS(); -#if 0 - d = codegen_reg_of_dst(jd, iptr, REG_NULL); - emit_lshift(jd, SHIFT_SAR, iptr); -#endif - break; + case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */ - case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */ - /* sx.val.i = constant */ - OOPS(); -#if 0 - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); - M_INTMOVE(s1, d); - M_LSRA_IMM(iptr->sx.val.i, d); - emit_store_dst(jd, iptr, d); -#endif - break; + case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */ case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */ - OOPS(); -#if 0 - d = codegen_reg_of_dst(jd, iptr, REG_NULL); - emit_lshift(jd, SHIFT_SHR, iptr); -#endif - break; - - case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */ - /* sx.val.l = constant */ - OOPS(); -#if 0 - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); - M_INTMOVE(s1, d); - M_LSRL_IMM(iptr->sx.val.i, d); - emit_store_dst(jd, iptr, d); -#endif - break; - case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */ - OOPS(); -#if 0 - 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 (s2 == d) - M_IAND(s1, d); - else { - M_INTMOVE(s1, d); - M_IAND(s2, d); + + /* Use only 6 bits of second operand */ + + M_INTMOVE(s2, REG_ITMP2); + s2 = REG_ITMP2; + ICONST(REG_ITMP1, 0x3F); + M_IAND(REG_ITMP1, s2); + + s1 = emit_load_s1(jd, iptr, REG_ITMP31_PACKED); /* even-odd pair */ + d = codegen_reg_of_dst(jd, iptr, REG_ITMP31_PACKED); + + /* Destination must be even-odd pair */ + + if (! N_IS_EVEN_ODD(d)) { + d = REG_ITMP31_PACKED; } + + assert(N_IS_EVEN_ODD(d)); + + M_LNGMOVE(s1, d); + + switch (iptr->opc) { + case ICMD_LSHL: + M_SLDL(s2, GET_HIGH_REG(d)); + break; + case ICMD_LSHR: + M_SRDA(s2, GET_HIGH_REG(d)); + break; + case ICMD_LUSHR: + M_SRDL(s2, GET_HIGH_REG(d)); + break; + default: + assert(0); + } + + emit_copy_dst(jd, iptr, d); emit_store_dst(jd, iptr, d); -#endif + break; - case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */ + case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */ + /* sx.val.i = constant */ + case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */ /* sx.val.i = constant */ - OOPS(); -#if 0 - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); - M_INTMOVE(s1, d); - M_IAND_IMM(iptr->sx.val.i, d); - emit_store_dst(jd, iptr, d); -#endif - break; + case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */ + /* sx.val.l = constant */ + case ICMD_LMULPOW2: + + d = codegen_reg_of_dst(jd, iptr, REG_ITMP31_PACKED); /* even-odd */ + if (! N_IS_EVEN_ODD(d)) { + d = REG_ITMP31_PACKED; + } + assert(N_IS_EVEN_ODD(d)); - case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */ - OOPS(); -#if 0 - 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 (s2 == d) - M_LAND(s1, d); - else { - M_INTMOVE(s1, d); - M_LAND(s2, d); + s1 = emit_load_s1(jd, iptr, d); + + M_LNGMOVE(s1, d); + + disp = iptr->sx.val.i & 0x3F; /* Use only 6 bits of operand */ + + switch (iptr->opc) { + case ICMD_LSHLCONST: + N_SLDL(GET_HIGH_REG(d), disp, RN); + break; + case ICMD_LSHRCONST: + N_SRDA(GET_HIGH_REG(d), disp, RN); + break; + case ICMD_LUSHRCONST: + N_SRDL(GET_HIGH_REG(d), disp, RN); + break; + case ICMD_LMULPOW2: + N_SLDL(GET_HIGH_REG(d), disp, RN); + break; + default: + assert(0); } - emit_store_dst(jd, iptr, d); -#endif - break; - case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */ - /* sx.val.l = constant */ - OOPS(); -#if 0 - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); - M_INTMOVE(s1, d); - if (IS_IMM32(iptr->sx.val.l)) - M_LAND_IMM(iptr->sx.val.l, d); - else { - M_MOV_IMM(iptr->sx.val.l, REG_ITMP2); - M_LAND(REG_ITMP2, d); - } + emit_copy_dst(jd, iptr, d); emit_store_dst(jd, iptr, d); -#endif break; - case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */ - OOPS(); -#if 0 + case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */ + 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 (s2 == d) - M_IOR(s1, d); + M_IAND(s1, d); else { M_INTMOVE(s1, d); - M_IOR(s2, d); + M_IAND(s2, d); } emit_store_dst(jd, iptr, d); -#endif - break; - case ICMD_IORCONST: /* ..., value ==> ..., value | constant */ - /* sx.val.i = constant */ - OOPS(); -#if 0 - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); - M_INTMOVE(s1, d); - M_IOR_IMM(iptr->sx.val.i, d); - emit_store_dst(jd, iptr, d); -#endif break; - case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */ - OOPS(); -#if 0 + case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */ + 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 (s2 == d) - M_LOR(s1, d); + M_IOR(s1, d); else { M_INTMOVE(s1, d); - M_LOR(s2, d); + M_IOR(s2, d); } emit_store_dst(jd, iptr, d); -#endif - break; - case ICMD_LORCONST: /* ..., value ==> ..., value | constant */ - /* sx.val.l = constant */ - OOPS(); -#if 0 - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); - M_INTMOVE(s1, d); - if (IS_IMM32(iptr->sx.val.l)) - M_LOR_IMM(iptr->sx.val.l, d); - else { - M_MOV_IMM(iptr->sx.val.l, REG_ITMP2); - M_LOR(REG_ITMP2, d); - } - emit_store_dst(jd, iptr, d); -#endif break; case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */ - OOPS(); -#if 0 + 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); @@ -1392,89 +1251,194 @@ bool codegen(jitdata *jd) M_IXOR(s2, d); } emit_store_dst(jd, iptr, d); -#endif + break; + + + case ICMD_IORCONST: /* ..., value ==> ..., value | constant */ + /* sx.val.i = constant */ + case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */ + /* sx.val.i = constant */ case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */ /* sx.val.i = constant */ - OOPS(); -#if 0 - s1 = emit_load_s1(jd, iptr, REG_ITMP1); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + M_INTMOVE(s1, d); - M_IXOR_IMM(iptr->sx.val.i, d); + ICONST(REG_ITMP2, iptr->sx.val.i); + + switch (iptr->opc) { + case ICMD_IANDCONST: + M_IAND(REG_ITMP2, d); + break; + case ICMD_IXORCONST: + M_IXOR(REG_ITMP2, d); + break; + case ICMD_IORCONST: + M_IOR(REG_ITMP2, d); + break; + default: + assert(0); + } + emit_store_dst(jd, iptr, d); -#endif + break; + case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */ case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */ - OOPS(); -#if 0 - 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 (s2 == d) - M_LXOR(s1, d); - else { - M_INTMOVE(s1, d); - M_LXOR(s2, d); + case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */ + + d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED); + + s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED)); + s2 = emit_load_s2_low(jd, iptr, REG_ITMP3); + dd = GET_LOW_REG(d); + + switch (iptr->opc) { + case ICMD_LAND: + if (s2 == dd) { + M_IAND(s1, dd); + } else { + M_INTMOVE(s1, dd); + M_IAND(s2, dd); + } + break; + case ICMD_LXOR: + if (s2 == dd) { + M_IXOR(s1, dd); + } else { + M_INTMOVE(s1, dd); + M_IXOR(s2, dd); + } + break; + case ICMD_LOR: + if (s2 == dd) { + M_IOR(s1, dd); + } else { + M_INTMOVE(s1, dd); + M_IOR(s2, dd); + } + break; + default: + assert(0); + } + + s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED)); + s2 = emit_load_s2_high(jd, iptr, REG_ITMP3); + dd = GET_HIGH_REG(d); + + switch (iptr->opc) { + case ICMD_LAND: + if (s2 == dd) { + M_IAND(s1, dd); + } else { + M_INTMOVE(s1, dd); + M_IAND(s2, dd); + } + break; + case ICMD_LXOR: + if (s2 == dd) { + M_IXOR(s1, dd); + } else { + M_INTMOVE(s1, dd); + M_IXOR(s2, dd); + } + break; + case ICMD_LOR: + if (s2 == dd) { + M_IOR(s1, dd); + } else { + M_INTMOVE(s1, dd); + M_IOR(s2, dd); + } + break; + default: + assert(0); } + emit_store_dst(jd, iptr, d); -#endif break; + case ICMD_LORCONST: /* ..., value ==> ..., value | constant */ + /* sx.val.l = constant */ case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */ /* sx.val.l = constant */ - OOPS(); -#if 0 - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); - M_INTMOVE(s1, d); - if (IS_IMM32(iptr->sx.val.l)) - M_LXOR_IMM(iptr->sx.val.l, d); - else { - M_MOV_IMM(iptr->sx.val.l, REG_ITMP2); - M_LXOR(REG_ITMP2, d); + case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */ + /* sx.val.l = constant */ + + /* TODO should use memory operand to access data segment, not load */ + + d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED); + + s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(d)); + s3 = iptr->sx.val.l & 0xffffffff; + + M_INTMOVE(s1, GET_LOW_REG(d)); + + ICONST(REG_ITMP3, s3); + + switch (iptr->opc) { + case ICMD_LANDCONST: + M_IAND(REG_ITMP3, GET_LOW_REG(d)); + break; + case ICMD_LXORCONST: + M_IXOR(REG_ITMP3, GET_LOW_REG(d)); + break; + case ICMD_LORCONST: + M_IOR(REG_ITMP3, GET_LOW_REG(d)); + break; + default: + assert(0); + } + + s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(d)); + s3 = iptr->sx.val.l >> 32; + + M_INTMOVE(s1, GET_HIGH_REG(d)); + + ICONST(REG_ITMP3, s3); + + switch (iptr->opc) { + case ICMD_LANDCONST: + M_IAND(REG_ITMP3, GET_HIGH_REG(d)); + break; + case ICMD_LXORCONST: + M_IXOR(REG_ITMP3, GET_HIGH_REG(d)); + break; + case ICMD_LORCONST: + M_IOR(REG_ITMP3, GET_HIGH_REG(d)); + break; + default: + assert(0); } + emit_store_dst(jd, iptr, d); -#endif - break; + break; /* floating operations ************************************************/ case ICMD_FNEG: /* ..., value ==> ..., - value */ - OOPS(); -#if 0 s1 = emit_load_s1(jd, iptr, REG_FTMP1); - d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); - disp = dseg_add_s4(cd, 0x80000000); - M_FLTMOVE(s1, d); - emit_movss_membase_reg(cd, RIP, -((cd->mcodeptr + 9) - cd->mcodebase) + disp, REG_FTMP2); - emit_xorps_reg_reg(cd, REG_FTMP2, d); + d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); + M_FMOVN(s1, d); emit_store_dst(jd, iptr, d); -#endif break; case ICMD_DNEG: /* ..., value ==> ..., - value */ - OOPS(); -#if 0 s1 = emit_load_s1(jd, iptr, REG_FTMP1); - d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); - disp = dseg_add_s8(cd, 0x8000000000000000); - M_FLTMOVE(s1, d); - emit_movd_membase_reg(cd, RIP, -((cd->mcodeptr + 9) - cd->mcodebase) + disp, REG_FTMP2); - emit_xorpd_reg_reg(cd, REG_FTMP2, d); + d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); + M_DMOVN(s1, d); emit_store_dst(jd, iptr, d); -#endif break; case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */ - OOPS(); -#if 0 s1 = emit_load_s1(jd, iptr, REG_FTMP1); s2 = emit_load_s2(jd, iptr, REG_FTMP2); - d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); + d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); if (s2 == d) M_FADD(s1, d); else { @@ -1482,15 +1446,12 @@ bool codegen(jitdata *jd) M_FADD(s2, d); } emit_store_dst(jd, iptr, d); -#endif break; case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */ - OOPS(); -#if 0 s1 = emit_load_s1(jd, iptr, REG_FTMP1); s2 = emit_load_s2(jd, iptr, REG_FTMP2); - d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); + d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); if (s2 == d) M_DADD(s1, d); else { @@ -1498,45 +1459,32 @@ bool codegen(jitdata *jd) M_DADD(s2, d); } emit_store_dst(jd, iptr, d); -#endif break; case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */ - OOPS(); -#if 0 s1 = emit_load_s1(jd, iptr, REG_FTMP1); - s2 = emit_load_s2(jd, iptr, REG_FTMP2); - d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); - if (s2 == d) { - M_FLTMOVE(s2, REG_FTMP2); - s2 = REG_FTMP2; - } + d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); + s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d); + M_FLTMOVE(s1, d); M_FSUB(s2, d); emit_store_dst(jd, iptr, d); -#endif break; case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */ - OOPS(); -#if 0 s1 = emit_load_s1(jd, iptr, REG_FTMP1); - s2 = emit_load_s2(jd, iptr, REG_FTMP2); - d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); - if (s2 == d) { - M_FLTMOVE(s2, REG_FTMP2); - s2 = REG_FTMP2; - } + d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); + s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d); + M_FLTMOVE(s1, d); M_DSUB(s2, d); emit_store_dst(jd, iptr, d); -#endif break; case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */ s1 = emit_load_s1(jd, iptr, REG_FTMP1); s2 = emit_load_s2(jd, iptr, REG_FTMP2); - d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); + d = codegen_reg_of_dst(jd, iptr, REG_FTMP2); if (s2 == d) M_FMUL(s1, d); else { @@ -1544,15 +1492,12 @@ bool codegen(jitdata *jd) M_FMUL(s2, d); } emit_store_dst(jd, iptr, d); - break; case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */ - OOPS(); -#if 0 s1 = emit_load_s1(jd, iptr, REG_FTMP1); s2 = emit_load_s2(jd, iptr, REG_FTMP2); - d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); + d = codegen_reg_of_dst(jd, iptr, REG_FTMP2); if (s2 == d) M_DMUL(s1, d); else { @@ -1560,39 +1505,26 @@ bool codegen(jitdata *jd) M_DMUL(s2, d); } emit_store_dst(jd, iptr, d); -#endif break; case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */ - OOPS(); -#if 0 s1 = emit_load_s1(jd, iptr, REG_FTMP1); - s2 = emit_load_s2(jd, iptr, REG_FTMP2); - d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); - if (s2 == d) { - M_FLTMOVE(s2, REG_FTMP2); - s2 = REG_FTMP2; - } + d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); + s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d); + M_FLTMOVE(s1, d); M_FDIV(s2, d); emit_store_dst(jd, iptr, d); -#endif break; case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */ - OOPS(); -#if 0 s1 = emit_load_s1(jd, iptr, REG_FTMP1); - s2 = emit_load_s2(jd, iptr, REG_FTMP2); - d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); - if (s2 == d) { - M_FLTMOVE(s2, REG_FTMP2); - s2 = REG_FTMP2; - } + d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); + s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d); + M_FLTMOVE(s1, d); M_DDIV(s2, d); emit_store_dst(jd, iptr, d); -#endif break; case ICMD_I2F: /* ..., value ==> ..., (float) value */ @@ -1609,172 +1541,158 @@ bool codegen(jitdata *jd) emit_store_dst(jd, iptr, d); break; - case ICMD_L2F: /* ..., value ==> ..., (float) value */ - OOPS(); -#if 0 - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); - M_CVTLF(s1, d); - emit_store_dst(jd, iptr, d); -#endif - break; - - case ICMD_L2D: /* ..., value ==> ..., (double) value */ - OOPS(); -#if 0 - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); - M_CVTLD(s1, d); - emit_store_dst(jd, iptr, d); -#endif - break; - case ICMD_F2I: /* ..., value ==> ..., (int) value */ - s1 = emit_load_s1(jd, iptr, REG_FTMP1); - d = codegen_reg_of_dst(jd, iptr, REG_ITMP3); - M_CVTFI(s1, d); - emit_store_dst(jd, iptr, d); - /* TODO: corner cases ? */ - break; - - case ICMD_D2I: /* ..., value ==> ..., (int) value */ - OOPS(); -#if 0 - s1 = emit_load_s1(jd, iptr, REG_FTMP1); - d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); - M_CVTDI(s1, d); - M_ICMP_IMM(0x80000000, d); /* corner cases */ - disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 + - ((REG_RESULT == d) ? 0 : 3); - M_BNE(disp); - M_FLTMOVE(s1, REG_FTMP1); - M_MOV_IMM(asm_builtin_d2i, REG_ITMP2); - M_CALL(REG_ITMP2); - M_INTMOVE(REG_RESULT, d); - emit_store_dst(jd, iptr, d); + case ICMD_D2I: + { + u1 *ref1; +#ifdef SUPPORT_HERCULES + u1 *ref2, *ref3; #endif - break; - case ICMD_F2L: /* ..., value ==> ..., (long) value */ - OOPS(); -#if 0 - s1 = emit_load_s1(jd, iptr, REG_FTMP1); - d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); - M_CVTFL(s1, d); - M_MOV_IMM(0x8000000000000000, REG_ITMP2); - M_LCMP(REG_ITMP2, d); /* corner cases */ - disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 + - ((REG_RESULT == d) ? 0 : 3); - M_BNE(disp); - M_FLTMOVE(s1, REG_FTMP1); - M_MOV_IMM(asm_builtin_f2l, REG_ITMP2); - M_CALL(REG_ITMP2); - M_INTMOVE(REG_RESULT, d); - emit_store_dst(jd, iptr, d); -#endif - break; + s1 = emit_load_s1(jd, iptr, REG_FTMP1); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP3); - case ICMD_D2L: /* ..., value ==> ..., (long) value */ - OOPS(); -#if 0 - s1 = emit_load_s1(jd, iptr, REG_FTMP1); - d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); - M_CVTDL(s1, d); - M_MOV_IMM(0x8000000000000000, REG_ITMP2); - M_LCMP(REG_ITMP2, d); /* corner cases */ - disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 + - ((REG_RESULT == d) ? 0 : 3); - M_BNE(disp); - M_FLTMOVE(s1, REG_FTMP1); - M_MOV_IMM(asm_builtin_d2l, REG_ITMP2); - M_CALL(REG_ITMP2); - M_INTMOVE(REG_RESULT, d); - emit_store_dst(jd, iptr, d); + /* Test if NAN */ + + switch (iptr->opc) { + case ICMD_F2I: + N_LTEBR(s1, s1); + break; + case ICMD_D2I: + N_LTDBR(s1, s1); + break; + } + + N_BRC(DD_0 | DD_1 | DD_2, SZ_BRC + SZ_LHI + SZ_BRC); /* Non a NaN */ + N_LHI(d, 0); /* Load 0 */ + ref1 = cd->mcodeptr; + N_BRC(DD_ANY, 0); /* Exit */ + + /* Convert */ + + switch (iptr->opc) { + case ICMD_F2I: + M_CVTFI(s1, d); + break; + case ICMD_D2I: + M_CVTDI(s1, d); + break; + } + +#ifdef SUPPORT_HERCULES + /* Hercules does the conversion using a plain C conversion. + * According to manual, real hardware should *NOT* require this. + * + * Corner case: Positive float leads to INT_MIN (overflow). + */ + + switch (iptr->opc) { + case ICMD_F2I: + N_LTEBR(s1, s1); + break; + case ICMD_D2I: + N_LTDBR(s1, s1); + break; + } + + ref2 = cd->mcodeptr; + N_BRC(DD_0 | DD_1 | DD_3, 0); /* If operand is positive, continue */ + + M_TEST(d); + + ref3 = cd->mcodeptr; + M_BGE(0); /* If integer result is negative, continue */ + + disp = dseg_add_s4(cd, 0x7fffffff); /* Load INT_MAX */ + M_ILD_DSEG(d, disp); #endif + N_BRC_BACK_PATCH(ref1); +#ifdef SUPPORT_HERCULES + N_BRC_BACK_PATCH(ref2); + N_BRC_BACK_PATCH(ref3); +#endif + emit_store_dst(jd, iptr, d); + } break; case ICMD_F2D: /* ..., value ==> ..., (double) value */ - OOPS(); -#if 0 - s1 = emit_load_s1(jd, iptr, REG_FTMP1); - d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); - M_CVTFD(s1, d); - emit_store_dst(jd, iptr, d); + { +#ifdef SUPPORT_HERCULES + u1 *ref; #endif + s1 = emit_load_s1(jd, iptr, REG_FTMP1); + d = codegen_reg_of_dst(jd, iptr, REG_FTMP2); +#ifdef SUPPORT_HERCULES + N_LTEBR(s1, s1); + ref = cd->mcodeptr; + N_BRC(DD_0 | DD_1 | DD_2, 0); /* Non a NaN */ + disp = dseg_add_double(cd, 0.0 / 0.0); + M_DLD_DSEG(d, disp, REG_ITMP1); + emit_label_br(cd, BRANCH_LABEL_1); + N_BRC_BACK_PATCH(ref); +#endif + M_CVTFD(s1, d); +#ifdef SUPPORT_HERCULES + emit_label(cd, BRANCH_LABEL_1); +#endif + emit_store_dst(jd, iptr, d); + } break; case ICMD_D2F: /* ..., value ==> ..., (float) value */ - OOPS(); -#if 0 s1 = emit_load_s1(jd, iptr, REG_FTMP1); - d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); + d = codegen_reg_of_dst(jd, iptr, REG_FTMP2); M_CVTDF(s1, d); emit_store_dst(jd, iptr, d); -#endif break; case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */ /* == => 0, < => 1, > => -1 */ - /* ICMD_FCMPL: s1 < s2 -> d := 1 */ /* TODO is this correct ? */ + case ICMD_DCMPL: case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */ /* == => 0, < => 1, > => -1 */ + case ICMD_DCMPG: + + s1 = emit_load_s1(jd, iptr, REG_FTMP1); + s2 = emit_load_s2(jd, iptr, REG_FTMP2); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP3); + + switch (iptr->opc) { + case ICMD_FCMPG: + case ICMD_FCMPL: + M_FCMP(s1, s2); + break; + case ICMD_DCMPG: + case ICMD_DCMPL: + M_DCMP(s1, s2); + break; + } - s1 = emit_load_s1(jd, iptr, REG_FTMP1); - s2 = emit_load_s2(jd, iptr, REG_FTMP2); - d = codegen_reg_of_dst(jd, iptr, REG_ITMP3); + N_BRC( /* load 1 */ + DD_H | (iptr->opc == ICMD_FCMPG || iptr->opc == ICMD_DCMPG ? DD_O : 0), + SZ_BRC + SZ_BRC + SZ_BRC + ); - N_CEBR(s1, s2); + N_BRC( /* load -1 */ + DD_L | (iptr->opc == ICMD_FCMPL || iptr->opc == ICMD_DCMPL ? DD_O : 0), + SZ_BRC + SZ_BRC + SZ_LHI + SZ_BRC + ); - M_BGT(SZ_BRC + SZ_BRC + SZ_BRC); - M_BLT(SZ_BRC + SZ_BRC + SZ_LHI + SZ_BRC); - M_BEQ(SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI + SZ_BRC); + N_BRC( /* load 0 */ + DD_E, + SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI + SZ_BRC + ); - N_LHI(d, iptr->opc == ICMD_FCMPL ? -1 : 1); /* s1 > s2 */ + N_LHI(d, 1); /* GT */ M_BR(SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI); - N_LHI(d, iptr->opc == ICMD_FCMPL ? 1 : -1); /* s1 < s2 */ + N_LHI(d, -1); /* LT */ M_BR(SZ_BRC + SZ_LHI); - N_LHI(d, 0); /* s1 == s2 */ - - emit_store_dst(jd, iptr, d); - - break; + N_LHI(d, 0); /* EQ */ - case ICMD_DCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */ - /* == => 0, < => 1, > => -1 */ - OOPS(); -#if 0 - s1 = emit_load_s1(jd, iptr, REG_FTMP1); - s2 = emit_load_s2(jd, iptr, REG_FTMP2); - d = codegen_reg_of_dst(jd, iptr, REG_ITMP3); - M_CLR(d); - M_MOV_IMM(1, REG_ITMP1); - M_MOV_IMM(-1, REG_ITMP2); - emit_ucomisd_reg_reg(cd, s1, s2); - M_CMOVB(REG_ITMP1, d); - M_CMOVA(REG_ITMP2, d); - M_CMOVP(REG_ITMP2, d); /* treat unordered as GT */ emit_store_dst(jd, iptr, d); -#endif - break; - case ICMD_DCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */ - /* == => 0, < => 1, > => -1 */ - OOPS(); -#if 0 - s1 = emit_load_s1(jd, iptr, REG_FTMP1); - s2 = emit_load_s2(jd, iptr, REG_FTMP2); - d = codegen_reg_of_dst(jd, iptr, REG_ITMP3); - M_CLR(d); - M_MOV_IMM(1, REG_ITMP1); - M_MOV_IMM(-1, REG_ITMP2); - emit_ucomisd_reg_reg(cd, s1, s2); - M_CMOVB(REG_ITMP1, d); - M_CMOVA(REG_ITMP2, d); - M_CMOVP(REG_ITMP1, d); /* treat unordered as LT */ - emit_store_dst(jd, iptr, d); -#endif break; @@ -1784,336 +1702,282 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); d = codegen_reg_of_dst(jd, iptr, REG_ITMP3); - gen_nullptr_check(s1); - M_ILD(d, s1, OFFSET(java_arrayheader, size)); + /* TODO softnull */ + /* implicit null-pointer check */ + M_ILD(d, s1, OFFSET(java_array_t, size)); emit_store_dst(jd, iptr, d); break; case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */ - OOPS(); -#if 0 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); - if (INSTRUCTION_MUST_CHECK(iptr)) { - gen_nullptr_check(s1); - gen_bound_check; - } - emit_movsbq_memindex_reg(cd, OFFSET(java_bytearray, data[0]), s1, s2, 0, d); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); + + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); + + N_IC(d, OFFSET(java_bytearray_t, data[0]), s2, s1); + + M_SLL_IMM(24, d); + M_SRA_IMM(24, d); + emit_store_dst(jd, iptr, d); -#endif break; case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */ - OOPS(); -#if 0 + 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); - if (INSTRUCTION_MUST_CHECK(iptr)) { - gen_nullptr_check(s1); - gen_bound_check; - } - emit_movzwq_memindex_reg(cd, OFFSET(java_chararray, data[0]), s1, s2, 1, d); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); + + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); + + M_INTMOVE(s2, REG_ITMP2); + M_SLL_IMM(1, REG_ITMP2); + + N_LH(d, OFFSET(java_chararray_t, data[0]), REG_ITMP2, s1); + + /* N_LH does sign extends, undo ! */ + + M_SLL_IMM(16, d); + M_SRL_IMM(16, d); + emit_store_dst(jd, iptr, d); -#endif break; case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */ - OOPS(); -#if 0 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); - if (INSTRUCTION_MUST_CHECK(iptr)) { - gen_nullptr_check(s1); - gen_bound_check; - } - emit_movswq_memindex_reg(cd, OFFSET(java_shortarray, data[0]), s1, s2, 1, d); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); + + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); + + M_INTMOVE(s2, REG_ITMP2); + M_SLL_IMM(1, REG_ITMP2); + + N_LH(d, OFFSET(java_shortarray_t, data[0]), REG_ITMP2, s1); emit_store_dst(jd, iptr, d); -#endif break; case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */ - OOPS(); -#if 0 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); - if (INSTRUCTION_MUST_CHECK(iptr)) { - gen_nullptr_check(s1); - gen_bound_check; - } - emit_movl_memindex_reg(cd, OFFSET(java_intarray, data[0]), s1, s2, 2, d); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); + + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); + + M_INTMOVE(s2, REG_ITMP2); + M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */ + N_L(d, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1); emit_store_dst(jd, iptr, d); -#endif break; case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */ - OOPS(); -#if 0 + 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); - if (INSTRUCTION_MUST_CHECK(iptr)) { - gen_nullptr_check(s1); - gen_bound_check; - } - emit_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]), s1, s2, 3, d); + + d = codegen_reg_of_dst(jd, iptr, REG_ITMP13_PACKED); + + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); + + M_INTMOVE(s2, REG_ITMP2); + M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */ + + N_L( + GET_LOW_REG(d) /* maybe itmp3 */, + OFFSET(java_intarray_t, data[0]) + 4, + REG_ITMP2, s1 /* maybe itmp1 */ + ); + + N_L( + GET_HIGH_REG(d) /* maybe itmp1 */, + OFFSET(java_intarray_t, data[0]), + REG_ITMP2, s1 /* maybe itmp1 */ + ); + emit_store_dst(jd, iptr, d); -#endif + break; case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */ - OOPS(); -#if 0 + s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); - d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); - if (INSTRUCTION_MUST_CHECK(iptr)) { - gen_nullptr_check(s1); - gen_bound_check; - } - emit_movss_memindex_reg(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2, d); + d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); + + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); + + M_INTMOVE(s2, REG_ITMP2); + M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */ + + N_LE(d, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1); + emit_store_dst(jd, iptr, d); -#endif break; case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */ - OOPS(); -#if 0 s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); - d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); - if (INSTRUCTION_MUST_CHECK(iptr)) { - gen_nullptr_check(s1); - gen_bound_check; - } - emit_movsd_memindex_reg(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3, d); + d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); + + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); + + M_INTMOVE(s2, REG_ITMP2); + M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */ + + N_LD(d, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1); + emit_store_dst(jd, iptr, d); -#endif break; case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */ 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); - emit_array_checks(cd, iptr, s1, s2); + + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); - M_INTMOVE(s1, REG_ITMP1); - N_SLL(REG_ITMP1, 2, RN); /* scale index by 4 */ - N_L(d, OFFSET(java_objectarray, data[0]), REG_ITMP1, s2); + M_INTMOVE(s2, REG_ITMP2); + M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */ + N_L(d, OFFSET(java_objectarray_t, data[0]), REG_ITMP2, s1); emit_store_dst(jd, iptr, d); break; case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */ - OOPS(); -#if 0 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); - emit_movb_reg_memindex(cd, s3, OFFSET(java_bytearray, data[0]), s1, s2, 0); -#endif + + N_STC(s3, OFFSET(java_bytearray_t, data[0]), s2, s1); break; case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */ - OOPS(); -#if 0 + 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); - emit_movw_reg_memindex(cd, s3, OFFSET(java_chararray, data[0]), s1, s2, 1); -#endif + + M_INTMOVE(s2, REG_ITMP2); + M_SLL_IMM(1, REG_ITMP2); + + N_STH(s3, OFFSET(java_chararray_t, data[0]), REG_ITMP2, s1); + break; case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */ - OOPS(); -#if 0 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); - emit_movw_reg_memindex(cd, s3, OFFSET(java_shortarray, data[0]), s1, s2, 1); -#endif + + M_INTMOVE(s2, REG_ITMP2); + M_SLL_IMM(1, REG_ITMP2); + + N_STH(s3, OFFSET(java_shortarray_t, data[0]), REG_ITMP2, s1); break; case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */ - OOPS(); -#if 0 + 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); - emit_movl_reg_memindex(cd, s3, OFFSET(java_intarray, data[0]), s1, s2, 2); -#endif + + M_INTMOVE(s2, REG_ITMP2); + M_SLL_IMM(2, REG_ITMP2); + + N_ST(s3, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1); break; case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */ - OOPS(); -#if 0 + 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; - } - s3 = emit_load_s3(jd, iptr, REG_ITMP3); - emit_mov_reg_memindex(cd, s3, OFFSET(java_longarray, data[0]), s1, s2, 3); -#endif + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); + + M_INTMOVE(s2, REG_ITMP2); + M_SLL_IMM(3, REG_ITMP2); + + s3 = emit_load_s3_high(jd, iptr, REG_ITMP3); + N_ST(s3, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1); + s3 = emit_load_s3_low(jd, iptr, REG_ITMP3); + N_ST(s3, OFFSET(java_intarray_t, data[0]) + 4, REG_ITMP2, s1); break; case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */ - OOPS(); -#if 0 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; - } - s3 = emit_load_s3(jd, iptr, REG_FTMP3); - emit_movss_reg_memindex(cd, s3, OFFSET(java_floatarray, data[0]), s1, s2, 2); -#endif - break; + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); + s3 = emit_load_s3(jd, iptr, REG_FTMP1); - case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */ - OOPS(); -#if 0 - 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; - } - s3 = emit_load_s3(jd, iptr, REG_FTMP3); - emit_movsd_reg_memindex(cd, s3, OFFSET(java_doublearray, data[0]), s1, s2, 3); -#endif + M_INTMOVE(s2, REG_ITMP2); + M_SLL_IMM(2, REG_ITMP2); + + N_STE(s3, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1); break; - case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */ - OOPS(); -#if 0 + 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; - } - s3 = emit_load_s3(jd, iptr, REG_ITMP3); + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); + s3 = emit_load_s3(jd, iptr, REG_FTMP1); - M_MOV(s1, REG_A0); - M_MOV(s3, REG_A1); - M_MOV_IMM(BUILTIN_canstore, REG_ITMP1); - M_CALL(REG_ITMP1); - M_TEST(REG_RESULT); - M_BEQ(0); - codegen_add_arraystoreexception_ref(cd); + M_INTMOVE(s2, REG_ITMP2); + M_SLL_IMM(3, REG_ITMP2); - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - s2 = emit_load_s2(jd, iptr, REG_ITMP2); - s3 = emit_load_s3(jd, iptr, REG_ITMP3); - emit_mov_reg_memindex(cd, s3, OFFSET(java_objectarray, data[0]), s1, s2, 3); -#endif + N_STD(s3, OFFSET(java_doublearray_t, data[0]), REG_ITMP2, s1); break; + case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */ - case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */ - OOPS(); -#if 0 - s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s1 = emit_load_s1(jd, iptr, REG_A0); s2 = emit_load_s2(jd, iptr, REG_ITMP2); - if (INSTRUCTION_MUST_CHECK(iptr)) { - gen_nullptr_check(s1); - gen_bound_check; - } - emit_movb_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_bytearray, data[0]), s1, s2, 0); -#endif - break; + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); + s3 = emit_load_s3(jd, iptr, REG_A1); - case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */ - OOPS(); -#if 0 - 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; - } - emit_movw_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_chararray, data[0]), s1, s2, 1); -#endif - break; + M_INTMOVE(s1, REG_A0); + M_INTMOVE(s3, REG_A1); - case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */ - OOPS(); -#if 0 - 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; - } - emit_movw_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_shortarray, data[0]), s1, s2, 1); -#endif - break; + disp = dseg_add_functionptr(cd, BUILTIN_FAST_canstore); + M_ALD_DSEG(REG_ITMP2, disp); + M_ASUB_IMM(96, REG_SP); + M_JSR(REG_RA, REG_ITMP2); + M_AADD_IMM(96, REG_SP); - case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */ - OOPS(); -#if 0 - 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; - } - emit_movl_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_intarray, data[0]), s1, s2, 2); -#endif - break; + emit_arraystore_check(cd, iptr); - case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */ - OOPS(); -#if 0 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; - } + s3 = emit_load_s3(jd, iptr, REG_ITMP3); - if (IS_IMM32(iptr->sx.s23.s3.constval)) { - emit_mov_imm_memindex(cd, (u4) (iptr->sx.s23.s3.constval & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3); - } else { - emit_movl_imm_memindex(cd, (u4) (iptr->sx.s23.s3.constval & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3); - emit_movl_imm_memindex(cd, (u4) (iptr->sx.s23.s3.constval >> 32), OFFSET(java_longarray, data[0]) + 4, s1, s2, 3); - } -#endif - break; + M_INTMOVE(s2, REG_ITMP2); + M_SLL_IMM(2, REG_ITMP2); + N_ST(s3, OFFSET(java_objectarray_t, data[0]), REG_ITMP2, s1); - case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */ - OOPS(); -#if 0 - 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; - } - emit_mov_imm_memindex(cd, 0, OFFSET(java_objectarray, data[0]), s1, s2, 3); -#endif + /* + M_SAADDQ(s2, s1, REG_ITMP1); itmp1 := 4 * s2 + s1 + M_AST(s3, REG_ITMP1, OFFSET(java_objectarray, data[0])); + */ break; @@ -2126,25 +1990,25 @@ bool codegen(jitdata *jd) /* PROFILE_CYCLE_STOP; */ - codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp); + patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp); /* PROFILE_CYCLE_START; */ } 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)) { PROFILE_CYCLE_STOP; - codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, 0); + patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->class, 0); PROFILE_CYCLE_START; } } - M_ALD(REG_ITMP1, REG_PV, disp); + M_ALD_DSEG(REG_ITMP1, disp); switch (fieldtype) { case TYPE_INT: @@ -2152,7 +2016,7 @@ bool codegen(jitdata *jd) M_ILD(d, REG_ITMP1, 0); break; case TYPE_LNG: - d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED); M_LLD(d, REG_ITMP1, 0); break; case TYPE_ADR: @@ -2180,19 +2044,21 @@ bool codegen(jitdata *jd) fieldtype = uf->fieldref->parseddesc.fd->type; disp = dseg_add_unique_address(cd, uf); - codegen_addpatchref(cd, PATCHER_get_putstatic, uf, disp); + patcher_add_patch_ref(jd, 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_addpatchref(cd, PATCHER_clinit, - fi->class, disp); + if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) { + PROFILE_CYCLE_STOP; + patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->class, disp); + PROFILE_CYCLE_START; + } } - M_ALD(REG_ITMP1, REG_PV, disp); + M_ALD_DSEG(REG_ITMP1, disp); switch (fieldtype) { case TYPE_INT: s1 = emit_load_s1(jd, iptr, REG_ITMP2); @@ -2217,50 +2083,6 @@ bool codegen(jitdata *jd) } break; - case ICMD_PUTSTATICCONST: /* ... ==> ... */ - /* val = value (in current instruction) */ - /* following NOP) */ - OOPS(); -#if 0 - if (INSTRUCTION_IS_UNRESOLVED(iptr)) { - 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; - fieldtype = fi->type; - disp = dseg_add_address(cd, &(fi->value)); - - if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) - codegen_add_patch_ref(cd, PATCHER_initialize_class, fi->class, - 0); - } - - M_ALD(REG_ITMP1, REG_PV, disp); - - switch (fieldtype) { - case TYPE_INT: - M_IST(REG_ZERO, REG_ITMP1, 0); - break; - case TYPE_LNG: - M_LST(REG_ZERO, REG_ITMP1, 0); - break; - case TYPE_ADR: - M_AST(REG_ZERO, REG_ITMP1, 0); - break; - case TYPE_FLT: - M_FST(REG_ZERO, REG_ITMP1, 0); - break; - case TYPE_DBL: - M_DST(REG_ZERO, REG_ITMP1, 0); - break; - } -#endif - break; - case ICMD_GETFIELD: /* ... ==> ..., value */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); @@ -2271,7 +2093,7 @@ bool codegen(jitdata *jd) fieldtype = uf->fieldref->parseddesc.fd->type; disp = 0; - codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0); + patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0); } else { fi = iptr->sx.s23.s3.fmiref->p.field; @@ -2285,14 +2107,14 @@ bool codegen(jitdata *jd) M_ILD(d, s1, disp); break; case TYPE_LNG: - d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED); if (GET_HIGH_REG(d) == s1) { M_ILD(GET_LOW_REG(d), s1, disp + 4); M_ILD(GET_HIGH_REG(d), s1, disp); } else { - M_ILD(GET_HIGH_REG(d), s1, disp); M_ILD(GET_LOW_REG(d), s1, disp + 4); + M_ILD(GET_HIGH_REG(d), s1, disp); } break; case TYPE_ADR: @@ -2300,86 +2122,28 @@ bool codegen(jitdata *jd) M_ALD(d, s1, disp); break; case TYPE_FLT: - d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); - M_FLD(d, s1, disp); - break; - case TYPE_DBL: - d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); - M_DLD(d, s1, disp); - break; - } - emit_store_dst(jd, iptr, d); - break; - - case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */ - - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - gen_nullptr_check(s1); - - s2 = emit_load_s2(jd, iptr, REG_IFTMP); - - if (INSTRUCTION_IS_UNRESOLVED(iptr)) { - uf = iptr->sx.s23.s3.uf; - fieldtype = uf->fieldref->parseddesc.fd->type; - disp = 0; - } - else { - fi = iptr->sx.s23.s3.fmiref->p.field; - fieldtype = fi->type; - disp = fi->offset; - } - - if (IS_INT_LNG_TYPE(fieldtype)) { - if (IS_2_WORD_TYPE(fieldtype)) - s2 = emit_load_s2(jd, iptr, REG_ITMP23_PACKED); - else - s2 = emit_load_s2(jd, iptr, REG_ITMP2); - } - else - s2 = emit_load_s2(jd, iptr, REG_FTMP2); - - if (INSTRUCTION_IS_UNRESOLVED(iptr)) - codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0); - - switch (fieldtype) { - case TYPE_INT: - M_IST(s2, s1, disp); - break; - case TYPE_LNG: - /* TODO really order */ - M_IST(GET_LOW_REG(s2), s1, disp + 4); /* keep this order */ - M_IST(GET_HIGH_REG(s2), s1, disp); /* keep this order */ - break; - case TYPE_ADR: - M_AST(s2, s1, disp); - break; - case TYPE_FLT: - M_FST(s2, s1, disp); + d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); + M_FLD(d, s1, disp); break; - case TYPE_DBL: - M_DST(s2, s1, disp); + case TYPE_DBL: + d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); + M_DLD(d, s1, disp); break; } + emit_store_dst(jd, iptr, d); break; - case ICMD_PUTFIELDCONST: /* ..., objectref, value ==> ... */ - /* val = value (in current instruction) */ - /* following NOP) */ - OOPS(); -#if 0 + case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */ + { + u1 *ref; + 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; fieldtype = uf->fieldref->parseddesc.fd->type; disp = 0; - -/* PROFILE_CYCLE_STOP; */ - - codegen_add_patch_ref(cd, PATCHER_putfieldconst, uf, 0); - -/* PROFILE_CYCLE_START; */ } else { fi = iptr->sx.s23.s3.fmiref->p.field; @@ -2387,43 +2151,76 @@ bool codegen(jitdata *jd) disp = fi->offset; } + /* We can't add a patcher ref behind this load, + * because the patcher would destroy REG_ITMP3. + * + * We pass in the disp parameter, how many bytes + * to skip to the to the actual store. + * + * XXX this relies on patcher_add_patch_ref internals + */ + + if (INSTRUCTION_IS_UNRESOLVED(iptr)) { + patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0); + ref = cd->mcodeptr; + } + + + if (IS_INT_LNG_TYPE(fieldtype)) { + if (IS_2_WORD_TYPE(fieldtype)) + s2 = emit_load_s2(jd, iptr, REG_ITMP23_PACKED); + else + s2 = emit_load_s2(jd, iptr, REG_ITMP2); + } else { + s2 = emit_load_s2(jd, iptr, REG_FTMP2); + } + + if (INSTRUCTION_IS_UNRESOLVED(iptr)) { + ((patchref_t *)list_first(jd->code->patchers))->disp = (cd->mcodeptr - ref); + } + switch (fieldtype) { - case TYPE_INT: - case TYPE_FLT: - M_IST32_IMM(iptr->sx.s23.s2.constval, s1, disp); - break; - case TYPE_LNG: - case TYPE_ADR: - case TYPE_DBL: - /* XXX why no check for IS_IMM32? */ - M_IST32_IMM(iptr->sx.s23.s2.constval, s1, disp); - M_IST32_IMM(iptr->sx.s23.s2.constval >> 32, s1, disp + 4); - break; + case TYPE_INT: + M_IST(s2, s1, disp); + break; + case TYPE_LNG: + M_IST(GET_LOW_REG(s2), s1, disp + 4); /* keep this order */ + M_IST(GET_HIGH_REG(s2), s1, disp); /* keep this order */ + break; + case TYPE_ADR: + M_AST(s2, s1, disp); + break; + case TYPE_FLT: + M_FST(s2, s1, disp); + break; + case TYPE_DBL: + M_DST(s2, s1, disp); + break; } -#endif - break; + } + break; /* branch operations **************************************************/ case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */ - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - M_INTMOVE(s1, REG_ITMP1_XPTR); - - PROFILE_CYCLE_STOP; + /* PROFILE_CYCLE_STOP; */ + + s1 = emit_load_s1(jd, iptr, REG_ITMP3); + M_INTMOVE(s1, REG_ITMP3_XPTR); #ifdef ENABLE_VERIFIER if (INSTRUCTION_IS_UNRESOLVED(iptr)) { uc = iptr->sx.s23.s2.uc; - codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0); + patcher_add_patch_ref(jd, PATCHER_resolve_class, uc, 0); } #endif /* ENABLE_VERIFIER */ disp = dseg_add_functionptr(cd, asm_handle_exception); - M_ALD(REG_ITMP2, REG_PV, disp); - M_JMP(REG_ITMP2_XPC, REG_ITMP2); + M_ALD_DSEG(REG_ITMP1, disp); + M_JMP(REG_ITMP1_XPC, REG_ITMP1); M_NOP; break; @@ -2431,31 +2228,28 @@ bool codegen(jitdata *jd) case ICMD_GOTO: /* ... ==> ... */ case ICMD_RET: /* ... ==> ... */ - M_BR(0); - codegen_add_branch_ref(cd, iptr->dst.block); + emit_br(cd, iptr->dst.block); break; case ICMD_JSR: /* ... ==> ... */ - OOPS(); -#if 0 - M_JMP_IMM(0); - codegen_add_branch_ref(cd, iptr->sx.s23.s3.jsrtarget.block); -#endif + + emit_br(cd, iptr->sx.s23.s3.jsrtarget.block); + break; case ICMD_IFNULL: /* ..., value ==> ... */ - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - M_TEST(s1); - M_BEQ(0); - codegen_add_branch_ref(cd, iptr->dst.block); - break; - case ICMD_IFNONNULL: /* ..., value ==> ... */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); M_TEST(s1); - M_BNE(0); - codegen_add_branch_ref(cd, iptr->dst.block); + switch (iptr->opc) { + case ICMD_IFNULL: + emit_beq(cd, iptr->dst.block); + break; + case ICMD_IFNONNULL: + emit_bne(cd, iptr->dst.block); + break; + } break; case ICMD_IFEQ: /* ..., value ==> ... */ @@ -2467,274 +2261,267 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); - if ((iptr->sx.val.i >= -32768) && (iptr->sx.val.i <= 32767)) - N_CHI(s1, iptr->sx.val.i); + if (N_VALID_IMM(iptr->sx.val.i)) + M_ICMP_IMM(s1, iptr->sx.val.i); else { disp = dseg_add_s4(cd, iptr->sx.val.i); - N_LHI(REG_ITMP2, disp); - N_CL(s1, 0, REG_ITMP2, REG_PV); + if (N_VALID_DSEG_DISP(disp)) { + N_C(s1, N_DSEG_DISP(disp), RN, REG_PV); + } else { + ICONST(REG_ITMP2, disp); + N_C(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV); + } } switch (iptr->opc) { case ICMD_IFLT: - M_BLT(0); + emit_blt(cd, iptr->dst.block); break; case ICMD_IFLE: - M_BLE(0); + emit_ble(cd, iptr->dst.block); break; case ICMD_IFNE: - M_BNE(0); + emit_bne(cd, iptr->dst.block); break; case ICMD_IFGT: - M_BGT(0); + emit_bgt(cd, iptr->dst.block); break; case ICMD_IFGE: - M_BGE(0); + emit_bge(cd, iptr->dst.block); break; case ICMD_IFEQ: - M_BEQ(0); + emit_beq(cd, iptr->dst.block); break; } - codegen_add_branch_ref(cd, iptr->dst.block); - - break; - case ICMD_IF_LEQ: /* ..., value ==> ... */ - OOPS(); -#if 0 - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - if (IS_IMM32(iptr->sx.val.l)) - M_LCMP_IMM(iptr->sx.val.l, s1); - else { - M_MOV_IMM(iptr->sx.val.l, REG_ITMP2); - M_LCMP(REG_ITMP2, s1); - } - M_BEQ(0); - codegen_add_branch_ref(cd, iptr->dst.block); -#endif break; case ICMD_IF_LLT: /* ..., value ==> ... */ - OOPS(); -#if 0 - - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - if (IS_IMM32(iptr->sx.val.l)) - M_LCMP_IMM(iptr->sx.val.l, s1); - else { - M_MOV_IMM(iptr->sx.val.l, REG_ITMP2); - M_LCMP(REG_ITMP2, s1); - } - M_BLT(0); - codegen_add_branch_ref(cd, iptr->dst.block); -#endif - break; - - case ICMD_IF_LLE: /* ..., value ==> ... */ - OOPS(); -#if 0 - - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - if (IS_IMM32(iptr->sx.val.l)) - M_LCMP_IMM(iptr->sx.val.l, s1); - else { - M_MOV_IMM(iptr->sx.val.l, REG_ITMP2); - M_LCMP(REG_ITMP2, s1); - } - M_BLE(0); - codegen_add_branch_ref(cd, iptr->dst.block); -#endif - break; + case ICMD_IF_LLE: /* op1 = target JavaVM pc, val.l = constant */ + case ICMD_IF_LGT: + case ICMD_IF_LGE: + case ICMD_IF_LEQ: + case ICMD_IF_LNE: - case ICMD_IF_LNE: /* ..., value ==> ... */ - OOPS(); -#if 0 + /* ATTENTION: compare high words signed and low words unsigned */ - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - if (IS_IMM32(iptr->sx.val.l)) - M_LCMP_IMM(iptr->sx.val.l, s1); - else { - M_MOV_IMM(iptr->sx.val.l, REG_ITMP2); - M_LCMP(REG_ITMP2, s1); - } - M_BNE(0); - codegen_add_branch_ref(cd, iptr->dst.block); -#endif - break; +# define LABEL_OUT BRANCH_LABEL_1 - case ICMD_IF_LGT: /* ..., value ==> ... */ - OOPS(); -#if 0 + s1 = emit_load_s1_high(jd, iptr, REG_ITMP1); - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - if (IS_IMM32(iptr->sx.val.l)) - M_LCMP_IMM(iptr->sx.val.l, s1); + if (N_VALID_IMM(iptr->sx.val.l >> 32)) + M_ICMP_IMM(s1, iptr->sx.val.l >> 32); else { - M_MOV_IMM(iptr->sx.val.l, REG_ITMP2); - M_LCMP(REG_ITMP2, s1); + disp = dseg_add_s4(cd, iptr->sx.val.l >> 32); + if (N_VALID_DSEG_DISP(disp)) { + N_C(s1, N_DSEG_DISP(disp), RN, REG_PV); + } else { + ICONST(REG_ITMP2, disp); + N_C(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV); + } } - M_BGT(0); - codegen_add_branch_ref(cd, iptr->dst.block); -#endif - break; - case ICMD_IF_LGE: /* ..., value ==> ... */ - OOPS(); -#if 0 - - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - if (IS_IMM32(iptr->sx.val.l)) - M_LCMP_IMM(iptr->sx.val.l, s1); - else { - M_MOV_IMM(iptr->sx.val.l, REG_ITMP2); - M_LCMP(REG_ITMP2, s1); + switch(iptr->opc) { + case ICMD_IF_LLT: + case ICMD_IF_LLE: + emit_blt(cd, iptr->dst.block); + /* EQ ... fall through */ + emit_label_bgt(cd, LABEL_OUT); + break; + case ICMD_IF_LGT: + case ICMD_IF_LGE: + emit_bgt(cd, iptr->dst.block); + /* EQ ... fall through */ + emit_label_blt(cd, LABEL_OUT); + break; + case ICMD_IF_LEQ: + /* EQ ... fall through */ + emit_label_bne(cd, LABEL_OUT); + break; + case ICMD_IF_LNE: + /* EQ ... fall through */ + emit_bne(cd, iptr->dst.block); + break; + default: + assert(0); } - M_BGE(0); - codegen_add_branch_ref(cd, iptr->dst.block); -#endif - break; - - case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */ - case ICMD_IF_ACMPEQ: /* op1 = target JavaVM pc */ - - 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); - break; - - case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */ - s1 = emit_load_s1_high(jd, iptr, REG_ITMP1); - s2 = emit_load_s2_high(jd, iptr, REG_ITMP2); - M_CMP(s1, s2); - /* load low-bits before the branch, so we know the distance */ - /* TODO do the loads modify the condition code? - * lr, l, la, lhi dont - */ s1 = emit_load_s1_low(jd, iptr, REG_ITMP1); - s2 = emit_load_s2_low(jd, iptr, REG_ITMP2); - M_BNE(SZ_BRC + SZ_CR + SZ_BRC); - M_CMP(s1, s2); - M_BEQ(0); - codegen_add_branch_ref(cd, iptr->dst.block); - break; - case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */ - - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - s2 = emit_load_s2(jd, iptr, REG_ITMP2); - M_ICMP(s2, s1); - M_BNE(0); - codegen_add_branch_ref(cd, iptr->dst.block); - - break; + disp = dseg_add_s4(cd, (s4)(iptr->sx.val.l & 0xffffffff)); + if (N_VALID_DSEG_DISP(disp)) { + N_CL(s1, N_DSEG_DISP(disp), RN, REG_PV); + } else { + ICONST(REG_ITMP2, disp); + N_CL(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV); + } - case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */ - OOPS(); -#if 0 + switch(iptr->opc) { + case ICMD_IF_LLT: + emit_blt(cd, iptr->dst.block); + emit_label(cd, LABEL_OUT); + break; + case ICMD_IF_LLE: + emit_ble(cd, iptr->dst.block); + emit_label(cd, LABEL_OUT); + break; + case ICMD_IF_LGT: + emit_bgt(cd, iptr->dst.block); + emit_label(cd, LABEL_OUT); + break; + case ICMD_IF_LGE: + emit_bge(cd, iptr->dst.block); + emit_label(cd, LABEL_OUT); + break; + case ICMD_IF_LEQ: + emit_beq(cd, iptr->dst.block); + emit_label(cd, LABEL_OUT); + break; + case ICMD_IF_LNE: + emit_bne(cd, iptr->dst.block); + break; + default: + assert(0); + } - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - s2 = emit_load_s2(jd, iptr, REG_ITMP2); - M_LCMP(s2, s1); - M_BNE(0); - codegen_add_branch_ref(cd, iptr->dst.block); -#endif +# undef LABEL_OUT break; + case ICMD_IF_ACMPEQ: /* ..., value, value ==> ... */ case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */ - case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */ - - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - s2 = emit_load_s2(jd, iptr, REG_ITMP2); - M_ICMP(s2, s1); - M_BLT(0); - codegen_add_branch_ref(cd, iptr->dst.block); - break; - - case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */ - OOPS(); -#if 0 + /* Compare addresses as 31 bit unsigned integers */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); - s2 = emit_load_s2(jd, iptr, REG_ITMP2); - M_LCMP(s2, s1); - M_BLT(0); - codegen_add_branch_ref(cd, iptr->dst.block); -#endif - break; - - case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */ + M_LDA(REG_ITMP1, s1, 0); - s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); - M_ICMP(s2, s1); - M_BGT(0); - codegen_add_branch_ref(cd, iptr->dst.block); + M_LDA(REG_ITMP2, s2, 0); - break; + M_CMP(REG_ITMP1, REG_ITMP2); - case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */ + switch (iptr->opc) { + case ICMD_IF_ACMPEQ: + emit_beq(cd, iptr->dst.block); + break; + case ICMD_IF_ACMPNE: + emit_bne(cd, iptr->dst.block); + break; + } - OOPS(); -#if 0 - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - s2 = emit_load_s2(jd, iptr, REG_ITMP2); - M_LCMP(s2, s1); - M_BGT(0); - codegen_add_branch_ref(cd, iptr->dst.block); -#endif break; + case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */ + case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */ + case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */ + case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */ case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */ + case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); - M_ICMP(s2, s1); - M_BLE(0); - codegen_add_branch_ref(cd, iptr->dst.block); + M_CMP(s1, s2); + switch (iptr->opc) { + case ICMD_IF_ICMPEQ: + emit_beq(cd, iptr->dst.block); + break; + case ICMD_IF_ICMPNE: + emit_bne(cd, iptr->dst.block); + break; + case ICMD_IF_ICMPLT: + emit_blt(cd, iptr->dst.block); + break; + case ICMD_IF_ICMPGT: + emit_bgt(cd, iptr->dst.block); + break; + case ICMD_IF_ICMPLE: + emit_ble(cd, iptr->dst.block); + break; + case ICMD_IF_ICMPGE: + emit_bge(cd, iptr->dst.block); + break; + } break; case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */ + case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */ + case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */ + case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */ + case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */ + case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */ + { - s1 = emit_load_s1_high(jd, iptr, REG_ITMP1); - s2 = emit_load_s2_high(jd, iptr, REG_ITMP2); - M_CMP(s1, s2); - M_BLT(0); - codegen_add_branch_ref(cd, iptr->dst.block); - /* load low-bits before the branch, so we know the distance */ - /* TODO: the loads should not touch the condition code. */ - s1 = emit_load_s1_low(jd, iptr, REG_ITMP1); - s2 = emit_load_s2_low(jd, iptr, REG_ITMP2); - M_BGT(SZ_BRC + SZ_CR + SZ_BRC); - M_CMP(s1, s2); - M_BLE(0); - codegen_add_branch_ref(cd, iptr->dst.block); - break; + u1 *out_ref = NULL; - case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */ + /* ATTENTION: compare high words signed and low words unsigned */ + + s1 = emit_load_s1_high(jd, iptr, REG_ITMP1); + s2 = emit_load_s2_high(jd, iptr, REG_ITMP2); + + M_ICMP(s1, s2); + + switch(iptr->opc) { + case ICMD_IF_LCMPLT: + case ICMD_IF_LCMPLE: + emit_blt(cd, iptr->dst.block); + /* EQ ... fall through */ + out_ref = cd->mcodeptr; + M_BGT(0); + break; + case ICMD_IF_LCMPGT: + case ICMD_IF_LCMPGE: + emit_bgt(cd, iptr->dst.block); + /* EQ ... fall through */ + out_ref = cd->mcodeptr; + M_BLT(0); + break; + case ICMD_IF_LCMPEQ: + /* EQ ... fall through */ + out_ref = cd->mcodeptr; + M_BNE(0); + break; + case ICMD_IF_LCMPNE: + /* EQ ... fall through */ + emit_bne(cd, iptr->dst.block); + break; + default: + assert(0); + } - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - s2 = emit_load_s2(jd, iptr, REG_ITMP2); - M_ICMP(s2, s1); - M_BGE(0); - codegen_add_branch_ref(cd, iptr->dst.block); + s1 = emit_load_s1_low(jd, iptr, REG_ITMP1); + s2 = emit_load_s2_low(jd, iptr, REG_ITMP2); + + M_ICMPU(s1, s2); - break; + switch(iptr->opc) { + case ICMD_IF_LCMPLT: + emit_blt(cd, iptr->dst.block); + break; + case ICMD_IF_LCMPLE: + emit_ble(cd, iptr->dst.block); + break; + case ICMD_IF_LCMPGT: + emit_bgt(cd, iptr->dst.block); + break; + case ICMD_IF_LCMPGE: + emit_bge(cd, iptr->dst.block); + break; + case ICMD_IF_LCMPEQ: + emit_beq(cd, iptr->dst.block); + break; + case ICMD_IF_LCMPNE: + emit_bne(cd, iptr->dst.block); + break; + default: + assert(0); + } - case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */ + if (out_ref != NULL) { + N_BRC_BACK_PATCH(out_ref); + } - OOPS(); -#if 0 - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - s2 = emit_load_s2(jd, iptr, REG_ITMP2); - M_LCMP(s2, s1); - M_BGE(0); - codegen_add_branch_ref(cd, iptr->dst.block); -#endif + } break; case ICMD_IRETURN: /* ..., retvalue ==> ... */ @@ -2754,7 +2541,9 @@ bool codegen(jitdata *jd) if (INSTRUCTION_IS_UNRESOLVED(iptr)) { unresolved_class *uc = iptr->sx.s23.s2.uc; - codegen_addpatchref(cd, PATCHER_athrow_areturn, uc, 0); + PROFILE_CYCLE_STOP; + patcher_add_patch_ref(jd, PATCHER_resolve_class, uc, 0); + PROFILE_CYCLE_START; } #endif /* ENABLE_VERIFIER */ goto nowperformreturn; @@ -2786,50 +2575,55 @@ nowperformreturn: /* call trace function */ - /*emit_verbosecall_exit(jd); TODO */ +#if !defined(NDEBUG) + if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) + emit_verbosecall_exit(jd); +#endif /* !defined(NDEBUG) */ #if defined(ENABLE_THREADS) - if (checksync && (m->flags & ACC_SYNCHRONIZED)) { - disp = dseg_add_functionptr(cd, LOCK_monitor_exit); - M_ALD(REG_ITMP3, REG_PV, disp); - M_CALL(REG_ITMP3); - + if (checksync && code_is_synchronized(code)) { /* we need to save the proper return value */ switch (iptr->opc) { case ICMD_LRETURN: - M_IST(REG_RESULT2, REG_SP, rd->memuse * 4 + 8); + M_IST(REG_RESULT2, REG_SP, ((rd->memuse + 1) * 8) + 4); /* fall through */ case ICMD_IRETURN: case ICMD_ARETURN: - M_IST(REG_RESULT , REG_SP, rd->memuse * 4 + 4); + M_IST(REG_RESULT , REG_SP, (rd->memuse + 1) * 8); break; case ICMD_FRETURN: - M_FST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4); + M_FST(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8); break; case ICMD_DRETURN: - M_DST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4); + M_DST(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8); break; } - M_ALD(REG_A0, REG_SP, rd->memuse * 4); - M_JSR; + M_ALD(REG_A0, REG_SP, rd->memuse * 8); + + disp = dseg_add_functionptr(cd, LOCK_monitor_exit); + M_ALD_DSEG(REG_ITMP2, disp); + + M_ASUB_IMM(96, REG_SP); + M_CALL(REG_ITMP2); + M_AADD_IMM(96, REG_SP); /* and now restore the proper return value */ switch (iptr->opc) { case ICMD_LRETURN: - M_ILD(REG_RESULT2, REG_SP, rd->memuse * 4 + 8); + M_ILD(REG_RESULT2, REG_SP, ((rd->memuse + 1) * 8) + 4); /* fall through */ case ICMD_IRETURN: case ICMD_ARETURN: - M_ILD(REG_RESULT , REG_SP, rd->memuse * 4 + 4); + M_ILD(REG_RESULT , REG_SP, (rd->memuse + 1) * 8); break; case ICMD_FRETURN: - M_FLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4); + M_FLD(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8); break; case ICMD_DRETURN: - M_DLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4); + M_DLD(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8); break; } } @@ -2837,30 +2631,31 @@ nowperformreturn: /* restore return address */ - p--; M_ALD(REG_RA, REG_SP, p * 4); + p--; M_ALD(REG_RA, REG_SP, p * 8); /* restore saved registers */ for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) { - p--; M_ILD(rd->savintregs[i], REG_SP, p * 4); + p--; M_ILD(rd->savintregs[i], REG_SP, p * 8); } for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) { - p -= 2; M_DLD(rd->savfltregs[i], REG_SP, p * 4); + p--; M_DLD(rd->savfltregs[i], REG_SP, p * 8); } /* deallocate stack */ if (cd->stackframesize) - M_AADD_IMM(cd->stackframesize * 4, REG_SP); + M_AADD_IMM(cd->stackframesize * 8, REG_SP); + + /* generate method profiling code */ + + PROFILE_CYCLE_STOP; M_RET; - ALIGNCODENOP; } break; case ICMD_TABLESWITCH: /* ..., index ==> ... */ - OOPS(); -#if 0 { s4 i, l; branch_target_t *table; @@ -2873,42 +2668,46 @@ nowperformreturn: s1 = emit_load_s1(jd, iptr, REG_ITMP1); M_INTMOVE(s1, REG_ITMP1); - if (l != 0) + if (l == 0) { + /* do nothing */ + } else if (N_VALID_IMM(-l)) { M_ISUB_IMM(l, REG_ITMP1); + } else { + ICONST(REG_ITMP2, l); + M_ISUB(REG_ITMP2, REG_ITMP1); + } /* number of targets */ + i = i - l + 1; - /* range check */ - M_ICMP_IMM(i - 1, REG_ITMP1); - M_BA(0); + /* range check */ - codegen_add_branch_ref(cd, table[0].block); /* default target */ + ICONST(REG_ITMP2, i); + M_ICMPU(REG_ITMP1, REG_ITMP2); + emit_bge(cd, table[0].block); /* build jump table top down and use address of lowest entry */ table += i; while (--i >= 0) { - dseg_add_target(cd, table->block); + dseg_add_target(cd, table->block); --table; } + } - /* length of dataseg after last dseg_add_target is used - by load */ + /* length of dataseg after last dseg_add_target is used by load */ + + M_SLL_IMM(2, REG_ITMP1); /* scale by 4 */ + M_ASUB_IMM(cd->dseglen, REG_ITMP1); + N_L(REG_ITMP1, -N_PV_OFFSET, REG_ITMP1, REG_PV); + M_JMP(RN, REG_ITMP1); - M_MOV_IMM(0, REG_ITMP2); - dseg_adddata(cd); - emit_mov_memindex_reg(cd, -(cd->dseglen), REG_ITMP2, REG_ITMP1, 3, REG_ITMP1); - M_JMP(REG_ITMP1); - } -#endif break; case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */ - OOPS(); -#if 0 { s4 i; lookup_target_t *lookup; @@ -2921,17 +2720,18 @@ nowperformreturn: s1 = emit_load_s1(jd, iptr, REG_ITMP1); while (--i >= 0) { - M_ICMP_IMM(lookup->value, s1); - M_BEQ(0); - codegen_add_branch_ref(cd, lookup->target.block); + if (N_VALID_IMM(lookup->value)) { + M_ICMP_IMM(s1, lookup->value); + } else { + ICONST(REG_ITMP2, lookup->value); + M_ICMP(REG_ITMP2, s1); + } + emit_beq(cd, lookup->target.block); lookup++; } - M_JMP_IMM(0); - - codegen_add_branch_ref(cd, iptr->sx.s23.s3.lookupdefault.block); + emit_br(cd, iptr->sx.s23.s3.lookupdefault.block); } -#endif break; @@ -2977,14 +2777,14 @@ gen_method: if (!md->params[s3].inmemory) { if (IS_2_WORD_TYPE(var->type)) { s1 = PACK_REGS( - rd->argintregs[GET_LOW_REG(md->params[s3].regoff)], - rd->argintregs[GET_HIGH_REG(md->params[s3].regoff)] + GET_LOW_REG(md->params[s3].regoff), + GET_HIGH_REG(md->params[s3].regoff) ); d = emit_load(jd, iptr, var, s1); M_LNGMOVE(d, s1); } else { - s1 = rd->argintregs[md->params[s3].regoff]; + s1 = md->params[s3].regoff; d = emit_load(jd, iptr, var, s1); M_INTMOVE(d, s1); } @@ -2992,62 +2792,81 @@ gen_method: else { if (IS_2_WORD_TYPE(var->type)) { d = emit_load(jd, iptr, var, REG_ITMP12_PACKED); - M_LST(d, REG_SP, md->params[s3].regoff * 4); + M_LST(d, REG_SP, md->params[s3].regoff); } else { d = emit_load(jd, iptr, var, REG_ITMP1); - M_IST(d, REG_SP, md->params[s3].regoff * 4); + M_IST(d, REG_SP, md->params[s3].regoff); } } } else { if (!md->params[s3].inmemory) { - s1 = rd->argfltregs[md->params[s3].regoff]; + s1 = md->params[s3].regoff; d = emit_load(jd, iptr, var, s1); M_FLTMOVE(d, s1); } 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 * 4); + M_DST(d, REG_SP, md->params[s3].regoff); else - M_FST(d, REG_SP, md->params[s3].regoff * 4); + M_FST(d, REG_SP, md->params[s3].regoff); } } } + /* generate method profiling code */ + + PROFILE_CYCLE_STOP; + switch (iptr->opc) { case ICMD_BUILTIN: - disp = dseg_add_functionptr(cd, bte->fp); + if (bte->stub == NULL) { + disp = dseg_add_functionptr(cd, bte->fp); + M_ASUB_IMM(96, REG_SP); /* register save area as required by C abi */ + } else { + disp = dseg_add_functionptr(cd, bte->stub); + } - N_LHI(REG_ITMP1, disp); - N_L(REG_PV, 0, REG_ITMP1, REG_PV); + if (N_VALID_DSEG_DISP(disp)) { + N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV); + } else { + N_LHI(REG_ITMP1, disp); + N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV); + } break; case ICMD_INVOKESPECIAL: - emit_nullpointer_check(cd, iptr, REG_A0); - M_ILD(REG_ITMP1, REG_A0, 0); /* hardware nullptr */ + /* TODO softnull */ + /* Implicit NULL pointer check */ + M_ILD(REG_ITMP1, REG_A0, 0); + /* fall through */ case ICMD_INVOKESTATIC: if (lm == NULL) { disp = dseg_add_unique_address(cd, um); - codegen_addpatchref(cd, PATCHER_invokestatic_special, + patcher_add_patch_ref(jd, PATCHER_invokestatic_special, um, disp); } else disp = dseg_add_address(cd, lm->stubroutine); - N_LHI(REG_ITMP1, disp); - N_L(REG_PV, 0, REG_ITMP1, REG_PV); + if (N_VALID_DSEG_DISP(disp)) { + N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV); + } else { + N_LHI(REG_ITMP1, disp); + N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV); + } break; case ICMD_INVOKEVIRTUAL: - emit_nullpointer_check(cd, iptr, REG_A0); + /* TODO softnull REG_A0 */ if (lm == NULL) { - codegen_addpatchref(cd, PATCHER_invokevirtual, um, 0); + patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, 0); s1 = 0; } @@ -3056,28 +2875,36 @@ gen_method: sizeof(methodptr) * lm->vftblindex; } - M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl)); + /* implicit null-pointer check */ + + M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl)); M_ALD(REG_PV, REG_METHODPTR, s1); break; case ICMD_INVOKEINTERFACE: - emit_nullpointer_check(cd, iptr, REG_A0); + /* TODO softnull REG_A0 */ + + /* s1 will be negative here, so use (0xFFF + s1) as displacement + * and -0xFFF in index register (itmp1) + */ if (lm == NULL) { - codegen_addpatchref(cd, PATCHER_invokeinterface, um, 0); + patcher_add_patch_ref(jd, 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_A0, OFFSET(java_objectheader, vftbl)); - M_ALD(REG_METHODPTR, REG_METHODPTR, s1); + /* Implicit null-pointer check */ + M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl)); + N_LHI(REG_ITMP2, s1); + N_L(REG_METHODPTR, 0, REG_ITMP2, REG_METHODPTR); M_ALD(REG_PV, REG_METHODPTR, s2); break; } @@ -3085,19 +2912,26 @@ gen_method: /* generate the actual call */ M_CALL(REG_PV); - REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr); - N_BASR(REG_ITMP1, RN); - disp = (s4) (cd->mcodeptr - cd->mcodebase); - M_LDA(REG_PV, REG_ITMP1, -disp); - - /* actually only used for ICMD_BUILTIN */ + emit_restore_pv(cd); - if (INSTRUCTION_MUST_CHECK(iptr)) { - M_TEST(REG_RESULT); - M_BEQ(0); - codegen_add_fillinstacktrace_ref(cd); + /* post call finalization */ + + switch (iptr->opc) { + case ICMD_BUILTIN: + if (bte->stub == NULL) { + M_AADD_IMM(96, REG_SP); /* remove C abi register save area */ + } + break; } + /* generate method profiling code */ + + PROFILE_CYCLE_START; + + /* store size of call code in replacement point */ + + REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr); + /* store return value */ d = md->returntype.type; @@ -3147,8 +2981,11 @@ gen_method: vftbl_t *supervftbl; s4 superindex; - u1 *class_label_refs[] = { 0 }, *class_label; - u1 *exit_label_refs[] = { 0, 0, 0, 0 }; +# define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1 +# define LABEL_CLASS BRANCH_LABEL_2 +# define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3 +# define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_4 +# define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_5 if (INSTRUCTION_IS_UNRESOLVED(iptr)) { super = NULL; @@ -3161,74 +2998,75 @@ gen_method: supervftbl = super->vftbl; } -#if defined(ENABLE_THREADS) - codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase); -#endif + if ((super == NULL) || !(super->flags & ACC_INTERFACE)) + CODEGEN_CRITICAL_SECTION_NEW; + s1 = emit_load_s1(jd, iptr, REG_ITMP1); /* if class is not resolved, check which code to call */ if (super == NULL) { M_TEST(s1); - exit_label_refs[0] = cd->mcodeptr; - M_BEQ(0); + emit_label_beq(cd, LABEL_EXIT_CHECK_NULL); disp = dseg_add_unique_s4(cd, 0); /* super->flags */ - codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_flags, + patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags, iptr->sx.s23.s3.c.ref, disp); - ICONST(REG_ITMP2, ACC_INTERFACE); - ICONST(REG_ITMP3, disp); /* TODO negative displacement */ - N_N(REG_ITMP2, 0, REG_ITMP3, REG_PV); - class_label_refs[0] = cd->mcodeptr; - M_BEQ(0); + ICONST(REG_ITMP3, ACC_INTERFACE); + + if (N_VALID_DSEG_DISP(disp)) { + N_N(REG_ITMP3, N_DSEG_DISP(disp), RN, REG_PV); + } else { + ICONST(REG_ITMP2, disp); + N_N(REG_ITMP3, -N_PV_OFFSET, REG_ITMP2, REG_PV); + } + emit_label_beq(cd, LABEL_CLASS); } /* interface checkcast code */ if ((super == NULL) || (super->flags & ACC_INTERFACE)) { if (super == NULL) { - codegen_add_patch_ref(cd, + patcher_add_patch_ref(jd, PATCHER_checkcast_instanceof_interface, iptr->sx.s23.s3.c.ref, 0); } else { M_TEST(s1); - exit_label_refs[1] = cd->mcodeptr; - M_BEQ(0); + emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL); } - 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_TEST(REG_ITMP3); - M_BLE(0); - codegen_add_classcastexception_ref(cd, s1); - M_ALD(REG_ITMP3, REG_ITMP2, - (s4) (OFFSET(vftbl_t, interfacetable[0]) - - superindex * sizeof(methodptr*))); - M_TEST(REG_ITMP3); - M_BEQ(0); - codegen_add_classcastexception_ref(cd, s1); + M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl)); + M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength)); + M_ISUB_IMM(superindex, REG_ITMP3); + emit_classcast_check(cd, iptr, BRANCH_LE, RN, s1); + N_AHI( + REG_ITMP2, + (s4) (OFFSET(vftbl_t, interfacetable[0]) - + superindex * sizeof(methodptr*)) + ); + M_ALD(REG_ITMP2, REG_ITMP2, 0); + emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP2, s1); if (super == NULL) { - exit_label_refs[2] = cd->mcodeptr; - M_BR(0); + emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE); } } /* class checkcast code */ - - class_label = cd->mcodeptr; + + if (super == NULL) { + emit_label(cd, LABEL_CLASS); + } if ((super == NULL) || !(super->flags & ACC_INTERFACE)) { if (super == NULL) { disp = dseg_add_unique_address(cd, NULL); - codegen_add_patch_ref(cd, + patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl, iptr->sx.s23.s3.c.ref, disp); @@ -3236,53 +3074,72 @@ gen_method: else { disp = dseg_add_address(cd, supervftbl); M_TEST(s1); - exit_label_refs[3] = cd->mcodeptr; - M_BEQ(0); + emit_label_beq(cd, LABEL_EXIT_CLASS_NULL); } - M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl)); - M_ALD(REG_ITMP3, REG_PV, disp); -#if defined(ENABLE_THREADS) - codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase); -#endif +#if 1 + CODEGEN_CRITICAL_SECTION_START; + + /* REG_ITMP3 := baseval(s1) */ + M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl)); + M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval)); + + /* REG_ITMP2 := baseval(class) */ + M_ALD_DSEG(REG_ITMP2, disp); 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)); + + /* REG_ITMP3 := REG_ITMP3 - REG_ITMP2 */ M_ISUB(REG_ITMP2, REG_ITMP3); - 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 - /* } */ - N_CLR(REG_ITMP2, REG_ITMP3); /* Unsigned compare */ + + /* REG_ITMP2 := diffval(class) */ + M_ALD_DSEG(REG_ITMP2, disp); + M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval)); + + CODEGEN_CRITICAL_SECTION_END; + + M_CMPU(REG_ITMP3, REG_ITMP2); /* Unsigned compare */ + /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */ - M_BGT(0); /* Branch if greater then */ /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */ - codegen_add_classcastexception_ref(cd, s1); - } + /* Branch if greater then */ +#else + M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl)); + M_ALD_DSEG(REG_ITMP3, disp); + + CODEGEN_CRITICAL_SECTION_START; - /* resolve labels by adding the correct displacement */ + M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval)); + M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval)); + M_ISUB(REG_ITMP3, REG_ITMP2); + M_ALD_DSEG(REG_ITMP3, disp); + M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval)); - for (s2 = 0; s2 < sizeof(exit_label_refs) / sizeof(exit_label_refs[0]); ++s2) { - if (exit_label_refs[s2]) - *(u4 *)exit_label_refs[s2] |= (u4)(cd->mcodeptr - exit_label_refs[s2]) / 2; + CODEGEN_CRITICAL_SECTION_END; + + M_CMPU(REG_ITMP2, REG_ITMP3); /* Unsigned compare */ + /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */ + /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */ + /* Branch if greater then */ +#endif + emit_classcast_check(cd, iptr, BRANCH_GT, RN, s1); } - for (s2 = 0; s2 < sizeof(class_label_refs) / sizeof(class_label_refs[0]); ++s2) { - if (class_label_refs[s2]) - *(u4 *)class_label_refs[s2] |= (u4)(class_label - class_label_refs[s2]) / 2; + if (super == NULL) { + emit_label(cd, LABEL_EXIT_CHECK_NULL); + emit_label(cd, LABEL_EXIT_INTERFACE_DONE); + } else if (super->flags & ACC_INTERFACE) { + emit_label(cd, LABEL_EXIT_INTERFACE_NULL); + } else { + emit_label(cd, LABEL_EXIT_CLASS_NULL); } d = codegen_reg_of_dst(jd, iptr, s1); + +# undef LABEL_EXIT_CHECK_NULL +# undef LABEL_CLASS +# undef LABEL_EXIT_INTERFACE_NULL +# undef LABEL_EXIT_INTERFACE_DONE +# undef LABEL_EXIT_CLASS_NULL } else { /* array type cast-check */ @@ -3293,7 +3150,7 @@ gen_method: if (INSTRUCTION_IS_UNRESOLVED(iptr)) { disp = dseg_add_unique_address(cd, NULL); - codegen_add_patch_ref(cd, + patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo, iptr->sx.s23.s3.c.ref, disp); @@ -3301,19 +3158,15 @@ gen_method: else disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls); - M_ALD(REG_A1, REG_PV, disp); + M_ALD_DSEG(REG_A1, disp); disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast); - ICONST(REG_ITMP1, disp); /* TODO negative displacement */ - N_L(REG_PV, 0, REG_ITMP1, REG_PV); - M_JSR(REG_RA, REG_PV); - N_BASR(REG_ITMP1, RN); - disp = (s4) (cd->mcodeptr - cd->mcodebase); - M_LDA(REG_PV, REG_ITMP1, -disp); + M_ALD_DSEG(REG_ITMP1, disp); + M_ASUB_IMM(96, REG_SP); + M_JSR(REG_RA, REG_ITMP1); + M_AADD_IMM(96, REG_SP); s1 = emit_load_s1(jd, iptr, REG_ITMP1); - M_TEST(REG_RESULT); - M_BEQ(0); - codegen_add_classcastexception_ref(cd, s1); + emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1); d = codegen_reg_of_dst(jd, iptr, s1); } @@ -3323,8 +3176,6 @@ gen_method: break; case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */ - OOPS(); -#if 0 /* val.a: (classinfo*) superclass */ /* superclass is an interface: @@ -3338,6 +3189,10 @@ gen_method: * return ((sub != NULL) && (0 * <= (sub->vftbl->baseval - super->vftbl->baseval) <= * super->vftbl->diffvall)); + * + * If superclass is unresolved, we include both code snippets + * above, a patcher resolves the class' flags and we select + * the right code at runtime. */ { @@ -3356,9 +3211,16 @@ gen_method: supervftbl = super->vftbl; } -#if defined(ENABLE_THREADS) - codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase); -#endif +# define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1 +# define LABEL_CLASS BRANCH_LABEL_2 +# define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3 +# define LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE BRANCH_LABEL_4 +# define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_5 +# define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_6 + + if ((super == NULL) || !(super->flags & ACC_INTERFACE)) + CODEGEN_CRITICAL_SECTION_NEW; + s1 = emit_load_s1(jd, iptr, REG_ITMP1); d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); if (s1 == d) { @@ -3366,35 +3228,29 @@ gen_method: s1 = REG_ITMP1; } - /* calculate interface instanceof code size */ - - s2 = 6; - if (super == NULL) - s2 += (d == REG_ITMP2 ? 1 : 0) + (opt_shownops ? 1 : 0); - - /* calculate class instanceof code size */ - - s3 = 7; - if (super == NULL) - s3 += (opt_shownops ? 1 : 0); - /* if class is not resolved, check which code to call */ if (super == NULL) { M_CLR(d); - M_BEQZ(s1, 4 + (opt_shownops ? 1 : 0) + s2 + 1 + s3); + + M_TEST(s1); + emit_label_beq(cd, LABEL_EXIT_CHECK_NULL); disp = dseg_add_unique_s4(cd, 0); /* super->flags */ - codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_flags, + patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags, iptr->sx.s23.s3.c.ref, disp); - M_ILD(REG_ITMP3, REG_PV, disp); + ICONST(REG_ITMP3, ACC_INTERFACE); + + if (N_VALID_DSEG_DISP(disp)) { + N_N(REG_ITMP3, N_DSEG_DISP(disp), RN, REG_PV); + } else { + ICONST(REG_ITMP2, disp); + N_N(REG_ITMP3, -N_PV_OFFSET, REG_ITMP2, REG_PV); + } - disp = dseg_add_s4(cd, ACC_INTERFACE); - M_ILD(REG_ITMP2, REG_PV, disp); - M_AND(REG_ITMP3, REG_ITMP2, REG_ITMP3); - M_BEQZ(REG_ITMP3, s2 + 1); + emit_label_beq(cd, LABEL_CLASS); } /* interface instanceof code */ @@ -3406,35 +3262,51 @@ gen_method: if (d == REG_ITMP2) M_CLR(d); - codegen_add_patch_ref(cd, + patcher_add_patch_ref(jd, PATCHER_checkcast_instanceof_interface, iptr->sx.s23.s3.c.ref, 0); } else { M_CLR(d); - M_BEQZ(s1, s2); + M_TEST(s1); + emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL); } - M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl)); + M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl)); M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength)); - M_LDA(REG_ITMP3, REG_ITMP3, -superindex); - M_BLEZ(REG_ITMP3, 2); - M_ALD(REG_ITMP1, REG_ITMP1, - (s4) (OFFSET(vftbl_t, interfacetable[0]) - - superindex * sizeof(methodptr*))); - M_CMPULT(REG_ZERO, REG_ITMP1, d); /* REG_ITMP1 != 0 */ + M_ISUB_IMM(superindex, REG_ITMP3); + + emit_label_ble(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE); + + N_AHI( + REG_ITMP1, + (s4) (OFFSET(vftbl_t, interfacetable[0]) - + superindex * sizeof(methodptr*)) + ); + M_ALD(REG_ITMP1, REG_ITMP1, 0); + + /* d := (REG_ITMP1 != 0) */ - if (super == NULL) - M_BR(s3); + N_LTR(d, REG_ITMP1); + M_BEQ(SZ_BRC + SZ_LHI); + N_LHI(d, 1); + + if (super == NULL) { + emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE); + } } /* class instanceof code */ + if (super == NULL) { + emit_label(cd, LABEL_CLASS); + } + if ((super == NULL) || !(super->flags & ACC_INTERFACE)) { if (super == NULL) { disp = dseg_add_unique_address(cd, NULL); - codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_vftbl, + patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl, iptr->sx.s23.s3.c.ref, disp); } @@ -3442,36 +3314,60 @@ gen_method: disp = dseg_add_address(cd, supervftbl); M_CLR(d); - M_BEQZ(s1, s3); + + M_TEST(s1); + emit_label_beq(cd, LABEL_EXIT_CLASS_NULL); } - M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl)); - M_ALD(REG_ITMP2, REG_PV, disp); -#if defined(ENABLE_THREADS) - codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase); -#endif + M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl)); + M_ALD_DSEG(REG_ITMP2, disp); + + CODEGEN_CRITICAL_SECTION_START; + 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)); -#if defined(ENABLE_THREADS) - codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase); -#endif - M_ISUB(REG_ITMP1, REG_ITMP3); - N_CLR(REG_ITMP1, REG_ITMP2); - M_CMPULE(REG_ITMP1, REG_ITMP2, d); + + CODEGEN_CRITICAL_SECTION_END; + + M_ISUB(REG_ITMP3, REG_ITMP1); /* itmp1 := itmp1 (sub.baseval) - itmp3 (super.baseval) */ + + M_CMPU(REG_ITMP1, REG_ITMP2); /* d := (uint)REG_ITMP1 <= (uint)REG_ITMP2 */ + N_LHI(d, 0); + M_BGT(SZ_BRC + SZ_LHI); + N_LHI(d, 1); + } + + if (super == NULL) { + emit_label(cd, LABEL_EXIT_CHECK_NULL); + emit_label(cd, LABEL_EXIT_INTERFACE_DONE); + emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE); + } else if (super->flags & ACC_INTERFACE) { + emit_label(cd, LABEL_EXIT_INTERFACE_NULL); + emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE); + } else { + emit_label(cd, LABEL_EXIT_CLASS_NULL); } + +# undef LABEL_EXIT_CHECK_NULL +# undef LABEL_CLASS +# undef LABEL_EXIT_INTERFACE_NULL +# undef LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE +# undef LABEL_EXIT_INTERFACE_DONE +# undef LABEL_EXIT_CLASS_NULL + emit_store_dst(jd, iptr, d); + } -#endif + break; case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */ - OOPS(); -#if 0 /* check for negative sizes and copy sizes to stack if necessary */ - MCODECHECK((10 * 4 * iptr->s1.argcount) + 5 + 10 * 8); + /*MCODECHECK((10 * 4 * iptr->s1.argcount) + 5 + 10 * 8);*/ + MCODECHECK(512); for (s1 = iptr->s1.argcount; --s1 >= 0; ) { @@ -3481,42 +3377,48 @@ gen_method: /* Already Preallocated? */ if (!(var->flags & PREALLOC)) { s2 = emit_load(jd, iptr, var, REG_ITMP1); - M_LST(s2, REG_SP, s1 * 8); + M_IST(s2, REG_SP, s1 * 4); } } /* is a patcher function set? */ if (INSTRUCTION_IS_UNRESOLVED(iptr)) { - codegen_add_patch_ref(cd, PATCHER_builtin_multianewarray, - iptr->sx.s23.s3.c.ref, 0); + disp = dseg_add_unique_address(cd, 0); + + patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo, + iptr->sx.s23.s3.c.ref, + disp); } + else + disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls); /* a0 = dimension count */ - M_MOV_IMM(iptr->s1.argcount, REG_A0); + ICONST(REG_A0, iptr->s1.argcount); /* a1 = classinfo */ - M_MOV_IMM(iptr->sx.s23.s3.c.cls, REG_A1); + M_ALD_DSEG(REG_A1, disp); /* a2 = pointer to dimensions = stack pointer */ M_MOV(REG_SP, REG_A2); - M_MOV_IMM(BUILTIN_multianewarray, REG_ITMP1); - M_CALL(REG_ITMP1); + disp = dseg_add_functionptr(cd, BUILTIN_multianewarray); + M_ALD_DSEG(REG_ITMP1, disp); + M_ASUB_IMM(96, REG_SP); + M_JSR(REG_RA, REG_ITMP1); + M_AADD_IMM(96, REG_SP); /* check for exception before result assignment */ - M_TEST(REG_RESULT); - M_BEQ(0); - codegen_add_fillinstacktrace_ref(cd); + emit_exception_check(cd, iptr); s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT); M_INTMOVE(REG_RESULT, s1); emit_store_dst(jd, iptr, s1); -#endif + break; default: @@ -3542,94 +3444,18 @@ gen_method: } /* if (bptr -> flags >= BBREACHED) */ } /* for basic block */ - dseg_createlinenumbertable(cd); - /* generate stubs */ - emit_exception_stubs(jd); - emit_patcher_stubs(jd); -#if 0 - emit_replacement_stubs(jd); -#endif - - codegen_finish(jd); + emit_patcher_traps(jd); /* everything's ok */ return true; } +/* codegen_emit_stub_native **************************************************** -/* createcompilerstub ********************************************************** - - Creates a stub routine which calls the compiler. - -*******************************************************************************/ - -#define COMPILERSTUB_DATASIZE (3 * SIZEOF_VOID_P) -#define COMPILERSTUB_CODESIZE (SZ_AHI + SZ_L + SZ_L + SZ_BCR) - -#define COMPILERSTUB_SIZE (COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE) - - -u1 *createcompilerstub(methodinfo *m) -{ - u1 *s; /* memory to hold the stub */ - ptrint *d; - codeinfo *code; - codegendata *cd; - s4 dumpsize; - - s = CNEW(u1, COMPILERSTUB_SIZE); - - /* set data pointer and code pointer */ - - d = (ptrint *) s; - s = s + COMPILERSTUB_DATASIZE; - - /* mark start of dump memory area */ - - dumpsize = dump_size(); - - cd = DNEW(codegendata); - cd->mcodeptr = s; - - /* Store the codeinfo pointer in the same place as in the - methodheader for compiled methods. */ - - code = code_codeinfo_new(m); - - d[0] = (ptrint) asm_call_jit_compiler; - d[1] = (ptrint) m; - d[2] = (ptrint) code; - - /* code for the stub */ - - /* don't touch ITMP3 as it cointains the return address */ - - M_ISUB_IMM((3 * 4), REG_PV); /* suppress negative displacements */ - - M_ILD(REG_ITMP1, REG_PV, 1 * 4); /* methodinfo */ - /* TODO where is methodpointer loaded into itmp2? is it already inside? */ - M_ILD(REG_PV, REG_PV, 0 * 4); /* compiler pointer */ - N_BR(REG_PV); - -#if defined(ENABLE_STATISTICS) - if (opt_stat) - count_cstub_len += COMPILERSTUB_SIZE; -#endif - - /* release dump area */ - - dump_release(dumpsize); - - return s; -} - - -/* createnativestub ************************************************************ - - Creates a stub routine which calls a native method. + Emits a stub routine which calls a native method. *******************************************************************************/ @@ -3653,334 +3479,279 @@ u1 *createcompilerstub(methodinfo *m) SP after method entry */ -u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd) +void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int skipparams) { - methodinfo *m; - codeinfo *code; - codegendata *cd; - registerdata *rd; - methoddesc *md; - s4 nativeparams; - s4 i, j; /* count variables */ - s4 t; - s4 s1, s2; - s4 disp; + methodinfo *m; + codeinfo *code; + codegendata *cd; + methoddesc *md; + int i, j; + int t; + int s1, s2; + int disp; /* get required compiler data */ m = jd->m; code = jd->code; cd = jd->cd; - rd = jd->rd; - /* initialize variables */ + /* set some variables */ md = m->parseddesc; - nativeparams = (m->flags & ACC_STATIC) ? 2 : 1; - /* calculate stack frame size */ -#if 0 - cd->stackframesize = - sizeof(stackframeinfo) / SIZEOF_VOID_P + - sizeof(localref_table) / SIZEOF_VOID_P + - INT_ARG_CNT + FLT_ARG_CNT + - 1 + /* functionptr, TODO: store in data segment */ - nmd->memuse; + /* calculate stackframe size */ - cd->stackframesize |= 0x1; /* keep stack 16-byte aligned */ -#endif + cd->stackframesize = + 1 + /* return address */ + sizeof(stackframeinfo_t) / 8 + + sizeof(localref_table) / 8 + + nmd->paramcount + + nmd->memuse + + (96 / 8); /* linkage area */ - cd->stackframesize = - 1 + /* r14 - return address */ + - sizeof(stackframeinfo) / SIZEOF_VOID_P + - sizeof(localref_table) / SIZEOF_VOID_P + - 1 + /* itmp3 */ - (INT_ARG_CNT + FLT_ARG_CNT) * 2 + - nmd->memuse + /* parameter passing */ - 96 / SIZEOF_VOID_P /* required by ABI */; + /* keep stack 8-byte aligned */ + /*ALIGN_2(cd->stackframesize);*/ /* 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); /* IsSync */ + (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* 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 */ - (void) dseg_addlinenumbertablesize(cd); - (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */ - - /* generate native method profiling code */ -#if 0 - if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) { - /* count frequency */ - - M_MOV_IMM(code, REG_ITMP3); - M_IINC_MEMBASE(REG_ITMP3, OFFSET(codeinfo, frequency)); - } -#endif - - /* generate stub code */ - N_AHI(REG_SP, -(cd->stackframesize * SIZEOF_VOID_P)); + /* generate code */ - /* save return address */ + M_ASUB_IMM(cd->stackframesize * 8, REG_SP); + M_AADD_IMM(N_PV_OFFSET, REG_PV); - N_ST(R14, (cd->stackframesize - 1) * SIZEOF_VOID_P, RN, REG_SP); + /* store return address */ -#if 0 -#if !defined(NDEBUG) - if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) - emit_verbosecall_enter(jd); -#endif -#endif + M_AST(REG_RA, REG_SP, (cd->stackframesize - 1) * 8); - /* get function address (this must happen before the stackframeinfo) */ +#if defined(ENABLE_GC_CACAO) + /* Save callee saved integer registers in stackframeinfo (GC may + need to recover them during a collection). */ - disp = dseg_add_functionptr(cd, f); + disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) + + OFFSET(stackframeinfo_t, intregs); -#if !defined(WITH_STATIC_CLASSPATH) - if (f == NULL) - codegen_add_patch_ref(cd, PATCHER_resolve_native, m, disp); + for (i = 0; i < INT_SAV_CNT; i++) + M_AST(abi_registers_integer_saved[i], REG_SP, disp + i * 4); #endif - M_ILD(REG_ITMP1, REG_PV, disp); - - j = 96 + (nmd->memuse * 4); - - /* todo some arg registers are not volatile in C-abi terms */ - /* save integer and float argument registers */ for (i = 0; i < md->paramcount; i++) { - if (! md->params[i].inmemory) { + if (!md->params[i].inmemory) { s1 = md->params[i].regoff; - if (IS_INT_LNG_TYPE(md->paramtypes[i].type)) { - if (IS_2_WORD_TYPE(t)) { - /* todo store multiple */ - N_ST(rd->argintregs[GET_HIGH_REG(s1)], j, RN, REG_SP); - N_ST(rd->argintregs[GET_LOW_REG(s1)], j + 4, RN, REG_SP); - } else { - N_ST(rd->argintregs[s1], j, RN, REG_SP); - } - } else { - if (IS_2_WORD_TYPE(t)) { - N_STD(rd->argfltregs[s1], j, RN, REG_SP); - } else { - N_STE(rd->argfltregs[s1], j, RN, REG_SP); - } + switch (md->paramtypes[i].type) { + case TYPE_INT: + case TYPE_ADR: + M_IST(s1, REG_SP, 96 + i * 8); + break; + case TYPE_LNG: + M_LST(s1, REG_SP, 96 + i * 8); + break; + case TYPE_FLT: + case TYPE_DBL: + M_DST(s1, REG_SP, 96 + i * 8); + break; } - - j += 8; } } - N_ST(REG_ITMP1, j, RN, REG_SP); - - /* create dynamic stack info */ - - N_LAE(REG_A0, (cd->stackframesize - 1) * 4, RN, REG_SP); /* datasp */ - N_LR(REG_A1, REG_PV); /* pv */ - N_LAE(REG_A2, cd->stackframesize * 4, RN, REG_SP); /* old SP */ - N_L(REG_A3, (cd->stackframesize - 1) * 4, RN, REG_SP); /* return address */ + /* create native stack info */ + M_MOV(REG_SP, REG_A0); + M_LDA(REG_A1, REG_PV, -N_PV_OFFSET); disp = dseg_add_functionptr(cd, codegen_start_native_call); - M_ILD(REG_ITMP1, REG_PV, disp); + M_ALD_DSEG(REG_ITMP2, disp); + M_CALL(REG_ITMP2); - M_CALL(REG_ITMP1); /* call */ + /* remember class argument */ - /* restore integer and float argument registers */ + if (m->flags & ACC_STATIC) + M_MOV(REG_RESULT, REG_ITMP3); - j = 96 + (nmd->memuse * 4); + /* restore integer and float argument registers */ for (i = 0; i < md->paramcount; i++) { - if (! md->params[i].inmemory) { + if (!md->params[i].inmemory) { s1 = md->params[i].regoff; - if (IS_INT_LNG_TYPE(md->paramtypes[i].type)) { - if (IS_2_WORD_TYPE(t)) { - /* todo load multiple ! */ - N_L(rd->argintregs[GET_HIGH_REG(s1)], j, RN, REG_SP); - N_L(rd->argintregs[GET_LOW_REG(s1)], j + 4, RN, REG_SP); - } else { - N_L(rd->argintregs[s1], j, RN, REG_SP); - } - } else { - if (IS_2_WORD_TYPE(t)) { - N_LD(rd->argfltregs[s1], j, RN, REG_SP); - } else { - N_LE(rd->argfltregs[s1], j, RN, REG_SP); - } + switch (md->paramtypes[i].type) { + case TYPE_INT: + case TYPE_ADR: + M_ILD(s1, REG_SP, 96 + i * 8); + break; + case TYPE_LNG: + M_LLD(s1, REG_SP, 96 + i * 8); + break; + case TYPE_FLT: + case TYPE_DBL: + M_DLD(s1, REG_SP, 96 + i * 8); + break; } - - j += 8; } } - N_L(REG_ITMP1, j, RN, REG_SP); - /* copy or spill arguments to new locations */ - for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) { + for (i = md->paramcount - 1, j = i + skipparams; i >= 0; i--, j--) { t = md->paramtypes[i].type; if (IS_INT_LNG_TYPE(t)) { - if (!md->params[i].inmemory) { - - s1 = rd->argintregs[md->params[i].regoff]; + s1 = md->params[i].regoff; + s2 = nmd->params[j].regoff; if (!nmd->params[j].inmemory) { - s2 = rd->argintregs[nmd->params[j].regoff]; - if (IS_2_WORD_TYPE(t)) { - N_LR(GET_HIGH_REG(s2), GET_HIGH_REG(s1)); - N_LR(GET_LOW_REG(s2), GET_LOW_REG(s1)); - } else { - N_LR(s2, s1); - } - } else { - s2 = nmd->params[j].regoff; - if (IS_2_WORD_TYPE(t)) { - N_LM(GET_LOW_REG(s1), GET_HIGH_REG(s1), 96 + (s2 * 4), REG_SP); - } else { - N_L(s1, 96 + (s2 * 4), RN, REG_SP); - } + if (IS_2_WORD_TYPE(t)) + M_LNGMOVE(s1, s2); + else + M_INTMOVE(s1, s2); } - - } else { - s1 = md->params[i].regoff + cd->stackframesize + 1; /* + 1 (RA) */ + else { + if (IS_2_WORD_TYPE(t)) + M_LST(s1, REG_SP, s2); + else + M_IST(s1, REG_SP, s2); + } + } + else { + s1 = md->params[i].regoff + cd->stackframesize * 8; s2 = nmd->params[j].regoff; - + if (IS_2_WORD_TYPE(t)) { - N_MVC(96 + (s2 * 4), 8, REG_SP, s1, REG_SP); + N_MVC(s2, 8, REG_SP, s1, REG_SP); } else { - N_MVC(96 + (s2 * 4), 4, REG_SP, s1, REG_SP); + N_MVC(s2, 4, REG_SP, s1, REG_SP); } } - - } else { - /* We only copy spilled float arguments, as the float argument */ - /* registers keep unchanged. */ + } + else { + /* We only copy spilled float arguments, as the float + argument registers keep unchanged. */ if (md->params[i].inmemory) { - s1 = md->params[i].regoff + cd->stackframesize + 1; /* + 1 (RA) */ + s1 = md->params[i].regoff + cd->stackframesize * 8; s2 = nmd->params[j].regoff; if (IS_2_WORD_TYPE(t)) { - N_MVC(96 + (s2 * 4), 8, REG_SP, s1, REG_SP); + N_MVC(s2, 8, REG_SP, s1, REG_SP); } else { - N_MVC(96 + (s2 * 4), 4, REG_SP, s1, REG_SP); + N_MVC(s2, 4, REG_SP, s1, REG_SP); } } } } - /* put class into second argument register */ + /* Handle native Java methods. */ - if (m->flags & ACC_STATIC) { - disp = dseg_add_address(cd, m->class); - M_ILD(REG_A1, REG_PV, disp); - } + if (m->flags & ACC_NATIVE) { + /* put class into second argument register */ - /* put env into first argument register */ + if (m->flags & ACC_STATIC) + M_MOV(REG_ITMP3, REG_A1); - disp = dseg_add_address(cd, _Jv_env); - M_ILD(REG_A0, REG_PV, disp); + /* put env into first argument register */ - /* do the native function call */ + disp = dseg_add_address(cd, _Jv_env); + M_ALD_DSEG(REG_A0, disp); + } - M_CALL(REG_ITMP1); /* call */ + /* Call native function. */ - /* save return value */ + disp = dseg_add_functionptr(cd, f); + M_ALD_DSEG(REG_ITMP2, disp); + M_CALL(REG_ITMP2); - t = md->returntype.type; + /* save return value */ - if (t != TYPE_VOID) { - if (IS_INT_LNG_TYPE(t)) { - if (IS_2_WORD_TYPE(t)) { - N_STM(REG_RESULT, REG_RESULT2, 96, REG_SP); - } else { - N_ST(REG_RESULT, 96, RN, REG_SP); - } - } else { - if (IS_2_WORD_TYPE(t)) { - N_STD(REG_FRESULT, 96, RN, REG_SP); - } else { - N_STE(REG_FRESULT, 96, RN, REG_SP); - } - } + switch (md->returntype.type) { + case TYPE_INT: + case TYPE_ADR: + M_IST(REG_RESULT, REG_SP, 96); + break; + case TYPE_LNG: + M_LST(REG_RESULT_PACKED, REG_SP, 96); + break; + case TYPE_FLT: + case TYPE_DBL: + M_DST(REG_FRESULT, REG_SP, 96); + break; + case TYPE_VOID: + break; } -#if 0 -#if !defined(NDEBUG) - if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) - emit_verbosecall_exit(jd); -#endif -#endif - /* remove native stackframe info */ - N_LAE(REG_A0, cd->stackframesize * 4, RN, REG_SP); + M_MOV(REG_SP, REG_A0); + M_LDA(REG_A1, REG_PV, -N_PV_OFFSET); disp = dseg_add_functionptr(cd, codegen_finish_native_call); - M_ILD(REG_ITMP1, REG_PV, disp); + M_ALD_DSEG(REG_ITMP1, disp); M_CALL(REG_ITMP1); - N_LR(REG_ITMP3, REG_RESULT); + + M_MOV(REG_RESULT, REG_ITMP3_XPTR); /* restore return value */ - if (t != TYPE_VOID) { - if (IS_INT_LNG_TYPE(t)) { - if (IS_2_WORD_TYPE(t)) { - N_LM(REG_RESULT, REG_RESULT2, 96, REG_SP); - } else { - N_L(REG_RESULT, 96, RN, REG_SP); - } - } else { - if (IS_2_WORD_TYPE(t)) { - N_LD(REG_FRESULT, 96, RN, REG_SP); - } else { - N_LE(REG_FRESULT, 96, RN, REG_SP); - } - } + switch (md->returntype.type) { + case TYPE_INT: + case TYPE_ADR: + M_ILD(REG_RESULT, REG_SP, 96); + break; + case TYPE_LNG: + M_LLD(REG_RESULT_PACKED, REG_SP, 96); + break; + case TYPE_FLT: + case TYPE_DBL: + M_DLD(REG_FRESULT, REG_SP, 96); + break; + case TYPE_VOID: + break; } - /* remove stackframe */ +#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); - N_AHI(REG_SP, cd->stackframesize * 4); + for (i = 0; i < INT_SAV_CNT; i++) + M_ALD(abi_registers_integer_saved[i], REG_SP, disp + i * 4); +#endif - /* test for exception */ + /* load return address */ - N_LTR(REG_ITMP3, REG_ITMP3); - N_BRC(DD_NE, SZ_BRC + SZ_BC); - N_BC(DD_ANY, 0, RN, REG_SP); /* return */ + M_ALD(REG_RA, REG_SP, (cd->stackframesize - 1) * 8); - /* handle exception */ + /* remove stackframe */ - N_LONG_0(); + M_AADD_IMM(cd->stackframesize * 8, REG_SP); -#if 0 - M_MOV(REG_ITMP3, REG_ITMP1_XPTR); - M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8); /* get return address from stack */ - M_ASUB_IMM(3, REG_ITMP2_XPC); /* callq */ + /* check for exception */ - M_MOV_IMM(asm_handle_nat_exception, REG_ITMP3); - M_JMP(REG_ITMP3); + M_TEST(REG_ITMP3_XPTR); + M_BNE(SZ_BRC + SZ_BCR); /* if no exception then return */ -#endif - /* generate patcher stubs */ + M_RET; - emit_patcher_stubs(jd); + /* handle exception */ - codegen_finish(jd); + M_MOV(REG_RA, REG_ITMP1_XPC); + M_ASUB_IMM(2, REG_ITMP1_XPC); - return code->entrypoint; - return NULL; + disp = dseg_add_functionptr(cd, asm_handle_nat_exception); + M_ALD_DSEG(REG_ITMP2, disp); + M_JMP(RN, REG_ITMP2); } - - /* * These are local overrides for various environment variables in Emacs. * Please do not remove this and leave it at the end of the file, where