[xbuild] Make Engine.DefaultToolsVersion 2.0 .
[mono.git] / mono / mini / mini-ppc.c
index 70bf728c803c53b5add949c790d030bf3e76446d..90240f63e5b6b31e228f6b16c0031290157b9057 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)
 {
@@ -329,6 +341,9 @@ is_load_sequence (guint32 *seq)
 #define ppc_load_get_off(l)    ((gint16)((l) & 0xffff))
 #endif
 
+/* ld || lwz */
+#define ppc_is_load_op(opcode) (ppc_opcode ((opcode)) == 58 || ppc_opcode ((opcode)) == 32)
+
 /* code must point to the blrl */
 gboolean
 mono_ppc_is_direct_call_sequence (guint32 *code)
@@ -338,12 +353,12 @@ mono_ppc_is_direct_call_sequence (guint32 *code)
 
        /* the thunk-less direct call sequence: lis/ori/sldi/oris/ori/mtlr/blrl */
        if (ppc_opcode (code [-1]) == 31) { /* mtlr */
-               if (ppc_opcode (code [-2]) == 58 && ppc_opcode (code [-3]) == 58) { /* ld/ld */
+               if (ppc_is_load_op (code [-2]) && ppc_is_load_op (code [-3])) { /* ld/ld */
                        if (!is_load_sequence (&code [-8]))
                                return FALSE;
-                       /* one of the loads must be "ld r2,8(rX)" */
-                       return (ppc_load_get_dest (code [-2]) == ppc_r2 && ppc_load_get_off (code [-2]) == 8) ||
-                               (ppc_load_get_dest (code [-3]) == ppc_r2 && ppc_load_get_off (code [-3]) == 8);
+                       /* one of the loads must be "ld r2,8(rX)" or "ld r2,4(rX) for ilp32 */
+                       return (ppc_load_get_dest (code [-2]) == ppc_r2 && ppc_load_get_off (code [-2]) == sizeof (gpointer)) ||
+                               (ppc_load_get_dest (code [-3]) == ppc_r2 && ppc_load_get_off (code [-3]) == sizeof (gpointer));
                }
                if (ppc_opcode (code [-2]) == 24 && ppc_opcode (code [-3]) == 31) /* mr/nop */
                        return is_load_sequence (&code [-8]);
@@ -361,53 +376,6 @@ mono_ppc_is_direct_call_sequence (guint32 *code)
 #endif
 }
 
-gpointer
-mono_arch_get_vcall_slot (guint8 *code_ptr, mgreg_t *regs, int *displacement)
-{
-       char *o = NULL;
-       int reg, offset = 0;
-       guint32* code = (guint32*)code_ptr;
-       mgreg_t *r = (mgreg_t*)regs;
-
-       *displacement = 0;
-
-       /* This is the 'blrl' instruction */
-       --code;
-
-       /* Sanity check: instruction must be 'blrl' */
-       if (*code != 0x4e800021)
-               return NULL;
-
-       if (mono_ppc_is_direct_call_sequence (code))
-               return NULL;
-
-       /* FIXME: more sanity checks here */
-       /* OK, we're now at the 'blrl' instruction. Now walk backwards
-       till we get to a 'mtlr rA' */
-       for (; --code;) {
-               if((*code & 0x7c0803a6) == 0x7c0803a6) {
-                       gint16 soff;
-                       /* Here we are: we reached the 'mtlr rA'.
-                       Extract the register from the instruction */
-                       reg = (*code & 0x03e00000) >> 21;
-                       --code;
-                       /* ok, this is a lwz reg, offset (vtreg) 
-                        * it is emitted with:
-                        * ppc_emit32 (c, (32 << 26) | ((D) << 21) | ((a) << 16) | (guint16)(d))
-                        */
-                       soff = (*code & 0xffff);
-                       offset = soff;
-                       reg = (*code >> 16) & 0x1f;
-                       g_assert (reg != ppc_r1);
-                       /*g_print ("patching reg is %d\n", reg);*/
-                       o = (gpointer)(gsize)r [reg];
-                       break;
-               }
-       }
-       *displacement = offset;
-       return o;
-}
-
 #define MAX_ARCH_DELEGATE_PARAMS 7
 
 static gpointer
@@ -476,11 +444,11 @@ mono_arch_get_delegate_invoke_impls (void)
        int i;
 
        code = get_delegate_invoke_impl (TRUE, 0, &code_len, TRUE);
-       res = g_slist_prepend (res, mono_aot_tramp_info_create (g_strdup ("delegate_invoke_impl_has_target"), code, code_len));
+       res = g_slist_prepend (res, mono_tramp_info_create (g_strdup ("delegate_invoke_impl_has_target"), code, code_len, NULL, NULL));
 
        for (i = 0; i < MAX_ARCH_DELEGATE_PARAMS; ++i) {
                code = get_delegate_invoke_impl (FALSE, i, &code_len, TRUE);
-               res = g_slist_prepend (res, mono_aot_tramp_info_create (g_strdup_printf ("delegate_invoke_impl_target_%d", i), code, code_len));
+               res = g_slist_prepend (res, mono_tramp_info_create (g_strdup_printf ("delegate_invoke_impl_target_%d", i), code, code_len, NULL, NULL));
        }
 
        return res;
@@ -502,7 +470,7 @@ mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_targe
                        return cached;
 
                if (mono_aot_only)
-                       start = mono_aot_get_named_code ("delegate_invoke_impl_has_target");
+                       start = mono_aot_get_trampoline ("delegate_invoke_impl_has_target");
                else
                        start = get_delegate_invoke_impl (TRUE, 0, NULL, FALSE);
 
@@ -526,7 +494,7 @@ mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_targe
 
                if (mono_aot_only) {
                        char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", sig->param_count);
-                       start = mono_aot_get_named_code (name);
+                       start = mono_aot_get_trampoline (name);
                        g_free (name);
                } else {
                        start = get_delegate_invoke_impl (FALSE, sig->param_count, NULL, FALSE);
@@ -540,13 +508,10 @@ mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_targe
 }
 
 gpointer
-mono_arch_get_this_arg_from_call (MonoGenericSharingContext *gsctx, MonoMethodSignature *sig, mgreg_t *regs, guint8 *code)
+mono_arch_get_this_arg_from_call (mgreg_t *regs, guint8 *code)
 {
        mgreg_t *r = (mgreg_t*)regs;
 
-       /* FIXME: handle returning a struct */
-       if (MONO_TYPE_ISSTRUCT (sig->ret))
-               return (gpointer)(gsize)r [ppc_r4];
        return (gpointer)(gsize)r [ppc_r3];
 }
 
@@ -599,7 +564,16 @@ linux_find_auxv (int *count)
 void
 mono_arch_cpu_init (void)
 {
-#ifdef __APPLE__
+}
+
+/*
+ * Initialize architecture specific code.
+ */
+void
+mono_arch_init (void)
+{
+#if defined(MONO_CROSS_COMPILE)
+#elif defined(__APPLE__)
        int mib [3];
        size_t len;
        mib [0] = CTL_HW;
@@ -653,7 +627,6 @@ mono_arch_cpu_init (void)
 #elif defined(G_COMPILER_CODEWARRIOR)
        cachelinesize = 32;
        cachelineinc = 32;
-#elif defined(MONO_CROSS_COMPILE)
 #else
 //#error Need a way to get cache line size
 #endif
@@ -664,15 +637,13 @@ mono_arch_cpu_init (void)
 
        if (mono_cpu_count () > 1)
                cpu_hw_caps |= PPC_SMP_CAPABLE;
-}
+       InitializeCriticalSection (&mini_arch_mutex);
 
-/*
- * Initialize architecture specific code.
- */
-void
-mono_arch_init (void)
-{
-       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);
+
+       mono_aot_register_jit_icall ("mono_ppc_throw_exception", mono_ppc_throw_exception);
 }
 
 /*
@@ -736,6 +707,7 @@ is_regsize_var (MonoType *t) {
        return FALSE;
 }
 
+#ifndef DISABLE_JIT
 GList *
 mono_arch_get_allocatable_int_vars (MonoCompile *cfg)
 {
@@ -763,6 +735,7 @@ mono_arch_get_allocatable_int_vars (MonoCompile *cfg)
 
        return vars;
 }
+#endif /* ifndef DISABLE_JIT */
 
 GList *
 mono_arch_get_global_int_regs (MonoCompile *cfg)
@@ -772,8 +745,14 @@ mono_arch_get_global_int_regs (MonoCompile *cfg)
        if (cfg->frame_reg != ppc_sp)
                top = 31;
        /* ppc_r13 is used by the system on PPC EABI */
-       for (i = 14; i < top; ++i)
-               regs = g_list_prepend (regs, GUINT_TO_POINTER (i));
+       for (i = 14; i < top; ++i) {
+               /*
+                * Reserve r29 for holding the vtable address for virtual calls in AOT mode,
+                * since the trampolines can clobber r11.
+                */
+               if (!(cfg->compile_aot && i == 29))
+                       regs = g_list_prepend (regs, GUINT_TO_POINTER (i));
+       }
 
        return regs;
 }
