X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fvm%2Fjit%2Fx86_64%2Femit.c;h=7a4c65a39d20537e2ec1d99604208695a9634156;hb=d1377204f560df4d6656f58914bc4d242193c5e0;hp=79cd94dd6a422ba7c1912202379bf55a18f68b8b;hpb=613437b7e5cef331a409663733b2bd06400a54ac;p=cacao.git diff --git a/src/vm/jit/x86_64/emit.c b/src/vm/jit/x86_64/emit.c index 79cd94dd6..7a4c65a39 100644 --- a/src/vm/jit/x86_64/emit.c +++ b/src/vm/jit/x86_64/emit.c @@ -233,6 +233,16 @@ void emit_cmovxx(codegendata *cd, instruction *iptr, s4 s, s4 d) } +/** + * 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) +{ + M_ICMP_IMM(value, reg); +} + + /* emit_branch ***************************************************************** Emits the code for conditional and unconditional branchs. @@ -424,6 +434,19 @@ void emit_trap_compiler(codegendata *cd) } +/* emit_patcher_alignment ****************************************************** + + Emit NOP to ensure placement at an even address. + +*******************************************************************************/ + +void emit_patcher_alignment(codegendata *cd) +{ + if ((uintptr_t) cd->mcodeptr & 1) + M_NOP; +} + + /* emit_trap ******************************************************************* Emit a trap instruction and return the original machine code. @@ -448,6 +471,207 @@ uint32_t emit_trap(codegendata *cd) } +/** + * Generates fast-path code for the below builtin. + * Function: LOCK_monitor_enter + * Signature: (Ljava/lang/Object;)V + * Slow-path: bool lock_monitor_enter(java_handle_t*); + */ +void emit_fastpath_monitor_enter(jitdata* jd, instruction* iptr, int d) +{ + // Get required compiler data. + codegendata* cd = jd->cd; + + // XXX Currently the fast-path always fails. Implement me! + M_CLR(d); +} + + +/** + * Generates fast-path code for the below builtin. + * Function: LOCK_monitor_exit + * Signature: (Ljava/lang/Object;)V + * Slow-path: bool lock_monitor_exit(java_handle_t*); + */ +void emit_fastpath_monitor_exit(jitdata* jd, instruction* iptr, int d) +{ + // Get required compiler data. + codegendata* cd = jd->cd; + + // XXX Currently the fast-path always fails. Implement me! + M_CLR(d); +} + + +/** + * Generates synchronization code to enter a monitor. + */ +#if defined(ENABLE_THREADS) +void emit_monitor_enter(jitdata* jd, int32_t syncslot_offset) +{ + int32_t p; + + // Get required compiler data. + methodinfo* m = jd->m; + codegendata* cd = jd->cd; + +# if !defined(NDEBUG) + if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) { + M_LSUB_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP); + + for (p = 0; p < INT_ARG_CNT; p++) + M_LST(abi_registers_integer_argument[p], REG_SP, p * 8); + + for (p = 0; p < FLT_ARG_CNT; p++) + M_DST(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8); + + syncslot_offset += (INT_ARG_CNT + FLT_ARG_CNT) * 8; + } +# endif + + /* decide which monitor enter function to call */ + + if (m->flags & ACC_STATIC) { + M_MOV_IMM(&m->clazz->object.header, REG_A0); + } + else { + M_TEST(REG_A0); + M_BNE(8); + M_ALD_MEM(REG_A0, TRAP_NullPointerException); + } + + M_AST(REG_A0, REG_SP, syncslot_offset); + M_MOV_IMM(LOCK_monitor_enter, REG_ITMP1); + M_CALL(REG_ITMP1); + +# if !defined(NDEBUG) + if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) { + + for (p = 0; p < INT_ARG_CNT; p++) + M_LLD(abi_registers_integer_argument[p], REG_SP, p * 8); + + for (p = 0; p < FLT_ARG_CNT; p++) + M_DLD(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8); + + M_LADD_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP); + } +# endif +} +#endif + + +/** + * Generates synchronization code to leave a monitor. + */ +#if defined(ENABLE_THREADS) +void emit_monitor_exit(jitdata* jd, int32_t syncslot_offset) +{ + // Get required compiler data. + methodinfo* m = jd->m; + codegendata* cd = jd->cd; + + M_ALD(REG_A0, REG_SP, syncslot_offset); + + /* we need to save the proper return value */ + + methoddesc* md = m->parseddesc; + + switch (md->returntype.type) { + case TYPE_INT: + case TYPE_ADR: + case TYPE_LNG: + M_LST(REG_RESULT, REG_SP, syncslot_offset); + break; + case TYPE_FLT: + case TYPE_DBL: + M_DST(REG_FRESULT, REG_SP, syncslot_offset); + break; + } + + M_MOV_IMM(LOCK_monitor_exit, REG_ITMP1); + M_CALL(REG_ITMP1); + + /* and now restore the proper return value */ + + switch (md->returntype.type) { + case TYPE_INT: + case TYPE_ADR: + case TYPE_LNG: + M_LLD(REG_RESULT, REG_SP, syncslot_offset); + break; + case TYPE_FLT: + case TYPE_DBL: + M_DLD(REG_FRESULT, REG_SP, syncslot_offset); + break; + } +} +#endif + + +/** + * Emit profiling code for method frequency counting. + */ +#if defined(ENABLE_PROFILING) +void emit_profile_method(codegendata* cd, codeinfo* code) +{ + M_MOV_IMM(code, REG_ITMP3); + M_IINC_MEMBASE(REG_ITMP3, OFFSET(codeinfo, frequency)); +} +#endif + + +/** + * Emit profiling code for basicblock frequency counting. + */ +#if defined(ENABLE_PROFILING) +void emit_profile_basicblock(codegendata* cd, codeinfo* code, basicblock* bptr) +{ + M_MOV_IMM(code->bbfrequency, REG_ITMP3); + M_IINC_MEMBASE(REG_ITMP3, bptr->nr * 4); +} +#endif + + +/** + * Emit profiling code to start CPU cycle counting. + */ +#if defined(ENABLE_PROFILING) +void emit_profile_cycle_start(codegendata* cd, codeinfo* code) +{ + M_PUSH(RAX); + M_PUSH(RDX); + + M_MOV_IMM(code, REG_ITMP3); + M_RDTSC; + M_ISUB_MEMBASE(RAX, REG_ITMP3, OFFSET(codeinfo, cycles)); + M_ISBB_MEMBASE(RDX, REG_ITMP3, OFFSET(codeinfo, cycles) + 4); + + M_POP(RDX); + M_POP(RAX); +} +#endif + + +/** + * Emit profiling code to stop CPU cycle counting. + */ +#if defined(ENABLE_PROFILING) +void emit_profile_cycle_stop(codegendata* cd, codeinfo* code) +{ + M_PUSH(RAX); + M_PUSH(RDX); + + M_MOV_IMM(code, REG_ITMP3); + M_RDTSC; + M_IADD_MEMBASE(RAX, REG_ITMP3, OFFSET(codeinfo, cycles)); + M_IADC_MEMBASE(RDX, REG_ITMP3, OFFSET(codeinfo, cycles) + 4); + + M_POP(RDX); + M_POP(RAX); +} +#endif + + /* emit_verbosecall_enter ****************************************************** Generates the code for the call trace. @@ -981,6 +1205,76 @@ void emit_lshift(jitdata *jd, s4 shift_op, instruction *iptr) /* low-level code emitter functions *******************************************/ +void emit_nop(codegendata *cd, int length) +{ + assert(length >= 1 && length <= 9); + switch (length) { + case 1: + *(cd->mcodeptr++) = 0x90; + break; + case 2: + *(cd->mcodeptr++) = 0x66; + *(cd->mcodeptr++) = 0x90; + break; + case 3: + *(cd->mcodeptr++) = 0x0f; + *(cd->mcodeptr++) = 0x1f; + *(cd->mcodeptr++) = 0x00; + break; + case 4: + *(cd->mcodeptr++) = 0x0f; + *(cd->mcodeptr++) = 0x1f; + *(cd->mcodeptr++) = 0x40; + *(cd->mcodeptr++) = 0x00; + break; + case 5: + *(cd->mcodeptr++) = 0x0f; + *(cd->mcodeptr++) = 0x1f; + *(cd->mcodeptr++) = 0x44; + *(cd->mcodeptr++) = 0x00; + *(cd->mcodeptr++) = 0x00; + break; + case 6: + *(cd->mcodeptr++) = 0x66; + *(cd->mcodeptr++) = 0x0f; + *(cd->mcodeptr++) = 0x1f; + *(cd->mcodeptr++) = 0x44; + *(cd->mcodeptr++) = 0x00; + *(cd->mcodeptr++) = 0x00; + break; + case 7: + *(cd->mcodeptr++) = 0x0f; + *(cd->mcodeptr++) = 0x1f; + *(cd->mcodeptr++) = 0x80; + *(cd->mcodeptr++) = 0x00; + *(cd->mcodeptr++) = 0x00; + *(cd->mcodeptr++) = 0x00; + *(cd->mcodeptr++) = 0x00; + break; + case 8: + *(cd->mcodeptr++) = 0x0f; + *(cd->mcodeptr++) = 0x1f; + *(cd->mcodeptr++) = 0x84; + *(cd->mcodeptr++) = 0x00; + *(cd->mcodeptr++) = 0x00; + *(cd->mcodeptr++) = 0x00; + *(cd->mcodeptr++) = 0x00; + *(cd->mcodeptr++) = 0x00; + break; + case 9: + *(cd->mcodeptr++) = 0x66; + *(cd->mcodeptr++) = 0x0f; + *(cd->mcodeptr++) = 0x1f; + *(cd->mcodeptr++) = 0x84; + *(cd->mcodeptr++) = 0x00; + *(cd->mcodeptr++) = 0x00; + *(cd->mcodeptr++) = 0x00; + *(cd->mcodeptr++) = 0x00; + *(cd->mcodeptr++) = 0x00; + break; + } +} + void emit_mov_reg_reg(codegendata *cd, s8 reg, s8 dreg) { emit_rex(1,(reg),0,(dreg)); @@ -2349,6 +2643,13 @@ void emit_rdtsc(codegendata *cd) *(cd->mcodeptr++) = 0x31; } +void emit_mfence(codegendata *cd) +{ + *(cd->mcodeptr++) = 0x0f; + *(cd->mcodeptr++) = 0xae; + *(cd->mcodeptr++) = 0xf0; +} + /* * These are local overrides for various environment variables in Emacs. @@ -2361,4 +2662,5 @@ void emit_rdtsc(codegendata *cd) * c-basic-offset: 4 * tab-width: 4 * End: + * vim:noexpandtab:sw=4:ts=4: */