Exemple #1
0
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;
}