X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Ftramp-arm.c;h=2872b1c13329feaaa1dc433d66be3f3a6883c1a3;hb=580ccb1ffb8e5c2e3fa0555e342d916764f42930;hp=5ff7bbfdfc8309b5105e0052c8b39dc1199e92b4;hpb=3e81958f1dd4cecb97167c5b3cb5541bda31c444;p=mono.git diff --git a/mono/mini/tramp-arm.c b/mono/mini/tramp-arm.c index 5ff7bbfdfc8..2872b1c1332 100644 --- a/mono/mini/tramp-arm.c +++ b/mono/mini/tramp-arm.c @@ -1,5 +1,6 @@ -/* - * tramp-arm.c: JIT trampoline code for ARM +/** + * \file + * JIT trampoline code for ARM * * Authors: * Paolo Molaro (lupus@ximian.com) @@ -28,52 +29,6 @@ #define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1)) -#ifdef USE_JUMP_TABLES - -static guint16 -decode_imm16 (guint32 insn) -{ - return (((insn >> 16) & 0xf) << 12) | (insn & 0xfff); -} - -#define INSN_MASK 0xff00000 -#define MOVW_MASK ((3 << 24) | (0 << 20)) -#define MOVT_MASK ((3 << 24) | (4 << 20)) - -gpointer* -mono_arch_jumptable_entry_from_code (guint8 *code) -{ - guint32 insn1 = ((guint32*)code) [0]; - guint32 insn2 = ((guint32*)code) [1]; - - if (((insn1 & INSN_MASK) == MOVW_MASK) && - ((insn2 & INSN_MASK) == MOVT_MASK) ) { - guint32 imm_lo = decode_imm16 (insn1); - guint32 imm_hi = decode_imm16 (insn2); - return (gpointer*) GUINT_TO_POINTER (imm_lo | (imm_hi << 16)); - } else { - g_assert_not_reached (); - return NULL; - } -} - -#undef INSN_MASK -#undef MOVW_MASK -#undef MOVT_MASK - -void -mono_arch_patch_callsite (guint8 *method_start, guint8 *code_ptr, guint8 *addr) -{ - gpointer *jte; - /* - * code_ptr is 4 instructions after MOVW/MOVT used to address - * jumptable entry. - */ - jte = mono_jumptable_get_entry (code_ptr - 16); - g_assert ( jte != NULL); - *jte = addr; -} -#else void mono_arch_patch_callsite (guint8 *method_start, guint8 *code_ptr, guint8 *addr) { @@ -101,7 +56,6 @@ mono_arch_patch_callsite (guint8 *method_start, guint8 *code_ptr, guint8 *addr) g_assert_not_reached (); } -#endif void mono_arch_patch_plt_entry (guint8 *code, gpointer *got, mgreg_t *regs, guint8 *addr) @@ -131,11 +85,17 @@ mono_arch_patch_plt_entry (guint8 *code, gpointer *got, mgreg_t *regs, guint8 *a *(guint8**)jump_entry = addr; } +gpointer +mono_arm_handler_block_trampoline_helper (gpointer *ptr) +{ + MonoJitTlsData *jit_tls = mono_tls_get_jit_tls (); + return jit_tls->handler_block_return_address; +} + #ifndef DISABLE_JIT #define arm_is_imm12(v) ((int)(v) > -4096 && (int)(v) < 4096) -#ifndef USE_JUMP_TABLES /* * Return the instruction to jump from code to target, 0 if not * reachable with a single instruction @@ -155,7 +115,6 @@ branch_for_target_reachable (guint8 *branch, guint8 *target) } return 0; } -#endif static inline guint8* emit_bx (guint8* code, int reg) @@ -182,21 +141,13 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf { char *tramp_name; guint8 *buf, *code = NULL; -#ifdef USE_JUMP_TABLES - gpointer *load_get_lmf_addr = NULL, *load_trampoline = NULL; -#else guint8 *load_get_lmf_addr = NULL, *load_trampoline = NULL; gpointer *constants; -#endif int i, cfa_offset, regsave_size, lr_offset; GSList *unwind_ops = NULL; MonoJumpInfo *ji = NULL; int buf_len; -#ifdef USE_JUMP_TABLES - g_assert (!aot); -#endif - /* Now we'll create in 'buf' the ARM trampoline code. This is the trampoline code common to all methods */ @@ -272,13 +223,8 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf code += 4; ARM_LDR_REG_REG (code, ARMREG_R0, ARMREG_PC, ARMREG_R0); } else { -#ifdef USE_JUMP_TABLES - load_get_lmf_addr = mono_jumptable_add_entry (); - code = mono_arm_load_jumptable_entry (code, load_get_lmf_addr, ARMREG_R0); -#else load_get_lmf_addr = code; code += 4; -#endif } ARM_MOV_REG_REG (code, ARMREG_LR, ARMREG_PC); code = emit_bx (code, ARMREG_R0); @@ -356,13 +302,8 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf code += 4; ARM_LDR_REG_REG (code, ARMREG_IP, ARMREG_PC, ARMREG_IP); } else { -#ifdef USE_JUMP_TABLES - load_trampoline = mono_jumptable_add_entry (); - code = mono_arm_load_jumptable_entry (code, load_trampoline, ARMREG_IP); -#else load_trampoline = code; code += 4; -#endif } ARM_MOV_REG_REG (code, ARMREG_LR, ARMREG_PC); @@ -388,16 +329,10 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf code += 4; ARM_LDR_REG_REG (code, ARMREG_IP, ARMREG_PC, ARMREG_IP); } else { -#ifdef USE_JUMP_TABLES - gpointer *jte = mono_jumptable_add_entry (); - code = mono_arm_load_jumptable_entry (code, jte, ARMREG_IP); - jte [0] = mono_interruption_checkpoint_from_trampoline; -#else ARM_LDR_IMM (code, ARMREG_IP, ARMREG_PC, 0); ARM_B (code, 0); *(gpointer*)code = mono_interruption_checkpoint_from_trampoline; code += 4; -#endif } ARM_MOV_REG_REG (code, ARMREG_LR, ARMREG_PC); code = emit_bx (code, ARMREG_IP); @@ -442,10 +377,6 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf else code = emit_bx (code, ARMREG_IP); -#ifdef USE_JUMP_TABLES - load_get_lmf_addr [0] = mono_get_lmf_addr; - load_trampoline [0] = (gpointer)mono_get_trampoline_func (tramp_type); -#else constants = (gpointer*)code; constants [0] = mono_get_lmf_addr; constants [1] = (gpointer)mono_get_trampoline_func (tramp_type); @@ -457,7 +388,6 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf } code += 8; -#endif /* Flush instruction cache, since we've generated code */ mono_arch_flush_icache (buf, code - buf); @@ -481,47 +411,24 @@ mono_arch_create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_ty { guint8 *code, *buf, *tramp; gpointer *constants; -#ifndef USE_JUMP_TABLES guint32 short_branch = FALSE; -#endif guint32 size = SPEC_TRAMP_SIZE; tramp = mono_get_trampoline_code (tramp_type); if (domain) { mono_domain_lock (domain); -#ifdef USE_JUMP_TABLES - code = buf = mono_domain_code_reserve_align (domain, size, 4); -#else code = buf = mono_domain_code_reserve_align (domain, size, 4); if ((short_branch = branch_for_target_reachable (code + 4, tramp))) { size = 12; mono_domain_code_commit (domain, code, SPEC_TRAMP_SIZE, size); - } -#endif + } mono_domain_unlock (domain); } else { code = buf = mono_global_codeman_reserve (size); short_branch = FALSE; } -#ifdef USE_JUMP_TABLES - /* For jumptables case we always generate the same code for trampolines, - * namely - * push {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, lr} - * movw lr, lo(jte) - * movt lr, hi(jte) - * ldr r1, [lr + 4] - * bx r1 - */ - ARM_PUSH (code, 0x5fff); - constants = mono_jumptable_add_entries (2); - code = mono_arm_load_jumptable_entry_addr (code, constants, ARMREG_LR); - ARM_LDR_IMM (code, ARMREG_R1, ARMREG_LR, 4); - code = emit_bx (code, ARMREG_R1); - constants [0] = arg1; - constants [1] = tramp; -#else /* we could reduce this to 12 bytes if tramp is within reach: * ARM_PUSH () * ARM_BL () @@ -551,7 +458,6 @@ mono_arch_create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_ty constants [1] = tramp; code += 8; } -#endif /* Flush instruction cache, since we've generated code */ mono_arch_flush_icache (buf, code - buf); @@ -580,30 +486,17 @@ mono_arch_get_unbox_trampoline (MonoMethod *m, gpointer addr) guint8 *code, *start; MonoDomain *domain = mono_domain_get (); GSList *unwind_ops; -#ifdef USE_JUMP_TABLES - gpointer *jte; - guint32 size = 20; -#else - guint32 size = 16; -#endif + guint32 size = 16; start = code = mono_domain_code_reserve (domain, size); unwind_ops = mono_arch_get_cie_program (); -#ifdef USE_JUMP_TABLES - jte = mono_jumptable_add_entry (); - code = mono_arm_load_jumptable_entry (code, jte, ARMREG_IP); - ARM_ADD_REG_IMM8 (code, ARMREG_R0, ARMREG_R0, sizeof (MonoObject)); - code = emit_bx (code, ARMREG_IP); - jte [0] = addr; -#else ARM_LDR_IMM (code, ARMREG_IP, ARMREG_PC, 4); ARM_ADD_REG_IMM8 (code, ARMREG_R0, ARMREG_R0, sizeof (MonoObject)); code = emit_bx (code, ARMREG_IP); *(guint32*)code = (guint32)addr; code += 4; -#endif mono_arch_flush_icache (start, code - start); mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_UNBOX_TRAMPOLINE, m); g_assert ((code - start) <= size); @@ -620,34 +513,19 @@ mono_arch_get_static_rgctx_trampoline (MonoMethod *m, MonoMethodRuntimeGenericCo { guint8 *code, *start; GSList *unwind_ops; -#ifdef USE_JUMP_TABLES - int buf_len = 20; - gpointer *jte; -#else int buf_len = 16; -#endif MonoDomain *domain = mono_domain_get (); start = code = mono_domain_code_reserve (domain, buf_len); unwind_ops = mono_arch_get_cie_program (); -#ifdef USE_JUMP_TABLES - jte = mono_jumptable_add_entries (2); - code = mono_arm_load_jumptable_entry_addr (code, jte, ARMREG_IP); - ARM_LDR_IMM (code, MONO_ARCH_RGCTX_REG, ARMREG_IP, 0); - ARM_LDR_IMM (code, ARMREG_IP, ARMREG_IP, 4); - ARM_BX (code, ARMREG_IP); - jte [0] = mrgctx; - jte [1] = addr; -#else ARM_LDR_IMM (code, MONO_ARCH_RGCTX_REG, ARMREG_PC, 0); ARM_LDR_IMM (code, ARMREG_PC, ARMREG_PC, 0); *(guint32*)code = (guint32)mrgctx; code += 4; *(guint32*)code = (guint32)addr; code += 4; -#endif g_assert ((code - start) <= buf_len); @@ -672,9 +550,6 @@ mono_arch_create_rgctx_lazy_fetch_trampoline (guint32 slot, MonoTrampInfo **info gboolean mrgctx; MonoJumpInfo *ji = NULL; GSList *unwind_ops = NULL; -#ifdef USE_JUMP_TABLES - gpointer *jte; -#endif mrgctx = MONO_RGCTX_SLOT_IS_MRGCTX (slot); index = MONO_RGCTX_SLOT_INDEX (slot); @@ -762,17 +637,10 @@ mono_arch_create_rgctx_lazy_fetch_trampoline (guint32 slot, MonoTrampInfo **info tramp = mono_arch_create_specific_trampoline (GUINT_TO_POINTER (slot), MONO_TRAMPOLINE_RGCTX_LAZY_FETCH, mono_get_root_domain (), &code_len); /* Jump to the actual trampoline */ -#ifdef USE_JUMP_TABLES - jte = mono_jumptable_add_entry (); - jte [0] = tramp; - code = mono_arm_load_jumptable_entry (code, jte, ARMREG_R1); - code = emit_bx (code, ARMREG_R1); -#else ARM_LDR_IMM (code, ARMREG_R1, ARMREG_PC, 0); /* temp reg */ code = emit_bx (code, ARMREG_R1); *(gpointer*)code = tramp; code += 4; -#endif } mono_arch_flush_icache (buf, code - buf); @@ -820,13 +688,6 @@ mono_arch_create_general_rgctx_lazy_fetch_trampoline (MonoTrampInfo **info, gboo return buf; } -static gpointer -handler_block_trampoline_helper (gpointer *ptr) -{ - MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id); - return jit_tls->handler_block_return_address; -} - gpointer mono_arch_create_handler_block_trampoline (MonoTrampInfo **info, gboolean aot) { @@ -836,8 +697,6 @@ mono_arch_create_handler_block_trampoline (MonoTrampInfo **info, gboolean aot) MonoJumpInfo *ji = NULL; GSList *unwind_ops = NULL; - g_assert (!aot); - code = buf = mono_global_codeman_reserve (tramp_size); unwind_ops = mono_arch_get_cie_program (); @@ -852,19 +711,30 @@ mono_arch_create_handler_block_trampoline (MonoTrampInfo **info, gboolean aot) * We are in a method frame after the call emitted by OP_CALL_HANDLER. */ /* Obtain jit_tls->handler_block_return_address */ - ARM_LDR_IMM (code, ARMREG_R0, ARMREG_PC, 0); - ARM_B (code, 0); - *(gpointer*)code = handler_block_trampoline_helper; - code += 4; + if (aot) { + code = mono_arm_emit_aotconst (&ji, code, buf, ARMREG_R0, MONO_PATCH_INFO_JIT_ICALL_ADDR, "mono_arm_handler_block_trampoline_helper"); + ARM_B (code, 0); + } else { + ARM_LDR_IMM (code, ARMREG_R0, ARMREG_PC, 0); + ARM_B (code, 0); + *(gpointer*)code = mono_arm_handler_block_trampoline_helper; + code += 4; + } /* Set it as the return address so the trampoline will return to it */ ARM_MOV_REG_REG (code, ARMREG_LR, ARMREG_R0); /* Call the trampoline */ - ARM_LDR_IMM (code, ARMREG_R0, ARMREG_PC, 0); - code = emit_bx (code, ARMREG_R0); - *(gpointer*)code = tramp; - code += 4; + if (aot) { + char *name = g_strdup_printf ("trampoline_func_%d", MONO_TRAMPOLINE_HANDLER_BLOCK_GUARD); + code = mono_arm_emit_aotconst (&ji, code, buf, ARMREG_R0, MONO_PATCH_INFO_JIT_ICALL_ADDR, name); + code = emit_bx (code, ARMREG_R0); + } else { + ARM_LDR_IMM (code, ARMREG_R0, ARMREG_PC, 0); + code = emit_bx (code, ARMREG_R0); + *(gpointer*)code = tramp; + code += 4; + } mono_arch_flush_icache (buf, code - buf); mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_HELPER, NULL); @@ -918,23 +788,27 @@ mono_arch_create_sdb_trampoline (gboolean single_step, MonoTrampInfo **info, gbo ARM_MOV_REG_REG (code, ARMREG_R0, ARMREG_FP); /* call */ - // FIXME: AOT -#ifdef USE_JUMP_TABLES - { - gpointer *jte = mono_jumptable_add_entry (); - code = mono_arm_load_jumptable_entry (code, jte, ARMREG_IP); - jte [0] = function; + if (aot) { + if (single_step) + ji = mono_patch_info_list_prepend (ji, code - buf, MONO_PATCH_INFO_JIT_ICALL_ADDR, "debugger_agent_single_step_from_context"); + else + ji = mono_patch_info_list_prepend (ji, code - buf, MONO_PATCH_INFO_JIT_ICALL_ADDR, "debugger_agent_breakpoint_from_context"); + ARM_LDR_IMM (code, ARMREG_IP, ARMREG_PC, 0); + ARM_B (code, 0); + *(gpointer*)code = NULL; + code += 4; + ARM_LDR_REG_REG (code, ARMREG_IP, ARMREG_PC, ARMREG_IP); + ARM_BLX_REG (code, ARMREG_IP); + } else { + ARM_LDR_IMM (code, ARMREG_IP, ARMREG_PC, 0); + ARM_B (code, 0); + if (single_step) + *(gpointer*)code = debugger_agent_single_step_from_context; + else + *(gpointer*)code = debugger_agent_breakpoint_from_context; + code += 4; + ARM_BLX_REG (code, ARMREG_IP); } -#else - ARM_LDR_IMM (code, ARMREG_IP, ARMREG_PC, 0); - ARM_B (code, 0); - if (single_step) - *(gpointer*)code = debugger_agent_single_step_from_context; - else - *(gpointer*)code = debugger_agent_breakpoint_from_context; - code += 4; -#endif - ARM_BLX_REG (code, ARMREG_IP); /* we're back; save ctx.eip and ctx.esp into the corresponding regs slots. */ ARM_LDR_IMM (code, ARMREG_R0, ARMREG_FP, MONO_STRUCT_OFFSET (MonoContext, pc)); @@ -1012,13 +886,8 @@ mono_arch_get_call_target (guint8 *code) { guint32 ins = ((guint32*)(gpointer)code) [-1]; -#if MONOTOUCH /* Should be a 'bl' or a 'b' */ if (((ins >> 25) & 0x7) == 0x5) { -#else - /* Should be a 'bl' */ - if ((((ins >> 25) & 0x7) == 0x5) && (((ins >> 24) & 0x1) == 0x1)) { -#endif gint32 disp = ((((gint32)ins) & 0xffffff) << 8) >> 8; guint8 *target = code - 4 + 8 + (disp * 4); @@ -1116,7 +985,6 @@ mono_arch_get_gsharedvt_arg_trampoline (MonoDomain *domain, gpointer arg, gpoint g_assert ((code - buf) <= buf_len); - nacl_domain_code_validate (domain, &buf, buf_len, &code); mono_arch_flush_icache (buf, code - buf); mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL);