X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fvm%2Fjit%2Farm%2Femit.c;h=f5617cd85cbc926b79e2e4d6c300c7eee1f81a93;hb=f703b1265fbfb70a3de51067803b6b211d5c5d4d;hp=c5ab738d8c1429d95b25f54ce507d1abf626d7c0;hpb=450c98e66250624d5c4bc4edee4c009a0e11c289;p=cacao.git diff --git a/src/vm/jit/arm/emit.c b/src/vm/jit/arm/emit.c index c5ab738d8..f5617cd85 100644 --- a/src/vm/jit/arm/emit.c +++ b/src/vm/jit/arm/emit.c @@ -1,9 +1,7 @@ /* src/vm/jit/arm/emit.c - Arm code emitter functions - 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,14 +20,13 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: emit.c 4398 2006-01-31 23:43:08Z twisti $ - */ #include "config.h" #include +#include #include "vm/types.h" @@ -37,21 +34,22 @@ #include "vm/jit/arm/codegen.h" -#include "mm/memory.h" +#include "mm/memory.hpp" -#if defined(ENABLE_THREADS) -# include "threads/native/lock.h" -#endif +#include "threads/lock.hpp" -#include "vm/builtin.h" #include "vm/global.h" +#include "vm/jit/abi.h" #include "vm/jit/asmpart.h" -#include "vm/jit/emit-common.h" -#include "vm/jit/jit.h" -#include "vm/jit/replace.h" +#include "vm/jit/emit-common.hpp" +#include "vm/jit/jit.hpp" +#include "vm/jit/patcher-common.hpp" +#include "vm/jit/replace.hpp" +#include "vm/jit/trace.hpp" +#include "vm/jit/trap.hpp" -#include "toolbox/logging.h" /* XXX for debugging only */ +#include "toolbox/logging.hpp" /* XXX for debugging only */ /* emit_load ******************************************************************* @@ -73,27 +71,41 @@ s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg) if (src->flags & INMEMORY) { COUNT_SPILLS; - disp = src->vv.regoff * 4; + disp = src->vv.regoff; - if (IS_FLT_DBL_TYPE(src->type)) { #if defined(ENABLE_SOFTFLOAT) - if (IS_2_WORD_TYPE(src->type)) - M_LLD(tempreg, REG_SP, disp); - else - M_ILD(tempreg, REG_SP, disp); -#else - if (IS_2_WORD_TYPE(src->type)) - M_DLD(tempreg, REG_SP, disp); - else - M_FLD(tempreg, REG_SP, disp); -#endif + switch (src->type) { + case TYPE_INT: + case TYPE_FLT: + case TYPE_ADR: + M_ILD(tempreg, REG_SP, disp); + break; + case TYPE_LNG: + case TYPE_DBL: + M_LLD(tempreg, REG_SP, disp); + break; + default: + vm_abort("emit_load: unknown type %d", src->type); } - else { - if (IS_2_WORD_TYPE(src->type)) - M_LLD(tempreg, REG_SP, disp); - else - M_ILD(tempreg, REG_SP, disp); +#else + switch (src->type) { + case TYPE_INT: + case TYPE_ADR: + M_ILD(tempreg, REG_SP, disp); + break; + case TYPE_LNG: + M_LLD(tempreg, REG_SP, disp); + break; + case TYPE_FLT: + M_FLD(tempreg, REG_SP, disp); + break; + case TYPE_DBL: + M_DLD(tempreg, REG_SP, disp); + break; + default: + vm_abort("emit_load: unknown type %d", src->type); } +#endif reg = tempreg; } @@ -125,7 +137,7 @@ s4 emit_load_low(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg) if (src->flags & INMEMORY) { COUNT_SPILLS; - disp = src->vv.regoff * 4; + disp = src->vv.regoff; #if defined(__ARMEL__) M_ILD(tempreg, REG_SP, disp); @@ -163,7 +175,7 @@ s4 emit_load_high(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg) if (src->flags & INMEMORY) { COUNT_SPILLS; - disp = src->vv.regoff * 4; + disp = src->vv.regoff; #if defined(__ARMEL__) M_ILD(tempreg, REG_SP, disp + 4); @@ -198,35 +210,40 @@ void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d) if (dst->flags & INMEMORY) { COUNT_SPILLS; - disp = dst->vv.regoff * 4; + disp = dst->vv.regoff; - if (IS_FLT_DBL_TYPE(dst->type)) { #if defined(ENABLE_SOFTFLOAT) - if (IS_2_WORD_TYPE(dst->type)) - M_LST(d, REG_SP, disp); - else - M_IST(d, REG_SP, disp); -#else - if (IS_2_WORD_TYPE(dst->type)) - M_DST(d, REG_SP, disp); - else - M_FST(d, REG_SP, disp); -#endif - } - else { - if (IS_2_WORD_TYPE(dst->type)) - M_LST(d, REG_SP, disp); - else - M_IST(d, REG_SP, disp); + switch (dst->type) { + case TYPE_INT: + case TYPE_FLT: + case TYPE_ADR: + M_IST(d, REG_SP, disp); + break; + case TYPE_LNG: + case TYPE_DBL: + M_LST(d, REG_SP, disp); + break; + default: + vm_abort("emit_store: unknown type %d", dst->type); } - } - else if (IS_LNG_TYPE(dst->type)) { -#if defined(__ARMEL__) - if (GET_HIGH_REG(dst->vv.regoff) == REG_SPLIT) - M_IST_INTERN(GET_HIGH_REG(d), REG_SP, 0 * 4); #else - if (GET_LOW_REG(dst->vv.regoff) == REG_SPLIT) - M_IST_INTERN(GET_LOW_REG(d), REG_SP, 0 * 4); + switch (dst->type) { + case TYPE_INT: + case TYPE_ADR: + M_IST(d, REG_SP, disp); + break; + case TYPE_LNG: + M_LST(d, REG_SP, disp); + break; + case TYPE_FLT: + M_FST(d, REG_SP, disp); + break; + case TYPE_DBL: + M_DST(d, REG_SP, disp); + break; + default: + vm_abort("emit_store: unknown type %d", dst->type); + } #endif } } @@ -234,20 +251,25 @@ void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d) /* emit_copy ******************************************************************* - XXX + Generates a register/memory to register/memory copy. *******************************************************************************/ -void emit_copy(jitdata *jd, instruction *iptr, varinfo *src, varinfo *dst) +void emit_copy(jitdata *jd, instruction *iptr) { - codegendata *cd; - registerdata *rd; - s4 s1, d; + codegendata *cd; + varinfo *src; + varinfo *dst; + s4 s1, d; /* get required compiler data */ cd = jd->cd; - rd = jd->rd; + + /* get source and destination variables */ + + src = VAROP(iptr->s1); + dst = VAROP(iptr->dst); /* XXX dummy call, removed me!!! */ d = codegen_reg_of_var(iptr->opc, dst, REG_ITMP1); @@ -255,6 +277,11 @@ void emit_copy(jitdata *jd, instruction *iptr, varinfo *src, varinfo *dst) if ((src->vv.regoff != dst->vv.regoff) || ((src->flags ^ dst->flags) & INMEMORY)) { + if ((src->type == TYPE_RET) || (dst->type == TYPE_RET)) { + /* emit nothing, as the value won't be used anyway */ + return; + } + /* If one of the variables resides in memory, we can eliminate the register move from/to the temporary register with the order of getting the destination register and the load. */ @@ -291,27 +318,45 @@ void emit_copy(jitdata *jd, instruction *iptr, varinfo *src, varinfo *dst) } if (s1 != d) { - if (IS_FLT_DBL_TYPE(src->type)) { #if defined(ENABLE_SOFTFLOAT) - if (IS_2_WORD_TYPE(src->type)) - M_LNGMOVE(s1, d); - else - /* XXX grrrr, wrong direction! */ - M_MOV(d, s1); -#else - if (IS_2_WORD_TYPE(src->type)) - M_DMOV(s1, d); - else - M_FMOV(s1, d); -#endif + switch (src->type) { + case TYPE_INT: + case TYPE_FLT: + case TYPE_ADR: + /* XXX grrrr, wrong direction! */ + M_MOV(d, s1); + break; + case TYPE_LNG: + case TYPE_DBL: + /* XXX grrrr, wrong direction! */ + M_MOV(GET_LOW_REG(d), GET_LOW_REG(s1)); + M_MOV(GET_HIGH_REG(d), GET_HIGH_REG(s1)); + break; + default: + vm_abort("emit_copy: unknown type %d", src->type); } - else { - if (IS_2_WORD_TYPE(src->type)) - M_LNGMOVE(s1, d); - else - /* XXX grrrr, wrong direction! */ - M_MOV(d, s1); +#else + switch (src->type) { + case TYPE_INT: + case TYPE_ADR: + /* XXX grrrr, wrong direction! */ + M_MOV(d, s1); + break; + case TYPE_LNG: + /* XXX grrrr, wrong direction! */ + M_MOV(GET_LOW_REG(d), GET_LOW_REG(s1)); + M_MOV(GET_HIGH_REG(d), GET_HIGH_REG(s1)); + break; + case TYPE_FLT: + M_FMOV(s1, d); + break; + case TYPE_DBL: + M_DMOV(s1, d); + break; + default: + vm_abort("emit_copy: unknown type %d", src->type); } +#endif } emit_store(jd, iptr, dst, d); @@ -338,291 +383,376 @@ void emit_iconst(codegendata *cd, s4 d, s4 value) } -/* emit_nullpointer_check ****************************************************** - - Emit a NullPointerException check. - -*******************************************************************************/ - -void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg) -{ - if (INSTRUCTION_MUST_CHECK(iptr)) { - M_TST(reg, reg); - M_BEQ(0); - codegen_add_nullpointerexception_ref(cd); - } -} - - -/* emit_arrayindexoutofbounds_check ******************************************** - - Emit a ArrayIndexOutOfBoundsException check. - -*******************************************************************************/ - -void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1, s4 s2) +/** + * Emits code updating the condition register by comparing one integer + * register to an immediate integer value. + */ +void emit_icmp_imm(codegendata* cd, int reg, int32_t value) { - if (INSTRUCTION_MUST_CHECK(iptr)) { - M_ILD_INTERN(REG_ITMP3, s1, OFFSET(java_arrayheader, size)); - M_CMP(s2, REG_ITMP3); - M_BHS(0); - codegen_add_arrayindexoutofboundsexception_ref(cd, s2); + int32_t disp; + + if (IS_IMM(value)) { + M_CMP_IMM(reg, value); + } else if (IS_IMM(-value)) { + M_CMN_IMM(reg, -value); + } else { + assert(reg != REG_ITMP3); + disp = dseg_add_s4(cd, value); + M_DSEG_LOAD(REG_ITMP3, disp); + M_CMP(reg, REG_ITMP3); } } -/* emit_exception_stubs ******************************************************** +/* emit_branch ***************************************************************** - Generates the code for the exception stubs. + Emits the code for conditional and unconditional branchs. *******************************************************************************/ -void emit_exception_stubs(jitdata *jd) +void emit_branch(codegendata *cd, s4 disp, s4 condition, s4 reg, u4 opt) { - codegendata *cd; - registerdata *rd; - exceptionref *er; - s4 branchmpc; - s4 targetmpc; - s4 targetdisp; - s4 disp; + s4 checkdisp; + s4 branchdisp; - /* get required compiler data */ + /* calculate the different displacements */ - cd = jd->cd; - rd = jd->rd; + checkdisp = (disp - 8); + branchdisp = (disp - 8) >> 2; - /* generate exception stubs */ + /* check which branch to generate */ - targetdisp = 0; + if (condition == BRANCH_UNCONDITIONAL) { + /* check displacement for overflow */ - for (er = cd->exceptionrefs; er != NULL; er = er->next) { - /* back-patch the branch to this exception code */ + if ((checkdisp < (s4) 0xff000000) || (checkdisp > (s4) 0x00ffffff)) { + /* if the long-branches flag isn't set yet, do it */ - branchmpc = er->branchpos; - targetmpc = cd->mcodeptr - cd->mcodebase; + if (!CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) { + cd->flags |= (CODEGENDATA_FLAG_ERROR | + CODEGENDATA_FLAG_LONGBRANCHES); + } - md_codegen_patch_branch(cd, branchmpc, targetmpc); + vm_abort("emit_branch: emit unconditional long-branch code"); + } + else { + M_B(branchdisp); + } + } + else { + /* and displacement for overflow */ - MCODECHECK(100); + if ((checkdisp < (s4) 0xff000000) || (checkdisp > (s4) 0x00ffffff)) { + /* if the long-branches flag isn't set yet, do it */ - /* Check if the exception is an - ArrayIndexOutOfBoundsException. If so, move index register - into REG_ITMP1. */ + if (!CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) { + cd->flags |= (CODEGENDATA_FLAG_ERROR | + CODEGENDATA_FLAG_LONGBRANCHES); + } - if (er->reg != -1) - M_MOV(REG_ITMP1, er->reg); + vm_abort("emit_branch: emit conditional long-branch code"); + } + else { + switch (condition) { + case BRANCH_EQ: + M_BEQ(branchdisp); + break; + case BRANCH_NE: + M_BNE(branchdisp); + break; + case BRANCH_LT: + M_BLT(branchdisp); + break; + case BRANCH_GE: + M_BGE(branchdisp); + break; + case BRANCH_GT: + M_BGT(branchdisp); + break; + case BRANCH_LE: + M_BLE(branchdisp); + break; + case BRANCH_UGT: + M_BHI(branchdisp); + break; + default: + vm_abort("emit_branch: unknown condition %d", condition); + } + } + } +} - /* calcuate exception address */ - assert((er->branchpos - 4) % 4 == 0); - M_ADD_IMM_EXT_MUL4(REG_ITMP2_XPC, REG_PV, (er->branchpos - 4) / 4); +/* emit_arithmetic_check ******************************************************* - /* move function to call into REG_ITMP3 */ + Emit an ArithmeticException check. - disp = dseg_add_functionptr(cd, er->function); - M_DSEG_LOAD(REG_ITMP3, disp); +*******************************************************************************/ - if (targetdisp == 0) { - targetdisp = ((u4 *) cd->mcodeptr) - ((u4 *) cd->mcodebase); +void emit_arithmetic_check(codegendata *cd, instruction *iptr, s4 reg) +{ + if (INSTRUCTION_MUST_CHECK(iptr)) { + CHECK_INT_REG(reg); + M_TEQ_IMM(reg, 0); + M_TRAPEQ(0, TRAP_ArithmeticException); + } +} - M_MOV(rd->argintregs[0], REG_PV); - M_MOV(rd->argintregs[1], REG_SP); - if (jd->isleafmethod) - M_MOV(rd->argintregs[2], REG_LR); - else - M_LDR(rd->argintregs[2], REG_SP, - cd->stackframesize * 4 - SIZEOF_VOID_P); +/* emit_nullpointer_check ****************************************************** - M_MOV(rd->argintregs[3], REG_ITMP2_XPC); + Emit a NullPointerException check. - /* save registers */ - /* TODO: we only need to save LR in leaf methods */ +*******************************************************************************/ - M_STMFD(BITMASK_ARGS | 1<mcodebase) + targetdisp) - - (((u4 *) cd->mcodeptr) + 2); +*******************************************************************************/ - M_B(disp); - } +void emit_arraystore_check(codegendata *cd, instruction *iptr) +{ + if (INSTRUCTION_MUST_CHECK(iptr)) { + M_TST(REG_RESULT, REG_RESULT); + M_TRAPEQ(0, TRAP_ArrayStoreException); } } -/* emit_patcher_stubs ********************************************************** +/* emit_classcast_check ******************************************************** - Generates the code for the patcher stubs. + Emit a ClassCastException check. *******************************************************************************/ -void emit_patcher_stubs(jitdata *jd) +void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 reg, s4 s1) { - codegendata *cd; - patchref *pref; - u4 mcode; - u1 *savedmcodeptr; - u1 *tmpmcodeptr; - s4 targetdisp; - s4 disp; + if (INSTRUCTION_MUST_CHECK(iptr)) { + switch (condition) { + case BRANCH_EQ: + M_TRAPEQ(s1, TRAP_ClassCastException); + break; - /* get required compiler data */ + case BRANCH_NE: + M_TRAPNE(s1, TRAP_ClassCastException); + break; - cd = jd->cd; + case BRANCH_LT: + M_TRAPLT(s1, TRAP_ClassCastException); + break; - /* generate patcher stub call code */ + case BRANCH_LE: + M_TRAPLE(s1, TRAP_ClassCastException); + break; - targetdisp = 0; + case BRANCH_UGT: + M_TRAPHI(s1, TRAP_ClassCastException); + break; - for (pref = cd->patchrefs; pref != NULL; pref = pref->next) { - /* check code segment size */ - - MCODECHECK(100); + default: + vm_abort("emit_classcast_check: unknown condition %d", condition); + } + } +} - /* Get machine code which is patched back in later. The - call is 1 instruction word long. */ +/* emit_exception_check ******************************************************** - tmpmcodeptr = (u1 *) (cd->mcodebase + pref->branchpos); + Emit an Exception check. - mcode = *((u4 *) tmpmcodeptr); +*******************************************************************************/ - /* Patch in the call to call the following code (done at - compile time). */ +void emit_exception_check(codegendata *cd, instruction *iptr) +{ + if (INSTRUCTION_MUST_CHECK(iptr)) { + M_TST(REG_RESULT, REG_RESULT); + M_TRAPEQ(0, TRAP_CHECK_EXCEPTION); + } +} - savedmcodeptr = cd->mcodeptr; /* save current mcodeptr */ - cd->mcodeptr = tmpmcodeptr; /* set mcodeptr to patch position */ - disp = ((u4 *) savedmcodeptr) - (((u4 *) tmpmcodeptr) + 2); - M_B(disp); +/* emit_trap_compiler ********************************************************** - cd->mcodeptr = savedmcodeptr; /* restore the current mcodeptr */ + Emit a trap instruction which calls the JIT compiler. - /* create stack frame (align stack to 8-byte) */ +*******************************************************************************/ - M_SUB_IMM(REG_SP, REG_SP, 8 * 4); +void emit_trap_compiler(codegendata *cd) +{ + M_TRAP(REG_METHODPTR, TRAP_COMPILER); +} - /* save itmp3 onto stack */ - M_STR_INTERN(REG_ITMP3, REG_SP, 6 * 4); +/* emit_trap ******************************************************************* - /* calculate return address and move it onto stack */ - /* ATTENTION: we can not use BL to branch to patcher stub, */ - /* ATTENTION: because we need to preserve LR for leaf methods */ + Emit a trap instruction and return the original machine code. - disp = (s4) (((u4 *) cd->mcodeptr) - (((u4 *) tmpmcodeptr) + 1) + 2); +*******************************************************************************/ - M_SUB_IMM_EXT_MUL4(REG_ITMP3, REG_PC, disp); - M_STR_INTERN(REG_ITMP3, REG_SP, 4 * 4); +uint32_t emit_trap(codegendata *cd) +{ + uint32_t mcode; - /* move pointer to java_objectheader onto stack */ + /* Get machine code which is patched back in later. The + trap is 1 instruction word long. */ -#if defined(ENABLE_THREADS) - /* order reversed because of data segment layout */ + mcode = *((uint32_t *) cd->mcodeptr); - (void) dseg_add_unique_address(cd, NULL); /* flcword */ - (void) dseg_add_unique_address(cd, lock_get_initial_lock_word()); - disp = dseg_add_unique_address(cd, NULL); /* vftbl */ + M_TRAP(0, TRAP_PATCHER); - M_SUB_IMM_EXT_MUL4(REG_ITMP3, REG_PV, -disp / 4); - M_STR_INTERN(REG_ITMP3, REG_SP, 3 * 4); -#else - M_EOR(REG_ITMP3, REG_ITMP3, REG_ITMP3); - M_STR_INTERN(REG_ITMP3, REG_SP, 3 * 4); -#endif + return mcode; +} - /* move machine code onto stack */ - disp = dseg_add_unique_s4(cd, mcode); - M_DSEG_LOAD(REG_ITMP3, disp); - M_STR_INTERN(REG_ITMP3, REG_SP, 2 * 4); +/** + * Emit code to recompute the procedure vector. + */ +void emit_recompute_pv(codegendata *cd) +{ + // This is used to recompute our PV (we use the IP for this) out + // of the current PC. + int32_t disp = (int32_t) (cd->mcodeptr - cd->mcodebase); + + // We use PC relative addressing. + disp += 8; + + // Sanity checks. + assert((disp & 0x03) == 0); + assert(disp >= 0 && disp <= 0x03ffffff); + + // ATTENTION: If you change this, you have to look at other functions + // as well! Following things depend on it: md_codegen_get_pv_from_pc(); + if (disp > 0x0003ffff) { + M_SUB_IMM(REG_PV, REG_PC, IMM_ROTL(disp >> 18, 9)); + M_SUB_IMM(REG_PV, REG_PV, IMM_ROTL(disp >> 10, 5)); + M_SUB_IMM(REG_PV, REG_PV, IMM_ROTL(disp >> 2, 1)); + } else if (disp > 0x000003ff) { + M_SUB_IMM(REG_PV, REG_PC, IMM_ROTL(disp >> 10, 5)); + M_SUB_IMM(REG_PV, REG_PV, IMM_ROTL(disp >> 2, 1)); + } else { + M_SUB_IMM(REG_PV, REG_PC, IMM_ROTL(disp >> 2, 1)); + } +} - /* move class/method/field reference onto stack */ - disp = dseg_add_unique_address(cd, pref->ref); - M_DSEG_LOAD(REG_ITMP3, disp); - M_STR_INTERN(REG_ITMP3, REG_SP, 1 * 4); +/** + * Generates synchronization code to enter a monitor. + */ +#if defined(ENABLE_THREADS) +void emit_monitor_enter(jitdata* jd, int32_t syncslot_offset) +{ + int32_t disp; - /* move data segment displacement onto stack */ + // Get required compiler data. + methodinfo* m = jd->m; + codegendata* cd = jd->cd; - disp = dseg_add_unique_s4(cd, pref->disp); - M_DSEG_LOAD(REG_ITMP3, disp); - M_STR_INTERN(REG_ITMP3, REG_SP, 5 * 4); +# if !defined(NDEBUG) + if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) { + M_STMFD(BITMASK_ARGS, REG_SP); + syncslot_offset += 4 * 4; + } +# endif - /* move patcher function pointer onto stack */ + /* get the correct lock object */ - disp = dseg_add_functionptr(cd, pref->patcher); - M_DSEG_LOAD(REG_ITMP3, disp); - M_STR_INTERN(REG_ITMP3, REG_SP, 0 * 4); + if (m->flags & ACC_STATIC) { + disp = dseg_add_address(cd, &m->clazz->object.header); + M_DSEG_LOAD(REG_A0, disp); + } + else { + emit_nullpointer_check_force(cd, NULL, REG_A0); + } - /* finally call the patcher via asm_patcher_wrapper */ - /* ATTENTION: don't use REG_PV here, because some patchers need it */ + M_STR(REG_A0, REG_SP, syncslot_offset); + disp = dseg_add_functionptr(cd, LOCK_monitor_enter); + M_DSEG_BRANCH(disp); + emit_recompute_pv(cd); - if (targetdisp == 0) { - targetdisp = ((u4 *) cd->mcodeptr) - ((u4 *) cd->mcodebase); +# if !defined(NDEBUG) + if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) + M_LDMFD(BITMASK_ARGS, REG_SP); +# endif +} +#endif - disp = dseg_add_functionptr(cd, asm_patcher_wrapper); - /*M_DSEG_BRANCH_NOLINK(REG_PC, REG_PV, a);*/ - /* TODO: this is only a hack */ - M_DSEG_LOAD(REG_ITMP3, disp); - M_MOV(REG_PC, REG_ITMP3); - } - else { - disp = (((u4 *) cd->mcodebase) + targetdisp) - - (((u4 *) cd->mcodeptr) + 2); - M_B(disp); - } - } -} +/** + * Generates synchronization code to leave a monitor. + */ +#if defined(ENABLE_THREADS) +void emit_monitor_exit(jitdata* jd, int32_t syncslot_offset) +{ + int32_t disp; + // Get required compiler data. + methodinfo* m = jd->m; + codegendata* cd = jd->cd; -/* emit_replacement_stubs ****************************************************** + /* we need to save the proper return value */ - Generates the code for the replacement stubs. + methoddesc* md = m->parseddesc; -*******************************************************************************/ + switch (md->returntype.type) { + case TYPE_INT: + case TYPE_ADR: + case TYPE_LNG: + case TYPE_FLT: /* XXX TWISTI: is that correct? */ + case TYPE_DBL: + M_STMFD(BITMASK_RESULT, REG_SP); + syncslot_offset += 2 * 4; + break; + } -#if defined(ENABLE_REPLACEMENT) -void emit_replacement_stubs(jitdata *jd) -{ - codegendata *cd; - codeinfo *code; - rplpoint *rplp; - u1 *savedmcodeptr; - s4 disp; - s4 i; + M_LDR(REG_A0, REG_SP, syncslot_offset); + disp = dseg_add_functionptr(cd, LOCK_monitor_exit); + M_DSEG_BRANCH(disp); - /* get required compiler data */ + /* we no longer need PV here, no more loading */ + /*emit_recompute_pv(cd);*/ - cd = jd->cd; - code = jd->code; + switch (md->returntype.type) { + case TYPE_INT: + case TYPE_ADR: + case TYPE_LNG: + case TYPE_FLT: /* XXX TWISTI: is that correct? */ + case TYPE_DBL: + M_LDMFD(BITMASK_RESULT, REG_SP); + break; + } } -#endif /* defined(ENABLE_REPLACEMENT) */ +#endif /* emit_verbosecall_enter ****************************************************** @@ -638,9 +768,8 @@ void emit_verbosecall_enter(jitdata *jd) codegendata *cd; registerdata *rd; methoddesc *md; - s4 stackframesize; s4 disp; - s4 i, t, s1, s2; + s4 i, s; /* get required compiler data */ @@ -650,86 +779,65 @@ void emit_verbosecall_enter(jitdata *jd) md = m->parseddesc; - /* stackframesize is changed below */ - - stackframesize = cd->stackframesize; - /* mark trace code */ M_NOP; - /* Save argument registers to stack (including LR and PV). Keep - stack 8-byte aligned. */ - - M_STMFD(BITMASK_ARGS | (1<paramcount - 1; - - if (i > 3) - i = 3; + /* Keep stack 8-byte aligned. */ - for (; i >= 0; i--) { - t = md->paramtypes[i].type; + M_STMFD((1<paramcount * 8); - /* load argument into register (s1) and make it of TYPE_LNG */ + /* save argument registers */ + for (i = 0; i < md->paramcount; i++) { if (!md->params[i].inmemory) { - s1 = md->params[i].regoff; - - if (!IS_2_WORD_TYPE(t)) { - M_MOV_IMM(REG_ITMP1, 0); - s1 = PACK_REGS(s1, REG_ITMP1); + s = md->params[i].regoff; + + switch (md->paramtypes[i].type) { + case TYPE_INT: + case TYPE_FLT: + case TYPE_ADR: + M_IST(s, REG_SP, i * 8); + break; + case TYPE_LNG: + case TYPE_DBL: + M_LST(s, REG_SP, i * 8); + break; } - else { - SPLIT_OPEN(t, s1, REG_ITMP1); - SPLIT_LOAD(t, s1, stackframesize); - } - } - else { - s1 = md->params[i].regoff + stackframesize; - - if (IS_2_WORD_TYPE(t)) - M_LLD(REG_ITMP12_PACKED, REG_SP, s1 * 4); - else - M_ILD(REG_ITMP1, REG_SP, s1 * 4); - } - - /* place argument for tracer */ - - if (i < 2) { -#if defined(__ARMEL__) - s2 = PACK_REGS(rd->argintregs[i * 2], rd->argintregs[i * 2 + 1]); -#else /* defined(__ARMEB__) */ - s2 = PACK_REGS(rd->argintregs[i * 2 + 1], rd->argintregs[i * 2]); -#endif - M_LNGMOVE(s1, s2); - } - else { - s2 = (i - 2) * 2; - M_LST(s1, REG_SP, s2 * 4); } } - /* prepare methodinfo pointer for tracer */ - disp = dseg_add_address(cd, m); - M_DSEG_LOAD(REG_ITMP1, disp); - M_STR_INTERN(REG_ITMP1, REG_SP, 16); + M_DSEG_LOAD(REG_A0, disp); + M_MOV(REG_A1, REG_SP); + M_ADD_IMM(REG_A2, REG_SP, md->paramcount * 8 + 2 * 4 + cd->stackframesize * 8); + M_LONGBRANCH(trace_java_call_enter); - /* call tracer here (we use a long branch) */ + /* restore argument registers */ - M_LONGBRANCH(builtin_verbosecall_enter); + for (i = 0; i < md->paramcount; i++) { + if (!md->params[i].inmemory) { + s = md->params[i].regoff; + + switch (md->paramtypes[i].type) { + case TYPE_INT: + case TYPE_FLT: + case TYPE_ADR: + M_ILD(s, REG_SP, i * 8); + break; + case TYPE_LNG: + case TYPE_DBL: + M_LLD(s, REG_SP, i * 8); + break; + } + } + } - /* Restore argument registers from stack. Keep stack 8-byte - aligned. */ + /* Keep stack 8-byte aligned. */ - M_ADD_IMM(REG_SP, REG_SP, (2 + 2 + 1 + 1) * 4); /* free argument stack */ - M_LDMFD(BITMASK_ARGS | (1<paramcount * 8); + M_LDMFD((1<returntype.type) { case TYPE_ADR: case TYPE_INT: - M_INTMOVE(REG_RESULT, GET_LOW_REG(REG_A0_A1_PACKED)); - M_MOV_IMM(GET_HIGH_REG(REG_A0_A1_PACKED), 0); + case TYPE_FLT: + M_IST(REG_RESULT, REG_SP, 0 * 8); break; - case TYPE_LNG: - M_LNGMOVE(REG_RESULT_PACKED, REG_A0_A1_PACKED); + case TYPE_DBL: + M_LST(REG_RESULT_PACKED, REG_SP, 0 * 8); break; + } + + disp = dseg_add_address(cd, m); + M_DSEG_LOAD(REG_A0, disp); + M_MOV(REG_A1, REG_SP); + M_LONGBRANCH(trace_java_call_exit); + /* restore return value */ + + switch (md->returntype.type) { + case TYPE_ADR: + case TYPE_INT: case TYPE_FLT: - M_IST(REG_RESULT, REG_SP, 0 * 4); + M_ILD(REG_RESULT, REG_SP, 0 * 8); break; - + case TYPE_LNG: case TYPE_DBL: - M_LNGMOVE(REG_RESULT_PACKED, REG_A2_A3_PACKED); + M_LLD(REG_RESULT_PACKED, REG_SP, 0 * 8); break; } - disp = dseg_add_address(cd, m); - M_DSEG_LOAD(REG_ITMP1, disp); - M_AST(REG_ITMP1, REG_SP, 1 * 4); - M_LONGBRANCH(builtin_verbosecall_exit); - /* Keep stack 8-byte aligned. */ - M_ADD_IMM(REG_SP, REG_SP, (1 + 1) * 4); /* free argument stack */ - M_LDMFD(BITMASK_RESULT | (1<