* 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__)
+#if (defined(__i386__) && !defined(MONO_CROSS_COMPILE)) || (defined(TARGET_X86))
/*HACK, move this to an eventual mono-signal.c*/
#if defined( __linux__) || defined(__sun) || defined(__APPLE__) || defined(__NetBSD__) || \
#define MONO_CONTEXT_GET_SP(ctx) ((gpointer)((ctx)->esp))
/*We set EAX to zero since we are clobering it anyway*/
+#ifdef _MSC_VER
+#define MONO_CONTEXT_GET_CURRENT(ctx) do { \
+ void *_ptr = &(ctx); \
+ __asm { \
+ __asm mov eax, _ptr \
+ __asm mov [eax+0x00], eax \
+ __asm mov [eax+0x04], ebx \
+ __asm mov [eax+0x08], ecx \
+ __asm mov [eax+0x0c], edx \
+ __asm mov [eax+0x10], ebp \
+ __asm mov [eax+0x14], esp \
+ __asm mov [eax+0x18], esi \
+ __asm mov [eax+0x1c], edi \
+ __asm call $+5 \
+ __asm pop dword ptr [eax+0x20] \
+ } \
+ } while (0)
+#else
#define MONO_CONTEXT_GET_CURRENT(ctx) \
__asm__ __volatile__( \
"movl $0x0, 0x00(%0)\n" \
: \
: "a" (&(ctx)) \
: "memory")
+#endif
+#define MONO_ARCH_HAS_MONO_CONTEXT 1
-#elif defined(__x86_64__) /* defined(__i386__) */
+#elif (defined(__x86_64__) && !defined(MONO_CROSS_COMPILE)) || (defined(TARGET_AMD64)) /* defined(__i386__) */
#if !defined( HOST_WIN32 ) && !defined(__native_client__) && !defined(__native_client_codegen__)
#define MONO_CONTEXT_GET_BP(ctx) ((gpointer)((ctx)->rbp))
#define MONO_CONTEXT_GET_SP(ctx) ((gpointer)((ctx)->rsp))
+#if defined(__native_client__)
+#define MONO_CONTEXT_GET_CURRENT(ctx) \
+ __asm__ __volatile__( \
+ "movq $0x0, %%nacl:0x00(%%r15, %0, 1)\n" \
+ "movq %%rbx, %%nacl:0x08(%%r15, %0, 1)\n" \
+ "movq %%rcx, %%nacl:0x10(%%r15, %0, 1)\n" \
+ "movq %%rdx, %%nacl:0x18(%%r15, %0, 1)\n" \
+ "movq %%rbp, %%nacl:0x20(%%r15, %0, 1)\n" \
+ "movq %%rsp, %%nacl:0x28(%%r15, %0, 1)\n" \
+ "movq %%rsi, %%nacl:0x30(%%r15, %0, 1)\n" \
+ "movq %%rdi, %%nacl:0x38(%%r15, %0, 1)\n" \
+ "movq %%r8, %%nacl:0x40(%%r15, %0, 1)\n" \
+ "movq %%r9, %%nacl:0x48(%%r15, %0, 1)\n" \
+ "movq %%r10, %%nacl:0x50(%%r15, %0, 1)\n" \
+ "movq %%r11, %%nacl:0x58(%%r15, %0, 1)\n" \
+ "movq %%r12, %%nacl:0x60(%%r15, %0, 1)\n" \
+ "movq %%r13, %%nacl:0x68(%%r15, %0, 1)\n" \
+ "movq %%r14, %%nacl:0x70(%%r15, %0, 1)\n" \
+ "movq %%r15, %%nacl:0x78(%%r15, %0, 1)\n" \
+ "leaq (%%rip), %%rdx\n" \
+ "movq %%rdx, %%nacl:0x80(%%r15, %0, 1)\n" \
+ : \
+ : "a" ((int64_t)&(ctx)) \
+ : "rdx", "memory")
+#else
#define MONO_CONTEXT_GET_CURRENT(ctx) \
__asm__ __volatile__( \
"movq $0x0, 0x00(%0)\n" \
: \
: "a" (&(ctx)) \
: "rdx", "memory")
+#endif
+
+#if !defined(HOST_WIN32)
+#define MONO_ARCH_HAS_MONO_CONTEXT 1
+#endif
-#elif defined(__arm__) /* defined(__x86_64__) */
+#elif (defined(__arm__) && !defined(MONO_CROSS_COMPILE)) || (defined(TARGET_ARM)) /* defined(__x86_64__) */
typedef struct {
- gulong eip; // pc
- gulong esp; // sp
- gulong regs [16];
- double fregs [8];
+ mgreg_t pc;
+ mgreg_t regs [16];
+ double fregs [16];
+ mgreg_t cpsr;
} MonoContext;
/* we have the stack pointer, not the base pointer in sigcontext */
-#define MONO_CONTEXT_SET_IP(ctx,ip) do { (ctx)->eip = (int)ip; } while (0);
-#define MONO_CONTEXT_SET_BP(ctx,bp) do { (ctx)->regs [ARMREG_FP] = (int)bp; } while (0);
-#define MONO_CONTEXT_SET_SP(ctx,bp) do { (ctx)->esp = (int)bp; } while (0);
+#define MONO_CONTEXT_SET_IP(ctx,ip) do { (ctx)->pc = (mgreg_t)ip; } while (0);
+#define MONO_CONTEXT_SET_BP(ctx,bp) do { (ctx)->regs [ARMREG_FP] = (mgreg_t)bp; } while (0);
+#define MONO_CONTEXT_SET_SP(ctx,bp) do { (ctx)->regs [ARMREG_SP] = (mgreg_t)bp; } while (0);
-#define MONO_CONTEXT_GET_IP(ctx) ((gpointer)((ctx)->eip))
+#define MONO_CONTEXT_GET_IP(ctx) ((gpointer)((ctx)->pc))
#define MONO_CONTEXT_GET_BP(ctx) ((gpointer)((ctx)->regs [ARMREG_FP]))
-#define MONO_CONTEXT_GET_SP(ctx) ((gpointer)((ctx)->esp))
+#define MONO_CONTEXT_GET_SP(ctx) ((gpointer)((ctx)->regs [ARMREG_SP]))
+
+#define MONO_CONTEXT_GET_CURRENT(ctx) do { \
+ __asm__ __volatile__( \
+ "push {r0}\n" \
+ "push {r1}\n" \
+ "mov r0, %0\n" \
+ "ldr r1, [sp, #4]\n" \
+ "str r1, [r0]!\n" \
+ "ldr r1, [sp, #0]\n" \
+ "str r1, [r0]!\n" \
+ "stmia r0!, {r2-r12}\n" \
+ "str sp, [r0]!\n" \
+ "str lr, [r0]!\n" \
+ "mov r1, pc\n" \
+ "str r1, [r0]!\n" \
+ "pop {r1}\n" \
+ "pop {r0}\n" \
+ : \
+ : "r" (&ctx.regs) \
+ : "memory" \
+ ); \
+ ctx.pc = ctx.regs [15]; \
+} while (0)
+
#elif defined(__mono_ppc__) /* defined(__arm__) */
#elif defined(__ia64__) /*defined(__sparc__) || defined(sparc) */
+#ifndef UNW_LOCAL_ONLY
+
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+
+#endif
+
typedef struct MonoContext {
unw_cursor_t cursor;
/* Whenever the ip in 'cursor' points to the ip where the exception happened */
#define MONO_CONTEXT_GET_BP(ctx) ((gpointer)(mono_ia64_context_get_fp ((ctx))))
#define MONO_CONTEXT_GET_SP(ctx) ((gpointer)(mono_ia64_context_get_sp ((ctx))))
+static inline unw_word_t
+mono_ia64_context_get_ip (MonoContext *ctx)
+{
+ unw_word_t ip;
+ int err;
+
+ err = unw_get_reg (&ctx->cursor, UNW_IA64_IP, &ip);
+ g_assert (err == 0);
+
+ if (ctx->precise_ip) {
+ return ip;
+ } else {
+ /* Subtrack 1 so ip points into the actual instruction */
+ return ip - 1;
+ }
+}
+
+static inline unw_word_t
+mono_ia64_context_get_sp (MonoContext *ctx)
+{
+ unw_word_t sp;
+ int err;
+
+ err = unw_get_reg (&ctx->cursor, UNW_IA64_SP, &sp);
+ g_assert (err == 0);
+
+ return sp;
+}
+
+static inline unw_word_t
+mono_ia64_context_get_fp (MonoContext *ctx)
+{
+ unw_cursor_t new_cursor;
+ unw_word_t fp;
+ int err;
+
+ {
+ unw_word_t ip, sp;
+
+ err = unw_get_reg (&ctx->cursor, UNW_IA64_SP, &sp);
+ g_assert (err == 0);
+
+ err = unw_get_reg (&ctx->cursor, UNW_IA64_IP, &ip);
+ g_assert (err == 0);
+ }
+
+ /* fp is the SP of the parent frame */
+ new_cursor = ctx->cursor;
+
+ err = unw_step (&new_cursor);
+ g_assert (err >= 0);
+
+ err = unw_get_reg (&new_cursor, UNW_IA64_SP, &fp);
+ g_assert (err == 0);
+
+ return fp;
+}
+
+#elif ((defined(__mips__) && !defined(MONO_CROSS_COMPILE)) || (defined(TARGET_MIPS))) && SIZEOF_REGISTER == 4 /* defined(__ia64__) */
+
+typedef struct {
+ mgreg_t sc_pc;
+ mgreg_t sc_regs [32];
+ gfloat sc_fpregs [32];
+} MonoContext;
+
+#define MONO_CONTEXT_SET_IP(ctx,ip) do { (ctx)->sc_pc = (mgreg_t)(ip); } while (0);
+#define MONO_CONTEXT_SET_BP(ctx,bp) do { (ctx)->sc_regs[mips_fp] = (mgreg_t)(bp); } while (0);
+#define MONO_CONTEXT_SET_SP(ctx,sp) do { (ctx)->sc_regs[mips_sp] = (mgreg_t)(sp); } while (0);
+
+#define MONO_CONTEXT_GET_IP(ctx) ((gpointer)((ctx)->sc_pc))
+#define MONO_CONTEXT_GET_BP(ctx) ((gpointer)((ctx)->sc_regs[mips_fp]))
+#define MONO_CONTEXT_GET_SP(ctx) ((gpointer)((ctx)->sc_regs[mips_sp]))
+
+#define MONO_CONTEXT_GET_CURRENT(ctx) \
+ __asm__ __volatile__( \
+ "sw $0,0(%0)\n\t" \
+ "sw $1,4(%0)\n\t" \
+ "sw $2,8(%0)\n\t" \
+ "sw $3,12(%0)\n\t" \
+ "sw $4,16(%0)\n\t" \
+ "sw $5,20(%0)\n\t" \
+ "sw $6,24(%0)\n\t" \
+ "sw $7,28(%0)\n\t" \
+ "sw $8,32(%0)\n\t" \
+ "sw $9,36(%0)\n\t" \
+ "sw $10,40(%0)\n\t" \
+ "sw $11,44(%0)\n\t" \
+ "sw $12,48(%0)\n\t" \
+ "sw $13,52(%0)\n\t" \
+ "sw $14,56(%0)\n\t" \
+ "sw $15,60(%0)\n\t" \
+ "sw $16,64(%0)\n\t" \
+ "sw $17,68(%0)\n\t" \
+ "sw $18,72(%0)\n\t" \
+ "sw $19,76(%0)\n\t" \
+ "sw $20,80(%0)\n\t" \
+ "sw $21,84(%0)\n\t" \
+ "sw $22,88(%0)\n\t" \
+ "sw $23,92(%0)\n\t" \
+ "sw $24,96(%0)\n\t" \
+ "sw $25,100(%0)\n\t" \
+ "sw $26,104(%0)\n\t" \
+ "sw $27,108(%0)\n\t" \
+ "sw $28,112(%0)\n\t" \
+ "sw $29,116(%0)\n\t" \
+ "sw $30,120(%0)\n\t" \
+ "sw $31,124(%0)\n\t" \
+ : : "r" (&(ctx).sc_regs [0]) \
+ : "memory" \
+ )
+
+#elif defined(__s390x__)
+
+#define MONO_ARCH_HAS_MONO_CONTEXT 1
+
+typedef struct ucontext MonoContext;
+
+#define MONO_CONTEXT_SET_IP(ctx,ip) \
+ do { \
+ (ctx)->uc_mcontext.gregs[14] = (unsigned long)ip; \
+ (ctx)->uc_mcontext.psw.addr = (unsigned long)ip; \
+ } while (0);
+
+#define MONO_CONTEXT_SET_SP(ctx,bp) MONO_CONTEXT_SET_BP((ctx),(bp))
+#define MONO_CONTEXT_SET_BP(ctx,bp) \
+ do { \
+ (ctx)->uc_mcontext.gregs[15] = (unsigned long)bp; \
+ (ctx)->uc_stack.ss_sp = (void*)bp; \
+ } while (0)
+
+#define MONO_CONTEXT_GET_IP(ctx) (gpointer) (ctx)->uc_mcontext.psw.addr
+#define MONO_CONTEXT_GET_SP(ctx) ((gpointer)((ctx)->uc_mcontext.gregs[15]))
+#define MONO_CONTEXT_GET_BP(ctx) ((gpointer)((ctx)->uc_mcontext.gregs[11]))
+
+#define MONO_CONTEXT_GET_CURRENT(ctx) \
+ __asm__ __volatile__( \
+ "stmg %%r0,%%r15,0(%0)\n" \
+ : : "r" (&(ctx).uc_mcontext.gregs[0]) \
+ : "memory" \
+ )
+
#else
#error "Implement mono-context for the current arch"