Merge pull request #704 from jgagnon/master
[mono.git] / mono / utils / mono-context.h
old mode 100755 (executable)
new mode 100644 (file)
index 251e581..dc53e85
 #include <signal.h>
 #endif
 
+#if defined (HOST_WATCHOS) || defined (HOST_APPLETVOS)
+#include <libunwind.h>
+#endif
+
 /*
  * General notes about mono-context.
  * Each arch defines a MonoContext struct with all GPR regs + IP/PC.
@@ -30,7 +34,9 @@
 /*HACK, move this to an eventual mono-signal.c*/
 #if defined( __linux__) || defined(__sun) || defined(__APPLE__) || defined(__NetBSD__) || \
        defined(__FreeBSD__) || defined(__OpenBSD__)
-#define MONO_SIGNAL_USE_SIGACTION
+#ifdef HAVE_SIGACTION
+#define MONO_SIGNAL_USE_SIGACTION 1
+#endif
 #endif
 
 #if defined(__native_client__)
@@ -145,40 +151,28 @@ typedef struct {
 
 #elif (defined(__x86_64__) && !defined(MONO_CROSS_COMPILE)) || (defined(TARGET_AMD64)) /* defined(__i386__) */
 
+#include <mono/arch/amd64/amd64-codegen.h>
 
 #if !defined( HOST_WIN32 ) && !defined(__native_client__) && !defined(__native_client_codegen__)
 
+#ifdef HAVE_SIGACTION
 #define MONO_SIGNAL_USE_SIGACTION 1
+#endif
 
 #endif
 
 typedef struct {
-       mgreg_t rax;
-       mgreg_t rbx;
-       mgreg_t rcx;
-       mgreg_t rdx;
-       mgreg_t rbp;
-       mgreg_t rsp;
-    mgreg_t rsi;
-       mgreg_t rdi;
-       mgreg_t r8;
-       mgreg_t r9;
-       mgreg_t r10;
-       mgreg_t r11;
-       mgreg_t r12;
-       mgreg_t r13;
-       mgreg_t r14;
-       mgreg_t r15;
-       mgreg_t rip;
+       mgreg_t gregs [AMD64_NREG];
+       double fregs [AMD64_XMM_NREG];
 } MonoContext;
 
-#define MONO_CONTEXT_SET_IP(ctx,ip) do { (ctx)->rip = (mgreg_t)(ip); } while (0); 
-#define MONO_CONTEXT_SET_BP(ctx,bp) do { (ctx)->rbp = (mgreg_t)(bp); } while (0); 
-#define MONO_CONTEXT_SET_SP(ctx,esp) do { (ctx)->rsp = (mgreg_t)(esp); } while (0); 
+#define MONO_CONTEXT_SET_IP(ctx,ip) do { (ctx)->gregs [AMD64_RIP] = (mgreg_t)(ip); } while (0);
+#define MONO_CONTEXT_SET_BP(ctx,bp) do { (ctx)->gregs [AMD64_RBP] = (mgreg_t)(bp); } while (0);
+#define MONO_CONTEXT_SET_SP(ctx,esp) do { (ctx)->gregs [AMD64_RSP] = (mgreg_t)(esp); } while (0);
 
-#define MONO_CONTEXT_GET_IP(ctx) ((gpointer)((ctx)->rip))
-#define MONO_CONTEXT_GET_BP(ctx) ((gpointer)((ctx)->rbp))
-#define MONO_CONTEXT_GET_SP(ctx) ((gpointer)((ctx)->rsp))
+#define MONO_CONTEXT_GET_IP(ctx) ((gpointer)((ctx)->gregs [AMD64_RIP]))
+#define MONO_CONTEXT_GET_BP(ctx) ((gpointer)((ctx)->gregs [AMD64_RBP]))
+#define MONO_CONTEXT_GET_SP(ctx) ((gpointer)((ctx)->gregs [AMD64_RSP]))
 
 #if defined (HOST_WIN32) && !defined(__GNUC__)
 /* msvc doesn't support inline assembly, so have to use a separate .asm file */
@@ -189,11 +183,11 @@ extern void mono_context_get_current (void *);
 #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 %%rcx, %%nacl:0x08(%%r15, %0, 1)\n"       \
+               "movq %%rdx, %%nacl:0x10(%%r15, %0, 1)\n"       \
+               "movq %%rbx, %%nacl:0x18(%%r15, %0, 1)\n"       \
+               "movq %%rsp, %%nacl:0x20(%%r15, %0, 1)\n"       \
+               "movq %%rbp, %%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"       \
@@ -210,14 +204,15 @@ extern void mono_context_get_current (void *);
                : "a" ((int64_t)&(ctx)) \
                : "rdx", "memory")
 #else
