Fix the build.
[mono.git] / mono / mini / mini-ppc.c
index e67d6313f2a085932af94e1e5cd5badafecaafc9..1bbb4f794a09c9139428e3a2a40f2dc757e2973f 100644 (file)
@@ -15,6 +15,7 @@
 #include <mono/metadata/appdomain.h>
 #include <mono/metadata/debug-helpers.h>
 #include <mono/utils/mono-proclib.h>
+#include <mono/utils/mono-mmap.h>
 
 #include "mini-ppc.h"
 #ifdef TARGET_POWERPC64
@@ -56,6 +57,8 @@ enum {
        PPC_HW_CAP_END
 };
 
+#define BREAKPOINT_SIZE (PPC_LOAD_SEQUENCE_LENGTH + 4)
+
 /* This mutex protects architecture specific caches */
 #define mono_mini_arch_lock() EnterCriticalSection (&mini_arch_mutex)
 #define mono_mini_arch_unlock() LeaveCriticalSection (&mini_arch_mutex)
@@ -66,6 +69,15 @@ static int tls_mode = TLS_MODE_DETECT;
 static int lmf_pthread_key = -1;
 static int monodomain_key = -1;
 
+/*
+ * The code generated for sequence points reads from this location, which is
+ * made read-only when single stepping is enabled.
+ */
+static gpointer ss_trigger_page;
+
+/* Enabled breakpoints read from this trigger page */
+static gpointer bp_trigger_page;
+
 static int
 offsets_from_pthread_key (guint32 key, int *offset2)
 {
@@ -653,8 +665,9 @@ mono_arch_cpu_init (void)
 #elif defined(G_COMPILER_CODEWARRIOR)
        cachelinesize = 32;
        cachelineinc = 32;
+#elif defined(MONO_CROSS_COMPILE)
 #else
-#warning Need a way to get cache line size
+//#error Need a way to get cache line size
 #endif
        if (!cachelinesize)
                cachelinesize = 32;
@@ -663,7 +676,6 @@ mono_arch_cpu_init (void)
 
        if (mono_cpu_count () > 1)
                cpu_hw_caps |= PPC_SMP_CAPABLE;
-       cpu_hw_caps = 0;
 }
 
 /*
@@ -672,7 +684,11 @@ mono_arch_cpu_init (void)
 void
 mono_arch_init (void)
 {
-       InitializeCriticalSection (&mini_arch_mutex);   
+       InitializeCriticalSection (&mini_arch_mutex);
+
+       ss_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ|MONO_MMAP_32BIT);
+       bp_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ|MONO_MMAP_32BIT);
+       mono_mprotect (bp_trigger_page, mono_pagesize (), 0);
 }
 
 /*
@@ -984,7 +1000,7 @@ calculate_sizes (MonoMethodSignature *sig, gboolean is_pinvoke)
 {
        guint i, fr, gr;
        int n = sig->hasthis + sig->param_count;
-       guint32 simpletype;
+       MonoType *simpletype;
        guint32 stack_size = 0;
        CallInfo *cinfo = g_malloc0 (sizeof (CallInfo) + sizeof (ArgInfo) * n);
 
@@ -1019,8 +1035,8 @@ calculate_sizes (MonoMethodSignature *sig, gboolean is_pinvoke)
                        n++;
                        continue;
                }
-               simpletype = mini_type_get_underlying_type (NULL, sig->params [i])->type;
-               switch (simpletype) {
+               simpletype = mini_type_get_underlying_type (NULL, sig->params [i]);
+               switch (simpletype->type) {
                case MONO_TYPE_BOOLEAN:
                case MONO_TYPE_I1:
                case MONO_TYPE_U1:
@@ -1055,7 +1071,7 @@ calculate_sizes (MonoMethodSignature *sig, gboolean is_pinvoke)
                        n++;
                        break;
                case MONO_TYPE_GENERICINST:
-                       if (!mono_type_generic_inst_is_valuetype (sig->params [i])) {
+                       if (!mono_type_generic_inst_is_valuetype (simpletype)) {
                                cinfo->args [n].size = sizeof (gpointer);
                                add_general (&gr, &stack_size, cinfo->args + n, TRUE);
                                n++;
@@ -1068,7 +1084,7 @@ calculate_sizes (MonoMethodSignature *sig, gboolean is_pinvoke)
                        MonoClass *klass;
 
                        klass = mono_class_from_mono_type (sig->params [i]);
-                       if (simpletype == MONO_TYPE_TYPEDBYREF)
+                       if (simpletype->type == MONO_TYPE_TYPEDBYREF)
                                size = sizeof (MonoTypedRef);
                        else if (is_pinvoke)
                            size = mono_class_native_size (klass, NULL);
@@ -1199,8 +1215,8 @@ calculate_sizes (MonoMethodSignature *sig, gboolean is_pinvoke)
        }
 
        {
-               simpletype = mini_type_get_underlying_type (NULL, sig->ret)->type;
-               switch (simpletype) {
+               simpletype = mini_type_get_underlying_type (NULL, sig->ret);
+               switch (simpletype->type) {
                case MONO_TYPE_BOOLEAN:
                case MONO_TYPE_I1:
                case MONO_TYPE_U1:
@@ -1230,7 +1246,7 @@ calculate_sizes (MonoMethodSignature *sig, gboolean is_pinvoke)
                        cinfo->ret.regtype = RegTypeFP;
                        break;
                case MONO_TYPE_GENERICINST:
-                       if (!mono_type_generic_inst_is_valuetype (sig->ret)) {
+                       if (!mono_type_generic_inst_is_valuetype (simpletype)) {
                                cinfo->ret.reg = ppc_r3;
                                break;
                        }
@@ -3264,6 +3280,33 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                case OP_NOT_REACHED:
                case OP_NOT_NULL:
                        break;
+               case OP_SEQ_POINT: {
+                       int i;
+
+                       if (cfg->compile_aot)
+                               NOT_IMPLEMENTED;
+
+                       /* 
+                        * Read from the single stepping trigger page. This will cause a
+                        * SIGSEGV when single stepping is enabled.
+                        * We do this _before_ the breakpoint, so single stepping after
+                        * a breakpoint is hit will step to the next IL offset.
+                        */
+                       if (ins->flags & MONO_INST_SINGLE_STEP_LOC) {
+                               ppc_load (code, ppc_r11, (gsize)ss_trigger_page);
+                               ppc_ldptr (code, ppc_r11, 0, ppc_r11);
+                       }
+
+                       mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
+
+                       /* 
+                        * A placeholder for a possible breakpoint inserted by
+                        * mono_arch_set_breakpoint ().
+                        */
+                       for (i = 0; i < BREAKPOINT_SIZE / 4; ++i)
+                               ppc_nop (code);
+                       break;
+               }
                case OP_TLS_GET:
                        emit_tls_access (code, ins->dreg, ins->inst_offset);
                        break;
@@ -5023,10 +5066,10 @@ mono_arch_emit_prolog (MonoCompile *cfg)
                                        break;
                                case 8:
                                        if (ppc_is_imm16 (inst->inst_offset)) {
-                                               ppc_str (code, ainfo->reg, inst->inst_offset, inst->inst_basereg);
+                                               ppc_str (code, ppc_r0, inst->inst_offset, inst->inst_basereg);
                                        } else {
                                                ppc_load (code, ppc_r11, inst->inst_offset);
-                                               ppc_str_indexed (code, ainfo->reg, ppc_r11, inst->inst_basereg);
+                                               ppc_str_indexed (code, ppc_r0, ppc_r11, inst->inst_basereg);
                                        }
                                        break;
 #else
@@ -5388,13 +5431,12 @@ mono_arch_emit_exceptions (MonoCompile *cfg)
      
        /* 
         * make sure we have enough space for exceptions
-        * 28 is the simulated call to throw_corlib_exception
         */
        for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
                if (patch_info->type == MONO_PATCH_INFO_EXC) {
                        i = exception_id_by_name (patch_info->data.target);
                        if (!exc_throw_found [i]) {
-                               max_epilog_size += 28;
+                               max_epilog_size += (2 * PPC_LOAD_SEQUENCE_LENGTH) + 5 * 4;
                                exc_throw_found [i] = TRUE;
                        }
                } else if (patch_info->type == MONO_PATCH_INFO_BB_OVF)
