X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fexceptions-sparc.c;h=184d28bdcc14d348b5eae91a48df571072d72213;hb=e51a9b6ba1a93bc981639a706c93bee413099fd6;hp=eba808cebceac6ac63a3d1831f60eaaa0968f2b0;hpb=e1794c04f1c873e95db1112894c8d66f757ccf04;p=mono.git diff --git a/mono/mini/exceptions-sparc.c b/mono/mini/exceptions-sparc.c index eba808cebce..184d28bdcc1 100644 --- a/mono/mini/exceptions-sparc.c +++ b/mono/mini/exceptions-sparc.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "mini.h" #include "mini-sparc.h" @@ -40,14 +41,14 @@ gpointer mono_arch_get_restore_context (void) { - static guint32 start [32]; + static guint32 *start; static int inited = 0; guint32 *code; if (inited) return start; - code = start; + code = start = mono_global_codeman_reserve (32 * sizeof (guint32)); sparc_ldi_imm (code, sparc_o0, G_STRUCT_OFFSET (MonoContext, ip), sparc_i7); sparc_ldi_imm (code, sparc_o0, G_STRUCT_OFFSET (MonoContext, sp), sparc_i6); @@ -75,7 +76,7 @@ mono_arch_get_restore_context (void) gpointer mono_arch_get_call_filter (void) { - static guint32 start [64]; + static guint32 *start; static int inited = 0; guint32 *code; int i; @@ -83,7 +84,7 @@ mono_arch_get_call_filter (void) if (inited) return start; - code = start; + code = start = mono_global_codeman_reserve (64 * sizeof (guint32)); /* * There are two frames here: @@ -176,16 +177,12 @@ throw_exception (MonoObject *exc, gpointer sp, gpointer ip, gboolean rethrow) g_assert_not_reached (); } -gpointer +static gpointer get_throw_exception (gboolean rethrow) { - guint32 *start; - guint32 *code; - - if (inited) - return start; + guint32 *start, *code; - code = start = g_new0 (16 * sizeof (guint32)); + code = start = mono_global_codeman_reserve (16 * sizeof (guint32)); sparc_save_imm (code, sparc_sp, -512, sparc_sp); @@ -252,7 +249,7 @@ mono_arch_get_rethrow_exception (void) gpointer mono_arch_get_throw_exception_by_name (void) { - static guint32 start [64]; + static guint32 *start; static int inited = 0; guint32 *code; int reg; @@ -261,7 +258,7 @@ mono_arch_get_throw_exception_by_name (void) return start; inited = 1; - code = start; + code = start = mono_global_codeman_reserve (64 * sizeof (guint32)); #ifdef SPARCV9 reg = sparc_g4; @@ -291,7 +288,64 @@ mono_arch_get_throw_exception_by_name (void) g_assert ((code - start) < 32); return start; -} +} + +/** + * mono_arch_get_throw_corlib_exception: + * + * 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); + * Here, offset is the offset which needs to be substracted from the caller IP + * to get the IP of the throw. Passing the offset has the advantage that it + * needs no relocations in the caller. + */ +gpointer +mono_arch_get_throw_corlib_exception (void) +{ + static guint32 *start; + static int inited = 0; + guint32 *code; + int reg; + + if (inited) + return start; + + inited = 1; + code = start = mono_global_codeman_reserve (64 * sizeof (guint32)); + +#ifdef SPARCV9 + reg = sparc_g4; +#else + reg = sparc_g1; +#endif + + sparc_mov_reg_reg (code, sparc_o7, sparc_o2); + sparc_save_imm (code, sparc_sp, -160, sparc_sp); + + sparc_set (code, MONO_TOKEN_TYPE_DEF, sparc_o7); + sparc_add (code, FALSE, sparc_i0, sparc_o7, sparc_o1); + sparc_set (code, mono_defaults.exception_class->image, sparc_o0); + sparc_set (code, mono_exception_from_token, sparc_o7); + sparc_jmpl (code, sparc_o7, sparc_g0, sparc_callsite); + sparc_nop (code); + + /* Return to the caller, so exception handling does not see this frame */ + sparc_restore (code, sparc_o0, sparc_g0, sparc_o0); + + /* Compute throw ip */ + sparc_sll_imm (code, sparc_o1, 2, sparc_o1); + sparc_sub (code, 0, sparc_o2, sparc_o1, sparc_o7); + + sparc_set (code, mono_arch_get_throw_exception (), reg); + /* Use a jmp instead of a call so o7 is preserved */ + sparc_jmpl_imm (code, reg, 0, sparc_g0); + sparc_nop (code); + + g_assert ((code - start) < 32); + + return start; +} /* mono_arch_find_jit_info: * @@ -338,8 +392,7 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInf new_ctx->sp = (gpointer*)(window [sparc_i6 - 16]); new_ctx->fp = (gpointer*)(MONO_SPARC_WINDOW_ADDR (new_ctx->sp) [sparc_i6 - 16]); - *res = *ji; - return res; + return ji; } else { if (!(*lmf)) @@ -351,7 +404,6 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInf return (gpointer)-1; if ((ji = mono_jit_info_table_find (domain, (gpointer)(*lmf)->ip))) { - *res = *ji; } else { memset (res, 0, sizeof (MonoJitInfo)); res->method = (*lmf)->method; @@ -363,7 +415,7 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInf *lmf = (*lmf)->previous_lmf; - return res; + return ji ? ji : res; } } @@ -373,6 +425,61 @@ mono_arch_has_unwind_info (gconstpointer addr) return FALSE; } +#ifdef __linux__ + +gboolean +mono_arch_handle_exception (void *sigctx, gpointer obj, gboolean test_only) +{ + MonoContext mctx; + struct sigcontext *sc = sigctx; + gpointer *window; + +#ifdef SPARCV9 + mctx.ip = (gpointer) sc->sigc_regs.tpc; + mctx.sp = (gpointer) sc->sigc_regs.u_regs[14]; +#else + mctx.ip = (gpointer) sc->si_regs.pc; + mctx.sp = (gpointer) sc->si_regs.u_regs[14]; +#endif + + window = (gpointer*)(((guint8*)mctx.sp) + MONO_SPARC_STACK_BIAS); + mctx.fp = window [sparc_fp - 16]; + + mono_handle_exception (&mctx, obj, mctx.ip, test_only); + +#ifdef SPARCV9 + sc->sigc_regs.tpc = (unsigned long) mctx.ip; + sc->sigc_regs.tnpc = (unsigned long) (mctx.ip + 4); + sc->sigc_regs.u_regs[14] = (unsigned long) mctx.sp; +#else + sc->si_regs.pc = (unsigned long) mctx.ip; + sc->si_regs.npc = (unsigned long) (mctx.ip + 4); + sc->si_regs.u_regs[14] = (unsigned long) mctx.sp; +#endif + + window = (gpointer*)(((guint8*)mctx.sp) + MONO_SPARC_STACK_BIAS); + window [sparc_fp - 16] = mctx.fp; + + return TRUE; +} + +gpointer +mono_arch_ip_from_context (void *sigctx) +{ + struct sigcontext *sc = sigctx; + gpointer *ret; + +#ifdef SPARCV9 + ret = (gpointer) sc->sigc_regs.tpc; +#else + ret = (gpointer) sc->si_regs.pc; +#endif + + return ret; +} + +#else /* !__linux__ */ + gboolean mono_arch_handle_exception (void *sigctx, gpointer obj, gboolean test_only) { @@ -385,12 +492,7 @@ mono_arch_handle_exception (void *sigctx, gpointer obj, gboolean test_only) * under documented under solaris. The code below seems to work under * Solaris 9. */ -#ifndef __linux__ g_assert (!ctx->uc_mcontext.gwins); -#else - /* better, but doesn't work all the time. need to rethink! */ - g_assert (!ctx->uc_mcontext.gregs); -#endif mctx.ip = ctx->uc_mcontext.gregs [REG_PC]; mctx.sp = ctx->uc_mcontext.gregs [REG_SP]; @@ -416,3 +518,4 @@ mono_arch_ip_from_context (void *sigctx) return (gpointer)ctx->uc_mcontext.gregs [REG_PC]; } +#endif