+
 #define MONO_CONTEXT_GET_CURRENT(ctx)  \
        __asm__ __volatile__(   \
                "movq $0x0,  0x00(%0)\n"        \
-               "movq %%rbx, 0x08(%0)\n"        \
-               "movq %%rcx, 0x10(%0)\n"        \
-               "movq %%rdx, 0x18(%0)\n"        \
-               "movq %%rbp, 0x20(%0)\n"        \
-               "movq %%rsp, 0x28(%0)\n"        \
+               "movq %%rcx, 0x08(%0)\n"        \
+               "movq %%rdx, 0x10(%0)\n"        \
+               "movq %%rbx, 0x18(%0)\n"        \
+               "movq %%rsp, 0x20(%0)\n"        \
+               "movq %%rbp, 0x28(%0)\n"        \
                "movq %%rsi, 0x30(%0)\n"        \
                "movq %%rdi, 0x38(%0)\n"        \
                "movq %%r8,  0x40(%0)\n"        \
@@ -240,6 +235,8 @@ extern void mono_context_get_current (void *);
 
 #elif (defined(__arm__) && !defined(MONO_CROSS_COMPILE)) || (defined(TARGET_ARM)) /* defined(__x86_64__) */
 
+#include <mono/arch/arm/arm-codegen.h>
+
 typedef struct {
        mgreg_t pc;
        mgreg_t regs [16];
@@ -256,6 +253,33 @@ typedef struct {
 #define MONO_CONTEXT_GET_BP(ctx) ((gpointer)((ctx)->regs [ARMREG_FP]))
 #define MONO_CONTEXT_GET_SP(ctx) ((gpointer)((ctx)->regs [ARMREG_SP]))
 
+#if defined(HOST_WATCHOS)
+
+#define MONO_CONTEXT_GET_CURRENT(ctx) do { \
+       unw_context_t uctx; \
+       unw_cursor_t c; \
+       unw_word_t data; \
+       g_assert (unw_getcontext (&uctx) == 0); \
+       g_assert (unw_init_local (&c, &uctx) == 0); \
+       for (int reg = 0; reg < 13; ++reg) { \
+               unw_get_reg (&c, (unw_regnum_t) UNW_ARM_R0 + reg, &data); \
+               ctx.regs[reg] = data; \
+       } \
+       unw_get_reg (&c, UNW_ARM_SP, &data); \
+       ctx.regs[ARMREG_SP] = data; \
+       unw_get_reg (&c, UNW_ARM_LR, &data); \
+       ctx.regs[ARMREG_LR] = data; \
+       unw_get_reg (&c, UNW_ARM_IP, &data); \
+       ctx.regs[ARMREG_PC] = data; \
+       ctx.pc = ctx.regs[ARMREG_PC]; \
+       for (int reg = 0; reg < 16; ++reg) { \
+               unw_get_reg (&c, (unw_regnum_t) UNW_ARM_D0 + reg, &data); \
+               ctx.fregs[reg] = data; \
+       } \
+} while (0);
+
+#else
+
 #define MONO_CONTEXT_GET_CURRENT(ctx)  do {    \
        __asm__ __volatile__(                   \
                "push {r0}\n"                           \
@@ -279,6 +303,10 @@ typedef struct {
        ctx.pc = ctx.regs [15];                 \
 } while (0)
 
+#endif
+
+#define MONO_ARCH_HAS_MONO_CONTEXT 1
+
 #elif (defined(__aarch64__) && !defined(MONO_CROSS_COMPILE)) || (defined(TARGET_ARM64))
 
 #include <mono/arch/arm64/arm64-codegen.h>
@@ -297,6 +325,15 @@ typedef struct {
 #define MONO_CONTEXT_GET_BP(ctx) (gpointer)((ctx)->regs [ARMREG_FP])
 #define MONO_CONTEXT_GET_SP(ctx) (gpointer)((ctx)->regs [ARMREG_SP])
 
+#if defined (HOST_APPLETVOS)
+
+#define MONO_CONTEXT_GET_CURRENT(ctx) do { \
+       fprintf (stderr, "MONO_CONTEXT_GET_CURRENT: Not implemented"); \
+       g_error ("MONO_CONTEXT_GET_CURRENT: Not implemented"); \
+} while (0);
+
+#else
+
 #define MONO_CONTEXT_GET_CURRENT(ctx)  do {    \
        __asm__ __volatile__(                   \
                "mov x16, %0\n" \
@@ -323,14 +360,18 @@ typedef struct {
                : "x30", "memory"                       \
        );                                                              \
        __asm__ __volatile__( \
-               "adr %0, L0\n" \
-               "L0:\n" \
+               "adr %0, L0%=\n" \
+               "L0%=:\n"       \
                : "=r" (ctx.pc)         \
                :                                       \
                : "memory"                       \
        ); \
 } while (0)
 
+#endif
+
+#define MONO_ARCH_HAS_MONO_CONTEXT 1
+
 #elif defined(__mono_ppc__) /* defined(__arm__) */
 
 /* we define our own structure and we'll copy the data
@@ -339,6 +380,100 @@ typedef struct {
  * We might also want to add an additional field to propagate
  * the original context from the signal handler.
  */
+#ifdef __mono_ppc64__
+
+typedef struct {
+       gulong sc_ir;          // pc 
+       gulong 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_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_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, 8(%0)\n"        \
+               "std 0, 8*0+16(%0)\n"   \
+               "std 1, 8*1+16(%0)\n"   \
+               "std 2, 8*2+16(%0)\n"   \
+               "std 3, 8*3+16(%0)\n"   \
+               "std 4, 8*4+16(%0)\n"   \
+               "std 5, 8*5+16(%0)\n"   \
+               "std 6, 8*6+16(%0)\n"   \
+               "std 7, 8*7+16(%0)\n"   \
+               "std 8, 8*8+16(%0)\n"   \
+               "std 9, 8*9+16(%0)\n"   \
+               "std 10, 8*10+16(%0)\n" \
+               "std 11, 8*11+16(%0)\n" \
+               "std 12, 8*12+16(%0)\n" \
+               "std 13, 8*13+16(%0)\n" \
+               "std 14, 8*14+16(%0)\n" \
+               "std 15, 8*15+16(%0)\n" \
+               "std 16, 8*16+16(%0)\n" \
+               "std 17, 8*17+16(%0)\n" \
+               "std 18, 8*18+16(%0)\n" \
+               "std 19, 8*19+16(%0)\n" \
+               "std 20, 8*20+16(%0)\n" \
+               "std 21, 8*21+16(%0)\n" \
+               "std 22, 8*22+16(%0)\n" \
+               "std 23, 8*23+16(%0)\n" \
+               "std 24, 8*24+16(%0)\n" \
+               "std 25, 8*25+16(%0)\n" \
+               "std 26, 8*26+16(%0)\n" \
+               "std 27, 8*27+16(%0)\n" \
+               "std 28, 8*28+16(%0)\n" \
+               "std 29, 8*29+16(%0)\n" \
+               "std 30, 8*30+16(%0)\n" \
+               "std 31, 8*31+16(%0)\n" \
+               "stfd 0, 8*0+8*32+16(%0)\n"     \
+               "stfd 1, 8*1+8*32+16(%0)\n"     \
+               "stfd 2, 8*2+8*32+16(%0)\n"     \
+               "stfd 3, 8*3+8*32+16(%0)\n"     \
+               "stfd 4, 8*4+8*32+16(%0)\n"     \
+               "stfd 5, 8*5+8*32+16(%0)\n"     \
+               "stfd 6, 8*6+8*32+16(%0)\n"     \
+               "stfd 7, 8*7+8*32+16(%0)\n"     \
+               "stfd 8, 8*8+8*32+16(%0)\n"     \
+               "stfd 9, 8*9+8*32+16(%0)\n"     \
+               "stfd 10, 8*10+8*32+16(%0)\n"   \
+               "stfd 11, 8*11+8*32+16(%0)\n"   \
+               "stfd 12, 8*12+8*32+16(%0)\n"   \
+               "stfd 13, 8*13+8*32+16(%0)\n"   \
+               "stfd 14, 8*14+8*32+16(%0)\n"   \
+               "stfd 15, 8*15+8*32+16(%0)\n"   \
+               "stfd 16, 8*16+8*32+16(%0)\n"   \
+               "stfd 17, 8*17+8*32+16(%0)\n"   \
+               "stfd 18, 8*18+8*32+16(%0)\n"   \
+               "stfd 19, 8*19+8*32+16(%0)\n"   \
+               "stfd 20, 8*20+8*32+16(%0)\n"   \
+               "stfd 21, 8*21+8*32+16(%0)\n"   \
+               "stfd 22, 8*22+8*32+16(%0)\n"   \
+               "stfd 23, 8*23+8*32+16(%0)\n"   \
+               "stfd 24, 8*24+8*32+16(%0)\n"   \
+               "stfd 25, 8*25+8*32+16(%0)\n"   \
+               "stfd 26, 8*26+8*32+16(%0)\n"   \
+               "stfd 27, 8*27+8*32+16(%0)\n"   \
+               "stfd 28, 8*28+8*32+16(%0)\n"   \
+               "stfd 29, 8*29+8*32+16(%0)\n"   \
+               "stfd 30, 8*30+8*32+16(%0)\n"   \
+               "stfd 31, 8*31+8*32+16(%0)\n"   \
+               : : "r" (&(ctx))        \
+               : "memory"                      \
+       )
+
+#define MONO_ARCH_HAS_MONO_CONTEXT 1
+
+#else 
+
 typedef struct {
        gulong sc_ir;          // pc 
        gulong sc_sp;          // r1
@@ -355,6 +490,7 @@ typedef struct {
 #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))
+#endif
 
 #elif defined(__sparc__) || defined(sparc) /* defined(__mono_ppc__) */
 
@@ -456,6 +592,8 @@ mono_ia64_context_get_fp (MonoContext *ctx)
 
 #elif ((defined(__mips__) && !defined(MONO_CROSS_COMPILE)) || (defined(TARGET_MIPS))) && SIZEOF_REGISTER == 4 /* defined(__ia64__) */
 
+#include <mono/arch/mips/mips-codegen.h>
+
 typedef struct {
        mgreg_t     sc_pc;
        mgreg_t         sc_regs [32];
@@ -548,7 +686,7 @@ typedef struct ucontext MonoContext;
  * The naming is misleading, the SIGCTX argument should be the platform's context
  * structure (ucontext_c on posix, CONTEXT on windows).
  */
-void mono_sigctx_to_monoctx (void *sigctx, MonoContext *mctx) MONO_INTERNAL;
+void mono_sigctx_to_monoctx (void *sigctx, MonoContext *mctx);
 
 /*
  * This will not completely initialize SIGCTX since MonoContext contains less
@@ -556,6 +694,6 @@ void mono_sigctx_to_monoctx (void *sigctx, MonoContext *mctx) MONO_INTERNAL;
  * the system, and use this function to override the parts of it which are
  * also in MonoContext.
  */
-void mono_monoctx_to_sigctx (MonoContext *mctx, void *sigctx) MONO_INTERNAL;
+void mono_monoctx_to_sigctx (MonoContext *mctx, void *sigctx);
 
 #endif /* __MONO_MONO_CONTEXT_H__ */