@@ -5403,7 +5445,7 @@ mono_arch_emit_exceptions (MonoCompile *cfg)
                        MonoOvfJump *ovfj = (MonoOvfJump*)patch_info->data.target;
                        i = exception_id_by_name (ovfj->data.exception);
                        if (!exc_throw_found [i]) {
-                               max_epilog_size += 28;
+                               max_epilog_size += (2 * PPC_LOAD_SEQUENCE_LENGTH) + 5 * 4;
                                exc_throw_found [i] = TRUE;
                        }
                        max_epilog_size += 8;
@@ -5549,7 +5591,7 @@ setup_tls_access (void)
                conf_size = confstr ( _CS_GNU_LIBPTHREAD_VERSION, confbuf, sizeof(confbuf));
                if ((conf_size > 4) && (strncmp (confbuf, "NPTL", 4) == 0))
                        tls_mode = TLS_MODE_NPTL;
-#else
+#elif !defined(TARGET_PS3)
                ins = (guint32*)pthread_getspecific;
                /* uncond branch to the real method */
                if ((*ins >> 26) == 18) {
@@ -5623,6 +5665,7 @@ setup_tls_access (void)
                }
 #endif
        }
+#ifndef TARGET_PS3
        if (tls_mode == TLS_MODE_DETECT)
                tls_mode = TLS_MODE_FAILED;
        if (tls_mode == TLS_MODE_FAILED)
@@ -5658,6 +5701,7 @@ setup_tls_access (void)
                        lmf_pthread_key = ptk;
                }
        }
+#endif
 }
 
 void
@@ -5828,12 +5872,6 @@ mono_arch_find_imt_method (mgreg_t *regs, guint8 *code)
 
        return (MonoMethod*)(gsize) r [MONO_ARCH_IMT_REG];
 }
-
-MonoObject*
-mono_arch_find_this_argument (mgreg_t *regs, MonoMethod *method, MonoGenericSharingContext *gsctx)
-{
-       return mono_arch_get_this_arg_from_call (gsctx, mono_method_signature (method), regs, NULL);
-}
 #endif
 
 MonoVTable*
@@ -5936,3 +5974,172 @@ mono_arch_emit_load_aotconst (guint8 *start, guint8 *code, MonoJumpInfo **ji, in
 
        return code;
 }