@@ -913,6 +892,8 @@ typedef struct {
        guint32 struct_ret;
        ArgInfo ret;
        ArgInfo sig_cookie;
+       gboolean vtype_retaddr;
+       int vret_arg_index;
        ArgInfo args [1];
 } CallInfo;
 
@@ -980,11 +961,11 @@ has_only_a_r48_field (MonoClass *klass)
 #endif
 
 static CallInfo*
-calculate_sizes (MonoMethodSignature *sig, gboolean is_pinvoke)
+calculate_sizes (MonoGenericSharingContext *gsctx, MonoMethodSignature *sig, gboolean is_pinvoke)
 {
-       guint i, fr, gr;
+       guint i, fr, gr, pstart;
        int n = sig->hasthis + sig->param_count;
-       guint32 simpletype;
+       MonoType *simpletype;
        guint32 stack_size = 0;
        CallInfo *cinfo = g_malloc0 (sizeof (CallInfo) + sizeof (ArgInfo) * n);
 
@@ -993,17 +974,45 @@ calculate_sizes (MonoMethodSignature *sig, gboolean is_pinvoke)
 
        /* FIXME: handle returning a struct */
        if (MONO_TYPE_ISSTRUCT (sig->ret)) {
-               add_general (&gr, &stack_size, &cinfo->ret, TRUE);
-               cinfo->struct_ret = PPC_FIRST_ARG_REG;
+               cinfo->vtype_retaddr = TRUE;
        }
 
+       pstart = 0;
        n = 0;
-       if (sig->hasthis) {
-               add_general (&gr, &stack_size, cinfo->args + n, TRUE);
-               n++;
+       /*
+        * To simplify get_this_arg_reg () and LLVM integration, emit the vret arg after
+        * the first argument, allowing 'this' to be always passed in the first arg reg.
+        * Also do this if the first argument is a reference type, since virtual calls
+        * are sometimes made using calli without sig->hasthis set, like in the delegate
+        * invoke wrappers.
+        */
+       if (cinfo->vtype_retaddr && !is_pinvoke && (sig->hasthis || (sig->param_count > 0 && MONO_TYPE_IS_REFERENCE (mini_type_get_underlying_type (gsctx, sig->params [0]))))) {
+               if (sig->hasthis) {
+                       add_general (&gr, &stack_size, cinfo->args + 0, TRUE);
+                       n ++;
+               } else {
+                       add_general (&gr, &stack_size, &cinfo->args [sig->hasthis + 0], TRUE);
+                       pstart = 1;
+                       n ++;
+               }
+               add_general (&gr, &stack_size, &cinfo->ret, TRUE);
+               cinfo->struct_ret = cinfo->ret.reg;
+               cinfo->vret_arg_index = 1;
+       } else {
+               /* this */
+               if (sig->hasthis) {
+                       add_general (&gr, &stack_size, cinfo->args + 0, TRUE);
+                       n ++;
+               }
+
+               if (cinfo->vtype_retaddr) {
+                       add_general (&gr, &stack_size, &cinfo->ret, TRUE);
+                       cinfo->struct_ret = cinfo->ret.reg;
+               }
        }
+
         DEBUG(printf("params: %d\n", sig->param_count));
-       for (i = 0; i < sig->param_count; ++i) {
+       for (i = pstart; i < sig->param_count; ++i) {
                if (!sig->pinvoke && (sig->call_convention == MONO_CALL_VARARG) && (i == sig->sentinelpos)) {
                         /* Prevent implicit arguments and sig_cookie from
                           being passed in registers */
@@ -1019,8 +1028,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 +1064,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 +1077,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 +1208,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 +1239,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;
                        }
@@ -1316,7 +1325,7 @@ mono_arch_allocate_vars (MonoCompile *m)
        if (m->method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE)
                m->param_area = MAX (m->param_area, sizeof (gpointer)*8);
 
-       header = mono_method_get_header (m->method);
+       header = m->header;
 
        /* 
         * We use the frame register also for any method that has
@@ -1453,6 +1462,11 @@ mono_arch_allocate_vars (MonoCompile *m)
                        }
                        if (MONO_TYPE_ISSTRUCT (sig->params [i]) && size < sizeof (gpointer))
                                size = align = sizeof (gpointer);
+                       /* 
+                        * Use at least 4/8 byte alignment, since these might be passed in registers, and
+                        * they are saved using std in the prolog.
+                        */
+                       align = sizeof (gpointer);
                        offset += align - 1;
                        offset &= ~(align - 1);
                        inst->inst_offset = offset;
@@ -1475,7 +1489,7 @@ mono_arch_allocate_vars (MonoCompile *m)
        m->stack_offset = offset;
 
        if (sig->call_convention == MONO_CALL_VARARG) {
-               CallInfo *cinfo = calculate_sizes (m->method->signature, m->method->signature->pinvoke);
+               CallInfo *cinfo = calculate_sizes (m->generic_sharing_context, m->method->signature, m->method->signature->pinvoke);
 
                m->sig_cookie = cinfo->sig_cookie.offset;
 
@@ -1521,7 +1535,7 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
        sig = call->signature;
        n = sig->param_count + sig->hasthis;
        
-       cinfo = calculate_sizes (sig, sig->pinvoke);
+       cinfo = calculate_sizes (cfg->generic_sharing_context, sig, sig->pinvoke);
 
        for (i = 0; i < n; ++i) {
                ArgInfo *ainfo = cinfo->args + i;
@@ -1648,6 +1662,8 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
        g_free (cinfo);
 }
 
+#ifndef DISABLE_JIT
+
 void
 mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src)
 {
@@ -1763,6 +1779,8 @@ mono_arch_is_inst_imm (gint64 imm)
        return TRUE;
 }
 
+#endif /* DISABLE_JIT */
+
 /*
  * Allow tracing to work with this interface (with an optional argument)
  */
@@ -2132,7 +2150,11 @@ mono_arch_decompose_opts (MonoCompile *cfg, MonoInst *ins)
 {
        switch (ins->opcode) {
        case OP_ICONV_TO_R_UN: {
+#if G_BYTE_ORDER == G_BIG_ENDIAN
                static const guint64 adjust_val = 0x4330000000000000ULL;
+#else
+               static const guint64 adjust_val = 0x0000000000003043ULL;
+#endif
                int msw_reg = mono_alloc_ireg (cfg);
                int adj_reg = mono_alloc_freg (cfg);
                int tmp_reg = mono_alloc_freg (cfg);
@@ -2250,12 +2272,9 @@ mono_arch_decompose_long_opts (MonoCompile *cfg, MonoInst *ins)
                NULLIFY_INS (ins);
                break;
        case OP_LNEG:
-               /* This is the old version from inssel-long32.brg */
-               MONO_EMIT_NEW_UNALU (cfg, OP_INOT, ins->dreg + 1, ins->sreg1 + 1);
-               MONO_EMIT_NEW_UNALU (cfg, OP_INOT, ins->dreg + 2, ins->sreg1 + 2);
-               /* ADC sets the condition codes */
-               MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADC_IMM, ins->dreg + 1, ins->dreg + 1, 1);
-               MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADC_IMM, ins->dreg + 2, ins->dreg + 2, 0);
+               /* From gcc generated code */
+               MONO_EMIT_NEW_BIALU_IMM (cfg, OP_PPC_SUBFIC, ins->dreg + 1, ins->sreg1 + 1, 0);
+               MONO_EMIT_NEW_UNALU (cfg, OP_PPC_SUBFZE, ins->dreg + 2, ins->sreg1 + 2);
                NULLIFY_INS (ins);
                break;
        default:
@@ -2887,12 +2906,12 @@ ppc_patch_full (guchar *code, const guchar *target, gboolean is_fd)
                /* the trampoline code will try to patch the blrl, blr, bcctr */
                if (ins == 0x4e800021 || ins == 0x4e800020 || ins == 0x4e800420) {
                        branch_ins = seq;
-                       if (ppc_opcode (seq [-3]) == 58 || ppc_opcode (seq [-3]) == 31) /* ld || mr */
+                       if (ppc_is_load_op (seq [-3]) || ppc_opcode (seq [-3]) == 31) /* ld || lwz || mr */
                                code -= 32;
                        else
                                code -= 24;
                } else {
-                       if (ppc_opcode (seq [5]) == 58 || ppc_opcode (seq [5]) == 31) /* ld || mr */
+                       if (ppc_is_load_op (seq [5]) || ppc_opcode (seq [5]) == 31) /* ld || lwz || mr */
                                branch_ins = seq + 8;
                        else
                                branch_ins = seq + 6;
@@ -2902,8 +2921,8 @@ ppc_patch_full (guchar *code, const guchar *target, gboolean is_fd)
                /* this is the lis/ori/sldi/oris/ori/(ld/ld|mr/nop)/mtlr/blrl sequence */
                g_assert (mono_ppc_is_direct_call_sequence (branch_ins));
 
-               if (ppc_opcode (seq [5]) == 58) {       /* ld */
-                       g_assert (ppc_opcode (seq [6]) == 58); /* ld */
+               if (ppc_is_load_op (seq [5])) {
+                       g_assert (ppc_is_load_op (seq [6]));
 
                        if (!is_fd) {
                                guint8 *buf = (guint8*)&seq [5];
@@ -2991,7 +3010,7 @@ emit_load_volatile_arguments (MonoCompile *cfg, guint8 *code)
 
        pos = 0;
 
-       cinfo = calculate_sizes (sig, sig->pinvoke);
+       cinfo = calculate_sizes (cfg->generic_sharing_context, sig, sig->pinvoke);
 
        if (MONO_TYPE_ISSTRUCT (sig->ret)) {
                ArgInfo *ainfo = &cinfo->ret;
@@ -3131,7 +3150,7 @@ ins_native_length (MonoCompile *cfg, MonoInst *ins)
 
        call = (MonoCallInst*)ins;
        sig = mono_method_signature (cfg->method);
-       cinfo = calculate_sizes (sig, sig->pinvoke);
+       cinfo = calculate_sizes (cfg->generic_sharing_context, sig, sig->pinvoke);
 
        if (MONO_TYPE_ISSTRUCT (sig->ret))
                len += 4;
@@ -3212,6 +3231,7 @@ emit_unreserve_param_area (MonoCompile *cfg, guint8 *code)
 
 #define MASK_SHIFT_IMM(i)      ((i) & MONO_PPC_32_64_CASE (0x1f, 0x3f))
 
+#ifndef DISABLE_JIT
 void
 mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
 {
@@ -3264,6 +3284,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;
@@ -3504,7 +3551,22 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        }
                        break;
                case OP_BREAK:
-                       ppc_break (code);
+                       /*
+                        * gdb does not like encountering a trap in the debugged code. So 
+                        * instead of emitting a trap, we emit a call a C function and place a 
+                        * breakpoint there.
+                        */
+                       //ppc_break (code);
+                       ppc_mr (code, ppc_r3, ins->sreg1);
+                       mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD, 
+                                            (gpointer)"mono_break");
+                       if ((FORCE_INDIR_CALL || cfg->method->dynamic) && !cfg->compile_aot) {
+                               ppc_load_func (code, ppc_r0, 0);
+                               ppc_mtlr (code, ppc_r0);
+                               ppc_blrl (code);
+                       } else {
+                               ppc_bl (code, 0);
+                       }
                        break;
                case OP_ADDCC:
                case OP_IADDCC:
@@ -3659,7 +3721,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                                ppc_sldi (code, ppc_r0, ppc_r0, 32);
 #endif
                        ppc_compare (code, 0, ins->sreg1, ppc_r0);
-                       EMIT_COND_SYSTEM_EXCEPTION_FLAGS (PPC_BR_TRUE, PPC_BR_EQ, "ArithmeticException");
+                       EMIT_COND_SYSTEM_EXCEPTION_FLAGS (PPC_BR_TRUE, PPC_BR_EQ, "OverflowException");
                        ppc_patch (divisor_is_m1, code);
                         /* XER format: SO, OV, CA, reserved [21 bits], count [8 bits]
                         */
@@ -3972,7 +4034,13 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                case OP_VCALL2_MEMBASE:
                case OP_VOIDCALL_MEMBASE:
                case OP_CALL_MEMBASE:
-                       ppc_ldptr (code, ppc_r0, ins->inst_offset, ins->sreg1);
+                       if (cfg->compile_aot && ins->sreg1 == ppc_r11) {
+                               /* The trampolines clobber this */
+                               ppc_mr (code, ppc_r29, ins->sreg1);
+                               ppc_ldptr (code, ppc_r0, ins->inst_offset, ppc_r29);
+                       } else {
+                               ppc_ldptr (code, ppc_r0, ins->inst_offset, ins->sreg1);
+                       }
                        ppc_mtlr (code, ppc_r0);
                        ppc_blrl (code);
                        /* FIXME: this should be handled somewhere else in the new jit */
@@ -4089,6 +4157,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                case OP_CALL_HANDLER: 
                        mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_BB, ins->inst_target_bb);
                        ppc_bl (code, 0);
+                       mono_cfg_add_try_hole (cfg, ins->inst_eh_block, code, bb);
                        break;
                case OP_LABEL:
                        ins->inst_c0 = code - cfg->native_code;
@@ -4411,7 +4480,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        EMIT_COND_SYSTEM_EXCEPTION (CEE_BEQ - CEE_BEQ, "ArithmeticException");
                        break;
                case OP_JUMP_TABLE:
-                       mono_add_patch_info (cfg, offset, (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
+                       mono_add_patch_info (cfg, offset, (MonoJumpInfoType)ins->inst_c1, ins->inst_p0);
 #ifdef __mono_ppc64__
                        ppc_load_sequence (code, ins->dreg, (guint64)0x0f0f0f0f0f0f0f0fLL);
 #else
@@ -4594,6 +4663,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
 
        cfg->code_len = code - cfg->native_code;
 }
+#endif /* !DISABLE_JIT */
 
 void
 mono_arch_register_lowlevel_calls (void)
@@ -4619,8 +4689,9 @@ mono_arch_register_lowlevel_calls (void)
        } while (0)
 #endif
 
+#ifndef DISABLE_JIT
 void
-mono_arch_patch_code (MonoMethod *method, MonoDomain *domain, guint8 *code, MonoJumpInfo *ji, gboolean run_cctors)
+mono_arch_patch_code (MonoMethod *method, MonoDomain *domain, guint8 *code, MonoJumpInfo *ji, MonoCodeManager *dyn_code_mp, gboolean run_cctors)
 {
        MonoJumpInfo *patch_info;
        gboolean compile_aot = !run_cctors;
@@ -4776,7 +4847,7 @@ mono_arch_emit_prolog (MonoCompile *cfg)
                tracing = 1;
 
        sig = mono_method_signature (method);
-       cfg->code_size = MONO_PPC_32_64_CASE (260, 384) + sig->param_count * 20;
+       cfg->code_size = 512 + sig->param_count * 32;
        code = cfg->native_code = g_malloc (cfg->code_size);
 
        cfa_offset = 0;
@@ -4860,7 +4931,7 @@ mono_arch_emit_prolog (MonoCompile *cfg)
        /* load arguments allocated to register from the stack */
        pos = 0;
 
-       cinfo = calculate_sizes (sig, sig->pinvoke);
+       cinfo = calculate_sizes (cfg->generic_sharing_context, sig, sig->pinvoke);
 
        if (MONO_TYPE_ISSTRUCT (sig->ret)) {
                ArgInfo *ainfo = &cinfo->ret;
@@ -4906,7 +4977,7 @@ mono_arch_emit_prolog (MonoCompile *cfg)
                                        } else {
                                                if (ppc_is_imm32 (inst->inst_offset)) {
                                                        ppc_addis (code, ppc_r11, inst->inst_basereg, ppc_ha(inst->inst_offset));
-                                                       ppc_stb (code, ainfo->reg, ppc_r11, inst->inst_offset);
+                                                       ppc_stb (code, ainfo->reg, inst->inst_offset, ppc_r11);
                                                } else {
                                                        ppc_load (code, ppc_r11, inst->inst_offset);
                                                        ppc_stbx (code, ainfo->reg, inst->inst_basereg, ppc_r11);
@@ -4919,7 +4990,7 @@ mono_arch_emit_prolog (MonoCompile *cfg)
                                        } else {
                                                if (ppc_is_imm32 (inst->inst_offset)) {
                                                        ppc_addis (code, ppc_r11, inst->inst_basereg, ppc_ha(inst->inst_offset));
-                                                       ppc_sth (code, ainfo->reg, ppc_r11, inst->inst_offset);
+                                                       ppc_sth (code, ainfo->reg, inst->inst_offset, ppc_r11);
                                                } else {
                                                        ppc_load (code, ppc_r11, inst->inst_offset);
                                                        ppc_sthx (code, ainfo->reg, inst->inst_basereg, ppc_r11);
@@ -4933,7 +5004,7 @@ mono_arch_emit_prolog (MonoCompile *cfg)
                                        } else {
                                                if (ppc_is_imm32 (inst->inst_offset)) {
                                                        ppc_addis (code, ppc_r11, inst->inst_basereg, ppc_ha(inst->inst_offset));
-                                                       ppc_stw (code, ainfo->reg, ppc_r11, inst->inst_offset);
+                                                       ppc_stw (code, ainfo->reg, inst->inst_offset, ppc_r11);
                                                } else {
                                                        ppc_load (code, ppc_r11, inst->inst_offset);
                                                        ppc_stwx (code, ainfo->reg, inst->inst_basereg, ppc_r11);
@@ -4967,7 +5038,7 @@ mono_arch_emit_prolog (MonoCompile *cfg)
                                        } else {
                                                if (ppc_is_imm32 (inst->inst_offset)) {
                                                        ppc_addis (code, ppc_r11, inst->inst_basereg, ppc_ha(inst->inst_offset));
-                                                       ppc_stptr (code, ainfo->reg, ppc_r11, inst->inst_offset);
+                                                       ppc_stptr (code, ainfo->reg, inst->inst_offset, ppc_r11);
                                                } else {
                                                        ppc_load (code, ppc_r11, inst->inst_offset);
                                                        ppc_stptr_indexed (code, ainfo->reg, inst->inst_basereg, ppc_r11);
@@ -4987,7 +5058,7 @@ mono_arch_emit_prolog (MonoCompile *cfg)
                                        } else {
                                                if (ppc_is_imm32 (inst->inst_offset)) {
                                                        ppc_addis (code, ppc_r11, inst->inst_basereg, ppc_ha(inst->inst_offset));
-                                                       ppc_stb (code, ppc_r0, ppc_r11, inst->inst_offset);
+                                                       ppc_stb (code, ppc_r0, inst->inst_offset, ppc_r11);
                                                } else {
                                                        ppc_load (code, ppc_r11, inst->inst_offset);
                                                        ppc_stbx (code, ppc_r0, inst->inst_basereg, ppc_r11);
@@ -5000,7 +5071,7 @@ mono_arch_emit_prolog (MonoCompile *cfg)
                                        } else {
                                                if (ppc_is_imm32 (inst->inst_offset)) {
                                                        ppc_addis (code, ppc_r11, inst->inst_basereg, ppc_ha(inst->inst_offset));
-                                                       ppc_sth (code, ppc_r0, ppc_r11, inst->inst_offset);
+                                                       ppc_sth (code, ppc_r0, inst->inst_offset, ppc_r11);
                                                } else {
                                                        ppc_load (code, ppc_r11, inst->inst_offset);
                                                        ppc_sthx (code, ppc_r0, inst->inst_basereg, ppc_r11);
@@ -5014,7 +5085,7 @@ mono_arch_emit_prolog (MonoCompile *cfg)
                                        } else {
                                                if (ppc_is_imm32 (inst->inst_offset)) {
                                                        ppc_addis (code, ppc_r11, inst->inst_basereg, ppc_ha(inst->inst_offset));
-                                                       ppc_stw (code, ppc_r0, ppc_r11, inst->inst_offset);
+                                                       ppc_stw (code, ppc_r0, inst->inst_offset, ppc_r11);
                                                } else {
                                                        ppc_load (code, ppc_r11, inst->inst_offset);
                                                        ppc_stwx (code, ppc_r0, inst->inst_basereg, ppc_r11);
@@ -5052,7 +5123,7 @@ mono_arch_emit_prolog (MonoCompile *cfg)
                                        } else {
                                                if (ppc_is_imm32 (inst->inst_offset)) {
                                                        ppc_addis (code, ppc_r11, inst->inst_basereg, ppc_ha(inst->inst_offset));
-                                                       ppc_stptr (code, ppc_r0, ppc_r11, inst->inst_offset);
+                                                       ppc_stptr (code, ppc_r0, inst->inst_offset, ppc_r11);
                                                } else {
                                                        ppc_load (code, ppc_r11, inst->inst_offset);
                                                        ppc_stptr_indexed (code, ppc_r0, inst->inst_basereg, ppc_r11);
@@ -5155,14 +5226,17 @@ mono_arch_emit_prolog (MonoCompile *cfg)
        }
 
        if (method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) {
-               ppc_load_ptr (code, ppc_r3, cfg->domain);
+               if (cfg->compile_aot)
+                       /* AOT code is only used in the root domain */
+                       ppc_load_ptr (code, ppc_r3, 0);
+               else
+                       ppc_load_ptr (code, ppc_r3, cfg->domain);
                mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD, (gpointer)"mono_jit_thread_attach");
                if ((FORCE_INDIR_CALL || cfg->method->dynamic) && !cfg->compile_aot) {
                        ppc_load_func (code, ppc_r0, 0);
                        ppc_mtlr (code, ppc_r0);
                        ppc_blrl (code);
                } else {
-                       // FIXME: AOT
                        ppc_bl (code, 0);
                }
        }
@@ -5351,6 +5425,7 @@ mono_arch_emit_epilog (MonoCompile *cfg)
        g_assert (cfg->code_len < cfg->code_size);
 
 }
+#endif /* ifndef DISABLE_JIT */
 
 /* remove once throw_exception_by_name is eliminated */
 static int
@@ -5370,31 +5445,38 @@ exception_id_by_name (const char *name)
                return MONO_EXC_NULL_REF;
        if (strcmp (name, "ArrayTypeMismatchException") == 0)
                return MONO_EXC_ARRAY_TYPE_MISMATCH;
+       if (strcmp (name, "ArgumentException") == 0)
+               return MONO_EXC_ARGUMENT;
        g_error ("Unknown intrinsic exception %s\n", name);
        return 0;
 }
 
+#ifndef DISABLE_JIT
 void
 mono_arch_emit_exceptions (MonoCompile *cfg)
 {
        MonoJumpInfo *patch_info;
        int i;
        guint8 *code;
-       const guint8* exc_throw_pos [MONO_EXC_INTRINS_NUM] = {NULL};
-       guint8 exc_throw_found [MONO_EXC_INTRINS_NUM] = {0};
+       guint8* exc_throw_pos [MONO_EXC_INTRINS_NUM];
+       guint8 exc_throw_found [MONO_EXC_INTRINS_NUM];
        int max_epilog_size = 50;
 
+       for (i = 0; i < MONO_EXC_INTRINS_NUM; i++) {
+               exc_throw_pos [i] = NULL;
+               exc_throw_found [i] = 0;
+       }
+
        /* count the number of exception infos */
      
        /* 
         * 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 +5485,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;
@@ -5462,7 +5544,7 @@ mono_arch_emit_exceptions (MonoCompile *cfg)
 
                        unsigned char *ip = patch_info->ip.i + cfg->native_code;
                        i = exception_id_by_name (patch_info->data.target);
-                       if (exc_throw_pos [i]) {
+                       if (exc_throw_pos [i] && !(ip > exc_throw_pos [i] && ip - exc_throw_pos [i] > 50000)) {
                                ppc_patch (ip, exc_throw_pos [i]);
                                patch_info->type = MONO_PATCH_INFO_NONE;
                                break;
@@ -5500,6 +5582,7 @@ mono_arch_emit_exceptions (MonoCompile *cfg)
 
        g_assert (cfg->code_len <= cfg->code_size);
 }
+#endif
 
 #if DEAD_CODE
 static int
@@ -5721,26 +5804,26 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI
                }
                size += item->chunk_size;
        }
+       /* the initial load of the vtable address */
+       size += PPC_LOAD_SEQUENCE_LENGTH + LOADSTORE_SIZE;
        if (fail_tramp) {
                code = mono_method_alloc_generic_virtual_thunk (domain, size);
        } else {
-               /* the initial load of the vtable address */
-               size += PPC_LOAD_SEQUENCE_LENGTH + LOADSTORE_SIZE;
                code = mono_domain_code_reserve (domain, size);
        }
        start = code;
-       if (!fail_tramp) {
-               /*
-                * We need to save and restore r11 because it might be
-                * used by the caller as the vtable register, so
-                * clobbering it will trip up the magic trampoline.
-                *
-                * FIXME: Get rid of this by making sure that r11 is
-                * not used as the vtable register in interface calls.
-                */
-               ppc_stptr (code, ppc_r11, PPC_RET_ADDR_OFFSET, ppc_sp);
-               ppc_load (code, ppc_r11, (gsize)(& (vtable->vtable [0])));
-       }
+
+       /*
+        * We need to save and restore r11 because it might be
+        * used by the caller as the vtable register, so
+        * clobbering it will trip up the magic trampoline.
+        *
+        * FIXME: Get rid of this by making sure that r11 is
+        * not used as the vtable register in interface calls.
+        */
+       ppc_stptr (code, ppc_r11, PPC_RET_ADDR_OFFSET, ppc_sp);
+       ppc_load (code, ppc_r11, (gsize)(& (vtable->vtable [0])));
+
        for (i = 0; i < count; ++i) {
                MonoIMTCheckItem *item = imt_entries [i];
                item->code_target = code;
@@ -5830,12 +5913,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*
@@ -5846,6 +5923,16 @@ mono_arch_find_static_call_vtable (mgreg_t *regs, guint8 *code)
        return (MonoVTable*)(gsize) r [MONO_ARCH_RGCTX_REG];
 }
 
+GSList*
+mono_arch_get_cie_program (void)
+{
+       GSList *l = NULL;
+
+       mono_add_unwind_op_def_cfa (l, (guint8*)NULL, (guint8*)NULL, ppc_r1, 0);
+
+       return l;
+}
+
 MonoInst*
 mono_arch_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
 {
@@ -5938,3 +6025,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