X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fvm%2Fjit%2Fs390%2Fcodegen.c;h=9b6209c808f9bbf35d16b0f4fdecddd5b90260ac;hb=d3f53f8ad60094f4191ad32a1b9bb0dac142265c;hp=5bb924621cd515e8678d3562220a144e8b997378;hpb=b118fbde6e6b984c5c530a8ba0489d5cdd8d8b9b;p=cacao.git diff --git a/src/vm/jit/s390/codegen.c b/src/vm/jit/s390/codegen.c index 5bb924621..9b6209c80 100644 --- a/src/vm/jit/s390/codegen.c +++ b/src/vm/jit/s390/codegen.c @@ -1,9 +1,7 @@ /* src/vm/jit/s390/codegen.c - machine code generator for s390 - Copyright (C) 1996-2005, 2006, 2007 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,8 +20,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: codegen.c 8296 2007-08-11 22:38:38Z pm $ - */ @@ -33,53 +29,55 @@ #include #include -#include "native/jni.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 "native/localref.h" #include "native/native.h" #include "mm/memory.h" -#if defined(ENABLE_THREADS) -# include "threads/lock-common.h" -# include "threads/native/lock.h" -#endif +#include "threads/lock.hpp" -#include "vmcore/loader.h" -#include "vmcore/options.h" -#include "vmcore/statistics.h" -#include "vm/builtin.h" -#include "vm/exceptions.h" +#include "vm/jit/builtin.hpp" +#include "vm/exceptions.hpp" #include "vm/global.h" +#include "vm/loader.hpp" +#include "vm/options.h" +#include "vm/statistics.h" +#include "vm/types.h" +#include "vm/vm.hpp" + #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/codegen-common.hpp" #include "vm/jit/dseg.h" -#include "vm/jit/emit-common.h" -#include "vm/jit/jit.h" +#include "vm/jit/emit-common.hpp" +#include "vm/jit/jit.hpp" +#include "vm/jit/linenumbertable.hpp" #include "vm/jit/methodheader.h" #include "vm/jit/parse.h" -#include "vm/jit/patcher-common.h" +#include "vm/jit/patcher-common.hpp" #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" +#include "vm/jit/replace.hpp" +#include "vm/jit/stacktrace.hpp" +#include "vm/jit/trap.h" + /* 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. */ +/* static void do__log(u4 *regs) { - /* insert stuff here */ } +*/ #define DO__LOG \ N_AHI(REG_SP, -200); \ @@ -90,7 +88,11 @@ static void do__log(u4 *regs) { N_LM(R0, R15, 96, REG_SP); \ N_AHI(REG_SP, 200); -#define SUPPORT_HERCULES 1 +/* If the following macro is defined, workaround code for hercules quirks + * is generated + */ + +/* #define SUPPORT_HERCULES 1 */ /* codegen ********************************************************************* @@ -131,11 +133,9 @@ bool codegen_emit(jitdata *jd) registerdata *rd; 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* */ @@ -178,7 +178,7 @@ bool codegen_emit(jitdata *jd) 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) @@ -187,7 +187,7 @@ bool codegen_emit(jitdata *jd) not be shared with place to save the return register since both values reside in R2. */ - if (checksync && (m->flags & ACC_SYNCHRONIZED)) { + 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; @@ -198,7 +198,7 @@ bool codegen_emit(jitdata *jd) 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 + 2) & ~2; @@ -207,39 +207,31 @@ bool codegen_emit(jitdata *jd) (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */ (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) * 8); /* IsSync */ + code->synchronizedoffset = rd->memuse * 8; + + /* REMOVEME: We still need it for exception handling in assembler. */ + + if (code_is_leafmethod(code)) + (void) dseg_add_unique_s4(cd, 1); else -#endif - (void) dseg_add_unique_s4(cd, 0); /* IsSync */ + (void) dseg_add_unique_s4(cd, 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); } - /* Offset PV */ + /* store return address */ - M_AADD_IMM(N_PV_OFFSET, REG_PV); + M_AST(REG_RA, REG_SP, (cd->stackframesize - 1) * 8); /* generate method profiling code */ @@ -255,15 +247,9 @@ bool codegen_emit(jitdata *jd) } #endif - /* create stack frame (if necessary) */ - - if (cd->stackframesize) - M_ASUB_IMM(cd->stackframesize * 8, REG_SP); - /* save used callee saved registers and return address */ - p = cd->stackframesize; - p--; M_AST(REG_RA, REG_SP, p * 8); + p = cd->stackframesize - 1; for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) { p--; M_IST(rd->savintregs[i], REG_SP, p * 8); @@ -360,7 +346,7 @@ bool codegen_emit(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; @@ -382,22 +368,22 @@ bool codegen_emit(jitdata *jd) /* decide which monitor enter function to call */ if (m->flags & ACC_STATIC) { - disp = dseg_add_address(cd, &m->class->object.header); + disp = dseg_add_address(cd, &m->clazz->object.header); M_ALD_DSEG(REG_A0, disp); } else { M_TEST(REG_A0); M_BNE(SZ_BRC + SZ_ILL); - M_ILL(EXCEPTION_HARDWARE_NULLPOINTER); + M_ILL(TRAP_NullPointerException); } disp = dseg_add_functionptr(cd, LOCK_monitor_enter); - M_ALD_DSEG(REG_ITMP3, disp); + M_ALD_DSEG(REG_ITMP2, disp); M_AST(REG_A0, REG_SP, s1 * 8); M_ASUB_IMM(96, REG_SP); - M_CALL(REG_ITMP3); + M_CALL(REG_ITMP2); M_AADD_IMM(96, REG_SP); #if !defined(NDEBUG) @@ -476,10 +462,10 @@ bool codegen_emit(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); } } @@ -493,8 +479,8 @@ bool codegen_emit(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); } } @@ -512,7 +498,7 @@ bool codegen_emit(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; } @@ -532,14 +518,14 @@ bool codegen_emit(jitdata *jd) case ICMD_INLINE_BODY: REPLACEMENT_POINT_INLINE_BODY(cd, iptr); - dseg_addlinenumber_inline_start(cd, iptr); - dseg_addlinenumber(cd, iptr->line); + linenumbertable_list_entry_add_inline_start(cd, iptr); + linenumbertable_list_entry_add(cd, iptr->line); break; case ICMD_INLINE_END: - dseg_addlinenumber_inline_end(cd, iptr); - dseg_addlinenumber(cd, iptr->line); + linenumbertable_list_entry_add_inline_end(cd, iptr); + linenumbertable_list_entry_add(cd, iptr->line); break; case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */ @@ -597,6 +583,16 @@ bool codegen_emit(jitdata *jd) } else { disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr); 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); @@ -649,17 +645,19 @@ bool codegen_emit(jitdata *jd) case ICMD_I2L: /* ..., value ==> ..., value */ - d = emit_alloc_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2); - s1 = emit_load_s1(jd, iptr, GET_HIGH_REG(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)); - ICONST(GET_LOW_REG(d), 0); M_SRDA_IMM(32, GET_HIGH_REG(d)); emit_copy_dst(jd, iptr, d); emit_store_dst(jd, iptr, d); - emit_restore_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2); - break; case ICMD_L2I: /* ..., value ==> ..., value */ @@ -671,7 +669,7 @@ bool codegen_emit(jitdata *jd) case ICMD_INT2BYTE: /* ..., value ==> ..., value */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); - d = codegen_reg_of_dst(jd, iptr, REG_ITMP3); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); M_INTMOVE(s1, d); M_SLL_IMM(24, d); M_SRA_IMM(24, d); @@ -680,7 +678,7 @@ bool codegen_emit(jitdata *jd) case ICMD_INT2CHAR: /* ..., value ==> ..., value */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); - d = codegen_reg_of_dst(jd, iptr, REG_ITMP3); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); M_INTMOVE(s1, d); M_SLL_IMM(16, d); M_SRL_IMM(16, d); @@ -690,7 +688,7 @@ bool codegen_emit(jitdata *jd) case ICMD_INT2SHORT: /* ..., value ==> ..., value */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); - d = codegen_reg_of_dst(jd, iptr, REG_ITMP3); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); M_INTMOVE(s1, d); M_SLL_IMM(16, d); M_SRA_IMM(16, d); @@ -929,47 +927,37 @@ bool codegen_emit(jitdata *jd) case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */ case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */ - s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2); - emit_arithmetic_check(cd, iptr, s2); + /* load s1 into r0 */ - /* For this operation we need a register pair. - * We will use r0 and itmp1 and will backup r0. - */ + 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); + + s2 = emit_load_s2(jd, iptr, REG_ITMP2); - M_INTMOVE(R0, REG_ITMP3); + /* extend s1 to long */ - /* We won't check for division by 0, we catch a SIGFPE instead - * Special case 0x80000000 / 0xffffffff handled by signal handler too. - */ + M_SRDA_IMM(32, GET_HIGH_REG(REG_ITMP31_PACKED)); - s1 = emit_load_s1(jd, iptr, R0); - M_INTMOVE(s1, R0); - M_CLR(REG_ITMP1); - M_SRDA_IMM(32, R0); + /* divide */ - N_DR(R0, s2); + N_DR(GET_HIGH_REG(REG_ITMP31_PACKED), s2); + + /* take result */ switch (iptr->opc) { case ICMD_IREM: - d = codegen_reg_of_dst(jd, iptr, R0); - M_INTMOVE(R0, d); + 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, REG_ITMP1); - M_INTMOVE(REG_ITMP1, d); + d = codegen_reg_of_dst(jd, iptr, GET_LOW_REG(REG_ITMP31_PACKED)); + M_INTMOVE(GET_LOW_REG(REG_ITMP31_PACKED), d); break; } emit_store_dst(jd, iptr, d); - /* If destionation of operation was not register R0, - * restore R0. - */ - - if (! ((d == R0) && !IS_INMEMORY(VAROP(iptr->dst)->flags))) { - M_INTMOVE(REG_ITMP3, R0); - } - break; case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */ @@ -999,8 +987,8 @@ bool codegen_emit(jitdata *jd) /* call builtin */ M_ASUB_IMM(96, REG_SP); - M_ALD_DSEG(REG_ITMP3, disp); - M_JSR(REG_RA, REG_ITMP3); + M_ALD_DSEG(REG_ITMP2, disp); + M_JSR(REG_RA, REG_ITMP2); M_AADD_IMM(96, REG_SP); /* store result */ @@ -1141,23 +1129,25 @@ bool codegen_emit(jitdata *jd) case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */ - s2 = emit_load_s2(jd, iptr, REG_ITMP3); /* d wont contain REG_ITMP3 */ + s2 = emit_load_s2(jd, iptr, REG_ITMP2); /* Use only 6 bits of second operand */ - M_INTMOVE(s2, REG_ITMP3); - s2 = REG_ITMP3; - ICONST(REG_ITMP2, 0x3F); - M_IAND(REG_ITMP2, s2); + M_INTMOVE(s2, REG_ITMP2); + s2 = REG_ITMP2; + ICONST(REG_ITMP1, 0x3F); + M_IAND(REG_ITMP1, s2); - d = emit_alloc_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2); + s1 = emit_load_s1(jd, iptr, REG_ITMP31_PACKED); /* even-odd pair */ + d = codegen_reg_of_dst(jd, iptr, REG_ITMP31_PACKED); - if ((s2 == GET_LOW_REG(d)) || (s2 == GET_HIGH_REG(d))) { - M_INTMOVE(s2, REG_ITMP3); - s2 = REG_ITMP3; + /* Destination must be even-odd pair */ + + if (! N_IS_EVEN_ODD(d)) { + d = REG_ITMP31_PACKED; } - s1 = emit_load_s1(jd, iptr, d); + assert(N_IS_EVEN_ODD(d)); M_LNGMOVE(s1, d); @@ -1177,7 +1167,6 @@ bool codegen_emit(jitdata *jd) emit_copy_dst(jd, iptr, d); emit_store_dst(jd, iptr, d); - emit_restore_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2); break; @@ -1189,7 +1178,12 @@ bool codegen_emit(jitdata *jd) /* sx.val.l = constant */ case ICMD_LMULPOW2: - d = emit_alloc_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2); /* won't contain itmp3 */ + 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, d); M_LNGMOVE(s1, d); @@ -1215,8 +1209,6 @@ bool codegen_emit(jitdata *jd) emit_copy_dst(jd, iptr, d); emit_store_dst(jd, iptr, d); - emit_restore_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2); - break; case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */ @@ -1627,7 +1619,9 @@ bool codegen_emit(jitdata *jd) case ICMD_F2D: /* ..., value ==> ..., (double) value */ { +#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 @@ -1708,24 +1702,24 @@ bool codegen_emit(jitdata *jd) case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., (int) length */ - s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1); + s1 = emit_load_s1(jd, iptr, REG_ITMP1); d = codegen_reg_of_dst(jd, iptr, REG_ITMP3); /* TODO softnull */ /* implicit null-pointer check */ - M_ILD(d, s1, OFFSET(java_arrayheader, size)); + M_ILD(d, s1, OFFSET(java_array_t, size)); emit_store_dst(jd, iptr, d); break; case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */ - s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1); - s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2); + 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); /* implicit null-pointer check */ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); - N_IC(d, OFFSET(java_bytearray, data[0]), s2, s1); + N_IC(d, OFFSET(java_bytearray_t, data[0]), s2, s1); M_SLL_IMM(24, d); M_SRA_IMM(24, d); @@ -1735,7 +1729,7 @@ bool codegen_emit(jitdata *jd) case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */ - s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1); + 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); @@ -1745,7 +1739,7 @@ bool codegen_emit(jitdata *jd) M_INTMOVE(s2, REG_ITMP2); M_SLL_IMM(1, REG_ITMP2); - N_LH(d, OFFSET(java_chararray, data[0]), REG_ITMP2, s1); + N_LH(d, OFFSET(java_chararray_t, data[0]), REG_ITMP2, s1); /* N_LH does sign extends, undo ! */ @@ -1756,7 +1750,7 @@ bool codegen_emit(jitdata *jd) break; case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */ - s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1); + 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); @@ -1766,12 +1760,12 @@ bool codegen_emit(jitdata *jd) M_INTMOVE(s2, REG_ITMP2); M_SLL_IMM(1, REG_ITMP2); - N_LH(d, OFFSET(java_shortarray, data[0]), REG_ITMP2, s1); + N_LH(d, OFFSET(java_shortarray_t, data[0]), REG_ITMP2, s1); emit_store_dst(jd, iptr, d); break; case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */ - s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1); + 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); @@ -1780,16 +1774,16 @@ bool codegen_emit(jitdata *jd) M_INTMOVE(s2, REG_ITMP2); M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */ - N_L(d, OFFSET(java_intarray, data[0]), REG_ITMP2, s1); + N_L(d, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1); emit_store_dst(jd, iptr, d); break; case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */ - s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP3); + s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); - d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP13_PACKED); /* implicit null-pointer check */ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); @@ -1797,22 +1791,25 @@ bool codegen_emit(jitdata *jd) M_INTMOVE(s2, REG_ITMP2); M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */ - /* We need to preserve the array address after the first load */ + N_L( + GET_LOW_REG(d) /* maybe itmp3 */, + OFFSET(java_longarray_t, data[0]) + 4, + REG_ITMP2, s1 /* maybe itmp1 */ + ); - if (GET_HIGH_REG(d) == s1) { - M_INTMOVE(s1, REG_ITMP3); - s1 = REG_ITMP3; - } + N_L( + GET_HIGH_REG(d) /* maybe itmp1 */, + OFFSET(java_longarray_t, data[0]), + REG_ITMP2, s1 /* maybe itmp1 */ + ); - N_L(GET_HIGH_REG(d) /* evntl. itmp1 */, OFFSET(java_intarray, data[0]), REG_ITMP2, s1); - N_L(GET_LOW_REG(d) /* evntl. itmp2 */, OFFSET(java_intarray, data[0]) + 4, REG_ITMP2, s1); emit_store_dst(jd, iptr, d); break; case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */ - s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1); + s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); @@ -1822,13 +1819,13 @@ bool codegen_emit(jitdata *jd) M_INTMOVE(s2, REG_ITMP2); M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */ - N_LE(d, OFFSET(java_floatarray, data[0]), REG_ITMP2, s1); + N_LE(d, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1); emit_store_dst(jd, iptr, d); break; case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */ - s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1); + s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); @@ -1838,13 +1835,13 @@ bool codegen_emit(jitdata *jd) M_INTMOVE(s2, REG_ITMP2); M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */ - N_LD(d, OFFSET(java_floatarray, data[0]), REG_ITMP2, s1); + N_LD(d, OFFSET(java_doublearray_t, data[0]), REG_ITMP2, s1); emit_store_dst(jd, iptr, d); break; case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */ - s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1); + 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); @@ -1853,23 +1850,23 @@ bool codegen_emit(jitdata *jd) M_INTMOVE(s2, REG_ITMP2); M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */ - N_L(d, OFFSET(java_objectarray, data[0]), REG_ITMP2, s1); + 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 ==> ... */ - s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1); - s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2); + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s2 = emit_load_s2(jd, iptr, REG_ITMP2); /* implicit null-pointer check */ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); s3 = emit_load_s3(jd, iptr, REG_ITMP3); - N_STC(s3, OFFSET(java_bytearray, data[0]), s2, s1); + N_STC(s3, OFFSET(java_bytearray_t, data[0]), s2, s1); break; case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */ - s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1); + s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); /* implicit null-pointer check */ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); @@ -1878,12 +1875,12 @@ bool codegen_emit(jitdata *jd) M_INTMOVE(s2, REG_ITMP2); M_SLL_IMM(1, REG_ITMP2); - N_STH(s3, OFFSET(java_chararray, data[0]), REG_ITMP2, s1); + N_STH(s3, OFFSET(java_chararray_t, data[0]), REG_ITMP2, s1); break; case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */ - s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1); + s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); /* implicit null-pointer check */ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); @@ -1892,12 +1889,12 @@ bool codegen_emit(jitdata *jd) M_INTMOVE(s2, REG_ITMP2); M_SLL_IMM(1, REG_ITMP2); - N_STH(s3, OFFSET(java_shortarray, data[0]), REG_ITMP2, s1); + N_STH(s3, OFFSET(java_shortarray_t, data[0]), REG_ITMP2, s1); break; case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */ - s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1); + s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); /* implicit null-pointer check */ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); @@ -1907,12 +1904,12 @@ bool codegen_emit(jitdata *jd) M_INTMOVE(s2, REG_ITMP2); M_SLL_IMM(2, REG_ITMP2); - N_ST(s3, OFFSET(java_intarray, data[0]), REG_ITMP2, s1); + N_ST(s3, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1); break; case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */ - s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1); + s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); /* implicit null-pointer check */ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); @@ -1921,13 +1918,13 @@ bool codegen_emit(jitdata *jd) M_SLL_IMM(3, REG_ITMP2); s3 = emit_load_s3_high(jd, iptr, REG_ITMP3); - N_ST(s3, OFFSET(java_intarray, data[0]), REG_ITMP2, s1); + N_ST(s3, OFFSET(java_longarray_t, data[0]), REG_ITMP2, s1); s3 = emit_load_s3_low(jd, iptr, REG_ITMP3); - N_ST(s3, OFFSET(java_intarray, data[0]) + 4, REG_ITMP2, s1); + N_ST(s3, OFFSET(java_longarray_t, data[0]) + 4, REG_ITMP2, s1); break; case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */ - s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1); + s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); /* implicit null-pointer check */ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); @@ -1936,11 +1933,11 @@ bool codegen_emit(jitdata *jd) M_INTMOVE(s2, REG_ITMP2); M_SLL_IMM(2, REG_ITMP2); - N_STE(s3, OFFSET(java_floatarray, data[0]), REG_ITMP2, s1); + N_STE(s3, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1); break; case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */ - s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1); + s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); /* implicit null-pointer check */ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); @@ -1949,12 +1946,12 @@ bool codegen_emit(jitdata *jd) M_INTMOVE(s2, REG_ITMP2); M_SLL_IMM(3, REG_ITMP2); - N_STD(s3, OFFSET(java_doublearray, data[0]), REG_ITMP2, s1); + N_STD(s3, OFFSET(java_doublearray_t, data[0]), REG_ITMP2, s1); break; case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */ - s1 = emit_load_s1_notzero(jd, iptr, REG_A0); + s1 = emit_load_s1(jd, iptr, REG_A0); s2 = emit_load_s2(jd, iptr, REG_ITMP2); /* implicit null-pointer check */ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); @@ -1963,13 +1960,13 @@ bool codegen_emit(jitdata *jd) M_INTMOVE(s1, REG_A0); M_INTMOVE(s3, REG_A1); - disp = dseg_add_functionptr(cd, BUILTIN_canstore); - M_ALD_DSEG(REG_ITMP3, disp); + 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_ITMP3); + M_JSR(REG_RA, REG_ITMP2); M_AADD_IMM(96, REG_SP); - emit_exception_check(cd, iptr); + emit_arraystore_check(cd, iptr); s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); @@ -1977,7 +1974,7 @@ bool codegen_emit(jitdata *jd) M_INTMOVE(s2, REG_ITMP2); M_SLL_IMM(2, REG_ITMP2); - N_ST(s3, OFFSET(java_objectarray, data[0]), REG_ITMP2, s1); + N_ST(s3, OFFSET(java_objectarray_t, data[0]), REG_ITMP2, s1); /* M_SAADDQ(s2, s1, REG_ITMP1); itmp1 := 4 * s2 + s1 @@ -2004,10 +2001,10 @@ bool codegen_emit(jitdata *jd) fieldtype = fi->type; disp = dseg_add_address(cd, fi->value); - if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) { + if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz)) { PROFILE_CYCLE_STOP; - patcher_add_patch_ref(jd, PATCHER_clinit, fi->class, 0); + patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->clazz, 0); PROFILE_CYCLE_START; } @@ -2056,9 +2053,9 @@ bool codegen_emit(jitdata *jd) fieldtype = fi->type; disp = dseg_add_address(cd, fi->value); - if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) { + if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz)) { PROFILE_CYCLE_STOP; - patcher_add_patch_ref(jd, PATCHER_clinit, fi->class, disp); + patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->clazz, disp); PROFILE_CYCLE_START; } } @@ -2090,7 +2087,7 @@ bool codegen_emit(jitdata *jd) case ICMD_GETFIELD: /* ... ==> ..., value */ - s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1); + s1 = emit_load_s1(jd, iptr, REG_ITMP1); emit_nullpointer_check(cd, iptr, s1); if (INSTRUCTION_IS_UNRESOLVED(iptr)) { @@ -2142,7 +2139,7 @@ bool codegen_emit(jitdata *jd) { u1 *ref; - s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1); + s1 = emit_load_s1(jd, iptr, REG_ITMP1); emit_nullpointer_check(cd, iptr, s1); if (INSTRUCTION_IS_UNRESOLVED(iptr)) { @@ -2181,7 +2178,7 @@ bool codegen_emit(jitdata *jd) } if (INSTRUCTION_IS_UNRESOLVED(iptr)) { - ((patchref_t *)list_first_unsynced(jd->code->patchers))->disp = (cd->mcodeptr - ref); + ((patchref_t *)list_first(jd->code->patchers))->disp = (cd->mcodeptr - ref); } switch (fieldtype) { @@ -2212,20 +2209,20 @@ bool codegen_emit(jitdata *jd) /* PROFILE_CYCLE_STOP; */ - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - M_INTMOVE(s1, REG_ITMP1_XPTR); + 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; - patcher_add_patch_ref(jd, 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_DSEG(REG_ITMP2, disp); - M_JMP(REG_ITMP2_XPC, REG_ITMP2); + M_ALD_DSEG(REG_ITMP1, disp); + M_JMP(REG_ITMP1_XPC, REG_ITMP1); M_NOP; break; @@ -2397,10 +2394,10 @@ bool codegen_emit(jitdata *jd) /* Compare addresses as 31 bit unsigned integers */ - s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1); + s1 = emit_load_s1(jd, iptr, REG_ITMP1); M_LDA(REG_ITMP1, s1, 0); - s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2); + s2 = emit_load_s2(jd, iptr, REG_ITMP2); M_LDA(REG_ITMP2, s2, 0); M_CMP(REG_ITMP1, REG_ITMP2); @@ -2522,9 +2519,8 @@ bool codegen_emit(jitdata *jd) assert(0); } - if (out_ref != NULL) { - *(u4 *)out_ref |= (u4)(cd->mcodeptr - out_ref) / 2; + N_BRC_BACK_PATCH(out_ref); } } @@ -2548,7 +2544,7 @@ bool codegen_emit(jitdata *jd) unresolved_class *uc = iptr->sx.s23.s2.uc; PROFILE_CYCLE_STOP; - patcher_add_patch_ref(jd, PATCHER_athrow_areturn, uc, 0); + patcher_add_patch_ref(jd, PATCHER_resolve_class, uc, 0); PROFILE_CYCLE_START; } #endif /* ENABLE_VERIFIER */ @@ -2587,7 +2583,7 @@ nowperformreturn: #endif /* !defined(NDEBUG) */ #if defined(ENABLE_THREADS) - if (checksync && (m->flags & ACC_SYNCHRONIZED)) { + if (checksync && code_is_synchronized(code)) { /* we need to save the proper return value */ switch (iptr->opc) { @@ -2609,10 +2605,10 @@ nowperformreturn: M_ALD(REG_A0, REG_SP, rd->memuse * 8); disp = dseg_add_functionptr(cd, LOCK_monitor_exit); - M_ALD_DSEG(REG_ITMP3, disp); + M_ALD_DSEG(REG_ITMP2, disp); M_ASUB_IMM(96, REG_SP); - M_CALL(REG_ITMP3); + M_CALL(REG_ITMP2); M_AADD_IMM(96, REG_SP); /* and now restore the proper return value */ @@ -2658,7 +2654,6 @@ nowperformreturn: PROFILE_CYCLE_STOP; M_RET; - ALIGNCODENOP; } break; @@ -2829,9 +2824,13 @@ gen_method: 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); + } - M_ASUB_IMM(96, REG_SP); /* register save area as required by C abi */ if (N_VALID_DSEG_DISP(disp)) { N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV); } else { @@ -2899,15 +2898,15 @@ gen_method: } 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); } /* Implicit null-pointer check */ M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl)); - N_LHI(REG_ITMP1, s1); - N_L(REG_METHODPTR, 0, REG_ITMP1, REG_METHODPTR); + N_LHI(REG_ITMP2, s1); + N_L(REG_METHODPTR, 0, REG_ITMP2, REG_METHODPTR); M_ALD(REG_PV, REG_METHODPTR, s2); break; } @@ -2921,8 +2920,9 @@ gen_method: switch (iptr->opc) { case ICMD_BUILTIN: - M_AADD_IMM(96, REG_SP); /* remove C abi register save area */ - emit_exception_check(cd, iptr); /* check for exception */ + if (bte->stub == NULL) { + M_AADD_IMM(96, REG_SP); /* remove C abi register save area */ + } break; } @@ -3000,10 +3000,7 @@ gen_method: supervftbl = super->vftbl; } - if ((super == NULL) || !(super->flags & ACC_INTERFACE)) - CODEGEN_CRITICAL_SECTION_NEW; - - s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1); + s1 = emit_load_s1(jd, iptr, REG_ITMP1); /* if class is not resolved, check which code to call */ @@ -3017,12 +3014,13 @@ gen_method: iptr->sx.s23.s3.c.ref, disp); - ICONST(REG_ITMP2, ACC_INTERFACE); + ICONST(REG_ITMP3, ACC_INTERFACE); + if (N_VALID_DSEG_DISP(disp)) { - N_N(REG_ITMP2, N_DSEG_DISP(disp), RN, REG_PV); + N_N(REG_ITMP3, N_DSEG_DISP(disp), RN, REG_PV); } else { - ICONST(REG_ITMP3, disp); - N_N(REG_ITMP2, -N_PV_OFFSET, REG_ITMP3, REG_PV); + ICONST(REG_ITMP2, disp); + N_N(REG_ITMP3, -N_PV_OFFSET, REG_ITMP2, REG_PV); } emit_label_beq(cd, LABEL_CLASS); } @@ -3078,10 +3076,30 @@ gen_method: emit_label_beq(cd, LABEL_EXIT_CLASS_NULL); } +#if 1 + /* REG_ITMP3 := baseval(s1) */ M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl)); - M_ALD_DSEG(REG_ITMP3, disp); + 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)); + + /* REG_ITMP3 := REG_ITMP3 - REG_ITMP2 */ + M_ISUB(REG_ITMP2, REG_ITMP3); + + /* REG_ITMP2 := diffval(class) */ + M_ALD_DSEG(REG_ITMP2, disp); + M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval)); - CODEGEN_CRITICAL_SECTION_START; + M_CMPU(REG_ITMP3, REG_ITMP2); /* 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 */ +#else + M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl)); + M_ALD_DSEG(REG_ITMP3, disp); M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval)); M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval)); @@ -3089,12 +3107,11 @@ gen_method: M_ALD_DSEG(REG_ITMP3, disp); M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval)); - 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); } @@ -3192,10 +3209,7 @@ gen_method: # 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_notzero(jd, iptr, REG_ITMP1); + s1 = emit_load_s1(jd, iptr, REG_ITMP1); d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); if (s1 == d) { M_MOV(s1, REG_ITMP1); @@ -3215,13 +3229,13 @@ gen_method: 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, ACC_INTERFACE); if (N_VALID_DSEG_DISP(disp)) { - N_N(REG_ITMP2, N_DSEG_DISP(disp), RN, REG_PV); + N_N(REG_ITMP3, N_DSEG_DISP(disp), RN, REG_PV); } else { - ICONST(REG_ITMP3, disp); - N_N(REG_ITMP2, -N_PV_OFFSET, REG_ITMP3, REG_PV); + ICONST(REG_ITMP2, disp); + N_N(REG_ITMP3, -N_PV_OFFSET, REG_ITMP2, REG_PV); } emit_label_beq(cd, LABEL_CLASS); @@ -3296,14 +3310,10 @@ gen_method: 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)); - 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 */ @@ -3418,8 +3428,6 @@ gen_method: } /* if (bptr -> flags >= BBREACHED) */ } /* for basic block */ - dseg_createlinenumbertable(cd); - /* generate stubs */ emit_patcher_traps(jd); @@ -3429,36 +3437,6 @@ gen_method: return true; } - -/* codegen_emit_stub_compiler ************************************************** - - Emits a stub routine which calls the compiler. - -*******************************************************************************/ - -void codegen_emit_stub_compiler(jitdata *jd) -{ - methodinfo *m; - codegendata *cd; - - /* get required compiler data */ - - m = jd->m; - cd = jd->cd; - - /* code for the stub */ - - /* don't touch ITMP3 as it cointains the return address */ - - M_AADD_IMM(N_PV_OFFSET, REG_PV); /* suppress negative displacements */ - - M_ILD_DSEG(REG_ITMP1, -2 * SIZEOF_VOID_P); /* methodinfo */ - /* TODO where is methodpointer loaded into itmp2? is it already inside? */ - M_ILD_DSEG(REG_PV, -3 * SIZEOF_VOID_P); /* compiler pointer */ - N_BR(REG_PV); -} - - /* codegen_emit_stub_native **************************************************** Emits a stub routine which calls a native method. @@ -3485,350 +3463,277 @@ void codegen_emit_stub_compiler(jitdata *jd) SP after method entry */ -void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f) +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 */ + /* calculate stackframe size */ - cd->stackframesize = - 1 + /* r14 - return address */ + - ((sizeof(stackframeinfo) + 7) / 8) + - ((sizeof(localref_table) + 7) / 8) + - 1 + /* itmp3 */ - (INT_ARG_CNT + FLT_ARG_CNT) + - nmd->memuse + /* parameter passing */ - (96 / 8) /* required by ABI */; + cd->stackframesize = + 1 + /* return address */ + sizeof(stackframeinfo_t) / 8 + + sizeof(localref_table) / 8 + + nmd->paramcount + + nmd->memuse + + (96 / 8); /* linkage area */ + + /* 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 * 8); /* FrameSize */ - (void) dseg_add_unique_s4(cd, 0); /* IsSync */ (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */ (void) dseg_add_unique_s4(cd, 0); /* IntSave */ (void) dseg_add_unique_s4(cd, 0); /* FltSave */ - (void) dseg_addlinenumbertablesize(cd); - (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */ - - /* generate stub code */ - - N_AHI(REG_SP, -(cd->stackframesize * 8)); - N_AHI(REG_PV, N_PV_OFFSET); - /* generate native method profiling code */ - -#if defined(ENABLE_PROFILING) - if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) { - /* count frequency */ - 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)); - } -#endif + /* 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) * 8, RN, REG_SP); + /* store return address */ -#if !defined(NDEBUG) - if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) - emit_verbosecall_enter(jd); -#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) - patcher_add_patch_ref(jd, PATCHER_resolve_native_function, 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_DSEG(REG_ITMP1, disp); - - j = 96 + (nmd->memuse * 8); - - /* 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; - t = md->paramtypes[i].type; - if (IS_INT_LNG_TYPE(t)) { - if (IS_2_WORD_TYPE(t)) { - /* todo store multiple */ - N_ST(GET_HIGH_REG(s1), j, RN, REG_SP); - N_ST(GET_LOW_REG(s1), j + 4, RN, REG_SP); - } else { - N_ST(s1, j, RN, REG_SP); - } - } else { - if (IS_2_WORD_TYPE(t)) { - N_STD(s1, j, RN, REG_SP); - } else { - N_STE(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) * 8 , RN, REG_SP); /* datasp */ - N_LA(REG_A1, -N_PV_OFFSET, RN, REG_PV); /* pv */ - N_LAE(REG_A2, cd->stackframesize * 8, RN, REG_SP); /* old SP */ - N_L(REG_A3, (cd->stackframesize - 1) * 8, 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_DSEG(REG_ITMP1, 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 * 8); + /* 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; - t = md->paramtypes[i].type; - if (IS_INT_LNG_TYPE(t)) { - if (IS_2_WORD_TYPE(t)) { - /* todo load multiple ! */ - N_L(GET_HIGH_REG(s1), j, RN, REG_SP); - N_L(GET_LOW_REG(s1), j + 4, RN, REG_SP); - } else { - N_L(s1, j, RN, REG_SP); - } - } else { - if (IS_2_WORD_TYPE(t)) { - N_LD(s1, j, RN, REG_SP); - } else { - N_LE(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 = md->params[i].regoff; + s2 = nmd->params[j].regoff; if (!nmd->params[j].inmemory) { - s2 = nmd->params[j].regoff; - if (IS_2_WORD_TYPE(t)) { - N_LR( - GET_LOW_REG(s2), - GET_LOW_REG(s1) - ); - N_LR( - GET_HIGH_REG(s2), - GET_HIGH_REG(s1) - ); - } else { - N_LR( - s2, - s1 - ); - } - } else { - s2 = nmd->params[j].regoff; - if (IS_2_WORD_TYPE(t)) { - N_STM( - GET_HIGH_REG(s1), - GET_LOW_REG(s1), - 96 + s2, REG_SP - ); - } else { - N_ST( - s1, - 96 + s2, RN, REG_SP - ); - } + if (IS_2_WORD_TYPE(t)) + M_LNGMOVE(s1, s2); + else + M_INTMOVE(s1, s2); } - - } else { - s1 = cd->stackframesize * 8 + md->params[i].regoff; + 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, 8, REG_SP, s1, REG_SP); + N_MVC(s2, 8, REG_SP, s1, REG_SP); } else { - N_MVC(96 + s2, 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 = cd->stackframesize * 8 + md->params[i].regoff; + s1 = md->params[i].regoff + cd->stackframesize * 8; s2 = nmd->params[j].regoff; if (IS_2_WORD_TYPE(t)) { - N_MVC(96 + s2, 8, REG_SP, s1, REG_SP); + N_MVC(s2, 8, REG_SP, s1, REG_SP); } else { - N_MVC(96 + s2, 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_DSEG(REG_A1, 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_DSEG(REG_A0, disp); + /* put env into first argument register */ - /* do the native function call */ + disp = dseg_add_address(cd, VM_get_jnienv()); + 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 !defined(NDEBUG) - if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) - emit_verbosecall_exit(jd); -#endif - /* remove native stackframe info */ - N_LAE(REG_A0, (cd->stackframesize - 1) * 8, RN, REG_SP); /* datasp */ + 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_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; } +#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); + + for (i = 0; i < INT_SAV_CNT; i++) + M_ALD(abi_registers_integer_saved[i], REG_SP, disp + i * 4); +#endif + /* load return address */ - - N_L(REG_ITMP2, (cd->stackframesize - 1) * 8, RN, REG_SP); - /* remove stackframe */ + M_ALD(REG_RA, REG_SP, (cd->stackframesize - 1) * 8); - N_AHI(REG_SP, cd->stackframesize * 8); + /* remove stackframe */ - /* test for exception */ + M_AADD_IMM(cd->stackframesize * 8, REG_SP); - N_LTR(REG_ITMP3, REG_ITMP3); - N_BRC(DD_NE, SZ_BRC + SZ_BCR); + /* check for exception */ - /* return */ + M_TEST(REG_ITMP3_XPTR); + M_BNE(SZ_BRC + SZ_BCR); /* if no exception then return */ - N_BCR(DD_ANY, REG_ITMP2); + M_RET; /* handle exception */ - M_MOV(REG_ITMP3, REG_ITMP1_XPTR); - M_MOV(REG_ITMP2, REG_ITMP2_XPC); /* get return address from stack */ - -#if 0 - /* TODO */ - M_ASUB_IMM(3, REG_ITMP2_XPC); /* callq */ -#endif + M_MOV(REG_RA, REG_ITMP1_XPC); + M_ASUB_IMM(2, REG_ITMP1_XPC); disp = dseg_add_functionptr(cd, asm_handle_nat_exception); - M_ALD_DSEG(REG_ITMP3, disp); - M_JMP(RN, REG_ITMP3); - - /* generate patcher stubs */ - - emit_patcher_traps(jd); -} - -s4 codegen_reg_of_dst_notzero(jitdata *jd, instruction *iptr, s4 tempregnum) { - codegendata *cd = jd->cd; - s4 reg = codegen_reg_of_dst(jd, iptr, tempregnum); - if (reg == 0) { - M_MOV(reg, tempregnum); - return tempregnum; - } else { - return reg; - } + M_ALD_DSEG(REG_ITMP2, disp); + M_JMP(RN, REG_ITMP2); } /*