示例#1
0
/*
 * arch_get_restore_context:
 *
 * Returns a pointer to a method which restores a previously saved sigcontext.
 * The first argument in r3 is the pointer to the context.
 */
gpointer
mono_arch_get_restore_context (MonoTrampInfo **info, gboolean aot)
{
	guint8 *start, *code;
	int size = MONO_PPC_32_64_CASE (128, 172) + PPC_FTNPTR_SIZE;
	MonoJumpInfo *ji = NULL;
	GSList *unwind_ops = NULL;

	code = start = mono_global_codeman_reserve (size);
	if (!aot)
		code = mono_ppc_create_pre_code_ftnptr (code);
	restore_regs_from_context (ppc_r3, ppc_r4, ppc_r5);
	/* restore also the stack pointer */
	ppc_ldptr (code, ppc_sp, G_STRUCT_OFFSET (MonoContext, sc_sp), ppc_r3);
	//ppc_break (code);
	/* jump to the saved IP */
	ppc_mtctr (code, ppc_r4);
	ppc_bcctr (code, PPC_BR_ALWAYS, 0);
	/* never reached */
	ppc_break (code);

	g_assert ((code - start) <= size);
	mono_arch_flush_icache (start, code - start);
	MONO_PROFILER_RAISE (jit_code_buffer, (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;
}
示例#2
0
/*
 * mono_arch_get_call_filter:
 *
 * Returns a pointer to a method which calls an exception filter. We
 * also use this function to call finally handlers (we pass NULL as 
 * @exc object in this case).
 */
gpointer
mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot)
{
	guint8 *start, *code;
	int alloc_size, pos, i;
	int size = MONO_PPC_32_64_CASE (320, 500) + PPC_FTNPTR_SIZE;
	MonoJumpInfo *ji = NULL;
	GSList *unwind_ops = NULL;

	/* call_filter (MonoContext *ctx, unsigned long eip, gpointer exc) */
	code = start = mono_global_codeman_reserve (size);
	if (!aot)
		code = mono_ppc_create_pre_code_ftnptr (code);

	/* store ret addr */
	ppc_mflr (code, ppc_r0);
	ppc_stptr (code, ppc_r0, PPC_RET_ADDR_OFFSET, ppc_sp);

	alloc_size = REG_SAVE_STACK_FRAME_SIZE;

	/* allocate stack frame and set link from sp in ctx */
	g_assert ((alloc_size & (MONO_ARCH_FRAME_ALIGNMENT-1)) == 0);
	ppc_ldptr (code, ppc_r0, G_STRUCT_OFFSET (MonoContext, sc_sp), ppc_r3);
	ppc_ldptr_indexed (code, ppc_r0, ppc_r0, ppc_r0);
	ppc_stptr_update (code, ppc_r0, -alloc_size, ppc_sp);

	code = emit_save_saved_regs (code, alloc_size);

	/* restore all the regs from ctx (in r3), but not r1, the stack pointer */
	restore_regs_from_context (ppc_r3, ppc_r6, ppc_r7);
	/* call handler at eip (r4) and set the first arg with the exception (r5) */
	ppc_mtctr (code, ppc_r4);
	ppc_mr (code, ppc_r3, ppc_r5);
	ppc_bcctrl (code, PPC_BR_ALWAYS, 0);

	/* epilog */
	ppc_ldptr (code, ppc_r0, alloc_size + PPC_RET_ADDR_OFFSET, ppc_sp);
	ppc_mtlr (code, ppc_r0);

	/* restore all the regs from the stack */
	pos = alloc_size;
	for (i = 31; i >= 14; --i) {
		pos -= sizeof (gdouble);
		ppc_lfd (code, i, pos, ppc_sp);
	}
	pos -= sizeof (gpointer) * MONO_SAVED_GREGS;
	ppc_load_multiple_regs (code, ppc_r13, pos, ppc_sp);

	ppc_addic (code, ppc_sp, ppc_sp, alloc_size);
	ppc_blr (code);

	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 ("call_filter", start, code - start, ji, unwind_ops);

	return start;
}