+
+/* Soft Debug support */
+#ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
+
+/*
+ * BREAKPOINTS
+ */
+
+/*
+ * mono_arch_set_breakpoint:
+ *
+ *   See mini-amd64.c for docs.
+ */
+void
+mono_arch_set_breakpoint (MonoJitInfo *ji, guint8 *ip)
+{
+       guint8 *code = ip;
+       guint8 *orig_code = code;
+
+       ppc_load_sequence (code, ppc_r11, (gsize)bp_trigger_page);
+       ppc_ldptr (code, ppc_r11, 0, ppc_r11);
+
+       g_assert (code - orig_code == BREAKPOINT_SIZE);
+
+       mono_arch_flush_icache (orig_code, code - orig_code);
+}
+
+/*
+ * mono_arch_clear_breakpoint:
+ *
+ *   See mini-amd64.c for docs.
+ */
+void
+mono_arch_clear_breakpoint (MonoJitInfo *ji, guint8 *ip)
+{
+       guint8 *code = ip;
+       int i;
+
+       for (i = 0; i < BREAKPOINT_SIZE / 4; ++i)
+               ppc_nop (code);
+
+       mono_arch_flush_icache (ip, code - ip);
+}
+
+/*
+ * mono_arch_is_breakpoint_event:
+ *
+ *   See mini-amd64.c for docs.
+ */
+gboolean
+mono_arch_is_breakpoint_event (void *info, void *sigctx)
+{
+       siginfo_t* sinfo = (siginfo_t*) info;
+       /* Sometimes the address is off by 4 */
+       if (sinfo->si_addr >= bp_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)bp_trigger_page + 128)
+               return TRUE;
+       else
+               return FALSE;
+}
+
+/*
+ * mono_arch_get_ip_for_breakpoint:
+ *
+ *   See mini-amd64.c for docs.
+ */
+guint8*
+mono_arch_get_ip_for_breakpoint (MonoJitInfo *ji, MonoContext *ctx)
+{
+       guint8 *ip = MONO_CONTEXT_GET_IP (ctx);
+
+       /* ip points at the ldptr instruction */
+       ip -= PPC_LOAD_SEQUENCE_LENGTH;
+
+       return ip;
+}
+
+/*
+ * mono_arch_skip_breakpoint:
+ *
+ *   See mini-amd64.c for docs.
+ */
+void
+mono_arch_skip_breakpoint (MonoContext *ctx)
+{
+       /* skip the ldptr */
+       MONO_CONTEXT_SET_IP (ctx, (guint8*)MONO_CONTEXT_GET_IP (ctx) + 4);
+}
+
+/*
+ * SINGLE STEPPING
+ */
+       
+/*
+ * mono_arch_start_single_stepping:
+ *
+ *   See mini-amd64.c for docs.
+ */
+void
+mono_arch_start_single_stepping (void)
+{
+       mono_mprotect (ss_trigger_page, mono_pagesize (), 0);
+}
+       
+/*
+ * mono_arch_stop_single_stepping:
+ *
+ *   See mini-amd64.c for docs.
+ */
+void
+mono_arch_stop_single_stepping (void)
+{
+       mono_mprotect (ss_trigger_page, mono_pagesize (), MONO_MMAP_READ);
+}
+
+/*
+ * mono_arch_is_single_step_event:
+ *
+ *   See mini-amd64.c for docs.
+ */
+gboolean
+mono_arch_is_single_step_event (void *info, void *sigctx)
+{
+       siginfo_t* sinfo = (siginfo_t*) info;
+       /* Sometimes the address is off by 4 */
+       if (sinfo->si_addr >= ss_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)ss_trigger_page + 128)
+               return TRUE;
+       else
+               return FALSE;
+}
+
+/*
+ * mono_arch_get_ip_for_single_step:
+ *
+ *   See mini-amd64.c for docs.
+ */
+guint8*
+mono_arch_get_ip_for_single_step (MonoJitInfo *ji, MonoContext *ctx)
+{
+       guint8 *ip = MONO_CONTEXT_GET_IP (ctx);
+
+       /* ip points after the ldptr instruction */
+       return ip;
+}
+
+/*
+ * mono_arch_skip_single_step:
+ *
+ *   See mini-amd64.c for docs.
+ */
+void
+mono_arch_skip_single_step (MonoContext *ctx)
+{
+       /* skip the ldptr */
+       MONO_CONTEXT_SET_IP (ctx, (guint8*)MONO_CONTEXT_GET_IP (ctx) + 4);
+}
+
+/*
+ * mono_arch_create_seq_point_info:
+ *
+ *   See mini-amd64.c for docs.
+ */
+gpointer
+mono_arch_get_seq_point_info (MonoDomain *domain, guint8 *code)
+{
+       NOT_IMPLEMENTED;
+       return NULL;
+}
+
+#endif