Merge pull request #2964 from ludovic-henry/sgen-monocontext
authorLudovic Henry <ludovic@xamarin.com>
Thu, 5 May 2016 12:46:12 +0000 (08:46 -0400)
committerLudovic Henry <ludovic@xamarin.com>
Thu, 5 May 2016 12:46:12 +0000 (08:46 -0400)
[MonoContext] Migrate remaining architectures + [sgen] Kill USE_MONO_CTX and ARCH_NUM_REGS

mono/metadata/sgen-client-mono.h
mono/metadata/sgen-mono.c
mono/metadata/sgen-os-mach.c
mono/metadata/sgen-os-posix.c
mono/metadata/sgen-os-win32.c
mono/metadata/sgen-stw.c
mono/sgen/sgen-archdep.h
mono/sgen/sgen-debug.c
mono/utils/mono-context.h

index e9f9b1a81a7a5ddeaad89a7ae0ddac596f328fcc..36d6e7e968151fd47f0474fe538fd49a4d1b9bf1 100644 (file)
@@ -64,12 +64,7 @@ struct _SgenClientThreadInfo {
        void *stack_start;
        void *stack_start_limit;
 
-       /*FIXME pretty please finish killing ARCH_NUM_REGS */
-#ifdef USE_MONO_CTX
        MonoContext ctx;                /* ditto */
-#else
-       gpointer regs[ARCH_NUM_REGS];       /* ditto */
-#endif
 };
 
 #else
index bbd97e955df2a69003dafb75b8333c0bb505859b..e4ad7665f56c9dd02f974f3d91fb37360d2167d6 100644 (file)
@@ -2183,11 +2183,7 @@ sgen_client_thread_register (SgenThreadInfo* info, void *stack_bottom_fallback)
                info->client_info.stack_end = (char*)stack_bottom;
        }
 
-#ifdef USE_MONO_CTX
        memset (&info->client_info.ctx, 0, sizeof (MonoContext));
-#else
-       memset (&info->client_info.regs, 0, sizeof (info->client_info.regs));
-#endif
 
        if (mono_gc_get_gc_callbacks ()->thread_attach_func)
                info->client_info.runtime_data = mono_gc_get_gc_callbacks ()->thread_attach_func ();
