diff --git a/src/mono/mono/mini/cpu-ppc.mdesc b/src/mono/mono/mini/cpu-ppc.mdesc index c92495c356fa51..301b96a6530bdf 100644 --- a/src/mono/mono/mini/cpu-ppc.mdesc +++ b/src/mono/mono/mini/cpu-ppc.mdesc @@ -348,4 +348,4 @@ atomic_cas_i4: src1:b src2:i src3:i dest:i len:38 liverange_start: len:0 liverange_end: len:0 -gc_safe_point: clob:c src1:i len:40 +gc_safe_point: clob:c src1:i len:44 diff --git a/src/mono/mono/mini/cpu-ppc64.mdesc b/src/mono/mono/mini/cpu-ppc64.mdesc index 4dca1bb3ab43cf..d2437a34fda45e 100644 --- a/src/mono/mono/mini/cpu-ppc64.mdesc +++ b/src/mono/mono/mini/cpu-ppc64.mdesc @@ -417,4 +417,4 @@ atomic_cas_i8: src1:b src2:i src3:i dest:i len:38 liverange_start: len:0 liverange_end: len:0 -gc_safe_point: clob:c src1:i len:40 +gc_safe_point: clob:c src1:i len:44 diff --git a/src/mono/mono/mini/mini-ppc.c b/src/mono/mono/mini/mini-ppc.c index 30dc899ab6969b..93abd63562ff53 100644 --- a/src/mono/mono/mini/mini-ppc.c +++ b/src/mono/mono/mini/mini-ppc.c @@ -311,7 +311,12 @@ mono_ppc_is_direct_call_sequence (guint32 *code) if (ppc_opcode (code [-2]) == 24 && ppc_opcode (code [-3]) == 31) /* mr/nop */ return is_load_sequence (&code [-8]); else +#if !defined(PPC_USES_FUNCTION_DESCRIPTOR) + /* the memory patch thunk sequence for ppc64le is: lis/ori/sldi/oris/ori/ld/mtlr/blrl */ + return is_load_sequence (&code [-7]); +#else return is_load_sequence (&code [-6]); +#endif } return FALSE; #else @@ -2692,6 +2697,10 @@ emit_float_to_int (MonoCompile *cfg, guchar *code, int dreg, int sreg, int size, static void emit_thunk (guint8 *code, gconstpointer target) { +#if defined(TARGET_POWERPC64) && !defined(PPC_USES_FUNCTION_DESCRIPTOR) + *(guint64*)code = (guint64)target; + code += sizeof (guint64); +#else guint8 *p = code; /* 2 bytes on 32bit, 5 bytes on 64bit */ @@ -2701,6 +2710,7 @@ emit_thunk (guint8 *code, gconstpointer target) ppc_bcctr (code, PPC_BR_ALWAYS, 0); mono_arch_flush_icache (p, code - p); +#endif } static void @@ -2731,9 +2741,14 @@ handle_thunk (MonoCompile *cfg, guchar *code, const guchar *target) } g_assert (*(guint32*)thunks == 0); + + emit_thunk (thunks, target); +#if defined(TARGET_POWERPC64) && !defined(PPC_USES_FUNCTION_DESCRIPTOR) + ppc_load_ptr_sequence (code, PPC_CALL_REG, thunks); +#else ppc_patch (code, thunks); - +#endif cfg->arch.thunks += THUNK_SIZE; cfg->arch.thunks_size -= THUNK_SIZE; } else { @@ -2753,7 +2768,9 @@ handle_thunk (MonoCompile *cfg, guchar *code, const guchar *target) if (orig_target >= thunks && orig_target < thunks + thunks_size) { /* The call already points to a thunk, because of trampolines etc. */ target_thunk = orig_target; - } else { + } +#if (defined(TARGET_POWERPC64) && defined(PPC_USES_FUNCTION_DESCRIPTOR)) || !defined(TARGET_POWERPC64) + else { for (p = thunks; p < thunks + thunks_size; p += THUNK_SIZE) { if (((guint32 *) p) [0] == 0) { /* Free entry */ @@ -2777,7 +2794,7 @@ handle_thunk (MonoCompile *cfg, guchar *code, const guchar *target) } } } - +#endif // g_print ("THUNK: %p %p %p\n", code, target, target_thunk); if (!target_thunk) { @@ -2787,7 +2804,9 @@ handle_thunk (MonoCompile *cfg, guchar *code, const guchar *target) } emit_thunk (target_thunk, target); +#if (defined(TARGET_POWERPC64) && defined(PPC_USES_FUNCTION_DESCRIPTOR)) || !defined(TARGET_POWERPC64) ppc_patch (code, target_thunk); +#endif mono_mini_arch_unlock (); } @@ -2875,6 +2894,9 @@ ppc_patch_full (MonoCompile *cfg, guchar *code, const guchar *target, gboolean i if (prim == 15 || ins == 0x4e800021 || ins == 0x4e800020 || ins == 0x4e800420) { #ifdef TARGET_POWERPC64 +#if !defined(PPC_USES_FUNCTION_DESCRIPTOR) + handle_thunk (cfg, code, target); +#else guint32 *seq = (guint32*)code; guint32 *branch_ins; @@ -2923,6 +2945,7 @@ ppc_patch_full (MonoCompile *cfg, guchar *code, const guchar *target, gboolean i ppc_load_ptr_sequence (code, PPC_CALL_REG, target); #endif mono_arch_flush_icache ((guint8*)seq, 28); +#endif #else guint32 *seq; /* the trampoline code will try to patch the blrl, blr, bcctr */ @@ -3349,6 +3372,10 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_JIT_ICALL_ID, GUINT_TO_POINTER (MONO_JIT_ICALL_mono_break)); if ((FORCE_INDIR_CALL || cfg->method->dynamic) && !cfg->compile_aot) { ppc_load_func (code, PPC_CALL_REG, 0); +#if defined(TARGET_POWERPC64) && !defined(PPC_USES_FUNCTION_DESCRIPTOR) + ppc_ldr (code, PPC_CALL_REG, 0, PPC_CALL_REG); + cfg->thunk_area += THUNK_SIZE; +#endif ppc_mtlr (code, PPC_CALL_REG); ppc_blrl (code); } else { @@ -3794,7 +3821,14 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) ppc_mtctr (code, ppc_r0); ppc_bcctr (code, PPC_BR_ALWAYS, 0); } else { +#if defined(TARGET_POWERPC64) && !defined(PPC_USES_FUNCTION_DESCRIPTOR) + ppc_load_func (code, PPC_CALL_REG, 0); + ppc_ldr (code, PPC_CALL_REG, 0, PPC_CALL_REG); + ppc_mtctr (code, PPC_CALL_REG); + ppc_bcctr (code, PPC_BR_ALWAYS, 0); +#else ppc_b (code, 0); +#endif } break; } @@ -3823,6 +3857,10 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) mono_call_add_patch_info (cfg, call, offset); if ((FORCE_INDIR_CALL || cfg->method->dynamic) && !cfg->compile_aot) { ppc_load_func (code, PPC_CALL_REG, 0); +#if defined(TARGET_POWERPC64) && !defined(PPC_USES_FUNCTION_DESCRIPTOR) + ppc_ldr (code, PPC_CALL_REG, 0, PPC_CALL_REG); + cfg->thunk_area += THUNK_SIZE; +#endif ppc_mtlr (code, PPC_CALL_REG); ppc_blrl (code); } else { @@ -3926,6 +3964,10 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_JIT_ICALL_ID, GUINT_TO_POINTER (MONO_JIT_ICALL_mono_arch_throw_exception)); if ((FORCE_INDIR_CALL || cfg->method->dynamic) && !cfg->compile_aot) { ppc_load_func (code, PPC_CALL_REG, 0); +#if defined(TARGET_POWERPC64) && !defined(PPC_USES_FUNCTION_DESCRIPTOR) + ppc_ldr (code, PPC_CALL_REG, 0, PPC_CALL_REG); + cfg->thunk_area += THUNK_SIZE; +#endif ppc_mtlr (code, PPC_CALL_REG); ppc_blrl (code); } else { @@ -3940,6 +3982,10 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) GUINT_TO_POINTER (MONO_JIT_ICALL_mono_arch_rethrow_exception)); if ((FORCE_INDIR_CALL || cfg->method->dynamic) && !cfg->compile_aot) { ppc_load_func (code, PPC_CALL_REG, 0); +#if defined(TARGET_POWERPC64) && !defined(PPC_USES_FUNCTION_DESCRIPTOR) + ppc_ldr (code, PPC_CALL_REG, 0, PPC_CALL_REG); + cfg->thunk_area += THUNK_SIZE; +#endif ppc_mtlr (code, PPC_CALL_REG); ppc_blrl (code); } else { @@ -4584,6 +4630,10 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) GUINT_TO_POINTER (MONO_JIT_ICALL_mono_threads_state_poll)); if ((FORCE_INDIR_CALL || cfg->method->dynamic) && !cfg->compile_aot) { ppc_load_func (code, PPC_CALL_REG, 0); +#if defined(TARGET_POWERPC64) && !defined(PPC_USES_FUNCTION_DESCRIPTOR) + ppc_ldr (code, PPC_CALL_REG, 0, PPC_CALL_REG); + cfg->thunk_area += THUNK_SIZE; +#endif ppc_mtlr (code, PPC_CALL_REG); ppc_blrl (code); } else { @@ -5185,6 +5235,10 @@ mono_arch_emit_prolog (MonoCompile *cfg) GUINT_TO_POINTER (MONO_JIT_ICALL_mono_tls_get_lmf_addr_extern)); if ((FORCE_INDIR_CALL || cfg->method->dynamic) && !cfg->compile_aot) { ppc_load_func (code, PPC_CALL_REG, 0); +#if defined(TARGET_POWERPC64) && !defined(PPC_USES_FUNCTION_DESCRIPTOR) + ppc_ldr (code, PPC_CALL_REG, 0, PPC_CALL_REG); + cfg->thunk_area += THUNK_SIZE; +#endif ppc_mtlr (code, PPC_CALL_REG); ppc_blrl (code); } else { @@ -5466,6 +5520,10 @@ mono_arch_emit_exceptions (MonoCompile *cfg) patch_info->ip.i = code - cfg->native_code; if (FORCE_INDIR_CALL || cfg->method->dynamic) { ppc_load_func (code, PPC_CALL_REG, 0); +#if defined(TARGET_POWERPC64) && !defined(PPC_USES_FUNCTION_DESCRIPTOR) + ppc_ldr (code, PPC_CALL_REG, 0, PPC_CALL_REG); + cfg->thunk_area += THUNK_SIZE; +#endif ppc_mtctr (code, PPC_CALL_REG); ppc_bcctr (code, PPC_BR_ALWAYS, 0); } else { diff --git a/src/mono/mono/mini/mini-ppc.h b/src/mono/mono/mini/mini-ppc.h index 281eee97b5bb1b..0b962aac233d24 100644 --- a/src/mono/mono/mini/mini-ppc.h +++ b/src/mono/mono/mini/mini-ppc.h @@ -33,7 +33,16 @@ #define MONO_ARCH_CODE_ALIGNMENT 32 #ifdef TARGET_POWERPC64 +#if !defined(PPC_USES_FUNCTION_DESCRIPTOR) +#define THUNK_SIZE 8 +#define GET_MEMORY_SLOT_THUNK_ADDRESS(c) \ + ((guint64)(((c)) [0] & 0x0000ffff) << 48) \ + + ((guint64)(((c)) [1] & 0x0000ffff) << 32) \ + + ((guint64)(((c)) [3] & 0x0000ffff) << 16) \ + + (guint64)(((c)) [4] & 0x0000ffff) +#else #define THUNK_SIZE ((2 + 5) * 4) +#endif #else #define THUNK_SIZE ((2 + 2) * 4) #endif @@ -118,8 +127,7 @@ typedef struct MonoCompileArch { #else #define MONO_ARCH_CALLEE_FREGS (0xff << ppc_f1) #endif -#define MONO_ARCH_CALLEE_SAVED_FREGS (~(MONO_ARCH_CALLEE_FRE -GS | 1)) +#define MONO_ARCH_CALLEE_SAVED_FREGS (~(MONO_ARCH_CALLEE_FREGS | 1)) #ifdef TARGET_POWERPC64 #define MONO_ARCH_INST_FIXED_REG(desc) (((desc) == 'a')? ppc_r3: \ diff --git a/src/mono/mono/mini/tramp-ppc.c b/src/mono/mono/mini/tramp-ppc.c index 3a78709c6f8cb9..59bcb275a48609 100644 --- a/src/mono/mono/mini/tramp-ppc.c +++ b/src/mono/mono/mini/tramp-ppc.c @@ -669,7 +669,17 @@ mono_arch_get_call_target (guint8 *code) guint8 *target = code - 4 + (disp * 4); return target; - } else { + } +#if defined(TARGET_POWERPC64) && !defined(PPC_USES_FUNCTION_DESCRIPTOR) + else if (((guint32*)(code - 32)) [0] >> 26 == 15) { + guint8 *thunk = GET_MEMORY_SLOT_THUNK_ADDRESS((guint32*)(code - 32)); + return thunk; + } else if (((guint32*)(code - 4)) [0] >> 26 == 15) { + guint8 *thunk = GET_MEMORY_SLOT_THUNK_ADDRESS((guint32*)(code - 4)); + return thunk; + } +#endif + else { return NULL; } }