X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2Fvm%2Fjit%2Fpowerpc%2Fcodegen.c;h=f010d98f489255c1cb97983b094fa09c9d6d2877;hb=b76e356b0af200d2568e6fc55e82e233f1808eb9;hp=95823e7472f8c6c62c12fde6e003f15e33ff8e64;hpb=6e15be8daacc628f1c085ce1b168cd662fd87063;p=cacao.git diff --git a/src/vm/jit/powerpc/codegen.c b/src/vm/jit/powerpc/codegen.c index 95823e747..f010d98f4 100644 --- a/src/vm/jit/powerpc/codegen.c +++ b/src/vm/jit/powerpc/codegen.c @@ -1,9 +1,7 @@ /* src/vm/jit/powerpc/codegen.c - machine code generator for 32-bit PowerPC - 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,17 +20,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - Contact: cacao@cacaojvm.org - - Authors: Andreas Krall - Stefan Ring - - Changes: Christian Thalinger - Christian Ullrich - Edwin Steiner - - $Id: codegen.c 5785 2006-10-15 22:25:54Z edwin $ - */ @@ -50,35 +37,40 @@ #include "vm/jit/powerpc/codegen.h" #include "mm/memory.h" + +#include "native/localref.h" #include "native/native.h" -#if defined(ENABLE_THREADS) -# include "threads/native/lock.h" -#endif +#include "threads/lock-common.h" #include "vm/builtin.h" #include "vm/exceptions.h" #include "vm/global.h" -#include "vm/loader.h" -#include "vm/options.h" #include "vm/stringlocal.h" #include "vm/vm.h" + +#include "vm/jit/abi.h" #include "vm/jit/abi-asm.h" #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/stacktrace.h" #if defined(ENABLE_LSRA) # include "vm/jit/allocator/lsra.h" #endif +#include "vmcore/loader.h" +#include "vmcore/options.h" + /* codegen ********************************************************************* @@ -86,26 +78,26 @@ *******************************************************************************/ -bool codegen(jitdata *jd) +bool codegen_emit(jitdata *jd) { methodinfo *m; codeinfo *code; codegendata *cd; registerdata *rd; s4 len, s1, s2, s3, d, disp; - ptrint a; - s4 fieldtype; - varinfo *var, *var1, *var2; + varinfo *var; basicblock *bptr; instruction *iptr; - exception_entry *ex; u2 currentline; methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */ unresolved_method *um; builtintable_entry *bte; methoddesc *md; - rplpoint *replacementpoint; - s4 varindex; + fieldinfo *fi; + unresolved_field *uf; + s4 fieldtype; + s4 varindex; + int i; /* get required compiler data */ @@ -116,9 +108,12 @@ bool codegen(jitdata *jd) /* prevent compiler warnings */ - d = 0; - lm = NULL; - bte = NULL; + d = 0; + fieldtype = 0; + lm = NULL; + um = NULL; + uf = NULL; + bte = NULL; { s4 i, p, t, l; @@ -129,7 +124,7 @@ 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; @@ -139,60 +134,36 @@ bool codegen(jitdata *jd) not be shared with place to save the return register on PPC, since both values reside in R3. */ - if (checksync && (m->flags & ACC_SYNCHRONIZED)) { - /* reserve 2 slots for long/double return values for monitorexit */ - - if (IS_2_WORD_TYPE(m->parseddesc->returntype.type)) - cd->stackframesize += 3; - else - cd->stackframesize += 2; - } - + if (checksync && code_is_synchronized(code)) + cd->stackframesize += 2; #endif /* create method header */ /* align stack to 16-bytes */ - if (!jd->isleafmethod || JITDATA_HAS_FLAG_VERBOSECALL(jd)) - cd->stackframesize = (cd->stackframesize + 3) & ~3; + if (!code_is_leafmethod(code) || JITDATA_HAS_FLAG_VERBOSECALL(jd)) + ALIGN_2(cd->stackframesize); - else if (jd->isleafmethod && (cd->stackframesize == LA_SIZE_IN_POINTERS)) + else if (code_is_leafmethod(code) && (cd->stackframesize == LA_SIZE_IN_POINTERS)) cd->stackframesize = 0; (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 */ - - (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 */ + code->synchronizedoffset = rd->memuse * 8; - dseg_addlinenumbertablesize(cd); + /* REMOVEME: We still need it for exception handling in assembler. */ - (void) dseg_add_unique_s4(cd, jd->exceptiontablelength); /* ExTableSize */ + if (code_is_leafmethod(code)) + (void) dseg_add_unique_s4(cd, 1); + else + (void) dseg_add_unique_s4(cd, 0); - /* create exception table */ + (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */ + (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */ - 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 defined(ENABLE_PROFILING) /* generate method profiling code */ if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) { @@ -205,25 +176,26 @@ bool codegen(jitdata *jd) /* PROFILE_CYCLE_START; */ } +#endif /* create stack frame (if necessary) */ - if (!jd->isleafmethod) { + if (!code_is_leafmethod(code)) { M_MFLR(REG_ZERO); M_AST(REG_ZERO, REG_SP, LA_LR_OFFSET); } if (cd->stackframesize) - M_STWU(REG_SP, REG_SP, -(cd->stackframesize * 4)); + M_STWU(REG_SP, REG_SP, -(cd->stackframesize * 8)); /* save return address and used callee saved registers */ p = cd->stackframesize; 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 */ @@ -242,95 +214,72 @@ bool codegen(jitdata *jd) continue; var = VAR(varindex); + s1 = md->params[p].regoff; - 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 (!md->params[p].inmemory) { /* register arguments */ - if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */ + if (IS_INT_LNG_TYPE(t)) { + if (!md->params[p].inmemory) { + if (!IS_INMEMORY(var->flags)) { if (IS_2_WORD_TYPE(t)) - M_LNGMOVE(s2, var->vv.regoff); + M_LNGMOVE(s1, var->vv.regoff); else - M_INTMOVE(s2, var->vv.regoff); - - } else { /* reg arg -> spilled */ + M_INTMOVE(s1, var->vv.regoff); + } + else { if (IS_2_WORD_TYPE(t)) - M_LST(s2, REG_SP, var->vv.regoff * 4); + M_LST(s1, REG_SP, var->vv.regoff); else - M_IST(s2, REG_SP, var->vv.regoff * 4); + M_IST(s1, REG_SP, var->vv.regoff); } - - } else { /* stack arguments */ - if (!IS_INMEMORY(var->flags)) { /* stack arg -> register */ + } + else { + if (!IS_INMEMORY(var->flags)) { if (IS_2_WORD_TYPE(t)) - M_LLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 4); + M_LLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1); else - M_ILD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 4); - - } else { /* stack arg -> spilled */ + M_ILD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1); + } + else { #if 1 - M_ILD(REG_ITMP1, REG_SP, (cd->stackframesize + s1) * 4); - M_IST(REG_ITMP1, REG_SP, var->vv.regoff * 4); + M_ILD(REG_ITMP1, REG_SP, cd->stackframesize * 8 + s1); + M_IST(REG_ITMP1, REG_SP, var->vv.regoff); 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_ILD(REG_ITMP1, REG_SP, cd->stackframesize * 8 + s1 + 4); + M_IST(REG_ITMP1, REG_SP, var->vv.regoff + 4); } #else /* Reuse Memory Position on Caller Stack */ - var->vv.regoff = cd->stackframesize + s1; + var->vv.regoff = cd->stackframesize * 8 + s1; #endif } } - - } else { /* floating args */ - if (!md->params[p].inmemory) { /* register arguments */ - s2 = rd->argfltregs[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); - else - M_FST(s2, REG_SP, var->vv.regoff * 4); - } - - } 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); - - else - M_FLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 4); - - } else { /* stack-arg -> spilled */ + } + else { + if (!md->params[p].inmemory) { + if (!IS_INMEMORY(var->flags)) + M_FLTMOVE(s1, var->vv.regoff); + else + M_DST(s1, REG_SP, var->vv.regoff); + } + else { + if (!IS_INMEMORY(var->flags)) + M_DLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1); + else { #if 1 - 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); - } + M_DLD(REG_FTMP1, REG_SP, cd->stackframesize * 8 + s1); + M_DST(REG_FTMP1, REG_SP, var->vv.regoff); #else /* Reuse Memory Position on Caller Stack */ - var->vv.regoff = cd->stackframesize + s1; + var->vv.regoff = cd->stackframesize * 8 + s1; #endif } } } - } /* end for */ + } #if defined(ENABLE_THREADS) /* call monitorenter function */ - if (checksync && (m->flags & ACC_SYNCHRONIZED)) { + if (checksync && code_is_synchronized(code)) { /* stack offset for monitor argument */ s1 = rd->memuse; @@ -340,44 +289,41 @@ bool codegen(jitdata *jd) M_AADD_IMM(REG_SP, -((LA_SIZE_IN_POINTERS + ARG_CNT) * 8), REG_SP); for (p = 0; p < INT_ARG_CNT; p++) - M_IST(rd->argintregs[p], REG_SP, LA_SIZE + p * 8); + M_IST(abi_registers_integer_argument[p], REG_SP, LA_SIZE + p * 8); for (p = 0; p < FLT_ARG_CNT; p++) - M_DST(rd->argfltregs[p], REG_SP, LA_SIZE + (INT_ARG_CNT + p) * 8); + M_DST(abi_registers_float_argument[p], REG_SP, LA_SIZE + (INT_ARG_CNT + p) * 8); - /* ATTENTION: We multiply here with 2, because we use * 8 - above for simplicity and below * 4! */ - - s1 += (LA_SIZE_IN_POINTERS + ARG_CNT) * 2; + s1 += LA_SIZE_IN_POINTERS + ARG_CNT; } # endif - p = dseg_add_functionptr(cd, LOCK_monitor_enter); - M_ALD(REG_ITMP3, REG_PV, p); + disp = dseg_add_functionptr(cd, LOCK_monitor_enter); + M_ALD(REG_ITMP3, REG_PV, disp); M_MTCTR(REG_ITMP3); /* get or test the lock object */ if (m->flags & ACC_STATIC) { - p = dseg_add_address(cd, &m->class->object.header); - M_ALD(REG_A0, REG_PV, p); + disp = dseg_add_address(cd, &m->clazz->object.header); + M_ALD(REG_A0, REG_PV, disp); } else { M_TST(REG_A0); - M_BEQ(0); - codegen_add_nullpointerexception_ref(cd); + M_BNE(1); + M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_NULLPOINTER); } - M_AST(REG_A0, REG_SP, s1 * 4); + M_AST(REG_A0, REG_SP, s1 * 8); M_JSR; # if !defined(NDEBUG) if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) { for (p = 0; p < INT_ARG_CNT; p++) - M_ILD(rd->argintregs[p], REG_SP, LA_SIZE + p * 8); + M_ILD(abi_registers_integer_argument[p], REG_SP, LA_SIZE + p * 8); for (p = 0; p < FLT_ARG_CNT; p++) - M_DLD(rd->argfltregs[p], REG_SP, LA_SIZE + (INT_ARG_CNT + p) * 8); + M_DLD(abi_registers_float_argument[p], REG_SP, LA_SIZE + (INT_ARG_CNT + p) * 8); M_AADD_IMM(REG_SP, (LA_SIZE_IN_POINTERS + ARG_CNT) * 8, REG_SP); } @@ -387,13 +333,14 @@ bool codegen(jitdata *jd) /* call trace function */ - if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) - emit_verbosecall_enter(jd); + emit_verbosecall_enter(jd); } /* end of header generation */ - replacementpoint = code->rplpoints; + /* create replacement points */ + + REPLACEMENT_POINTS_INIT(cd, jd); /* walk through all basic blocks */ @@ -402,27 +349,15 @@ bool codegen(jitdata *jd) bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase); if (bptr->flags >= BBREACHED) { - /* branch resolving */ - { - branchref *brefs; - for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) { - gen_resolvebranch((u1*) cd->mcodebase + brefs->branchpos, - brefs->branchpos, - bptr->mpc); - } - } + codegen_resolve_branchrefs(cd, bptr); -#if 0 /* handle replacement points */ - if (bptr->bitflags & BBFLAG_REPLACEMENT) { - replacementpoint->pc = (u1*)(ptrint)bptr->mpc; /* will be resolved later */ - - replacementpoint++; - } -#endif + REPLACEMENT_POINT_BLOCK_START(cd, bptr); + +#if defined(ENABLE_PROFILING) /* generate basicblock profiling code */ if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) { @@ -439,6 +374,7 @@ bool codegen(jitdata *jd) /* if (bptr->type == BBTYPE_EXH) */ /* PROFILE_CYCLE_START; */ } +#endif /* copy interface registers to their destination */ @@ -485,24 +421,40 @@ bool codegen(jitdata *jd) for (iptr = bptr->iinstr; len > 0; len--, iptr++) { if (iptr->line != currentline) { - dseg_addlinenumber(cd, iptr->line); + linenumbertable_list_entry_add(cd, iptr->line); currentline = iptr->line; } MCODECHECK(64); /* an instruction usually needs < 64 words */ - switch (iptr->opc) { - case ICMD_NOP: /* ... ==> ... */ - case ICMD_INLINE_START: - case ICMD_INLINE_END: - break; + switch (iptr->opc) { + case ICMD_NOP: /* ... ==> ... */ + case ICMD_POP: /* ..., value ==> ... */ + case ICMD_POP2: /* ..., value, value ==> ... */ + 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 */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); - M_TST(s1); - M_BEQ(0); - codegen_add_nullpointerexception_ref(cd); + emit_nullpointer_check(cd, iptr, s1); break; /* constant operations ************************************************/ @@ -524,16 +476,16 @@ bool codegen(jitdata *jd) case ICMD_FCONST: /* ... ==> ..., constant */ d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); - a = dseg_add_float(cd, iptr->sx.val.f); - M_FLD(d, REG_PV, a); + disp = dseg_add_float(cd, iptr->sx.val.f); + M_FLD(d, REG_PV, disp); emit_store_dst(jd, iptr, d); break; case ICMD_DCONST: /* ... ==> ..., constant */ d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); - a = dseg_add_double(cd, iptr->sx.val.d); - M_DLD(d, REG_PV, a); + disp = dseg_add_double(cd, iptr->sx.val.d); + M_DLD(d, REG_PV, disp); emit_store_dst(jd, iptr, d); break; @@ -546,11 +498,8 @@ bool codegen(jitdata *jd) disp = dseg_add_unique_address(cd, cr); - codegen_addpatchref(cd, PATCHER_resolve_classref_to_classinfo, + patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo, cr, disp); - - if (opt_showdisassemble) - M_NOP; } else disp = dseg_add_address(cd, iptr->sx.val.anyptr); @@ -568,24 +517,19 @@ bool codegen(jitdata *jd) case ICMD_FLOAD: case ICMD_DLOAD: case ICMD_ISTORE: /* ..., value ==> ... */ - case ICMD_ASTORE: /* dst = local variable */ case ICMD_LSTORE: case ICMD_FSTORE: case ICMD_DSTORE: case ICMD_COPY: case ICMD_MOVE: - emit_copy(jd, iptr, VAROP(iptr->s1), VAROP(iptr->dst)); + emit_copy(jd, iptr); break; + + case ICMD_ASTORE: - - /* pop operations *****************************************************/ - - /* attention: double and longs are only one entry in CACAO ICMDs */ - - case ICMD_POP: /* ..., value ==> ... */ - case ICMD_POP2: /* ..., value, value ==> ... */ - + if (!(iptr->flags.bits & INS_FLAG_RETADDR)) + emit_copy(jd, iptr); break; @@ -788,9 +732,7 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); - M_TST(s2); - M_BEQ(0); - codegen_add_arithmeticexception_ref(cd); + emit_arithmetic_check(cd, iptr, s2); M_LDAH(REG_ITMP3, REG_ZERO, 0x8000); M_CMP(REG_ITMP3, s1); M_BNE(3 + (s1 != d)); @@ -807,9 +749,7 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); - M_TST(s2); - M_BEQ(0); - codegen_add_arithmeticexception_ref(cd); + emit_arithmetic_check(cd, iptr, s2); M_LDAH(REG_ITMP3, REG_ZERO, 0x8000); M_CMP(REG_ITMP3, s1); M_BNE(4); @@ -826,26 +766,21 @@ bool codegen(jitdata *jd) case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */ case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */ - bte = iptr->sx.s23.s3.bte; - md = bte->md; + s1 = emit_load_s1(jd, iptr, REG_A0_A1_PACKED); + s2 = emit_load_s2(jd, iptr, REG_A2_A3_PACKED); - s2 = emit_load_s2(jd, iptr, REG_ITMP12_PACKED); - M_OR_TST(GET_HIGH_REG(s2), GET_LOW_REG(s2), REG_ITMP3); - M_BEQ(0); - codegen_add_arithmeticexception_ref(cd); + /* XXX TODO: only do this if arithmetic check is really done! */ + M_IOR_TST(GET_HIGH_REG(s2), GET_LOW_REG(s2), REG_ITMP3); + /* XXX could be optimized */ + emit_arithmetic_check(cd, iptr, REG_ITMP3); + bte = iptr->sx.s23.s3.bte; disp = dseg_add_functionptr(cd, bte->fp); M_ALD(REG_ITMP3, REG_PV, disp); M_MTCTR(REG_ITMP3); - s3 = PACK_REGS(rd->argintregs[GET_LOW_REG(md->params[1].regoff)], - rd->argintregs[GET_HIGH_REG(md->params[1].regoff)]); - M_LNGMOVE(s2, s3); - - s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED); - s3 = PACK_REGS(rd->argintregs[GET_LOW_REG(md->params[0].regoff)], - rd->argintregs[GET_HIGH_REG(md->params[0].regoff)]); - M_LNGMOVE(s1, s3); + M_LNGMOVE(s1, REG_A0_A1_PACKED); + M_LNGMOVE(s2, REG_A2_A3_PACKED); M_JSR; @@ -891,7 +826,7 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); - M_AND_IMM(s2, 0x1f, REG_ITMP3); + M_IAND_IMM(s2, 0x1f, REG_ITMP3); M_SLL(s1, REG_ITMP3, d); emit_store_dst(jd, iptr, d); break; @@ -910,7 +845,7 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); - M_AND_IMM(s2, 0x1f, REG_ITMP3); + M_IAND_IMM(s2, 0x1f, REG_ITMP3); M_SRA(s1, REG_ITMP3, d); emit_store_dst(jd, iptr, d); break; @@ -929,7 +864,7 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); - M_AND_IMM(s2, 0x1f, REG_ITMP2); + M_IAND_IMM(s2, 0x1f, REG_ITMP2); M_SRL(s1, REG_ITMP2, d); emit_store_dst(jd, iptr, d); break; @@ -952,7 +887,7 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); - M_AND(s1, s2, d); + M_IAND(s1, s2, d); emit_store_dst(jd, iptr, d); break; @@ -962,7 +897,7 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); if ((iptr->sx.val.i >= 0) && (iptr->sx.val.i <= 65535)) - M_AND_IMM(s1, iptr->sx.val.i, d); + M_IAND_IMM(s1, iptr->sx.val.i, d); /* else if (iptr->sx.val.i == 0xffffff) { M_RLWINM(s1, 0, 8, 31, d); @@ -970,7 +905,7 @@ bool codegen(jitdata *jd) */ else { ICONST(REG_ITMP3, iptr->sx.val.i); - M_AND(s1, REG_ITMP3, d); + M_IAND(s1, REG_ITMP3, d); } emit_store_dst(jd, iptr, d); break; @@ -980,10 +915,10 @@ bool codegen(jitdata *jd) s1 = emit_load_s1_low(jd, iptr, REG_ITMP1); s2 = emit_load_s2_low(jd, iptr, REG_ITMP2); d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED); - M_AND(s1, s2, GET_LOW_REG(d)); + M_IAND(s1, s2, GET_LOW_REG(d)); s1 = emit_load_s1_high(jd, iptr, REG_ITMP1); s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);/* don't use REG_ITMP2*/ - M_AND(s1, s2, GET_HIGH_REG(d)); + M_IAND(s1, s2, GET_HIGH_REG(d)); emit_store_dst(jd, iptr, d); break; @@ -994,18 +929,18 @@ bool codegen(jitdata *jd) s1 = emit_load_s1_low(jd, iptr, REG_ITMP1); d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED); if ((s3 >= 0) && (s3 <= 65535)) - M_AND_IMM(s1, s3, GET_LOW_REG(d)); + M_IAND_IMM(s1, s3, GET_LOW_REG(d)); else { ICONST(REG_ITMP3, s3); - M_AND(s1, REG_ITMP3, GET_LOW_REG(d)); + M_IAND(s1, REG_ITMP3, GET_LOW_REG(d)); } s1 = emit_load_s1_high(jd, iptr, REG_ITMP1); s3 = iptr->sx.val.l >> 32; if ((s3 >= 0) && (s3 <= 65535)) - M_AND_IMM(s1, s3, GET_HIGH_REG(d)); + M_IAND_IMM(s1, s3, GET_HIGH_REG(d)); else { ICONST(REG_ITMP3, s3); /* don't use REG_ITMP2 */ - M_AND(s1, REG_ITMP3, GET_HIGH_REG(d)); + M_IAND(s1, REG_ITMP3, GET_HIGH_REG(d)); } emit_store_dst(jd, iptr, d); break; @@ -1020,7 +955,7 @@ bool codegen(jitdata *jd) M_BGE(1 + 2*(iptr->sx.val.i >= 32768)); if (iptr->sx.val.i >= 32768) { M_ADDIS(REG_ZERO, iptr->sx.val.i >> 16, REG_ITMP2); - M_OR_IMM(REG_ITMP2, iptr->sx.val.i, REG_ITMP2); + M_IOR_IMM(REG_ITMP2, iptr->sx.val.i, REG_ITMP2); M_IADD(s1, REG_ITMP2, REG_ITMP2); } else { @@ -1041,7 +976,7 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); - M_OR(s1, s2, d); + M_IOR(s1, s2, d); emit_store_dst(jd, iptr, d); break; @@ -1051,10 +986,10 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); if ((iptr->sx.val.i >= 0) && (iptr->sx.val.i <= 65535)) - M_OR_IMM(s1, iptr->sx.val.i, d); + M_IOR_IMM(s1, iptr->sx.val.i, d); else { ICONST(REG_ITMP3, iptr->sx.val.i); - M_OR(s1, REG_ITMP3, d); + M_IOR(s1, REG_ITMP3, d); } emit_store_dst(jd, iptr, d); break; @@ -1064,10 +999,10 @@ bool codegen(jitdata *jd) s1 = emit_load_s1_low(jd, iptr, REG_ITMP1); s2 = emit_load_s2_low(jd, iptr, REG_ITMP2); d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED); - M_OR(s1, s2, GET_LOW_REG(d)); + M_IOR(s1, s2, GET_LOW_REG(d)); s1 = emit_load_s1_high(jd, iptr, REG_ITMP1); s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);/* don't use REG_ITMP2*/ - M_OR(s1, s2, GET_HIGH_REG(d)); + M_IOR(s1, s2, GET_HIGH_REG(d)); emit_store_dst(jd, iptr, d); break; @@ -1078,18 +1013,18 @@ bool codegen(jitdata *jd) s1 = emit_load_s1_low(jd, iptr, REG_ITMP1); d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED); if ((s3 >= 0) && (s3 <= 65535)) - M_OR_IMM(s1, s3, GET_LOW_REG(d)); + M_IOR_IMM(s1, s3, GET_LOW_REG(d)); else { ICONST(REG_ITMP3, s3); - M_OR(s1, REG_ITMP3, GET_LOW_REG(d)); + M_IOR(s1, REG_ITMP3, GET_LOW_REG(d)); } s1 = emit_load_s1_high(jd, iptr, REG_ITMP1); s3 = iptr->sx.val.l >> 32; if ((s3 >= 0) && (s3 <= 65535)) - M_OR_IMM(s1, s3, GET_HIGH_REG(d)); + M_IOR_IMM(s1, s3, GET_HIGH_REG(d)); else { ICONST(REG_ITMP3, s3); /* don't use REG_ITMP2 */ - M_OR(s1, REG_ITMP3, GET_HIGH_REG(d)); + M_IOR(s1, REG_ITMP3, GET_HIGH_REG(d)); } emit_store_dst(jd, iptr, d); break; @@ -1153,50 +1088,11 @@ bool codegen(jitdata *jd) break; case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */ - /******************************************************************* - TODO: CHANGE THIS TO A VERSION THAT WORKS !!! - *******************************************************************/ + s1 = emit_load_s1_high(jd, iptr, REG_ITMP3); s2 = emit_load_s2_high(jd, iptr, REG_ITMP2); d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); - { - int tempreg = false; - int dreg; - u1 *br1; - - var1 = VAROP(iptr->s1); - var2 = VAROP(iptr->sx.s23.s2); - - if (IS_INMEMORY(var1->flags)) { - tempreg = tempreg || (d == REG_ITMP3) || (d == REG_ITMP2); - } else { - tempreg = tempreg || (d == GET_HIGH_REG(var1->vv.regoff)) - || (d == GET_LOW_REG(var1->vv.regoff)); - } - if (IS_INMEMORY(var2->flags)) { - tempreg = tempreg || (d == REG_ITMP3) || (d == REG_ITMP2); - } else { - tempreg = tempreg || (d == GET_HIGH_REG(var2->vv.regoff)) - || (d == GET_LOW_REG(var2->vv.regoff)); - } - - dreg = tempreg ? REG_ITMP1 : d; - M_IADD_IMM(REG_ZERO, 1, dreg); - M_CMP(s1, s2); - M_BGT(0); - br1 = cd->mcodeptr; - M_BLT(0); - s1 = emit_load_s1_low(jd, iptr, REG_ITMP3); - s2 = emit_load_s2_low(jd, iptr, REG_ITMP2); - M_CMPU(s1, s2); - M_BGT(3); - M_BEQ(1); - M_IADD_IMM(dreg, -1, dreg); - M_IADD_IMM(dreg, -1, dreg); - gen_resolvebranch(br1, br1, cd->mcodeptr); - gen_resolvebranch(br1 + 1 * 4, br1 + 1 * 4, cd->mcodeptr - 2 * 4); - M_INTMOVE(dreg, d); - } + vm_abort("codegen: implement ICMD_LCMP!"); emit_store_dst(jd, iptr, d); break; @@ -1328,7 +1224,6 @@ bool codegen(jitdata *jd) case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */ case ICMD_DCMPL: /* == => 0, < => 1, > => -1 */ - s1 = emit_load_s1(jd, iptr, REG_FTMP1); s2 = emit_load_s2(jd, iptr, REG_FTMP2); d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); @@ -1358,122 +1253,6 @@ bool codegen(jitdata *jd) emit_store_dst(jd, iptr, d); break; - case ICMD_IF_FCMPEQ: /* ..., value, value ==> ... */ - case ICMD_IF_DCMPEQ: - - s1 = emit_load_s1(jd, iptr, REG_FTMP1); - s2 = emit_load_s2(jd, iptr, REG_FTMP2); - M_FCMPU(s1, s2); - M_BNAN(1); - M_BEQ(0); - codegen_addreference(cd, iptr->dst.block); - break; - - case ICMD_IF_FCMPNE: /* ..., value, value ==> ... */ - case ICMD_IF_DCMPNE: - - s1 = emit_load_s1(jd, iptr, REG_FTMP1); - s2 = emit_load_s2(jd, iptr, REG_FTMP2); - M_FCMPU(s1, s2); - M_BNAN(0); - codegen_addreference(cd, iptr->dst.block); - M_BNE(0); - codegen_addreference(cd, iptr->dst.block); - break; - - - case ICMD_IF_FCMPL_LT: /* ..., value, value ==> ... */ - case ICMD_IF_DCMPL_LT: - - s1 = emit_load_s1(jd, iptr, REG_FTMP1); - s2 = emit_load_s2(jd, iptr, REG_FTMP2); - M_FCMPU(s1, s2); - M_BNAN(0); - codegen_addreference(cd, iptr->dst.block); - M_BLT(0); - codegen_addreference(cd, iptr->dst.block); - break; - - case ICMD_IF_FCMPL_GT: /* ..., value, value ==> ... */ - case ICMD_IF_DCMPL_GT: - - s1 = emit_load_s1(jd, iptr, REG_FTMP1); - s2 = emit_load_s2(jd, iptr, REG_FTMP2); - M_FCMPU(s1, s2); - M_BNAN(1); - M_BGT(0); - codegen_addreference(cd, iptr->dst.block); - break; - - case ICMD_IF_FCMPL_LE: /* ..., value, value ==> ... */ - case ICMD_IF_DCMPL_LE: - - s1 = emit_load_s1(jd, iptr, REG_FTMP1); - s2 = emit_load_s2(jd, iptr, REG_FTMP2); - M_FCMPU(s1, s2); - M_BNAN(0); - codegen_addreference(cd, iptr->dst.block); - M_BLE(0); - codegen_addreference(cd, iptr->dst.block); - break; - - case ICMD_IF_FCMPL_GE: /* ..., value, value ==> ... */ - case ICMD_IF_DCMPL_GE: - - s1 = emit_load_s1(jd, iptr, REG_FTMP1); - s2 = emit_load_s2(jd, iptr, REG_FTMP2); - M_FCMPU(s1, s2); - M_BNAN(1); - M_BGE(0); - codegen_addreference(cd, iptr->dst.block); - break; - - case ICMD_IF_FCMPG_LT: /* ..., value, value ==> ... */ - case ICMD_IF_DCMPG_LT: - - s1 = emit_load_s1(jd, iptr, REG_FTMP1); - s2 = emit_load_s2(jd, iptr, REG_FTMP2); - M_FCMPU(s1, s2); - M_BNAN(1); - M_BLT(0); - codegen_addreference(cd, iptr->dst.block); - break; - - case ICMD_IF_FCMPG_GT: /* ..., value, value ==> ... */ - case ICMD_IF_DCMPG_GT: - - s1 = emit_load_s1(jd, iptr, REG_FTMP1); - s2 = emit_load_s2(jd, iptr, REG_FTMP2); - M_FCMPU(s1, s2); - M_BNAN(0); - codegen_addreference(cd, iptr->dst.block); - M_BGT(0); - codegen_addreference(cd, iptr->dst.block); - break; - - case ICMD_IF_FCMPG_LE: /* ..., value, value ==> ... */ - case ICMD_IF_DCMPG_LE: - - s1 = emit_load_s1(jd, iptr, REG_FTMP1); - s2 = emit_load_s2(jd, iptr, REG_FTMP2); - M_FCMPU(s1, s2); - M_BNAN(1); - M_BLE(0); - codegen_addreference(cd, iptr->dst.block); - break; - - case ICMD_IF_FCMPG_GE: /* ..., value, value ==> ... */ - case ICMD_IF_DCMPG_GE: - - s1 = emit_load_s1(jd, iptr, REG_FTMP1); - s2 = emit_load_s2(jd, iptr, REG_FTMP2); - M_FCMPU(s1, s2); - M_BNAN(0); - codegen_addreference(cd, iptr->dst.block); - M_BGE(0); - codegen_addreference(cd, iptr->dst.block); - break; - /* memory operations **************************************************/ @@ -1481,8 +1260,8 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); - gen_nullptr_check(s1); - M_ILD(d, s1, OFFSET(java_arrayheader, size)); + /* implicit null-pointer check */ + M_ILD(d, s1, OFFSET(java_array_t, size)); emit_store_dst(jd, iptr, d); break; @@ -1491,11 +1270,9 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); - if (INSTRUCTION_MUST_CHECK(iptr)) { - gen_nullptr_check(s1); - gen_bound_check; - } - M_IADD_IMM(s2, OFFSET(java_chararray, data[0]), REG_ITMP2); + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); + M_IADD_IMM(s2, OFFSET(java_bytearray_t, data[0]), REG_ITMP2); + /* implicit null-pointer check */ M_LBZX(d, s1, REG_ITMP2); M_BSEXT(d, d); emit_store_dst(jd, iptr, d); @@ -1506,12 +1283,10 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); - if (INSTRUCTION_MUST_CHECK(iptr)) { - gen_nullptr_check(s1); - gen_bound_check; - } + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); M_SLL_IMM(s2, 1, REG_ITMP2); - M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray, data[0]), REG_ITMP2); + M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray_t, data[0]), REG_ITMP2); + /* implicit null-pointer check */ M_LHZX(d, s1, REG_ITMP2); emit_store_dst(jd, iptr, d); break; @@ -1521,12 +1296,10 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); - if (INSTRUCTION_MUST_CHECK(iptr)) { - gen_nullptr_check(s1); - gen_bound_check; - } + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); M_SLL_IMM(s2, 1, REG_ITMP2); - M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray, data[0]), REG_ITMP2); + M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray_t, data[0]), REG_ITMP2); + /* implicit null-pointer check */ M_LHAX(d, s1, REG_ITMP2); emit_store_dst(jd, iptr, d); break; @@ -1536,12 +1309,10 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); - if (INSTRUCTION_MUST_CHECK(iptr)) { - gen_nullptr_check(s1); - gen_bound_check; - } + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); M_SLL_IMM(s2, 2, REG_ITMP2); - M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2); + M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray_t, data[0]), REG_ITMP2); + /* implicit null-pointer check */ M_LWZX(d, s1, REG_ITMP2); emit_store_dst(jd, iptr, d); break; @@ -1551,13 +1322,11 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED); - if (INSTRUCTION_MUST_CHECK(iptr)) { - gen_nullptr_check(s1); - gen_bound_check; - } + /* implicit null-pointer check */ + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); M_SLL_IMM(s2, 3, REG_ITMP2); M_IADD(s1, REG_ITMP2, REG_ITMP2); - M_LLD_INTERN(d, REG_ITMP2, OFFSET(java_longarray, data[0])); + M_LLD_INTERN(d, REG_ITMP2, OFFSET(java_longarray_t, data[0])); emit_store_dst(jd, iptr, d); break; @@ -1566,12 +1335,10 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); - if (INSTRUCTION_MUST_CHECK(iptr)) { - gen_nullptr_check(s1); - gen_bound_check; - } + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); M_SLL_IMM(s2, 2, REG_ITMP2); - M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2); + M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray_t, data[0]), REG_ITMP2); + /* implicit null-pointer check */ M_LFSX(d, s1, REG_ITMP2); emit_store_dst(jd, iptr, d); break; @@ -1581,12 +1348,10 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); - if (INSTRUCTION_MUST_CHECK(iptr)) { - gen_nullptr_check(s1); - gen_bound_check; - } + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); M_SLL_IMM(s2, 3, REG_ITMP2); - M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2); + M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray_t, data[0]), REG_ITMP2); + /* implicit null-pointer check */ M_LFDX(d, s1, REG_ITMP2); emit_store_dst(jd, iptr, d); break; @@ -1596,12 +1361,10 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); - if (INSTRUCTION_MUST_CHECK(iptr)) { - gen_nullptr_check(s1); - gen_bound_check; - } + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); M_SLL_IMM(s2, 2, REG_ITMP2); - M_IADD_IMM(REG_ITMP2, OFFSET(java_objectarray, data[0]), REG_ITMP2); + M_IADD_IMM(REG_ITMP2, OFFSET(java_objectarray_t, data[0]), REG_ITMP2); + /* implicit null-pointer check */ M_LWZX(d, s1, REG_ITMP2); emit_store_dst(jd, iptr, d); break; @@ -1611,12 +1374,10 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); - if (INSTRUCTION_MUST_CHECK(iptr)) { - gen_nullptr_check(s1); - gen_bound_check; - } + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); s3 = emit_load_s3(jd, iptr, REG_ITMP3); - M_IADD_IMM(s2, OFFSET(java_bytearray, data[0]), REG_ITMP2); + M_IADD_IMM(s2, OFFSET(java_bytearray_t, data[0]), REG_ITMP2); + /* implicit null-pointer check */ M_STBX(s3, s1, REG_ITMP2); break; @@ -1624,13 +1385,11 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); - if (INSTRUCTION_MUST_CHECK(iptr)) { - gen_nullptr_check(s1); - gen_bound_check; - } + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); s3 = emit_load_s3(jd, iptr, REG_ITMP3); M_SLL_IMM(s2, 1, REG_ITMP2); - M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray, data[0]), REG_ITMP2); + M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray_t, data[0]), REG_ITMP2); + /* implicit null-pointer check */ M_STHX(s3, s1, REG_ITMP2); break; @@ -1638,13 +1397,11 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); - if (INSTRUCTION_MUST_CHECK(iptr)) { - gen_nullptr_check(s1); - gen_bound_check; - } + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); s3 = emit_load_s3(jd, iptr, REG_ITMP3); M_SLL_IMM(s2, 1, REG_ITMP2); - M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray, data[0]), REG_ITMP2); + M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray_t, data[0]), REG_ITMP2); + /* implicit null-pointer check */ M_STHX(s3, s1, REG_ITMP2); break; @@ -1652,13 +1409,11 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); - if (INSTRUCTION_MUST_CHECK(iptr)) { - gen_nullptr_check(s1); - gen_bound_check; - } + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); s3 = emit_load_s3(jd, iptr, REG_ITMP3); M_SLL_IMM(s2, 2, REG_ITMP2); - M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2); + M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray_t, data[0]), REG_ITMP2); + /* implicit null-pointer check */ M_STWX(s3, s1, REG_ITMP2); break; @@ -1666,13 +1421,11 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); - if (INSTRUCTION_MUST_CHECK(iptr)) { - gen_nullptr_check(s1); - gen_bound_check; - } + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); s3 = emit_load_s3_high(jd, iptr, REG_ITMP3); M_SLL_IMM(s2, 3, REG_ITMP2); - M_IADD_IMM(REG_ITMP2, OFFSET(java_longarray, data[0]), REG_ITMP2); + M_IADD_IMM(REG_ITMP2, OFFSET(java_longarray_t, data[0]), REG_ITMP2); + /* implicit null-pointer check */ M_STWX(s3, s1, REG_ITMP2); M_IADD_IMM(REG_ITMP2, 4, REG_ITMP2); s3 = emit_load_s3_low(jd, iptr, REG_ITMP3); @@ -1683,13 +1436,11 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); - if (INSTRUCTION_MUST_CHECK(iptr)) { - gen_nullptr_check(s1); - gen_bound_check; - } + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); s3 = emit_load_s3(jd, iptr, REG_FTMP3); M_SLL_IMM(s2, 2, REG_ITMP2); - M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2); + M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray_t, data[0]), REG_ITMP2); + /* implicit null-pointer check */ M_STFSX(s3, s1, REG_ITMP2); break; @@ -1697,13 +1448,11 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); - if (INSTRUCTION_MUST_CHECK(iptr)) { - gen_nullptr_check(s1); - gen_bound_check; - } + emit_arrayindexoutofbounds_check(cd, iptr, s1, s2); s3 = emit_load_s3(jd, iptr, REG_FTMP3); M_SLL_IMM(s2, 3, REG_ITMP2); - M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2); + M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray_t, data[0]), REG_ITMP2); + /* implicit null-pointer check */ M_STFDX(s3, s1, REG_ITMP2); break; @@ -1711,13 +1460,11 @@ bool codegen(jitdata *jd) 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_arrayindexoutofbounds_check(cd, iptr, s1, s2); s3 = emit_load_s3(jd, iptr, REG_A1); - disp = dseg_add_functionptr(cd, BUILTIN_canstore); + /* XXX what if array is NULL */ + disp = dseg_add_functionptr(cd, BUILTIN_FAST_canstore); M_ALD(REG_ITMP3, REG_PV, disp); M_MTCTR(REG_ITMP3); @@ -1725,15 +1472,14 @@ bool codegen(jitdata *jd) M_INTMOVE(s3, REG_A1); M_JSR; - M_TST(REG_RESULT); - M_BEQ(0); - codegen_add_arraystoreexception_ref(cd); + emit_arraystore_check(cd, iptr); s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); s3 = emit_load_s3(jd, iptr, REG_ITMP3); M_SLL_IMM(s2, 2, REG_ITMP2); - M_IADD_IMM(REG_ITMP2, OFFSET(java_objectarray, data[0]), REG_ITMP2); + M_IADD_IMM(REG_ITMP2, OFFSET(java_objectarray_t, data[0]), REG_ITMP2); + /* implicit null-pointer check */ M_STWX(s3, s1, REG_ITMP2); break; @@ -1741,29 +1487,20 @@ bool codegen(jitdata *jd) case ICMD_GETSTATIC: /* ... ==> ..., value */ if (INSTRUCTION_IS_UNRESOLVED(iptr)) { - unresolved_field *uf = iptr->sx.s23.s3.uf; - + uf = iptr->sx.s23.s3.uf; fieldtype = uf->fieldref->parseddesc.fd->type; - disp = dseg_add_unique_address(cd, uf); - - codegen_addpatchref(cd, PATCHER_get_putstatic, uf, disp); + disp = dseg_add_unique_address(cd, uf); - if (opt_showdisassemble) - M_NOP; + patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp); } else { - fieldinfo *fi = iptr->sx.s23.s3.fmiref->p.field; - + fi = iptr->sx.s23.s3.fmiref->p.field; fieldtype = fi->type; - disp = dseg_add_address(cd, &(fi->value)); - - if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) { - codegen_addpatchref(cd, PATCHER_initialize_class, - fi->class, disp); + disp = dseg_add_address(cd, fi->value); - if (opt_showdisassemble) - M_NOP; - } + if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz)) + patcher_add_patch_ref(jd, PATCHER_initialize_class, + fi->clazz, disp); } M_ALD(REG_ITMP1, REG_PV, disp); @@ -1796,29 +1533,20 @@ bool codegen(jitdata *jd) case ICMD_PUTSTATIC: /* ..., value ==> ... */ if (INSTRUCTION_IS_UNRESOLVED(iptr)) { - unresolved_field *uf = iptr->sx.s23.s3.uf; - + uf = iptr->sx.s23.s3.uf; fieldtype = uf->fieldref->parseddesc.fd->type; - disp = dseg_add_unique_address(cd, uf); + disp = dseg_add_unique_address(cd, uf); - codegen_addpatchref(cd, PATCHER_get_putstatic, uf, disp); - - if (opt_showdisassemble) - M_NOP; + patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp); } else { - fieldinfo *fi = iptr->sx.s23.s3.fmiref->p.field; - + fi = iptr->sx.s23.s3.fmiref->p.field; fieldtype = fi->type; - disp = dseg_add_address(cd, &(fi->value)); + disp = dseg_add_address(cd, fi->value); - if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) { - codegen_addpatchref(cd, PATCHER_initialize_class, - fi->class, disp); - - if (opt_showdisassemble) - M_NOP; - } + if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz)) + patcher_add_patch_ref(jd, PATCHER_initialize_class, + fi->clazz, disp); } M_ALD(REG_ITMP1, REG_PV, disp); @@ -1850,26 +1578,21 @@ bool codegen(jitdata *jd) case ICMD_GETFIELD: /* ... ==> ..., value */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); - gen_nullptr_check(s1); if (INSTRUCTION_IS_UNRESOLVED(iptr)) { - unresolved_field *uf = iptr->sx.s23.s3.uf; - + uf = iptr->sx.s23.s3.uf; fieldtype = uf->fieldref->parseddesc.fd->type; + disp = 0; - codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0); - - if (opt_showdisassemble) - M_NOP; - - disp = 0; + patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0); } else { - fieldinfo *fi = iptr->sx.s23.s3.fmiref->p.field; + fi = iptr->sx.s23.s3.fmiref->p.field; fieldtype = fi->type; disp = fi->offset; } + /* implicit null-pointer check */ switch (fieldtype) { case TYPE_INT: d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); @@ -1905,9 +1628,19 @@ bool codegen(jitdata *jd) case ICMD_PUTFIELD: /* ..., value ==> ... */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); - gen_nullptr_check(s1); - if (!IS_FLT_DBL_TYPE(fieldtype)) { + 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 @@ -1916,24 +1649,10 @@ bool codegen(jitdata *jd) else s2 = emit_load_s2(jd, iptr, REG_FTMP2); - if (INSTRUCTION_IS_UNRESOLVED(iptr)) { - unresolved_field *uf = iptr->sx.s23.s3.uf; - - fieldtype = uf->fieldref->parseddesc.fd->type; - - codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0); - - if (opt_showdisassemble) - M_NOP; - - disp = 0; - } - else { - fieldinfo *fi = iptr->sx.s23.s3.fmiref->p.field; - fieldtype = fi->type; - disp = fi->offset; - } + if (INSTRUCTION_IS_UNRESOLVED(iptr)) + patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0); + /* implicit null-pointer check */ switch (fieldtype) { case TYPE_INT: M_IST(s2, s1, disp); @@ -1966,10 +1685,7 @@ bool codegen(jitdata *jd) if (INSTRUCTION_IS_UNRESOLVED(iptr)) { unresolved_class *uc = iptr->sx.s23.s2.uc; - codegen_addpatchref(cd, PATCHER_resolve_class, uc, 0); - - if (opt_showdisassemble) - M_NOP; + patcher_add_patch_ref(jd, PATCHER_resolve_class, uc, 0); } #endif /* ENABLE_VERIFIER */ @@ -1977,13 +1693,13 @@ bool codegen(jitdata *jd) M_ALD(REG_ITMP2, REG_PV, disp); M_MTCTR(REG_ITMP2); - if (jd->isleafmethod) + if (code_is_leafmethod(code)) M_MFLR(REG_ITMP3); /* save LR */ M_BL(0); /* get current PC */ M_MFLR(REG_ITMP2_XPC); - if (jd->isleafmethod) + if (code_is_leafmethod(code)) M_MTLR(REG_ITMP3); /* restore LR */ M_RTS; /* jump to CTR */ @@ -1993,32 +1709,22 @@ bool codegen(jitdata *jd) case ICMD_GOTO: /* ... ==> ... */ case ICMD_RET: /* ... ==> ... */ - M_BR(0); - codegen_addreference(cd, iptr->dst.block); + emit_br(cd, iptr->dst.block); ALIGNCODENOP; break; case ICMD_JSR: /* ... ==> ... */ - M_BR(0); - codegen_addreference(cd, iptr->sx.s23.s3.jsrtarget.block); + emit_br(cd, iptr->sx.s23.s3.jsrtarget.block); ALIGNCODENOP; break; case ICMD_IFNULL: /* ..., value ==> ... */ + case ICMD_IFNONNULL: s1 = emit_load_s1(jd, iptr, REG_ITMP1); M_TST(s1); - M_BEQ(0); - codegen_addreference(cd, iptr->dst.block); - break; - - case ICMD_IFNONNULL: /* ..., value ==> ... */ - - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - M_TST(s1); - M_BNE(0); - codegen_addreference(cd, iptr->dst.block); + emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFNULL, BRANCH_OPT_NONE); break; case ICMD_IFLT: @@ -2035,27 +1741,7 @@ bool codegen(jitdata *jd) ICONST(REG_ITMP2, iptr->sx.val.i); M_CMP(s1, REG_ITMP2); } - switch (iptr->opc) { - case ICMD_IFLT: - M_BLT(0); - break; - case ICMD_IFLE: - M_BLE(0); - break; - case ICMD_IFNE: - M_BNE(0); - break; - case ICMD_IFGT: - M_BGT(0); - break; - case ICMD_IFGE: - M_BGE(0); - break; - case ICMD_IFEQ: - M_BEQ(0); - break; - } - codegen_addreference(cd, iptr->dst.block); + emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFEQ, BRANCH_OPT_NONE); break; @@ -2064,49 +1750,50 @@ bool codegen(jitdata *jd) s1 = emit_load_s1_low(jd, iptr, REG_ITMP1); s2 = emit_load_s1_high(jd, iptr, REG_ITMP2); if (iptr->sx.val.l == 0) { - M_OR_TST(s1, s2, REG_ITMP3); + M_IOR_TST(s1, s2, REG_ITMP3); } else if ((iptr->sx.val.l >= 0) && (iptr->sx.val.l <= 0xffff)) { M_XOR_IMM(s2, 0, REG_ITMP2); M_XOR_IMM(s1, iptr->sx.val.l & 0xffff, REG_ITMP1); - M_OR_TST(REG_ITMP1, REG_ITMP2, REG_ITMP3); + M_IOR_TST(REG_ITMP1, REG_ITMP2, REG_ITMP3); } else { ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff); M_XOR(s1, REG_ITMP3, REG_ITMP1); ICONST(REG_ITMP3, iptr->sx.val.l >> 32); M_XOR(s2, REG_ITMP3, REG_ITMP2); - M_OR_TST(REG_ITMP1, REG_ITMP2, REG_ITMP3); + M_IOR_TST(REG_ITMP1, REG_ITMP2, REG_ITMP3); } - M_BEQ(0); - codegen_addreference(cd, iptr->dst.block); + emit_beq(cd, iptr->dst.block); break; case ICMD_IF_LLT: /* ..., value ==> ... */ + s1 = emit_load_s1_low(jd, iptr, REG_ITMP1); s2 = emit_load_s1_high(jd, iptr, REG_ITMP2); if (iptr->sx.val.l == 0) { /* if high word is less than zero, the whole long is too */ M_CMPI(s2, 0); + emit_blt(cd, iptr->dst.block); } else if ((iptr->sx.val.l >= 0) && (iptr->sx.val.l <= 0xffff)) { M_CMPI(s2, 0); - M_BLT(0); - codegen_addreference(cd, iptr->dst.block); - M_BGT(2); + emit_blt(cd, iptr->dst.block); + emit_label_bgt(cd, BRANCH_LABEL_1); M_CMPUI(s1, iptr->sx.val.l & 0xffff); + emit_blt(cd, iptr->dst.block); + emit_label(cd, BRANCH_LABEL_1); } else { ICONST(REG_ITMP3, iptr->sx.val.l >> 32); M_CMP(s2, REG_ITMP3); - M_BLT(0); - codegen_addreference(cd, iptr->dst.block); - M_BGT(3); + emit_blt(cd, iptr->dst.block); + emit_label_bgt(cd, BRANCH_LABEL_1); ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff); M_CMPU(s1, REG_ITMP3); + emit_blt(cd, iptr->dst.block); + emit_label(cd, BRANCH_LABEL_1); } - M_BLT(0); - codegen_addreference(cd, iptr->dst.block); break; case ICMD_IF_LLE: /* ..., value ==> ... */ @@ -2114,28 +1801,26 @@ bool codegen(jitdata *jd) s1 = emit_load_s1_low(jd, iptr, REG_ITMP1); s2 = emit_load_s1_high(jd, iptr, REG_ITMP2); /* if (iptr->sx.val.l == 0) { */ -/* M_OR(s1, s2, REG_ITMP3); */ +/* M_IOR(s1, s2, REG_ITMP3); */ /* M_CMPI(REG_ITMP3, 0); */ /* } else */ if ((iptr->sx.val.l >= 0) && (iptr->sx.val.l <= 0xffff)) { M_CMPI(s2, 0); - M_BLT(0); - codegen_addreference(cd, iptr->dst.block); - M_BGT(2); + emit_blt(cd, iptr->dst.block); + emit_label_bgt(cd, BRANCH_LABEL_1); M_CMPUI(s1, iptr->sx.val.l & 0xffff); } else { ICONST(REG_ITMP3, iptr->sx.val.l >> 32); M_CMP(s2, REG_ITMP3); - M_BLT(0); - codegen_addreference(cd, iptr->dst.block); - M_BGT(3); + emit_blt(cd, iptr->dst.block); + emit_label_bgt(cd, BRANCH_LABEL_1); ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff); M_CMPU(s1, REG_ITMP3); } - M_BLE(0); - codegen_addreference(cd, iptr->dst.block); + emit_ble(cd, iptr->dst.block); + emit_label(cd, BRANCH_LABEL_1); break; case ICMD_IF_LNE: /* ..., value ==> ... */ @@ -2143,22 +1828,21 @@ bool codegen(jitdata *jd) s1 = emit_load_s1_low(jd, iptr, REG_ITMP1); s2 = emit_load_s1_high(jd, iptr, REG_ITMP2); if (iptr->sx.val.l == 0) { - M_OR_TST(s1, s2, REG_ITMP3); + M_IOR_TST(s1, s2, REG_ITMP3); } else if ((iptr->sx.val.l >= 0) && (iptr->sx.val.l <= 0xffff)) { M_XOR_IMM(s2, 0, REG_ITMP2); M_XOR_IMM(s1, iptr->sx.val.l & 0xffff, REG_ITMP1); - M_OR_TST(REG_ITMP1, REG_ITMP2, REG_ITMP3); + M_IOR_TST(REG_ITMP1, REG_ITMP2, REG_ITMP3); } else { ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff); M_XOR(s1, REG_ITMP3, REG_ITMP1); ICONST(REG_ITMP3, iptr->sx.val.l >> 32); M_XOR(s2, REG_ITMP3, REG_ITMP2); - M_OR_TST(REG_ITMP1, REG_ITMP2, REG_ITMP3); + M_IOR_TST(REG_ITMP1, REG_ITMP2, REG_ITMP3); } - M_BNE(0); - codegen_addreference(cd, iptr->dst.block); + emit_bne(cd, iptr->dst.block); break; case ICMD_IF_LGT: /* ..., value ==> ... */ @@ -2166,28 +1850,26 @@ bool codegen(jitdata *jd) s1 = emit_load_s1_low(jd, iptr, REG_ITMP1); s2 = emit_load_s1_high(jd, iptr, REG_ITMP2); /* if (iptr->sx.val.l == 0) { */ -/* M_OR(s1, s2, REG_ITMP3); */ +/* M_IOR(s1, s2, REG_ITMP3); */ /* M_CMPI(REG_ITMP3, 0); */ /* } else */ if ((iptr->sx.val.l >= 0) && (iptr->sx.val.l <= 0xffff)) { M_CMPI(s2, 0); - M_BGT(0); - codegen_addreference(cd, iptr->dst.block); - M_BLT(2); + emit_bgt(cd, iptr->dst.block); + emit_label_blt(cd, BRANCH_LABEL_1); M_CMPUI(s1, iptr->sx.val.l & 0xffff); } else { ICONST(REG_ITMP3, iptr->sx.val.l >> 32); M_CMP(s2, REG_ITMP3); - M_BGT(0); - codegen_addreference(cd, iptr->dst.block); - M_BLT(3); + emit_bgt(cd, iptr->dst.block); + emit_label_blt(cd, BRANCH_LABEL_1); ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff); M_CMPU(s1, REG_ITMP3); } - M_BGT(0); - codegen_addreference(cd, iptr->dst.block); + emit_bgt(cd, iptr->dst.block); + emit_label(cd, BRANCH_LABEL_1); break; case ICMD_IF_LGE: /* ..., value ==> ... */ @@ -2197,35 +1879,48 @@ bool codegen(jitdata *jd) if (iptr->sx.val.l == 0) { /* if high word is greater equal zero, the whole long is too */ M_CMPI(s2, 0); + emit_bge(cd, iptr->dst.block); } else if ((iptr->sx.val.l >= 0) && (iptr->sx.val.l <= 0xffff)) { M_CMPI(s2, 0); - M_BGT(0); - codegen_addreference(cd, iptr->dst.block); - M_BLT(2); + emit_bgt(cd, iptr->dst.block); + emit_label_blt(cd, BRANCH_LABEL_1); M_CMPUI(s1, iptr->sx.val.l & 0xffff); + emit_bge(cd, iptr->dst.block); + emit_label(cd, BRANCH_LABEL_1); } else { ICONST(REG_ITMP3, iptr->sx.val.l >> 32); M_CMP(s2, REG_ITMP3); - M_BGT(0); - codegen_addreference(cd, iptr->dst.block); - M_BLT(3); + emit_bgt(cd, iptr->dst.block); + emit_label_blt(cd, BRANCH_LABEL_1); ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff); M_CMPU(s1, REG_ITMP3); + emit_bge(cd, iptr->dst.block); + emit_label(cd, BRANCH_LABEL_1); } - M_BGE(0); - codegen_addreference(cd, iptr->dst.block); break; case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */ + case ICMD_IF_ICMPNE: + case ICMD_IF_ICMPLT: + case ICMD_IF_ICMPGT: + case ICMD_IF_ICMPLE: + case ICMD_IF_ICMPGE: + + s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s2 = emit_load_s2(jd, iptr, REG_ITMP2); + M_CMP(s1, s2); + emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_ICMPEQ, BRANCH_OPT_NONE); + break; + case ICMD_IF_ACMPEQ: /* op1 = target JavaVM pc */ + case ICMD_IF_ACMPNE: s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); M_CMP(s1, s2); - M_BEQ(0); - codegen_addreference(cd, iptr->dst.block); + emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_ACMPEQ, BRANCH_OPT_NONE); break; case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */ @@ -2233,23 +1928,12 @@ bool codegen(jitdata *jd) 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 */ + emit_label_bne(cd, BRANCH_LABEL_1); s1 = emit_load_s1_low(jd, iptr, REG_ITMP1); s2 = emit_load_s2_low(jd, iptr, REG_ITMP2); - M_BNE(2); - M_CMP(s1, s2); - M_BEQ(0); - codegen_addreference(cd, iptr->dst.block); - break; - - case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */ - case ICMD_IF_ACMPNE: /* 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_BNE(0); - codegen_addreference(cd, iptr->dst.block); + emit_beq(cd, iptr->dst.block); + emit_label(cd, BRANCH_LABEL_1); break; case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */ @@ -2257,22 +1941,11 @@ bool codegen(jitdata *jd) s1 = emit_load_s1_high(jd, iptr, REG_ITMP1); s2 = emit_load_s2_high(jd, iptr, REG_ITMP2); M_CMP(s1, s2); - M_BNE(0); - codegen_addreference(cd, iptr->dst.block); + emit_bne(cd, iptr->dst.block); s1 = emit_load_s1_low(jd, iptr, REG_ITMP1); s2 = emit_load_s2_low(jd, iptr, REG_ITMP2); M_CMP(s1, s2); - M_BNE(0); - codegen_addreference(cd, iptr->dst.block); - break; - - case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */ - - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - s2 = emit_load_s2(jd, iptr, REG_ITMP2); - M_CMP(s1, s2); - M_BLT(0); - codegen_addreference(cd, iptr->dst.block); + emit_bne(cd, iptr->dst.block); break; case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */ @@ -2280,24 +1953,13 @@ bool codegen(jitdata *jd) 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_addreference(cd, iptr->dst.block); - /* load low-bits before the branch, so we know the distance */ + emit_blt(cd, iptr->dst.block); + emit_label_bgt(cd, BRANCH_LABEL_1); s1 = emit_load_s1_low(jd, iptr, REG_ITMP1); s2 = emit_load_s2_low(jd, iptr, REG_ITMP2); - M_BGT(2); M_CMPU(s1, s2); - M_BLT(0); - codegen_addreference(cd, iptr->dst.block); - break; - - case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */ - - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - s2 = emit_load_s2(jd, iptr, REG_ITMP2); - M_CMP(s1, s2); - M_BGT(0); - codegen_addreference(cd, iptr->dst.block); + emit_blt(cd, iptr->dst.block); + emit_label(cd, BRANCH_LABEL_1); break; case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */ @@ -2305,24 +1967,13 @@ bool codegen(jitdata *jd) s1 = emit_load_s1_high(jd, iptr, REG_ITMP1); s2 = emit_load_s2_high(jd, iptr, REG_ITMP2); M_CMP(s1, s2); - M_BGT(0); - codegen_addreference(cd, iptr->dst.block); - /* load low-bits before the branch, so we know the distance */ + emit_bgt(cd, iptr->dst.block); + emit_label_blt(cd, BRANCH_LABEL_1); s1 = emit_load_s1_low(jd, iptr, REG_ITMP1); s2 = emit_load_s2_low(jd, iptr, REG_ITMP2); - M_BLT(2); M_CMPU(s1, s2); - M_BGT(0); - codegen_addreference(cd, iptr->dst.block); - break; - - case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */ - - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - s2 = emit_load_s2(jd, iptr, REG_ITMP2); - M_CMP(s1, s2); - M_BLE(0); - codegen_addreference(cd, iptr->dst.block); + emit_bgt(cd, iptr->dst.block); + emit_label(cd, BRANCH_LABEL_1); break; case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */ @@ -2330,24 +1981,13 @@ bool codegen(jitdata *jd) 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_addreference(cd, iptr->dst.block); - /* load low-bits before the branch, so we know the distance */ + emit_blt(cd, iptr->dst.block); + emit_label_bgt(cd, BRANCH_LABEL_1); s1 = emit_load_s1_low(jd, iptr, REG_ITMP1); s2 = emit_load_s2_low(jd, iptr, REG_ITMP2); - M_BGT(2); M_CMPU(s1, s2); - M_BLE(0); - codegen_addreference(cd, iptr->dst.block); - break; - - case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */ - - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - s2 = emit_load_s2(jd, iptr, REG_ITMP2); - M_CMP(s1, s2); - M_BGE(0); - codegen_addreference(cd, iptr->dst.block); + emit_ble(cd, iptr->dst.block); + emit_label(cd, BRANCH_LABEL_1); break; case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */ @@ -2355,25 +1995,25 @@ bool codegen(jitdata *jd) s1 = emit_load_s1_high(jd, iptr, REG_ITMP1); s2 = emit_load_s2_high(jd, iptr, REG_ITMP2); M_CMP(s1, s2); - M_BGT(0); - codegen_addreference(cd, iptr->dst.block); - /* load low-bits before the branch, so we know the distance */ + emit_bgt(cd, iptr->dst.block); + emit_label_blt(cd, BRANCH_LABEL_1); s1 = emit_load_s1_low(jd, iptr, REG_ITMP1); s2 = emit_load_s2_low(jd, iptr, REG_ITMP2); - M_BLT(2); M_CMPU(s1, s2); - M_BGE(0); - codegen_addreference(cd, iptr->dst.block); + emit_bge(cd, iptr->dst.block); + emit_label(cd, BRANCH_LABEL_1); break; case ICMD_IRETURN: /* ..., retvalue ==> ... */ + REPLACEMENT_POINT_RETURN(cd, iptr); s1 = emit_load_s1(jd, iptr, REG_RESULT); M_INTMOVE(s1, REG_RESULT); goto nowperformreturn; case ICMD_ARETURN: /* ..., retvalue ==> ... */ + REPLACEMENT_POINT_RETURN(cd, iptr); s1 = emit_load_s1(jd, iptr, REG_RESULT); M_INTMOVE(s1, REG_RESULT); @@ -2381,16 +2021,14 @@ bool codegen(jitdata *jd) if (INSTRUCTION_IS_UNRESOLVED(iptr)) { unresolved_class *uc = iptr->sx.s23.s2.uc; - codegen_addpatchref(cd, PATCHER_resolve_class, uc, 0); - - if (opt_showdisassemble) - M_NOP; + patcher_add_patch_ref(jd, PATCHER_resolve_class, uc, 0); } #endif /* ENABLE_VERIFIER */ goto nowperformreturn; case ICMD_LRETURN: /* ..., retvalue ==> ... */ + REPLACEMENT_POINT_RETURN(cd, iptr); s1 = emit_load_s1(jd, iptr, REG_RESULT_PACKED); M_LNGMOVE(s1, REG_RESULT_PACKED); goto nowperformreturn; @@ -2398,12 +2036,15 @@ bool codegen(jitdata *jd) case ICMD_FRETURN: /* ..., retvalue ==> ... */ case ICMD_DRETURN: + REPLACEMENT_POINT_RETURN(cd, iptr); s1 = emit_load_s1(jd, iptr, REG_FRESULT); M_FLTMOVE(s1, REG_FRESULT); goto nowperformreturn; case ICMD_RETURN: /* ... ==> ... */ + REPLACEMENT_POINT_RETURN(cd, iptr); + nowperformreturn: { s4 i, p; @@ -2412,11 +2053,10 @@ nowperformreturn: /* call trace function */ - if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) - emit_verbosecall_exit(jd); + emit_verbosecall_exit(jd); #if defined(ENABLE_THREADS) - if (checksync && (m->flags & ACC_SYNCHRONIZED)) { + if (checksync && code_is_synchronized(code)) { disp = dseg_add_functionptr(cd, LOCK_monitor_exit); M_ALD(REG_ITMP3, REG_PV, disp); M_MTCTR(REG_ITMP3); @@ -2425,38 +2065,34 @@ nowperformreturn: switch (iptr->opc) { case ICMD_LRETURN: - M_IST(REG_RESULT2, REG_SP, rd->memuse * 4 + 8); + M_IST(REG_RESULT2, REG_SP, rd->memuse * 8 + 8); /* 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 * 8 + 4); break; case ICMD_FRETURN: - M_FST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4); - break; case ICMD_DRETURN: - M_DST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4); + M_DST(REG_FRESULT, REG_SP, rd->memuse * 8 + 4); break; } - M_ALD(REG_A0, REG_SP, rd->memuse * 4); + M_ALD(REG_A0, REG_SP, rd->memuse * 8); M_JSR; /* 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 * 8 + 8); /* 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 * 8 + 4); break; case ICMD_FRETURN: - M_FLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4); - break; case ICMD_DRETURN: - M_DLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4); + M_DLD(REG_FRESULT, REG_SP, rd->memuse * 8 + 4); break; } } @@ -2464,27 +2100,27 @@ nowperformreturn: /* restore return address */ - if (!jd->isleafmethod) { + if (!code_is_leafmethod(code)) { /* ATTENTION: Don't use REG_ZERO (r0) here, as M_ALD may have a displacement overflow. */ - M_ALD(REG_ITMP1, REG_SP, p * 4 + LA_LR_OFFSET); + M_ALD(REG_ITMP1, REG_SP, p * 8 + LA_LR_OFFSET); M_MTLR(REG_ITMP1); } /* 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_LDA(REG_SP, REG_SP, cd->stackframesize * 4); + M_LDA(REG_SP, REG_SP, cd->stackframesize * 8); M_RET; ALIGNCODENOP; @@ -2517,8 +2153,7 @@ nowperformreturn: /* range check */ M_CMPUI(REG_ITMP1, i - 1); - M_BGT(0); - codegen_addreference(cd, table[0].block); + emit_bgt(cd, table[0].block); /* build jump table top down and use address of lowest entry */ @@ -2562,14 +2197,11 @@ nowperformreturn: M_ILD(REG_ITMP2, REG_PV, disp); M_CMP(s1, REG_ITMP2); } - M_BEQ(0); - codegen_addreference(cd, lookup->target.block); + emit_beq(cd, lookup->target.block); lookup++; } - M_BR(0); - codegen_addreference(cd, iptr->sx.s23.s3.lookupdefault.block); - + emit_br(cd, iptr->sx.s23.s3.lookupdefault.block); ALIGNCODENOP; break; } @@ -2577,6 +2209,8 @@ nowperformreturn: case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */ + REPLACEMENT_POINT_FORGC_BUILTIN(cd, iptr); + bte = iptr->sx.s23.s3.bte; md = bte->md; goto gen_method; @@ -2587,6 +2221,8 @@ nowperformreturn: case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */ case ICMD_INVOKEINTERFACE: + REPLACEMENT_POINT_INVOKE(cd, iptr); + if (INSTRUCTION_IS_UNRESOLVED(iptr)) { lm = NULL; um = iptr->sx.s23.s3.um; @@ -2599,97 +2235,111 @@ nowperformreturn: } gen_method: - s3 = md->paramcount; + i = md->paramcount; - MCODECHECK((s3 << 1) + 64); + MCODECHECK((i << 1) + 64); - /* copy arguments to registers or stack location */ + /* Copy arguments to registers or stack location. */ - for (s3 = s3 - 1; s3 >= 0; s3--) { - var = VAR(iptr->sx.s23.s2.args[s3]); + for (i = i - 1; i >= 0; i--) { + var = VAR(iptr->sx.s23.s2.args[i]); + d = md->params[i].regoff; + + /* Already pre-allocated? */ - /* Already Preallocated? */ if (var->flags & PREALLOC) continue; - if (IS_INT_LNG_TYPE(var->type)) { - 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)]); - d = emit_load(jd, iptr, var, s1); - M_LNGMOVE(d, s1); - } - else { - s1 = rd->argintregs[md->params[s3].regoff]; - d = emit_load(jd, iptr, var, s1); - M_INTMOVE(d, s1); - } - } - 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); - } - else { - d = emit_load(jd, iptr, var, REG_ITMP1); - M_IST(d, REG_SP, md->params[s3].regoff * 4); - } + if (!md->params[i].inmemory) { + s1 = emit_load(jd, iptr, var, d); + + switch (var->type) { + case TYPE_INT: + case TYPE_ADR: + M_INTMOVE(s1, d); + break; + + case TYPE_LNG: + M_LNGMOVE(s1, d); + break; + + case TYPE_FLT: + case TYPE_DBL: + M_FLTMOVE(s1, d); + break; } } else { - if (!md->params[s3].inmemory) { - s1 = rd->argfltregs[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); - else - M_FST(d, REG_SP, md->params[s3].regoff * 4); + switch (var->type) { + case TYPE_INT: + case TYPE_ADR: + s1 = emit_load(jd, iptr, var, REG_ITMP1); + M_IST(s1, REG_SP, d); + break; + + case TYPE_LNG: + s1 = emit_load(jd, iptr, var, REG_ITMP12_PACKED); + M_LST(s1, REG_SP, d); + break; + + case TYPE_FLT: + case TYPE_DBL: + s1 = emit_load(jd, iptr, var, REG_FTMP1); + M_DST(s1, REG_SP, d); + break; } } } switch (iptr->opc) { case ICMD_BUILTIN: - disp = dseg_add_functionptr(cd, bte->fp); + if (bte->stub == NULL) + disp = dseg_add_functionptr(cd, bte->fp); + else + disp = dseg_add_functionptr(cd, bte->stub); M_ALD(REG_PV, REG_PV, disp); /* pointer to built-in-function */ + + /* generate the actual call */ + + M_MTCTR(REG_PV); + M_JSR; + REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr); + REPLACEMENT_POINT_FORGC_BUILTIN_RETURN(cd, iptr); + disp = (s4) (cd->mcodeptr - cd->mcodebase); + M_MFLR(REG_ITMP1); + M_LDA(REG_PV, REG_ITMP1, -disp); break; case ICMD_INVOKESPECIAL: - gen_nullptr_check(REG_A0); - M_ILD(REG_ITMP1, REG_A0, 0); /* hardware nullptr */ - /* fall through */ + emit_nullpointer_check(cd, iptr, REG_A0); + /* 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); - - if (opt_showdisassemble) - M_NOP; } else disp = dseg_add_address(cd, lm->stubroutine); M_ALD(REG_PV, REG_PV, disp); + + /* generate the actual call */ + + M_MTCTR(REG_PV); + M_JSR; + REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr); + disp = (s4) (cd->mcodeptr - cd->mcodebase); + M_MFLR(REG_ITMP1); + M_LDA(REG_PV, REG_ITMP1, -disp); break; case ICMD_INVOKEVIRTUAL: - gen_nullptr_check(REG_A0); - if (lm == NULL) { - codegen_addpatchref(cd, PATCHER_invokevirtual, um, 0); - - if (opt_showdisassemble) - M_NOP; + patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, 0); s1 = 0; } @@ -2698,92 +2348,80 @@ 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); + + /* generate the actual call */ + + M_MTCTR(REG_PV); + M_JSR; + REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr); + disp = (s4) (cd->mcodeptr - cd->mcodebase); + M_MFLR(REG_ITMP1); + M_LDA(REG_PV, REG_ITMP1, -disp); break; case ICMD_INVOKEINTERFACE: - gen_nullptr_check(REG_A0); - if (lm == NULL) { - codegen_addpatchref(cd, PATCHER_invokeinterface, um, 0); - - if (opt_showdisassemble) - M_NOP; + 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)); + /* implicit null-pointer check */ + M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl)); M_ALD(REG_METHODPTR, REG_METHODPTR, s1); M_ALD(REG_PV, REG_METHODPTR, s2); - break; - } - - /* generate the actual call */ - M_MTCTR(REG_PV); - M_JSR; - disp = (s4) (cd->mcodeptr - cd->mcodebase); - M_MFLR(REG_ITMP1); - M_LDA(REG_PV, REG_ITMP1, -disp); - - /* actually only used for ICMD_BUILTIN */ + /* generate the actual call */ - if (INSTRUCTION_MUST_CHECK(iptr)) { - M_CMPI(REG_RESULT, 0); - M_BEQ(0); - codegen_add_fillinstacktrace_ref(cd); + M_MTCTR(REG_PV); + M_JSR; + REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr); + disp = (s4) (cd->mcodeptr - cd->mcodebase); + M_MFLR(REG_ITMP1); + M_LDA(REG_PV, REG_ITMP1, -disp); + break; } - /* store return value */ + /* Store return value. */ + + switch (md->returntype.type) { + case TYPE_INT: + case TYPE_ADR: + s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT); + M_INTMOVE(REG_RESULT, s1); + emit_store_dst(jd, iptr, s1); + break; - d = md->returntype.type; + case TYPE_LNG: + s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED); + M_LNGMOVE(REG_RESULT_PACKED, s1); + emit_store_dst(jd, iptr, s1); + break; - if (d != TYPE_VOID) { - if (IS_INT_LNG_TYPE(d)) { - if (IS_2_WORD_TYPE(d)) { - s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED); - M_LNGMOVE(REG_RESULT_PACKED, s1); - } - else { - s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT); - M_INTMOVE(REG_RESULT, s1); - } - } - else { - s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT); - M_FLTMOVE(REG_FRESULT, s1); - } + case TYPE_FLT: + case TYPE_DBL: + s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT); + M_FLTMOVE(REG_FRESULT, s1); emit_store_dst(jd, iptr, s1); + break; + + case TYPE_VOID: + break; } break; case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */ - /* val.a: (classinfo*) superclass */ - - /* superclass is an interface: - * - * OK if ((sub == NULL) || - * (sub->vftbl->interfacetablelength > super->index) && - * (sub->vftbl->interfacetable[-super->index] != NULL)); - * - * superclass is a class: - * - * OK if ((sub == NULL) || (0 - * <= (sub->vftbl->baseval - super->vftbl->baseval) <= - * super->vftbl->diffvall)); - */ if (!(iptr->flags.bits & INS_FLAG_ARRAY)) { /* object type cast-check */ @@ -2792,132 +2430,121 @@ gen_method: s4 superindex; if (INSTRUCTION_IS_UNRESOLVED(iptr)) { - super = NULL; + super = NULL; superindex = 0; } else { - super = iptr->sx.s23.s3.c.cls; + super = iptr->sx.s23.s3.c.cls; superindex = super->index; } - -#if defined(ENABLE_THREADS) - codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase); -#endif - - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - - /* calculate interface checkcast code size */ - - s2 = 7; - if (super == NULL) - s2 += (opt_showdisassemble ? 1 : 0); - /* calculate class checkcast code size */ + if ((super == NULL) || !(super->flags & ACC_INTERFACE)) + CODEGEN_CRITICAL_SECTION_NEW; - s3 = 8 + (s1 == REG_ITMP1); - if (super == NULL) - s3 += (opt_showdisassemble ? 1 : 0); + s1 = emit_load_s1(jd, iptr, REG_ITMP1); /* if class is not resolved, check which code to call */ if (super == NULL) { M_TST(s1); - M_BEQ(3 + (opt_showdisassemble ? 1 : 0) + s2 + 1 + s3); + emit_label_beq(cd, BRANCH_LABEL_1); disp = dseg_add_unique_s4(cd, 0); /* super->flags */ - codegen_addpatchref(cd, + patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags, iptr->sx.s23.s3.c.ref, disp); - if (opt_showdisassemble) - M_NOP; - M_ILD(REG_ITMP2, REG_PV, disp); - M_AND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2); - M_BEQ(s2 + 1); + M_IAND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2); + emit_label_beq(cd, BRANCH_LABEL_2); } /* interface checkcast code */ if ((super == NULL) || (super->flags & ACC_INTERFACE)) { if (super == NULL) { - codegen_addpatchref(cd, - PATCHER_checkcast_instanceof_interface, + patcher_add_patch_ref(jd, + PATCHER_checkcast_interface, iptr->sx.s23.s3.c.ref, 0); - - if (opt_showdisassemble) - M_NOP; } else { M_TST(s1); - M_BEQ(s2); + emit_label_beq(cd, BRANCH_LABEL_3); } - M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl)); + M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl)); M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength)); M_LDATST(REG_ITMP3, REG_ITMP3, -superindex); - M_BLE(0); - codegen_add_classcastexception_ref(cd, s1); + emit_classcast_check(cd, iptr, BRANCH_LE, REG_ITMP3, s1); + M_ALD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetable[0]) - superindex * sizeof(methodptr*)); M_TST(REG_ITMP3); - M_BEQ(0); - codegen_add_classcastexception_ref(cd, s1); + emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP3, s1); if (super == NULL) - M_BR(s3); + emit_label_br(cd, BRANCH_LABEL_4); + else + emit_label(cd, BRANCH_LABEL_3); } /* class checkcast code */ if ((super == NULL) || !(super->flags & ACC_INTERFACE)) { if (super == NULL) { + emit_label(cd, BRANCH_LABEL_2); + disp = dseg_add_unique_address(cd, NULL); - codegen_addpatchref(cd, PATCHER_resolve_classref_to_vftbl, + patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl, iptr->sx.s23.s3.c.ref, disp); - - if (opt_showdisassemble) - M_NOP; } else { disp = dseg_add_address(cd, super->vftbl); M_TST(s1); - M_BEQ(s3); + emit_label_beq(cd, BRANCH_LABEL_5); } - M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl)); -#if defined(ENABLE_THREADS) - codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase); -#endif + M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl)); + + CODEGEN_CRITICAL_SECTION_START; + M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval)); M_ALD(REG_ITMP2, REG_PV, disp); if (s1 != REG_ITMP1) { M_ILD(REG_ITMP1, 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 + + CODEGEN_CRITICAL_SECTION_END; + M_ISUB(REG_ITMP3, REG_ITMP1, REG_ITMP3); - } else { + } + else { M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval)); M_ISUB(REG_ITMP3, REG_ITMP2, REG_ITMP3); M_ALD(REG_ITMP2, REG_PV, disp); M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval)); -#if defined(ENABLE_THREADS) - codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase); -#endif + + CODEGEN_CRITICAL_SECTION_END; } M_CMPU(REG_ITMP3, REG_ITMP2); - M_BGT(0); - codegen_add_classcastexception_ref(cd, s1); + emit_classcast_check(cd, iptr, BRANCH_GT, REG_ITMP3, s1); + + if (super != NULL) + emit_label(cd, BRANCH_LABEL_5); } + + if (super == NULL) { + emit_label(cd, BRANCH_LABEL_1); + emit_label(cd, BRANCH_LABEL_4); + } + d = codegen_reg_of_dst(jd, iptr, s1); } else { @@ -2929,12 +2556,9 @@ gen_method: if (INSTRUCTION_IS_UNRESOLVED(iptr)) { disp = dseg_add_unique_address(cd, NULL); - codegen_addpatchref(cd, PATCHER_resolve_classref_to_classinfo, + patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo, iptr->sx.s23.s3.c.ref, disp); - - if (opt_showdisassemble) - M_NOP; } else disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls); @@ -2945,8 +2569,7 @@ gen_method: M_MTCTR(REG_ITMP2); M_JSR; M_TST(REG_RESULT); - M_BEQ(0); - codegen_add_classcastexception_ref(cd, s1); + emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1); s1 = emit_load_s1(jd, iptr, REG_ITMP1); d = codegen_reg_of_dst(jd, iptr, s1); @@ -2956,94 +2579,63 @@ gen_method: break; case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */ - /* val.a: (classinfo*) superclass */ - - /* superclass is an interface: - * - * return (sub != NULL) && - * (sub->vftbl->interfacetablelength > super->index) && - * (sub->vftbl->interfacetable[-super->index] != NULL); - * - * superclass is a class: - * - * return ((sub != NULL) && (0 - * <= (sub->vftbl->baseval - super->vftbl->baseval) <= - * super->vftbl->diffvall)); - */ { classinfo *super; s4 superindex; if (INSTRUCTION_IS_UNRESOLVED(iptr)) { - super = NULL; + super = NULL; superindex = 0; } else { - super = iptr->sx.s23.s3.c.cls; + super = iptr->sx.s23.s3.c.cls; superindex = super->index; } -#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); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); if (s1 == d) { M_MOV(s1, REG_ITMP1); s1 = REG_ITMP1; } - /* calculate interface instanceof code size */ - - s2 = 8; - if (super == NULL) - s2 += (opt_showdisassemble ? 1 : 0); - - /* calculate class instanceof code size */ - - s3 = 10; - if (super == NULL) - s3 += (opt_showdisassemble ? 1 : 0); - M_CLR(d); /* if class is not resolved, check which code to call */ if (super == NULL) { M_TST(s1); - M_BEQ(3 + (opt_showdisassemble ? 1 : 0) + s2 + 1 + s3); + emit_label_beq(cd, BRANCH_LABEL_1); disp = dseg_add_unique_s4(cd, 0); /* super->flags */ - codegen_addpatchref(cd, PATCHER_resolve_classref_to_flags, + patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags, iptr->sx.s23.s3.c.ref, disp); - if (opt_showdisassemble) - M_NOP; - M_ILD(REG_ITMP3, REG_PV, disp); - M_AND_IMM(REG_ITMP3, ACC_INTERFACE, REG_ITMP3); - M_BEQ(s2 + 1); + M_IAND_IMM(REG_ITMP3, ACC_INTERFACE, REG_ITMP3); + emit_label_beq(cd, BRANCH_LABEL_2); } /* interface instanceof code */ if ((super == NULL) || (super->flags & ACC_INTERFACE)) { if (super == NULL) { - codegen_addpatchref(cd, - PATCHER_checkcast_instanceof_interface, + patcher_add_patch_ref(jd, + PATCHER_instanceof_interface, iptr->sx.s23.s3.c.ref, 0); - - if (opt_showdisassemble) - M_NOP; } else { M_TST(s1); - M_BEQ(s2); + emit_label_beq(cd, BRANCH_LABEL_3); } - 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_LDATST(REG_ITMP3, REG_ITMP3, -superindex); M_BLE(4); @@ -3055,46 +2647,56 @@ gen_method: M_IADD_IMM(REG_ZERO, 1, d); if (super == NULL) - M_BR(s3); + emit_label_br(cd, BRANCH_LABEL_4); + else + emit_label(cd, BRANCH_LABEL_3); } /* class instanceof code */ if ((super == NULL) || !(super->flags & ACC_INTERFACE)) { if (super == NULL) { + emit_label(cd, BRANCH_LABEL_2); + disp = dseg_add_unique_address(cd, NULL); - codegen_addpatchref(cd, PATCHER_resolve_classref_to_vftbl, + patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl, iptr->sx.s23.s3.c.ref, disp); - - if (opt_showdisassemble) - M_NOP; } else { disp = dseg_add_address(cd, super->vftbl); M_TST(s1); - M_BEQ(s3); + emit_label_beq(cd, BRANCH_LABEL_5); } - M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl)); + M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl)); M_ALD(REG_ITMP2, REG_PV, disp); -#if defined(ENABLE_THREADS) - codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase); -#endif + + 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 + + CODEGEN_CRITICAL_SECTION_END; + M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1); M_CMPU(REG_ITMP1, REG_ITMP2); M_CLR(d); M_BGT(1); M_IADD_IMM(REG_ZERO, 1, d); + + if (super != NULL) + emit_label(cd, BRANCH_LABEL_5); } + + if (super == NULL) { + emit_label(cd, BRANCH_LABEL_1); + emit_label(cd, BRANCH_LABEL_4); + } + emit_store_dst(jd, iptr, d); } break; @@ -3130,11 +2732,8 @@ gen_method: if (INSTRUCTION_IS_UNRESOLVED(iptr)) { disp = dseg_add_unique_address(cd, NULL); - codegen_addpatchref(cd, PATCHER_resolve_classref_to_classinfo, + patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo, iptr->sx.s23.s3.c.ref, disp); - - if (opt_showdisassemble) - M_NOP; } else disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls); @@ -3158,9 +2757,7 @@ gen_method: /* check for exception before result assignment */ - M_CMPI(REG_RESULT, 0); - M_BEQ(0); - codegen_add_fillinstacktrace_ref(cd); + emit_exception_check(cd, iptr); d = codegen_reg_of_dst(jd, iptr, REG_RESULT); M_INTMOVE(REG_RESULT, d); @@ -3168,9 +2765,8 @@ gen_method: break; default: - *exceptionptr = - new_internalerror("Unknown ICMD %d during code generation", - iptr->opc); + exceptions_throw_internalerror("Unknown ICMD %d during code generation", + iptr->opc); return false; } /* switch */ @@ -3179,15 +2775,9 @@ gen_method: } /* if (bptr -> flags >= BBREACHED) */ } /* for basic block */ - dseg_createlinenumbertable(cd); + /* generate traps */ - /* generate stubs */ - - emit_exception_stubs(jd); - emit_patcher_stubs(jd); - emit_replacement_stubs(jd); - - codegen_finish(jd); + emit_patcher_traps(jd); /* everything's ok */ @@ -3195,330 +2785,238 @@ gen_method: } -/* createcompilerstub ********************************************************** - - Creates a stub routine which calls the compiler. - -*******************************************************************************/ - -#define COMPILERSTUB_DATASIZE 3 * SIZEOF_VOID_P -#define COMPILERSTUB_CODESIZE 4 * 4 +/* codegen_emit_stub_native **************************************************** -#define COMPILERSTUB_SIZE COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE + Emits a stub routine which calls a native method. +*******************************************************************************/ -u1 *createcompilerstub(methodinfo *m) +void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int skipparams) { - u1 *s; /* memory to hold the stub */ - ptrint *d; + methodinfo *m; 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; + methoddesc *md; + s4 i, j; /* count variables */ + s4 t; + s4 s1, s2; + int disp; - M_ALD_INTERN(REG_ITMP1, REG_PV, -2 * SIZEOF_VOID_P); - M_ALD_INTERN(REG_PV, REG_PV, -3 * SIZEOF_VOID_P); - M_MTCTR(REG_PV); - M_RTS; - - md_cacheflush((u1 *) d, COMPILERSTUB_SIZE); - -#if defined(ENABLE_STATISTICS) - if (opt_stat) - count_cstub_len += COMPILERSTUB_SIZE; -#endif - - /* release dump area */ - - dump_release(dumpsize); - - return s; -} + /* Sanity check. */ + assert(f != NULL); -/* createnativestub ************************************************************ - - Creates a stub routine which calls a native method. - -*******************************************************************************/ - -u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd) -{ - methodinfo *m; - codeinfo *code; - codegendata *cd; - registerdata *rd; - methoddesc *md; - s4 nativeparams; - s4 i, j; /* count variables */ - s4 t; - s4 s1, s2, disp; - s4 funcdisp; - - /* get required compiler data */ + /* Get required compiler data. */ m = jd->m; code = jd->code; cd = jd->cd; - rd = jd->rd; /* set some variables */ md = m->parseddesc; - nativeparams = (m->flags & ACC_STATIC) ? 2 : 1; /* calculate stackframe size */ cd->stackframesize = - sizeof(stackframeinfo) / SIZEOF_VOID_P + + sizeof(stackframeinfo_t) / SIZEOF_VOID_P + sizeof(localref_table) / SIZEOF_VOID_P + - 4 + /* 4 stackframeinfo arguments (darwin)*/ - nmd->paramcount * 2 + /* assume all arguments are doubles */ + 4 + /* 4 stackframeinfo arguments (darwin) */ + nmd->paramcount + nmd->memuse; /* keep stack 16-byte aligned */ - cd->stackframesize = (cd->stackframesize + 3) & ~3; + 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, 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 code */ M_MFLR(REG_ZERO); M_AST_INTERN(REG_ZERO, REG_SP, LA_LR_OFFSET); - M_STWU(REG_SP, REG_SP, -(cd->stackframesize * 4)); + M_STWU(REG_SP, REG_SP, -(cd->stackframesize * 8)); - if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) - emit_verbosecall_enter(jd); +#if defined(ENABLE_GC_CACAO) + /* Save callee saved integer registers in stackframeinfo (GC may + need to recover them during a collection). */ - /* get function address (this must happen before the stackframeinfo) */ + disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) + + OFFSET(stackframeinfo_t, intregs); - funcdisp = dseg_add_functionptr(cd, f); - -#if !defined(WITH_STATIC_CLASSPATH) - if (f == NULL) { - codegen_addpatchref(cd, PATCHER_resolve_native_function, m, funcdisp); - - if (opt_showdisassemble) - M_NOP; - } + for (i = 0; i < INT_SAV_CNT; i++) + M_AST(abi_registers_integer_saved[i], REG_SP, disp + i * 4); #endif /* save integer and float argument registers */ - j = 0; - for (i = 0; i < md->paramcount; i++) { - t = md->paramtypes[i].type; - - if (IS_INT_LNG_TYPE(t)) { - if (!md->params[i].inmemory) { - s1 = md->params[i].regoff; - if (IS_2_WORD_TYPE(t)) { - M_IST(rd->argintregs[GET_HIGH_REG(s1)], REG_SP, LA_SIZE + 4 * 4 + j * 4); - j++; - M_IST(rd->argintregs[GET_LOW_REG(s1)], REG_SP, LA_SIZE + 4 * 4 + j * 4); - } else { - M_IST(rd->argintregs[s1], REG_SP, LA_SIZE + 4 * 4 + j * 4); - } - j++; - } - } - } + if (!md->params[i].inmemory) { + s1 = md->params[i].regoff; - for (i = 0; i < md->paramcount; i++) { - if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) { - if (!md->params[i].inmemory) { - s1 = md->params[i].regoff; - M_DST(rd->argfltregs[s1], REG_SP, LA_SIZE + 4 * 4 + j * 8); - j++; + switch (md->paramtypes[i].type) { + case TYPE_INT: + case TYPE_ADR: + M_IST(s1, REG_SP, LA_SIZE + 4*4 + i * 8); + break; + case TYPE_LNG: + M_LST(s1, REG_SP, LA_SIZE + 4*4 + i * 8); + break; + case TYPE_FLT: + case TYPE_DBL: + M_DST(s1, REG_SP, LA_SIZE + 4*4 + i * 8); + break; } } } /* create native stack info */ - M_AADD_IMM(REG_SP, cd->stackframesize * 4, REG_A0); + M_MOV(REG_SP, REG_A0); M_MOV(REG_PV, REG_A1); - M_AADD_IMM(REG_SP, cd->stackframesize * 4, REG_A2); - M_ALD(REG_A3, REG_SP, cd->stackframesize * 4 + LA_LR_OFFSET); disp = dseg_add_functionptr(cd, codegen_start_native_call); M_ALD(REG_ITMP1, REG_PV, disp); M_MTCTR(REG_ITMP1); M_JSR; - /* restore integer and float argument registers */ + /* remember class argument */ + + if (m->flags & ACC_STATIC) + M_MOV(REG_RESULT, REG_ITMP3); - j = 0; + /* restore integer and float argument registers */ for (i = 0; i < md->paramcount; i++) { - t = md->paramtypes[i].type; + if (!md->params[i].inmemory) { + s1 = md->params[i].regoff; - if (IS_INT_LNG_TYPE(t)) { - if (!md->params[i].inmemory) { - s1 = md->params[i].regoff; - - if (IS_2_WORD_TYPE(t)) { - M_ILD(rd->argintregs[GET_HIGH_REG(s1)], REG_SP, LA_SIZE + 4 * 4 + j * 4); - j++; - M_ILD(rd->argintregs[GET_LOW_REG(s1)], REG_SP, LA_SIZE + 4 * 4 + j * 4); - } else { - M_ILD(rd->argintregs[s1], REG_SP, LA_SIZE + 4 * 4 + j * 4); - } - j++; + switch (md->paramtypes[i].type) { + case TYPE_INT: + case TYPE_ADR: + M_ILD(s1, REG_SP, LA_SIZE + 4*4 + i * 8); + break; + case TYPE_LNG: + M_LLD(s1, REG_SP, LA_SIZE + 4*4 + i * 8); + break; + case TYPE_FLT: + case TYPE_DBL: + M_DLD(s1, REG_SP, LA_SIZE + 4*4 + i * 8); + break; } } } - for (i = 0; i < md->paramcount; i++) { - if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) { - if (!md->params[i].inmemory) { - s1 = md->params[i].regoff; - M_DLD(rd->argfltregs[s1], REG_SP, LA_SIZE + 4 * 4 + j * 8); - j++; - } - } - } - /* 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) { - if (IS_2_WORD_TYPE(t)) - s1 = PACK_REGS( - rd->argintregs[GET_LOW_REG(md->params[i].regoff)], - rd->argintregs[GET_HIGH_REG(md->params[i].regoff)]); - else - s1 = rd->argintregs[md->params[i].regoff]; - - if (!nmd->params[j].inmemory) { - if (IS_2_WORD_TYPE(t)) { - s2 = PACK_REGS( - rd->argintregs[GET_LOW_REG(nmd->params[j].regoff)], - rd->argintregs[GET_HIGH_REG(nmd->params[j].regoff)]); - M_LNGMOVE(s1, s2); - } else { - s2 = rd->argintregs[nmd->params[j].regoff]; - M_INTMOVE(s1, s2); - } - - } else { - s2 = nmd->params[j].regoff; - if (IS_2_WORD_TYPE(t)) - M_LST(s1, REG_SP, s2 * 4); - else - M_IST(s1, REG_SP, s2 * 4); - } + if (!md->params[i].inmemory) { + s1 = md->params[i].regoff; + s2 = nmd->params[j].regoff; - } else { - s1 = md->params[i].regoff + cd->stackframesize; - s2 = nmd->params[j].regoff; + switch (t) { + case TYPE_INT: + case TYPE_ADR: + if (!nmd->params[j].inmemory) + M_INTMOVE(s1, s2); + else + M_IST(s1, REG_SP, s2); + break; - M_ILD(REG_ITMP1, REG_SP, s1 * 4); - if (IS_2_WORD_TYPE(t)) - M_ILD(REG_ITMP2, REG_SP, s1 * 4 + 4); + case TYPE_LNG: + if (!nmd->params[j].inmemory) + M_LNGMOVE(s1, s2); + else + M_LST(s1, REG_SP, s2); + break; - M_IST(REG_ITMP1, REG_SP, s2 * 4); - if (IS_2_WORD_TYPE(t)) - M_IST(REG_ITMP2, REG_SP, s2 * 4 + 4); + case TYPE_FLT: + case TYPE_DBL: + /* We only copy spilled float arguments, as the float + argument registers keep unchanged. */ + break; } + } + else { + s1 = md->params[i].regoff + cd->stackframesize * 8; + s2 = nmd->params[j].regoff; - } else { - /* We only copy spilled float arguments, as the float - argument registers keep unchanged. */ + switch (t) { + case TYPE_INT: + case TYPE_ADR: + M_ILD(REG_ITMP1, REG_SP, s1); + M_IST(REG_ITMP1, REG_SP, s2); + break; - if (md->params[i].inmemory) { - s1 = md->params[i].regoff + cd->stackframesize; - s2 = nmd->params[j].regoff; + case TYPE_LNG: + M_LLD(REG_ITMP12_PACKED, REG_SP, s1); + M_LST(REG_ITMP12_PACKED, REG_SP, s2); + break; - if (IS_2_WORD_TYPE(t)) { - M_DLD(REG_FTMP1, REG_SP, s1 * 4); - M_DST(REG_FTMP1, REG_SP, s2 * 4); + case TYPE_FLT: + M_DLD(REG_FTMP1, REG_SP, s1); + M_FST(REG_FTMP1, REG_SP, s2); + break; - } else { - M_FLD(REG_FTMP1, REG_SP, s1 * 4); - M_FST(REG_FTMP1, REG_SP, s2 * 4); - } + case TYPE_DBL: + M_DLD(REG_FTMP1, REG_SP, s1); + M_DST(REG_FTMP1, REG_SP, s2); + break; } } } - /* put class into second argument register */ + /* Handle native Java methods. */ - if (m->flags & ACC_STATIC) { - disp = dseg_add_address(cd, m->class); - M_ALD(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_ALD(REG_A0, REG_PV, disp); + /* put env into first argument register */ + + disp = dseg_add_address(cd, _Jv_env); + M_ALD(REG_A0, REG_PV, disp); + } - /* generate the actual native call */ + /* Call the native function. */ - M_ALD(REG_ITMP3, REG_PV, funcdisp); + disp = dseg_add_functionptr(cd, f); + M_ALD(REG_ITMP3, REG_PV, disp); M_MTCTR(REG_ITMP3); M_JSR; - /* print call trace */ - - if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) - emit_verbosecall_exit(jd); - /* save return value */ - if (md->returntype.type != TYPE_VOID) { - if (IS_INT_LNG_TYPE(md->returntype.type)) { - if (IS_2_WORD_TYPE(md->returntype.type)) - M_IST(REG_RESULT2, REG_SP, LA_SIZE + 2 * 4); - M_IST(REG_RESULT, REG_SP, LA_SIZE + 1 * 4); - } - else { - if (IS_2_WORD_TYPE(md->returntype.type)) - M_DST(REG_FRESULT, REG_SP, LA_SIZE + 1 * 4); - else - M_FST(REG_FRESULT, REG_SP, LA_SIZE + 1 * 4); - } + switch (md->returntype.type) { + case TYPE_INT: + case TYPE_ADR: + M_IST(REG_RESULT, REG_SP, LA_SIZE + 2 * 4); + break; + case TYPE_LNG: + M_LST(REG_RESULT_PACKED, REG_SP, LA_SIZE + 2 * 4); + break; + case TYPE_FLT: + case TYPE_DBL: + M_DST(REG_FRESULT, REG_SP, LA_SIZE + 2 * 4); + break; + case TYPE_VOID: + break; } /* remove native stackframe info */ - M_AADD_IMM(REG_SP, cd->stackframesize * 4, REG_A0); + M_MOV(REG_SP, REG_A0); + M_MOV(REG_PV, REG_A1); disp = dseg_add_functionptr(cd, codegen_finish_native_call); M_ALD(REG_ITMP1, REG_PV, disp); M_MTCTR(REG_ITMP1); @@ -3527,23 +3025,36 @@ u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd) /* restore return value */ - if (md->returntype.type != TYPE_VOID) { - if (IS_INT_LNG_TYPE(md->returntype.type)) { - if (IS_2_WORD_TYPE(md->returntype.type)) - M_ILD(REG_RESULT2, REG_SP, LA_SIZE + 2 * 4); - M_ILD(REG_RESULT, REG_SP, LA_SIZE + 1 * 4); - } - else { - if (IS_2_WORD_TYPE(md->returntype.type)) - M_DLD(REG_FRESULT, REG_SP, LA_SIZE + 1 * 4); - else - M_FLD(REG_FRESULT, REG_SP, LA_SIZE + 1 * 4); - } + switch (md->returntype.type) { + case TYPE_INT: + case TYPE_ADR: + M_ILD(REG_RESULT, REG_SP, LA_SIZE + 2 * 4); + break; + case TYPE_LNG: + M_LLD(REG_RESULT_PACKED, REG_SP, LA_SIZE + 2 * 4); + break; + case TYPE_FLT: + case TYPE_DBL: + M_DLD(REG_FRESULT, REG_SP, LA_SIZE + 2 * 4); + break; + case TYPE_VOID: + break; } - M_ALD(REG_ITMP2_XPC, REG_SP, cd->stackframesize * 4 + LA_LR_OFFSET); +#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 + + M_ALD(REG_ITMP2_XPC, REG_SP, cd->stackframesize * 8 + LA_LR_OFFSET); M_MTLR(REG_ITMP2_XPC); - M_LDA(REG_SP, REG_SP, cd->stackframesize * 4); /* remove stackframe */ + M_LDA(REG_SP, REG_SP, cd->stackframesize * 8); /* remove stackframe */ /* check for exception */ @@ -3560,14 +3071,6 @@ u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd) M_ALD(REG_ITMP3, REG_PV, disp); M_MTCTR(REG_ITMP3); M_RTS; - - /* generate patcher stubs */ - - emit_patcher_stubs(jd); - - codegen_finish(jd); - - return code->entrypoint; }