@@ -2350,13 +2346,9 @@ sgen_client_scan_thread_data (void *start_nursery, void *end_nursery, gboolean p
                }
 
                if (!precise) {
-#ifdef USE_MONO_CTX
                        sgen_conservatively_pin_objects_from ((void**)&info->client_info.ctx, (void**)(&info->client_info.ctx + 1),
                                start_nursery, end_nursery, PIN_TYPE_STACK);
-#else
-                       sgen_conservatively_pin_objects_from ((void**)&info->client_info.regs, (void**)&info->client_info.regs + ARCH_NUM_REGS,
-                                       start_nursery, end_nursery, PIN_TYPE_STACK);
-#endif
+
                        {
                                // This is used on Coop GC for platforms where we cannot get the data for individual registers.
                                // We force a spill of all registers into the stack and pass a chunk of data into sgen.
index 1c45e375af5dffb372cc6b0338189ecee7e96d82..1f87eb137f329b42144817e3f483c7b3ab74df89 100644 (file)
@@ -78,11 +78,7 @@ sgen_suspend_thread (SgenThreadInfo *info)
        if (stack_start >= info->client_info.stack_start_limit && stack_start <= info->client_info.stack_end) {
                info->client_info.stack_start = stack_start;
 
-#ifdef USE_MONO_CTX
                mono_sigctx_to_monoctx (&ctx, &info->client_info.ctx);
-#else
-               ARCH_COPY_SIGCTX_REGS (&info->client_info.regs, &ctx);
-#endif
        } else {
                g_assert (!info->client_info.stack_start);
        }
index dc9d29ff1395ad81be62b1a63edde30f691135dc..5a9bae85b6db35d7c95d81b19ad82a6c2e921a65 100644 (file)
@@ -42,9 +42,6 @@ static void
 suspend_thread (SgenThreadInfo *info, void *context)
 {
        int stop_count;
-#ifndef USE_MONO_CTX
-       gpointer regs [ARCH_NUM_REGS];
-#endif
        MonoContext ctx;
        gpointer stack_start;
 
@@ -55,7 +52,6 @@ suspend_thread (SgenThreadInfo *info, void *context)
        if (0 && info->client_info.stop_count == stop_count)
                return;
 
-#ifdef USE_MONO_CTX
        if (context) {
                mono_sigctx_to_monoctx (context, &ctx);
                info->client_info.stopped_ip = MONO_CONTEXT_GET_IP (&ctx);
@@ -64,30 +60,17 @@ suspend_thread (SgenThreadInfo *info, void *context)
                info->client_info.stopped_ip = NULL;
                stack_start = NULL;
        }
-#else
-       info->client_info.stopped_ip = context ? (gpointer) ARCH_SIGCTX_IP (context) : NULL;
-       stack_start = context ? (char*) ARCH_SIGCTX_SP (context) - REDZONE_SIZE : NULL;
-#endif
 
        /* If stack_start is not within the limits, then don't set it
           in info and we will be restarted. */
        if (stack_start >= info->client_info.stack_start_limit && stack_start <= info->client_info.stack_end) {
                info->client_info.stack_start = stack_start;
 
-#ifdef USE_MONO_CTX
                if (context) {
                        memcpy (&info->client_info.ctx, &ctx, sizeof (MonoContext));
                } else {
                        memset (&info->client_info.ctx, 0, sizeof (MonoContext));
                }
-#else
-               if (context) {
-                       ARCH_COPY_SIGCTX_REGS (regs, context);
-                       memcpy (&info->client_info.regs, regs, sizeof (info->client_info.regs));
-               } else {
-                       memset (&info->client_info.regs, 0, sizeof (info->client_info.regs));
-               }
-#endif
        } else {
                g_assert (!info->client_info.stack_start);
        }
index 3e78396ccd10f536f2bd73be7b41f01c69b76435..8b78616129a9da8ed7a593fab28349e1143bd791 100644 (file)
@@ -58,7 +58,6 @@ sgen_suspend_thread (SgenThreadInfo *info)
        CloseHandle (handle);
 
 #if !defined(MONO_CROSS_COMPILE)
-#ifdef USE_MONO_CTX
        memset (&info->client_info.ctx, 0, sizeof (MonoContext));
 #ifdef TARGET_AMD64
     info->client_info.ctx.gregs[AMD64_RIP] = context.Rip;
@@ -92,19 +91,6 @@ sgen_suspend_thread (SgenThreadInfo *info)
        info->client_info.stopped_ip = (gpointer)context.Eip;
        info->client_info.stack_start = (char*)context.Esp - REDZONE_SIZE;
 #endif
-
-#else
-       info->client_info.regs [0] = context.Edi;
-       info->client_info.regs [1] = context.Esi;
-       info->client_info.regs [2] = context.Ebx;
-       info->client_info.regs [3] = context.Edx;
-       info->client_info.regs [4] = context.Ecx;
-       info->client_info.regs [5] = context.Eax;
-       info->client_info.regs [6] = context.Ebp;
-       info->client_info.regs [7] = context.Esp;
-       info->client_info.stopped_ip = (gpointer)context.Eip;
-       info->client_info.stack_start = (char*)context.Esp - REDZONE_SIZE;
-#endif
 #endif
 
        /* Notify the JIT */
index 4185ce07b8ad67d96965485b9516dcf02fb70a59..501a9f41b85acd08790d8f74784299f7bf3ea01d 100644 (file)
@@ -43,34 +43,20 @@ align_pointer (void *ptr)
        return (void*)p;
 }
 
-#ifdef USE_MONO_CTX
 static MonoContext cur_thread_ctx;
-#else
-static mword cur_thread_regs [ARCH_NUM_REGS];
-#endif
 
 static void
 update_current_thread_stack (void *start)
 {
        int stack_guard = 0;
-#if !defined(USE_MONO_CTX)
-       void *reg_ptr = cur_thread_regs;
-#endif
        SgenThreadInfo *info = mono_thread_info_current ();
        
        info->client_info.stack_start = align_pointer (&stack_guard);
        g_assert (info->client_info.stack_start >= info->client_info.stack_start_limit && info->client_info.stack_start < info->client_info.stack_end);
-#ifdef USE_MONO_CTX
        MONO_CONTEXT_GET_CURRENT (cur_thread_ctx);
        memcpy (&info->client_info.ctx, &cur_thread_ctx, sizeof (MonoContext));
        if (mono_gc_get_gc_callbacks ()->thread_suspend_func)
                mono_gc_get_gc_callbacks ()->thread_suspend_func (info->client_info.runtime_data, NULL, &info->client_info.ctx);
-#else
-       ARCH_STORE_REGS (reg_ptr);
-       memcpy (&info->client_info.regs, reg_ptr, sizeof (info->client_info.regs));
-       if (mono_gc_get_gc_callbacks ()->thread_suspend_func)
-               mono_gc_get_gc_callbacks ()->thread_suspend_func (info->client_info.runtime_data, NULL, NULL);
-#endif
 }
 
 static gboolean
@@ -251,11 +237,7 @@ sgen_client_restart_world (int generation, GGTimingInfo *timing)
 
        FOREACH_THREAD (info) {
                info->client_info.stack_start = NULL;
-#ifdef USE_MONO_CTX
                memset (&info->client_info.ctx, 0, sizeof (MonoContext));
-#else
-               memset (&info->client_info.regs, 0, sizeof (info->client_info.regs));
-#endif
        } FOREACH_THREAD_END
 
        TV_GETTIME (start_handshake);
@@ -363,11 +345,7 @@ update_sgen_info (SgenThreadInfo *info)
                g_error ("BAD STACK");
 
        info->client_info.stack_start = stack_start;
-#ifdef USE_MONO_CTX
        info->client_info.ctx = mono_thread_info_get_suspend_state (info)->ctx;
-#else
-       g_assert_not_reached ();
-#endif
 }
 
 static void
index c72ed326b00afbb28d565e48b113352bed1965d1..da6aaf01823c56265c44967c7e78504ec1165670 100644 (file)
 
 #include <mono/utils/mono-context.h>
 
-/*
- * Define either USE_MONO_CTX, or
- * ARCH_SIGCTX_SP/ARCH_SIGCTX_IP/ARCH_STORE_REGS/ARCH_COPY_SIGCTX_REGS.
- * Define ARCH_NUM_REGS to be the number of general registers in MonoContext, or the
- * number of registers stored by ARCH_STORE_REGS.
- */
-
 #if defined(MONO_CROSS_COMPILE)
 
 #define REDZONE_SIZE   0
 
-#define ARCH_NUM_REGS 0
-#define ARCH_STORE_REGS(ptr)
-#define ARCH_SIGCTX_SP(ctx) NULL
-#define ARCH_SIGCTX_IP(ctx) NULL
-#define ARCH_COPY_SIGCTX_REGS(a,ctx)
-
 #elif defined(TARGET_X86)
 
 #define REDZONE_SIZE   0
 
-#define ARCH_NUM_REGS 8
-
 #ifndef MONO_ARCH_HAS_MONO_CONTEXT
 #error 0
 #endif
 
-#define USE_MONO_CTX
-
 #elif defined(TARGET_AMD64)
 
 #define REDZONE_SIZE   128
 
-#define ARCH_NUM_REGS 16
-#define USE_MONO_CTX
-
 #elif defined(TARGET_POWERPC)
 
 #define REDZONE_SIZE   224
 
-#define ARCH_NUM_REGS 32
-#ifdef __APPLE__
-#define ARCH_STORE_REGS(ptr)   \
-       __asm__ __volatile__(   \
-               "stmw r0, 0(%0)\n"      \
-               :                       \
-               : "b" (ptr)             \
-       )
-#else
-#define ARCH_STORE_REGS(ptr)   \
-       __asm__ __volatile__(   \
-               "stmw 0, 0(%0)\n"       \
-               :                       \
-               : "b" (ptr)             \
-       )
-#endif
-#define ARCH_SIGCTX_SP(ctx)    (UCONTEXT_REG_Rn((ctx), 1))
-#define ARCH_SIGCTX_IP(ctx)    (UCONTEXT_REG_NIP((ctx)))
-#define ARCH_COPY_SIGCTX_REGS(a,ctx) do {      \
-       int __i;        \
-       for (__i = 0; __i < 32; ++__i)  \
-               ((a)[__i]) = (gpointer) UCONTEXT_REG_Rn((ctx), __i);    \
-       } while (0)
-
 /* MS_BLOCK_SIZE must be a multiple of the system pagesize, which for some
    architectures is 64k.  */
 #if defined(TARGET_POWERPC) || defined(TARGET_POWERPC64)
 #elif defined(TARGET_ARM)
 
 #define REDZONE_SIZE   0
