gpointer mono_arch_get_restore_context (MonoTrampInfo **info, gboolean aot) { guint8 *start, *code; MonoJumpInfo *ji = NULL; GSList *unwind_ops = NULL; int i, ctx_reg, size; guint8 *labels [16]; size = 256; code = start = mono_global_codeman_reserve (size); arm_movx (code, ARMREG_IP0, ARMREG_R0); ctx_reg = ARMREG_IP0; /* Restore fregs */ arm_ldrx (code, ARMREG_IP1, ctx_reg, MONO_STRUCT_OFFSET (MonoContext, has_fregs)); labels [0] = code; arm_cbzx (code, ARMREG_IP1, 0); for (i = 0; i < 32; ++i) arm_ldrfpx (code, i, ctx_reg, MONO_STRUCT_OFFSET (MonoContext, fregs) + (i * 8)); mono_arm_patch (labels [0], code, MONO_R_ARM64_CBZ); /* Restore gregs */ // FIXME: Restore less registers // FIXME: fp should be restored later code = mono_arm_emit_load_regarray (code, 0xffffffff & ~(1 << ctx_reg) & ~(1 << ARMREG_SP), ctx_reg, MONO_STRUCT_OFFSET (MonoContext, regs)); /* ip0/ip1 doesn't need to be restored */ /* ip1 = pc */ arm_ldrx (code, ARMREG_IP1, ctx_reg, MONO_STRUCT_OFFSET (MonoContext, pc)); /* ip0 = sp */ arm_ldrx (code, ARMREG_IP0, ctx_reg, MONO_STRUCT_OFFSET (MonoContext, regs) + (ARMREG_SP * 8)); /* Restore sp, ctx is no longer valid */ arm_movspx (code, ARMREG_SP, ARMREG_IP0); /* Branch to pc */ arm_brx (code, ARMREG_IP1); /* Not reached */ arm_brk (code, 0); g_assert ((code - start) < size); mono_arch_flush_icache (start, code - start); mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL); if (info) *info = mono_tramp_info_create ("restore_context", start, code - start, ji, unwind_ops); return start; }
/* * mono_arch_get_gsharedvt_arg_trampoline: * * See tramp-x86.c for documentation. */ gpointer mono_arch_get_gsharedvt_arg_trampoline (MonoDomain *domain, gpointer arg, gpointer addr) { guint8 *code, *buf; int buf_len = 40; /* * Return a trampoline which calls ADDR passing in ARG. * Pass the argument in ip1, clobbering ip0. */ buf = code = mono_global_codeman_reserve (buf_len); code = mono_arm_emit_imm64 (code, ARMREG_IP1, (guint64)arg); code = mono_arm_emit_imm64 (code, ARMREG_IP0, (guint64)addr); arm_brx (code, ARMREG_IP0); g_assert ((code - buf) < buf_len); mono_arch_flush_icache (buf, code - buf); return buf; }