#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
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)
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)
{
#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;
if (mono_cpu_count () > 1)
cpu_hw_caps |= PPC_SMP_CAPABLE;
- cpu_hw_caps = 0;
}
/*
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);
}
/*
{
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);
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:
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++;
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);
}
{
- 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:
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;
}
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;
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
/*
* 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)
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;
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) {
}
#endif
}
+#ifndef TARGET_PS3
if (tls_mode == TLS_MODE_DETECT)
tls_mode = TLS_MODE_FAILED;
if (tls_mode == TLS_MODE_FAILED)
lmf_pthread_key = ptk;
}
}
+#endif
}
void
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*
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