-/*
- * exceptions-ppc.c: exception support for PowerPC
+/**
+ * \file
+ * exception support for PowerPC
*
* Authors:
* Dietmar Maurer (dietmar@ximian.com)
#define restore_regs_from_context(ctx_reg,ip_reg,tmp_reg) do { \
int reg; \
ppc_ldptr (code, ip_reg, G_STRUCT_OFFSET (MonoContext, sc_ir), ctx_reg); \
- ppc_load_multiple_regs (code, ppc_r13, G_STRUCT_OFFSET (MonoContext, regs), ctx_reg); \
- for (reg = 0; reg < MONO_SAVED_FREGS; ++reg) { \
- ppc_lfd (code, (14 + reg), \
+ ppc_load_multiple_regs (code, MONO_PPC_FIRST_SAVED_GREG, \
+ G_STRUCT_OFFSET (MonoContext, regs) + MONO_PPC_FIRST_SAVED_GREG * sizeof (gpointer), ctx_reg); \
+ for (reg = MONO_PPC_FIRST_SAVED_FREG; reg < MONO_MAX_FREGS; ++reg) { \
+ ppc_lfd (code, reg, \
G_STRUCT_OFFSET(MonoContext, fregs) + reg * sizeof (gdouble), ctx_reg); \
} \
} while (0)
return start;
}
-#define SAVED_REGS_LENGTH (sizeof (gdouble) * MONO_SAVED_FREGS + sizeof (gpointer) * MONO_SAVED_GREGS)
+#define SAVED_REGS_LENGTH (sizeof (gdouble) * MONO_MAX_FREGS + sizeof (gpointer) * MONO_MAX_IREGS)
#define ALIGN_STACK_FRAME_SIZE(s) (((s) + MONO_ARCH_FRAME_ALIGNMENT - 1) & ~(MONO_ARCH_FRAME_ALIGNMENT - 1))
/* The 64 bytes here are for outgoing arguments and a bit of spare.
We don't use it all, but it doesn't hurt. */
{
int i;
- for (i = 31; i >= 14; --i) {
+ for (i = MONO_MAX_FREGS - 1; i >= MONO_PPC_FIRST_SAVED_FREG; --i) {
pos -= sizeof (gdouble);
ppc_stfd (code, i, pos, ppc_sp);
}
+ pos -= (MONO_MAX_FREGS - MONO_SAVED_FREGS) * sizeof (gdouble);
pos -= sizeof (gpointer) * MONO_SAVED_GREGS;
- ppc_store_multiple_regs (code, ppc_r13, pos, ppc_sp);
+ ppc_store_multiple_regs (code, MONO_PPC_FIRST_SAVED_GREG, pos, ppc_sp);
return code;
}
/* restore all the regs from the stack */
pos = alloc_size;
- for (i = 31; i >= 14; --i) {
+ for (i = MONO_MAX_FREGS - 1; i >= MONO_PPC_FIRST_SAVED_FREG; --i) {
pos -= sizeof (gdouble);
ppc_lfd (code, i, pos, ppc_sp);
}
+ pos -= (MONO_MAX_FREGS - MONO_SAVED_FREGS) * sizeof (gdouble);
pos -= sizeof (gpointer) * MONO_SAVED_GREGS;
- ppc_load_multiple_regs (code, ppc_r13, pos, ppc_sp);
+ ppc_load_multiple_regs (code, MONO_PPC_FIRST_SAVED_GREG, pos, ppc_sp);
ppc_addic (code, ppc_sp, ppc_sp, alloc_size);
ppc_blr (code);
void
mono_ppc_throw_exception (MonoObject *exc, unsigned long eip, unsigned long esp, mgreg_t *int_regs, gdouble *fp_regs, gboolean rethrow)
{
+ MonoError error;
MonoContext ctx;
/* adjust eip so that it point into the call instruction */
/*printf ("stack in throw: %p\n", esp);*/
MONO_CONTEXT_SET_BP (&ctx, esp);
MONO_CONTEXT_SET_IP (&ctx, eip);
- memcpy (&ctx.regs, int_regs, sizeof (mgreg_t) * MONO_SAVED_GREGS);
- memcpy (&ctx.fregs, fp_regs, sizeof (double) * MONO_SAVED_FREGS);
+ memcpy (&ctx.regs, int_regs, sizeof (mgreg_t) * MONO_MAX_IREGS);
+ memcpy (&ctx.fregs, fp_regs, sizeof (double) * MONO_MAX_FREGS);
- if (mono_object_isinst (exc, mono_defaults.exception_class)) {
+ if (mono_object_isinst_checked (exc, mono_defaults.exception_class, &error)) {
MonoException *mono_ex = (MonoException*)exc;
if (!rethrow) {
mono_ex->stack_trace = NULL;
mono_ex->trace_ips = NULL;
}
}
+ mono_error_assert_ok (&error);
mono_handle_exception (&ctx, exc);
mono_restore_context (&ctx);
else
ppc_mr (code, ppc_r4, ppc_r0); /* caller ip */
/* pointer to the saved fp regs */
- pos = alloc_size - sizeof (gdouble) * MONO_SAVED_FREGS;
+ pos = alloc_size - sizeof (gdouble) * MONO_MAX_FREGS;
ppc_addi (code, ppc_r7, ppc_sp, pos);
/* pointer to the saved int regs */
- pos -= sizeof (gpointer) * MONO_SAVED_GREGS;
+ pos -= sizeof (gpointer) * MONO_MAX_IREGS;
ppc_addi (code, ppc_r6, ppc_sp, pos);
ppc_li (code, ppc_r8, rethrow);
/**
* mono_arch_get_rethrow_exception:
- *
- * Returns a function pointer which can be used to rethrow
+ * \returns a function pointer which can be used to rethrow
* exceptions. The returned function has the following
* signature: void (*func) (MonoException *exc);
- *
*/
gpointer
mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot)
/**
* mono_arch_get_throw_corlib_exception:
- *
- * Returns a function pointer which can be used to raise
+ * \returns a function pointer which can be used to raise
* corlib exceptions. The returned function has the following
* signature: void (*func) (guint32 ex_token, guint32 offset);
* On PPC, we pass the ip instead of the offset
guint32 unwind_info_len;
guint8 *unwind_info;
- frame->type = FRAME_TYPE_MANAGED;
+ if (ji->is_trampoline)
+ frame->type = FRAME_TYPE_TRAMPOLINE;
+ else
+ frame->type = FRAME_TYPE_MANAGED;
unwind_info = mono_jinfo_get_unwind_info (ji, &unwind_info_len);
sframe = (MonoPPCStackFrame*)MONO_CONTEXT_GET_SP (ctx);
MONO_CONTEXT_SET_BP (new_ctx, sframe->sp);
- if (jinfo_get_method (ji)->save_lmf) {
+ if (!ji->is_trampoline && jinfo_get_method (ji)->save_lmf) {
/* sframe->sp points just past the end of the LMF */
guint8 *lmf_addr = (guint8*)sframe->sp - sizeof (MonoLMF);
- memcpy (&new_ctx->fregs, lmf_addr + G_STRUCT_OFFSET (MonoLMF, fregs), sizeof (double) * MONO_SAVED_FREGS);
- memcpy (&new_ctx->regs, lmf_addr + G_STRUCT_OFFSET (MonoLMF, iregs), sizeof (mgreg_t) * MONO_SAVED_GREGS);
+ memcpy (&new_ctx->fregs [MONO_PPC_FIRST_SAVED_FREG], lmf_addr + G_STRUCT_OFFSET (MonoLMF, fregs), sizeof (double) * MONO_SAVED_FREGS);
+ memcpy (&new_ctx->regs [MONO_PPC_FIRST_SAVED_GREG], lmf_addr + G_STRUCT_OFFSET (MonoLMF, iregs), sizeof (mgreg_t) * MONO_SAVED_GREGS);
/* the calling IP is in the parent frame */
sframe = (MonoPPCStackFrame*)sframe->sp;
/* we substract 4, so that the IP points into the call instruction */
} else {
regs [ppc_lr] = ctx->sc_ir;
regs [ppc_sp] = ctx->sc_sp;
- for (i = 0; i < MONO_SAVED_GREGS; ++i)
- regs [ppc_r13 + i] = ctx->regs [i];
+ for (i = MONO_PPC_FIRST_SAVED_GREG; i < MONO_MAX_IREGS; ++i)
+ regs [i] = ctx->regs [i];
mono_unwind_frame (unwind_info, unwind_info_len, ji->code_start,
(guint8*)ji->code_start + ji->code_size,
MONO_CONTEXT_SET_IP (new_ctx, regs [ppc_lr] - 4);
MONO_CONTEXT_SET_BP (new_ctx, cfa);
- for (i = 0; i < MONO_SAVED_GREGS; ++i)
- new_ctx->regs [i] = regs [ppc_r13 + i];
+ for (i = MONO_PPC_FIRST_SAVED_GREG; i < MONO_MAX_IREGS; ++i)
+ new_ctx->regs [i] = regs [i];
}
return TRUE;
MONO_CONTEXT_SET_IP (new_ctx, sframe->lr);*/
MONO_CONTEXT_SET_BP (new_ctx, (*lmf)->ebp);
MONO_CONTEXT_SET_IP (new_ctx, (*lmf)->eip);
- memcpy (&new_ctx->regs, (*lmf)->iregs, sizeof (mgreg_t) * MONO_SAVED_GREGS);
- memcpy (&new_ctx->fregs, (*lmf)->fregs, sizeof (double) * MONO_SAVED_FREGS);
+ memcpy (&new_ctx->regs [MONO_PPC_FIRST_SAVED_GREG], (*lmf)->iregs, sizeof (mgreg_t) * MONO_SAVED_GREGS);
+ memcpy (&new_ctx->fregs [MONO_PPC_FIRST_SAVED_FREG], (*lmf)->fregs, sizeof (double) * MONO_SAVED_FREGS);
frame->ji = ji;
frame->type = FRAME_TYPE_MANAGED_TO_NATIVE;
const char *method;
/* we don't do much now, but we can warn the user with a useful message */
fprintf (stderr, "Stack overflow: IP: %p, SP: %p\n", mono_arch_ip_from_context (sigctx), (gpointer)UCONTEXT_REG_Rn(uc, 1));
- if (ji && jinfo_get_method (ji))
+ if (ji && !ji->is_trampoline && jinfo_get_method (ji))
method = mono_method_full_name (jinfo_get_method (ji), TRUE);
else
method = "Unmanaged";
abort ();
}
if (!ji)
- mono_handle_native_sigsegv (SIGSEGV, sigctx, siginfo);
+ mono_handle_native_crash ("SIGSEGV", sigctx, siginfo);
/* setup a call frame on the real stack so that control is returned there
* and exception handling can continue.
* The frame looks like:
}
#else
UCONTEXT_REG_NIP(uc) = (unsigned long)altstack_handle_and_restore;
+#if _CALL_ELF == 2
+ /* ELF v2 ABI calling convention requires to put the target address into
+ * r12 if we use the global entry point of a function. */
+ UCONTEXT_REG_Rn(uc, 12) = (unsigned long) altstack_handle_and_restore;
+#endif
#endif
UCONTEXT_REG_Rn(uc, 1) = (unsigned long)sp;
UCONTEXT_REG_Rn(uc, PPC_FIRST_ARG_REG) = (unsigned long)(sp + 16);
static void
handle_signal_exception (gpointer obj)
{
- MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = mono_tls_get_jit_tls ();
MonoContext ctx;
memcpy (&ctx, &jit_tls->ex_ctx, sizeof (MonoContext));
}
#else
UCONTEXT_REG_NIP(uc) = (unsigned long)func;
+#if _CALL_ELF == 2
+ /* ELF v2 ABI calling convention requires to put the target address into
+ * r12 if we use the global entry point of a function. */
+ UCONTEXT_REG_Rn(uc, 12) = (unsigned long) func;
+#endif
#endif
#endif
}
* signal is disabled, and we could run arbitrary code though the debugger. So
* resume into the normal stack and do most work there if possible.
*/
- MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = mono_tls_get_jit_tls ();
mgreg_t sp;
void *sigctx = ctx;
int frame_size;
return result;
#endif
}
+
+
+// FIX ME: This is not complete
+void
+mono_arch_setup_async_callback (MonoContext *ctx, void (*async_cb)(void *fun), gpointer user_data)
+{
+ uintptr_t sp = (uintptr_t) MONO_CONTEXT_GET_SP(ctx);
+ sp -= PPC_MINIMAL_STACK_SIZE;
+ *(unsigned long *)sp = MONO_CONTEXT_GET_SP(ctx);
+ MONO_CONTEXT_SET_BP(ctx, sp);
+ MONO_CONTEXT_SET_IP(ctx, (unsigned long) async_cb);
+}
+