#include "mini.h"
#include "mini-ppc.h"
+static guint8* nullified_class_init_trampoline;
+
/*
* Return the instruction to jump from code to target, 0 if not
* reachable with a single instruction
int this_pos = 3;
guint32 short_branch;
MonoDomain *domain = mono_domain_get ();
- int size = MONO_PPC_32_64_CASE (20, 32);
+ int size = MONO_PPC_32_64_CASE (20, 32) + PPC_FTNPTR_SIZE;
addr = mono_get_addr_from_ftnptr (addr);
this_pos = 4;
mono_domain_lock (domain);
- start = code = mono_code_manager_reserve (domain->code_mp, size);
+ start = code = mono_domain_code_reserve (domain, size);
+ code = mono_ppc_create_pre_code_ftnptr (code);
short_branch = branch_for_target_reachable (code + 4, addr);
if (short_branch)
- mono_code_manager_commit (domain->code_mp, code, size, 8);
+ mono_domain_code_commit (domain, code, size, 8);
mono_domain_unlock (domain);
if (short_branch) {
/*g_print ("unbox trampoline at %d for %s:%s\n", this_pos, m->klass->name, m->name);
g_print ("unbox code is at %p for method at %p\n", start, addr);*/
- return mono_create_ftnptr (domain, start);
+ return start;
+}
+
+/*
+ * mono_arch_get_static_rgctx_trampoline:
+ *
+ * Create a trampoline which sets RGCTX_REG to MRGCTX, then jumps to ADDR.
+ */
+gpointer
+mono_arch_get_static_rgctx_trampoline (MonoMethod *m, MonoMethodRuntimeGenericContext *mrgctx, gpointer addr)
+{
+ guint8 *code, *start;
+ guint32 short_branch;
+ MonoDomain *domain = mono_domain_get ();
+ int size = MONO_PPC_32_64_CASE (24, 36) + PPC_FTNPTR_SIZE;
+
+ addr = mono_get_addr_from_ftnptr (addr);
+
+ mono_domain_lock (domain);
+ start = code = mono_domain_code_reserve (domain, size);
+ code = mono_ppc_create_pre_code_ftnptr (code);
+ short_branch = branch_for_target_reachable (code + 8, addr);
+ if (short_branch)
+ mono_domain_code_commit (domain, code, size, 12);
+ mono_domain_unlock (domain);
+
+ if (short_branch) {
+ ppc_load (code, MONO_ARCH_RGCTX_REG, mrgctx);
+ ppc_emit32 (code, short_branch);
+ } else {
+ ppc_load (code, ppc_r0, addr);
+ ppc_mtctr (code, ppc_r0);
+ ppc_load (code, MONO_ARCH_RGCTX_REG, mrgctx);
+ ppc_bcctr (code, 20, 0);
+ }
+ mono_arch_flush_icache (start, code - start);
+ g_assert ((code - start) <= size);
+
+ return start;
}
void
void
mono_arch_nullify_class_init_trampoline (guint8 *code, gssize *regs)
{
- return;
+ mono_arch_patch_callsite (NULL, code, nullified_class_init_trampoline);
}
void
guint8 *buf, *code = NULL;
int i, offset;
gconstpointer tramp_handler;
- int size = MONO_PPC_32_64_CASE (512, 688);
+ int size = MONO_PPC_32_64_CASE (516, 692);
/* Now we'll create in 'buf' the PowerPC trampoline code. This
is the trampoline code common to all methods */
* now the integer registers.
*/
offset = STACK - sizeof (MonoLMF) + G_STRUCT_OFFSET (MonoLMF, iregs);
- ppc_store_multiple_regs (buf, ppc_r13, ppc_r1, offset);
+ ppc_store_multiple_regs (buf, ppc_r13, offset, ppc_r1);
/* Now save the rest of the registers below the MonoLMF struct, first 14
* fp regs and then the 13 gregs.
ppc_load_reg (buf, ppc_r5, GREGS_OFFSET, ppc_r1);
if ((tramp_type == MONO_TRAMPOLINE_JIT) || (tramp_type == MONO_TRAMPOLINE_JUMP))
ppc_store_reg (buf, ppc_r5, G_STRUCT_OFFSET(MonoLMF, method), ppc_r11);
- ppc_store_reg (buf, ppc_sp, G_STRUCT_OFFSET(MonoLMF, ebp), ppc_r11);
+ /* store the frame pointer of the calling method */
+ ppc_addi (buf, ppc_r0, ppc_sp, STACK);
+ ppc_store_reg (buf, ppc_r0, G_STRUCT_OFFSET(MonoLMF, ebp), ppc_r11);
/* save the IP (caller ip) */
if (tramp_type == MONO_TRAMPOLINE_JUMP) {
ppc_li (buf, ppc_r0, 0);
*/
if (!MONO_TRAMPOLINE_TYPE_MUST_RETURN (tramp_type)) {
#ifdef PPC_USES_FUNCTION_DESCRIPTOR
- if (tramp_type != MONO_TRAMPOLINE_DELEGATE)
- ppc_load_reg (buf, ppc_r3, 0, ppc_r3);
+ ppc_load_reg (buf, ppc_r3, 0, ppc_r3);
#endif
ppc_mtctr (buf, ppc_r3);
}
/* *(lmf_addr) = previous_lmf */
ppc_store_reg (buf, ppc_r5, G_STRUCT_OFFSET(MonoLMF, previous_lmf), ppc_r6);
/* restore iregs */
- ppc_load_multiple_regs (buf, ppc_r13, ppc_r11, G_STRUCT_OFFSET(MonoLMF, iregs));
+ ppc_load_multiple_regs (buf, ppc_r13, G_STRUCT_OFFSET(MonoLMF, iregs), ppc_r11);
/* restore fregs */
for (i = 14; i < 32; i++)
ppc_lfd (buf, i, G_STRUCT_OFFSET(MonoLMF, fregs) + ((i-14) * sizeof (gdouble)), ppc_r11);
/* Sanity check */
g_assert ((buf - code) <= size);
+ if (tramp_type == MONO_TRAMPOLINE_CLASS_INIT) {
+ guint32 code_len;
+
+ /* Initialize the nullified class init trampoline used in the AOT case */
+ nullified_class_init_trampoline = mono_arch_get_nullified_class_init_trampoline (&code_len);
+ }
+
return code;
}
tramp = mono_get_trampoline_code (tramp_type);
mono_domain_lock (domain);
- code = buf = mono_code_manager_reserve_align (domain->code_mp, TRAMPOLINE_SIZE, 4);
+ code = buf = mono_domain_code_reserve_align (domain, TRAMPOLINE_SIZE, 4);
short_branch = branch_for_target_reachable (code + MONO_PPC_32_64_CASE (8, 5*4), tramp);
#ifdef __mono_ppc64__
/* FIXME: make shorter if possible */
#else
if (short_branch)
- mono_code_manager_commit (domain->code_mp, code, TRAMPOLINE_SIZE, 12);
+ mono_domain_code_commit (domain, code, TRAMPOLINE_SIZE, 12);
#endif
mono_domain_unlock (domain);
guint8 *jump;
int tramp_size;
- tramp_size = 32;
+ tramp_size = MONO_PPC_32_64_CASE (32, 44);
code = buf = mono_global_codeman_reserve (tramp_size);
return buf;
}
+
+gpointer
+mono_arch_get_nullified_class_init_trampoline (guint32 *code_len)
+{
+ guint8 *code, *buf;
+ guint32 tramp_size = 64;
+
+ code = buf = mono_global_codeman_reserve (tramp_size);
+ code = mono_ppc_create_pre_code_ftnptr (code);
+ ppc_blr (code);
+
+ mono_arch_flush_icache (buf, code - buf);
+
+ *code_len = code - buf;
+
+ g_assert (code - buf <= tramp_size);
+
+ return buf;
+}