-#define USE_MONO_CTX
-
-/* We dont store ip, sp */
-#define ARCH_NUM_REGS 14
 
 #elif defined(TARGET_ARM64)
 
 #else
 #error "Not implemented."
 #endif
-#define USE_MONO_CTX
-#define ARCH_NUM_REGS 31
 
 #elif defined(__mips__)
 
 #define REDZONE_SIZE   0
 
-#define USE_MONO_CTX
-#define ARCH_NUM_REGS 32
-
 #elif defined(__s390x__)
 
 #define REDZONE_SIZE   0
 
-#define USE_MONO_CTX
-#define ARCH_NUM_REGS 16       
-
 #elif defined(__sparc__)
 
 #define REDZONE_SIZE   0
 
-/* Don't bother with %g0 (%r0), it's always hard-coded to zero */
-#define ARCH_NUM_REGS 15       
-#ifdef __sparcv9
-#define ARCH_STORE_REGS(ptr)   \
-       __asm__ __volatile__(   \
-               "st %%g1,[%0]\n\t"      \
-               "st %%g2,[%0+0x08]\n\t" \
-               "st %%g3,[%0+0x10]\n\t" \
-               "st %%g4,[%0+0x18]\n\t" \
-               "st %%g5,[%0+0x20]\n\t" \
-               "st %%g6,[%0+0x28]\n\t" \
-               "st %%g7,[%0+0x30]\n\t" \
-               "st %%o0,[%0+0x38]\n\t" \
-               "st %%o1,[%0+0x40]\n\t" \
-               "st %%o2,[%0+0x48]\n\t" \
-               "st %%o3,[%0+0x50]\n\t" \
-               "st %%o4,[%0+0x58]\n\t" \
-               "st %%o5,[%0+0x60]\n\t" \
-               "st %%o6,[%0+0x68]\n\t" \
-               "st %%o7,[%0+0x70]\n\t" \
-               :                       \
-               : "r" (ptr)             \
-               : "memory"                      \
-       )
-#else
-#define ARCH_STORE_REGS(ptr)   \
-       __asm__ __volatile__(   \
-               "st %%g1,[%0]\n\t"      \
-               "st %%g2,[%0+0x04]\n\t" \
-               "st %%g3,[%0+0x08]\n\t" \
-               "st %%g4,[%0+0x0c]\n\t" \
-               "st %%g5,[%0+0x10]\n\t" \
-               "st %%g6,[%0+0x14]\n\t" \
-               "st %%g7,[%0+0x18]\n\t" \
-               "st %%o0,[%0+0x1c]\n\t" \
-               "st %%o1,[%0+0x20]\n\t" \
-               "st %%o2,[%0+0x24]\n\t" \
-               "st %%o3,[%0+0x28]\n\t" \
-               "st %%o4,[%0+0x2c]\n\t" \
-               "st %%o5,[%0+0x30]\n\t" \
-               "st %%o6,[%0+0x34]\n\t" \
-               "st %%o7,[%0+0x38]\n\t" \
-               :                       \
-               : "r" (ptr)             \
-               : "memory"                      \
-       )
-#endif
-
-#ifndef REG_SP
-#define REG_SP REG_O6
-#endif
-
-#define ARCH_SIGCTX_SP(ctx)    (((ucontext_t *)(ctx))->uc_mcontext.gregs [REG_SP])
-#define ARCH_SIGCTX_IP(ctx)    (((ucontext_t *)(ctx))->uc_mcontext.gregs [REG_PC])
-#define ARCH_COPY_SIGCTX_REGS(a,ctx) do {      \
-       (a)[0] = (gpointer) (((ucontext_t *)(ctx))->uc_mcontext.gregs [REG_G1]);        \
-       (a)[1] = (gpointer) (((ucontext_t *)(ctx))->uc_mcontext.gregs [REG_G2]);        \
-       (a)[2] = (gpointer) (((ucontext_t *)(ctx))->uc_mcontext.gregs [REG_G3]);        \
-       (a)[3] = (gpointer) (((ucontext_t *)(ctx))->uc_mcontext.gregs [REG_G4]);        \
-       (a)[4] = (gpointer) (((ucontext_t *)(ctx))->uc_mcontext.gregs [REG_G5]);        \
-       (a)[5] = (gpointer) (((ucontext_t *)(ctx))->uc_mcontext.gregs [REG_G6]);        \
-       (a)[6] = (gpointer) (((ucontext_t *)(ctx))->uc_mcontext.gregs [REG_G7]);        \
-       (a)[7] = (gpointer) (((ucontext_t *)(ctx))->uc_mcontext.gregs [REG_O0]);        \
-       (a)[8] = (gpointer) (((ucontext_t *)(ctx))->uc_mcontext.gregs [REG_O1]);        \
-       (a)[9] = (gpointer) (((ucontext_t *)(ctx))->uc_mcontext.gregs [REG_O2]);        \
-       (a)[10] = (gpointer) (((ucontext_t *)(ctx))->uc_mcontext.gregs [REG_O3]);       \
-       (a)[11] = (gpointer) (((ucontext_t *)(ctx))->uc_mcontext.gregs [REG_O4]);       \
-       (a)[12] = (gpointer) (((ucontext_t *)(ctx))->uc_mcontext.gregs [REG_O5]);       \
-       (a)[13] = (gpointer) (((ucontext_t *)(ctx))->uc_mcontext.gregs [REG_O6]);       \
-       (a)[14] = (gpointer) (((ucontext_t *)(ctx))->uc_mcontext.gregs [REG_O7]);       \
-       } while (0)
-
 #endif
 
 #endif /* __MONO_SGENARCHDEP_H__ */
