Use ppc_r12 for some global call sequences After the mechanical exchange of ppc_r11 and ppc_r12 we now can use ppc_r12 for global calls to hold the callees address without clobbering r11 (which potentially contains IMT_REG, VTABLE_REG and RGCTX_REG). We don't need to change all indirect calls, only those potentially reaching functions containing a TOC setup based on r12 (in particular functions in shared libs). As the instruction sequence patcher can only deal with one destination register we also need to make some additional calls use r12. We probably should convert all calls that currently use r0 to use r12 if no other conflicts arise but this is enough to build. Index: mono-3.4.0/mono/mini/exceptions-ppc.c =================================================================== --- mono-3.4.0.orig/mono/mini/exceptions-ppc.c +++ mono-3.4.0/mono/mini/exceptions-ppc.c @@ -391,8 +391,8 @@ mono_arch_get_throw_exception_generic (i ppc_bcctrl (code, PPC_BR_ALWAYS, 0); } else { ppc_load (code, ppc_r3, (gulong)mono_defaults.corlib); - ppc_load_func (code, ppc_r0, mono_exception_from_token); - ppc_mtctr (code, ppc_r0); + ppc_load_func (code, PPC_CALL_REG, mono_exception_from_token); + ppc_mtctr (code, PPC_CALL_REG); ppc_bcctrl (code, PPC_BR_ALWAYS, 0); } } @@ -426,8 +426,8 @@ mono_arch_get_throw_exception_generic (i ppc_mtctr (code, ppc_r12); ppc_bcctrl (code, PPC_BR_ALWAYS, 0); } else { - ppc_load_func (code, ppc_r0, mono_ppc_throw_exception); - ppc_mtctr (code, ppc_r0); + ppc_load_func (code, PPC_CALL_REG, mono_ppc_throw_exception); + ppc_mtctr (code, PPC_CALL_REG); ppc_bcctrl (code, PPC_BR_ALWAYS, 0); } /* we should never reach this breakpoint */ Index: mono-3.4.0/mono/mini/mini-ppc.c =================================================================== --- mono-3.4.0.orig/mono/mini/mini-ppc.c +++ mono-3.4.0/mono/mini/mini-ppc.c @@ -1782,8 +1782,8 @@ mono_arch_instrument_prolog (MonoCompile ppc_load_ptr (code, ppc_r3, cfg->method); ppc_li (code, ppc_r4, 0); /* NULL ebp for now */ - ppc_load_func (code, ppc_r0, func); - ppc_mtlr (code, ppc_r0); + ppc_load_func (code, PPC_CALL_REG, func); + ppc_mtlr (code, PPC_CALL_REG); ppc_blrl (code); return code; } @@ -1880,8 +1880,8 @@ mono_arch_instrument_epilog_full (MonoCo } ppc_load_ptr (code, ppc_r3, cfg->method); - ppc_load_func (code, ppc_r0, func); - ppc_mtlr (code, ppc_r0); + ppc_load_func (code, PPC_CALL_REG, func); + ppc_mtlr (code, PPC_CALL_REG); ppc_blrl (code); switch (save_mode) { @@ -2922,7 +2922,7 @@ ppc_patch_full (guchar *code, const guch if (!is_fd) { guint8 *buf = (guint8*)&seq [5]; - ppc_mr (buf, ppc_r0, ppc_r12); + ppc_mr (buf, PPC_CALL_REG, ppc_r12); ppc_nop (buf); } } else { @@ -2935,7 +2935,7 @@ ppc_patch_full (guchar *code, const guch /* FIXME: we're assuming we're using r12 here */ ppc_load_ptr_sequence (code, ppc_r12, target); #else - ppc_load_ptr_sequence (code, ppc_r0, target); + ppc_load_ptr_sequence (code, PPC_CALL_REG, target); #endif mono_arch_flush_icache ((guint8*)seq, 28); #else @@ -2951,8 +2951,8 @@ ppc_patch_full (guchar *code, const guch g_assert ((seq [2] >> 26) == 31); g_assert (seq [3] == 0x4e800021 || seq [3] == 0x4e800020 || seq [3] == 0x4e800420); /* FIXME: make this thread safe */ - ppc_lis (code, ppc_r0, (guint32)(target) >> 16); - ppc_ori (code, ppc_r0, ppc_r0, (guint32)(target) & 0xffff); + ppc_lis (code, PPC_CALL_REG, (guint32)(target) >> 16); + ppc_ori (code, PPC_CALL_REG, PPC_CALL_REG, (guint32)(target) & 0xffff); mono_arch_flush_icache (code - 8, 8); #endif } else { @@ -3370,8 +3370,8 @@ mono_arch_output_basic_block (MonoCompil mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD, (gpointer)"mono_break"); if ((FORCE_INDIR_CALL || cfg->method->dynamic) && !cfg->compile_aot) { - ppc_load_func (code, ppc_r0, 0); - ppc_mtlr (code, ppc_r0); + ppc_load_func (code, PPC_CALL_REG, 0); + ppc_mtlr (code, PPC_CALL_REG); ppc_blrl (code); } else { ppc_bl (code, 0); @@ -3818,8 +3818,8 @@ mono_arch_output_basic_block (MonoCompil else mono_add_patch_info (cfg, offset, MONO_PATCH_INFO_ABS, call->fptr); if ((FORCE_INDIR_CALL || cfg->method->dynamic) && !cfg->compile_aot) { - ppc_load_func (code, ppc_r0, 0); - ppc_mtlr (code, ppc_r0); + ppc_load_func (code, PPC_CALL_REG, 0); + ppc_mtlr (code, PPC_CALL_REG); ppc_blrl (code); } else { ppc_bl (code, 0); @@ -3912,8 +3912,8 @@ mono_arch_output_basic_block (MonoCompil mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD, (gpointer)"mono_arch_throw_exception"); if ((FORCE_INDIR_CALL || cfg->method->dynamic) && !cfg->compile_aot) { - ppc_load_func (code, ppc_r0, 0); - ppc_mtlr (code, ppc_r0); + ppc_load_func (code, PPC_CALL_REG, 0); + ppc_mtlr (code, PPC_CALL_REG); ppc_blrl (code); } else { ppc_bl (code, 0); @@ -3926,8 +3926,8 @@ mono_arch_output_basic_block (MonoCompil mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD, (gpointer)"mono_arch_rethrow_exception"); if ((FORCE_INDIR_CALL || cfg->method->dynamic) && !cfg->compile_aot) { - ppc_load_func (code, ppc_r0, 0); - ppc_mtlr (code, ppc_r0); + ppc_load_func (code, PPC_CALL_REG, 0); + ppc_mtlr (code, PPC_CALL_REG); ppc_blrl (code); } else { ppc_bl (code, 0); @@ -5070,8 +5070,8 @@ mono_arch_emit_prolog (MonoCompile *cfg) mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD, (gpointer)"mono_get_lmf_addr"); if ((FORCE_INDIR_CALL || cfg->method->dynamic) && !cfg->compile_aot) { - ppc_load_func (code, ppc_r0, 0); - ppc_mtlr (code, ppc_r0); + ppc_load_func (code, PPC_CALL_REG, 0); + ppc_mtlr (code, PPC_CALL_REG); ppc_blrl (code); } else { ppc_bl (code, 0); @@ -5380,8 +5380,8 @@ mono_arch_emit_exceptions (MonoCompile * patch_info->data.name = "mono_arch_throw_corlib_exception"; patch_info->ip.i = code - cfg->native_code; if (FORCE_INDIR_CALL || cfg->method->dynamic) { - ppc_load_func (code, ppc_r0, 0); - ppc_mtctr (code, ppc_r0); + ppc_load_func (code, PPC_CALL_REG, 0); + ppc_mtctr (code, PPC_CALL_REG); ppc_bcctr (code, PPC_BR_ALWAYS, 0); } else { ppc_bl (code, 0); Index: mono-3.4.0/mono/mini/mini-ppc.h =================================================================== --- mono-3.4.0.orig/mono/mini/mini-ppc.h +++ mono-3.4.0/mono/mini/mini-ppc.h @@ -172,6 +172,8 @@ typedef struct MonoCompileArch { #define PPC_FIRST_FPARG_REG ppc_f1 #endif +#define PPC_CALL_REG ppc_r12 + #if defined(HAVE_WORKING_SIGALTSTACK) && !defined(__APPLE__) #define MONO_ARCH_SIGSEGV_ON_ALTSTACK 1 #define MONO_ARCH_SIGNAL_STACK_SIZE (12 * 1024) Index: mono-3.4.0/mono/mini/tramp-ppc.c =================================================================== --- mono-3.4.0.orig/mono/mini/tramp-ppc.c +++ mono-3.4.0/mono/mini/tramp-ppc.c @@ -306,8 +306,8 @@ mono_arch_create_generic_trampoline (Mon ppc_mtlr (code, ppc_r12); ppc_blrl (code); } else { - ppc_load_func (code, ppc_r0, mono_get_lmf_addr); - ppc_mtlr (code, ppc_r0); + ppc_load_func (code, PPC_CALL_REG, mono_get_lmf_addr); + ppc_mtlr (code, PPC_CALL_REG); ppc_blrl (code); } /* we build the MonoLMF structure on the stack - see mini-ppc.h @@ -368,8 +368,8 @@ mono_arch_create_generic_trampoline (Mon ppc_blrl (code); } else { tramp_handler = mono_get_trampoline_func (tramp_type); - ppc_load_func (code, ppc_r0, tramp_handler); - ppc_mtlr (code, ppc_r0); + ppc_load_func (code, PPC_CALL_REG, tramp_handler); + ppc_mtlr (code, PPC_CALL_REG); ppc_blrl (code); }