index 28e77a77e87d53c9a3145a586f0545f3b049c639..1d3c897bd726f4277fc1c7a04d1590aea4acb066 100644 (file)
@@ -493,10 +493,10 @@ static void
 find_pinning_ref_from_thread (char *obj, size_t size)
 {
 #ifndef SGEN_WITHOUT_MONO
-       int j;
        char *endobj = obj + size;
 
        FOREACH_THREAD (info) {
+               mword *ctxstart, *ctxcurrent, *ctxend;
                char **start = (char**)info->client_info.stack_start;
                if (info->client_info.skip || info->client_info.gc_disabled)
                        continue;
@@ -506,15 +506,11 @@ find_pinning_ref_from_thread (char *obj, size_t size)
                        start++;
                }
 
-               for (j = 0; j < ARCH_NUM_REGS; ++j) {
-#ifdef USE_MONO_CTX
-                       mword w = ((mword*)&info->client_info.ctx) [j];
-#else
-                       mword w = (mword)&info->client_info.regs [j];
-#endif
+               for (ctxstart = ctxcurrent = (mword*) &info->client_info.ctx, ctxend = (mword*) (&info->client_info.ctx + 1); ctxcurrent < ctxend; ctxcurrent ++) {
+                       mword w = *ctxcurrent;
 
                        if (w >= (mword)obj && w < (mword)obj + size)
-                               SGEN_LOG (0, "Object %p referenced in saved reg %d of thread %p (id %p)", obj, j, info, (gpointer)mono_thread_info_get_tid (info));
+                               SGEN_LOG (0, "Object %p referenced in saved reg %d of thread %p (id %p)", obj, (int) (ctxcurrent - ctxstart), info, (gpointer)mono_thread_info_get_tid (info));
                }
        } FOREACH_THREAD_END
 #endif
index 374171cf6747b828f5e85b5e649cc07fd08a6a8e..e0741ccf5db775be7ab9c2ad3c68e61b4efb9e5a 100644 (file)
@@ -10,6 +10,8 @@
 #ifndef __MONO_MONO_CONTEXT_H__
 #define __MONO_MONO_CONTEXT_H__
 
+#include <glib.h>
+
 #include "mono-compiler.h"
 #include "mono-sigcontext.h"
 #include "mono-machine.h"
  * MONO_CONTEXT_GET_CURRENT captures the current context as close as possible. One reg might be clobbered
  *  to hold the address of the target MonoContext. It will be a caller save one, so should not be a problem.
  */
-#if (defined(__i386__) && !defined(MONO_CROSS_COMPILE)) || (defined(TARGET_X86))
+#if defined(MONO_CROSS_COMPILE)
+
+typedef struct {} MonoContext;
+
+#define MONO_CONTEXT_SET_IP(ctx,ip) g_assert_not_reached ()
+#define MONO_CONTEXT_SET_BP(ctx,bp) g_assert_not_reached ()
+#define MONO_CONTEXT_SET_SP(ctx,sp) g_assert_not_reached ()
+
+#define MONO_CONTEXT_GET_IP(ctx) NULL
+#define MONO_CONTEXT_GET_BP(ctx) NULL
+#define MONO_CONTEXT_GET_SP(ctx) NULL
+
+#define MONO_CONTEXT_GET_CURRENT(ctx) do {} while (0)
+
+#elif defined(__i386__) || defined(TARGET_X86)
 
 /*HACK, move this to an eventual mono-signal.c*/
 #if defined( __linux__) || defined(__sun) || defined(__APPLE__) || defined(__NetBSD__) || \
@@ -146,7 +162,7 @@ typedef struct {
 
 #define MONO_ARCH_HAS_MONO_CONTEXT 1
 
-#elif (defined(__x86_64__) && !defined(MONO_CROSS_COMPILE)) || (defined(TARGET_AMD64)) /* defined(__i386__) */
+#elif defined(__x86_64__) || defined(TARGET_AMD64) /* defined(__i386__) */
 
 #include <mono/arch/amd64/amd64-codegen.h>
 
@@ -230,7 +246,7 @@ extern void mono_context_get_current (void *);
 
 #define MONO_ARCH_HAS_MONO_CONTEXT 1
 
-#elif (defined(__arm__) && !defined(MONO_CROSS_COMPILE)) || (defined(TARGET_ARM)) /* defined(__x86_64__) */
+#elif defined(__arm__) || defined(TARGET_ARM) /* defined(__x86_64__) */
 
 #include <mono/arch/arm/arm-codegen.h>
 
@@ -284,7 +300,7 @@ typedef struct {
 
 #define MONO_ARCH_HAS_MONO_CONTEXT 1
 
-#elif (defined(__aarch64__) && !defined(MONO_CROSS_COMPILE)) || (defined(TARGET_ARM64))
+#elif defined(__aarch64__) || defined(TARGET_ARM64)
 
 #include <mono/arch/arm64/arm64-codegen.h>
 
@@ -453,31 +469,105 @@ typedef struct {
                : "memory"                      \
        )
 
-#define MONO_ARCH_HAS_MONO_CONTEXT 1
-
-#else 
+#else /* !defined(__mono_ppc64__) */
 
 typedef struct {
-       gulong sc_ir;          // pc 
-       gulong sc_sp;          // r1
-       mgreg_t regs [19]; /*FIXME, this must be changed to 32 for sgen*/
-       double fregs [18];
+       mgreg_t sc_ir;          // pc
+       mgreg_t sc_sp;          // r1
+       mgreg_t regs [32];
+       double fregs [32];
 } MonoContext;
 
 /* we have the stack pointer, not the base pointer in sigcontext */
-#define MONO_CONTEXT_SET_IP(ctx,ip) do { (ctx)->sc_ir = (gulong)ip; } while (0);
+#define MONO_CONTEXT_SET_IP(ctx,ip) do { (ctx)->sc_ir = (mgreg_t)ip; } while (0);
 /* FIXME: should be called SET_SP */
-#define MONO_CONTEXT_SET_BP(ctx,bp) do { (ctx)->sc_sp = (gulong)bp; } while (0);
-#define MONO_CONTEXT_SET_SP(ctx,sp) do { (ctx)->sc_sp = (gulong)sp; } while (0);
+#define MONO_CONTEXT_SET_BP(ctx,bp) do { (ctx)->sc_sp = (mgreg_t)bp; } while (0);
+#define MONO_CONTEXT_SET_SP(ctx,sp) do { (ctx)->sc_sp = (mgreg_t)sp; } while (0);
 
 #define MONO_CONTEXT_GET_IP(ctx) ((gpointer)((ctx)->sc_ir))
 #define MONO_CONTEXT_GET_BP(ctx) ((gpointer)((ctx)->regs [ppc_r31-13]))
 #define MONO_CONTEXT_GET_SP(ctx) ((gpointer)((ctx)->sc_sp))
+
+#define MONO_CONTEXT_GET_CURRENT(ctx)  \
+       __asm__ __volatile__(   \
+               "std 0, 0(%0)\n"        \
+               "std 1, 4(%0)\n"        \
+               "std 0, 4*0+8(%0)\n"    \
+               "std 1, 4*1+8(%0)\n"    \
+               "std 2, 4*2+8(%0)\n"    \
+               "std 3, 4*3+8(%0)\n"    \
+               "std 4, 4*4+8(%0)\n"    \
+               "std 5, 4*5+8(%0)\n"    \
+               "std 6, 4*6+8(%0)\n"    \
+               "std 7, 4*7+8(%0)\n"    \
+               "std 8, 4*8+8(%0)\n"    \
+               "std 9, 4*9+8(%0)\n"    \
+               "std 10, 4*10+8(%0)\n"  \
+               "std 11, 4*11+8(%0)\n"  \
+               "std 12, 4*12+8(%0)\n"  \
+               "std 13, 4*13+8(%0)\n"  \
+               "std 14, 4*14+8(%0)\n"  \
+               "std 15, 4*15+8(%0)\n"  \
+               "std 16, 4*16+8(%0)\n"  \
+               "std 17, 4*17+8(%0)\n"  \
+               "std 18, 4*18+8(%0)\n"  \
+               "std 19, 4*19+8(%0)\n"  \
+               "std 20, 4*20+8(%0)\n"  \
+               "std 21, 4*21+8(%0)\n"  \
+               "std 22, 4*22+8(%0)\n"  \
+               "std 23, 4*23+8(%0)\n"  \
+               "std 24, 4*24+8(%0)\n"  \
+               "std 25, 4*25+8(%0)\n"  \
+               "std 26, 4*26+8(%0)\n"  \
+               "std 27, 4*27+8(%0)\n"  \
+               "std 28, 4*28+8(%0)\n"  \
+               "std 29, 4*29+8(%0)\n"  \
+               "std 30, 4*30+8(%0)\n"  \
+               "std 31, 4*31+8(%0)\n"  \
+               "stfd 0, 8*0+4*32+8(%0)\n"      \
+               "stfd 1, 8*1+4*32+8(%0)\n"      \
+               "stfd 2, 8*2+4*32+8(%0)\n"      \
+               "stfd 3, 8*3+4*32+8(%0)\n"      \
+               "stfd 4, 8*4+4*32+8(%0)\n"      \
+               "stfd 5, 8*5+4*32+8(%0)\n"      \
+               "stfd 6, 8*6+4*32+8(%0)\n"      \
+               "stfd 7, 8*7+4*32+8(%0)\n"      \
+               "stfd 8, 8*8+4*32+8(%0)\n"      \
+               "stfd 9, 8*9+4*32+8(%0)\n"      \
+               "stfd 10, 8*10+4*32+8(%0)\n"    \
+               "stfd 11, 8*11+4*32+8(%0)\n"    \
+               "stfd 12, 8*12+4*32+8(%0)\n"    \
+               "stfd 13, 8*13+4*32+8(%0)\n"    \
+               "stfd 14, 8*14+4*32+8(%0)\n"    \
+               "stfd 15, 8*15+4*32+8(%0)\n"    \
+               "stfd 16, 8*16+4*32+8(%0)\n"    \
+               "stfd 17, 8*17+4*32+8(%0)\n"    \
+               "stfd 18, 8*18+4*32+8(%0)\n"    \
+               "stfd 19, 8*19+4*32+8(%0)\n"    \
+               "stfd 20, 8*20+4*32+8(%0)\n"    \
+               "stfd 21, 8*21+4*32+8(%0)\n"    \
+               "stfd 22, 8*22+4*32+8(%0)\n"    \
+               "stfd 23, 8*23+4*32+8(%0)\n"    \
+               "stfd 24, 8*24+4*32+8(%0)\n"    \
+               "stfd 25, 8*25+4*32+8(%0)\n"    \
+               "stfd 26, 8*26+4*32+8(%0)\n"    \
+               "stfd 27, 8*27+4*32+8(%0)\n"    \
+               "stfd 28, 8*28+4*32+8(%0)\n"    \
+               "stfd 29, 8*29+4*32+8(%0)\n"    \
+               "stfd 30, 8*30+4*32+8(%0)\n"    \
+               "stfd 31, 8*31+4*32+8(%0)\n"    \
+               : : "r" (&(ctx))        \
+               : "memory"                      \
+       )
+
 #endif
 
+#define MONO_ARCH_HAS_MONO_CONTEXT 1
+
 #elif defined(__sparc__) || defined(sparc) /* defined(__mono_ppc__) */
 
 typedef struct MonoContext {
+       mgreg_t regs [15];
        guint8 *ip;
        gpointer *sp;
        gpointer *fp;
@@ -491,6 +581,54 @@ typedef struct MonoContext {
 #define MONO_CONTEXT_GET_BP(ctx) ((gpointer)((ctx)->fp))
 #define MONO_CONTEXT_GET_SP(ctx) ((gpointer)((ctx)->sp))
 
+#ifdef __sparcv9
+#define MONO_CONTEXT_GET_CURRENT(ctx)  \
+       __asm__ __volatile__(   \
+               "st %%g1,[%0]\n"        \
+               "st %%g2,[%0+0x08]\n"   \
+               "st %%g3,[%0+0x10]\n"   \
+               "st %%g4,[%0+0x18]\n"   \
+               "st %%g5,[%0+0x20]\n"   \
+               "st %%g6,[%0+0x28]\n"   \
+               "st %%g7,[%0+0x30]\n"   \
+               "st %%o0,[%0+0x38]\n"   \
+               "st %%o1,[%0+0x40]\n"   \
+               "st %%o2,[%0+0x48]\n"   \
+               "st %%o3,[%0+0x50]\n"   \
+               "st %%o4,[%0+0x58]\n"   \
+               "st %%o5,[%0+0x60]\n"   \
+               "st %%o6,[%0+0x68]\n"   \
+               "st %%o7,[%0+0x70]\n"   \
+               :                       \
+               : "r" (&(ctx))          \
+               : "memory"                      \
+       )
+#else
+#define MONO_CONTEXT_GET_CURRENT(ctx)  \
+       __asm__ __volatile__(   \
+               "st %%g1,[%0]\n"        \
+               "st %%g2,[%0+0x04]\n"   \
+               "st %%g3,[%0+0x08]\n"   \
+               "st %%g4,[%0+0x0c]\n"   \
+               "st %%g5,[%0+0x10]\n"   \
+               "st %%g6,[%0+0x14]\n"   \
+               "st %%g7,[%0+0x18]\n"   \
+               "st %%o0,[%0+0x1c]\n"   \
+               "st %%o1,[%0+0x20]\n"   \
+               "st %%o2,[%0+0x24]\n"   \
+               "st %%o3,[%0+0x28]\n"   \
+               "st %%o4,[%0+0x2c]\n"   \
+               "st %%o5,[%0+0x30]\n"   \
+               "st %%o6,[%0+0x34]\n"   \
+               "st %%o7,[%0+0x38]\n"   \
+               :                       \
+               : "r" (&(ctx))          \
+               : "memory"                      \
+       )
+#endif
+
+#define MONO_ARCH_HAS_MONO_CONTEXT 1
+
 #elif defined(__ia64__) /*defined(__sparc__) || defined(sparc) */
 
 #ifndef UNW_LOCAL_ONLY
@@ -573,7 +711,7 @@ mono_ia64_context_get_fp (MonoContext *ctx)
        return fp;
 }
 
-#elif ((defined(__mips__) && !defined(MONO_CROSS_COMPILE)) || (defined(TARGET_MIPS))) && SIZEOF_REGISTER == 4 /* defined(__ia64__) */
+#elif (defined(__mips__) || defined(TARGET_MIPS)) && SIZEOF_REGISTER == 4 /* defined(__ia64__) */
 
 #include <mono/arch/mips/mips-codegen.h>