Merge pull request #1225 from strawd/bug22307
[mono.git] / mono / mini / mini-mips.c
index 3c4d9065066461e65c72ec6a7dc274e51e105df0..362fa3a14bac36bfaf82a57b24611e83821e706b 100644 (file)
 #include <string.h>
 #include <asm/cachectl.h>
 
+#include <mono/metadata/abi-details.h>
 #include <mono/metadata/appdomain.h>
 #include <mono/metadata/debug-helpers.h>
 #include <mono/utils/mono-mmap.h>
+#include <mono/utils/mono-hwcap-mips.h>
 
 #include <mono/arch/mips/mips-codegen.h>
 
 #include "ir-emit.h"
 
 #define SAVE_FP_REGS           0
-#define EXTRA_STACK_SPACE      0       /* suppresses some s-reg corruption issues */
 
-#define ALWAYS_USE_FP          1
 #define ALWAYS_SAVE_RA         1       /* call-handler & switch currently clobber ra */
 
 #define PROMOTE_R4_TO_R8       1       /* promote single values in registers to doubles */
-#define USE_MUL                        1       /* use mul instead of mult/mflo for multiply */
+#define USE_MUL                        0       /* use mul instead of mult/mflo for multiply
+                                                          remember to update cpu-mips.md if you change this */
 
 /* Emit a call sequence to 'v', using 'D' as a scratch register if necessary */
 #define mips_call(c,D,v) do {  \
@@ -56,15 +57,14 @@ enum {
 };
 
 /* 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 CRITICAL_SECTION mini_arch_mutex;
+#define mono_mini_arch_lock() mono_mutex_lock (&mini_arch_mutex)
+#define mono_mini_arch_unlock() mono_mutex_unlock (&mini_arch_mutex)
+static mono_mutex_t mini_arch_mutex;
 
 int mono_exc_esp_offset = 0;
 static int tls_mode = TLS_MODE_DETECT;
 static int lmf_pthread_key = -1;
 static int monothread_key = -1;
-static int monodomain_key = -1;
 
 /* Whenever the host is little-endian */
 static int little_endian;
@@ -518,7 +518,7 @@ mono_arch_get_argument_info (MonoMethodSignature *csig, int param_count, MonoJit
        arg_info [0].size = frame_size;
 
        for (k = 0; k < param_count; k++) {
-               size = mini_type_stack_size_full (NULL, csig->params [k], &align, csig->pinvoke);
+               size = mini_type_stack_size_full (csig->params [k], &align, csig->pinvoke);
 
                /* ignore alignment for now */
                align = 1;
@@ -544,7 +544,7 @@ mono_arch_get_argument_info (MonoMethodSignature *csig, int param_count, MonoJit
 #define MAX_ARCH_DELEGATE_PARAMS (4 - 1)
 
 static gpointer
-get_delegate_invoke_impl (gboolean has_target, gboolean param_count, guint32 *code_size)
+get_delegate_invoke_impl (MonoTrampInfo **info, gboolean has_target, gboolean param_count)
 {
        guint8 *code, *start;
 
@@ -552,8 +552,8 @@ get_delegate_invoke_impl (gboolean has_target, gboolean param_count, guint32 *co
                start = code = mono_global_codeman_reserve (16);
 
                /* Replace the this argument with the target */
-               mips_lw (code, mips_temp, mips_a0, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
-               mips_lw (code, mips_a0, mips_a0, G_STRUCT_OFFSET (MonoDelegate, target));
+               mips_lw (code, mips_temp, mips_a0, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
+               mips_lw (code, mips_a0, mips_a0, MONO_STRUCT_OFFSET (MonoDelegate, target));
                mips_jr (code, mips_temp);
                mips_nop (code);
 
@@ -566,7 +566,7 @@ get_delegate_invoke_impl (gboolean has_target, gboolean param_count, guint32 *co
                size = 16 + param_count * 4;
                start = code = mono_global_codeman_reserve (size);
 
-               mips_lw (code, mips_temp, mips_a0, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
+               mips_lw (code, mips_temp, mips_a0, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
                /* slide down the arguments */
                for (i = 0; i < param_count; ++i) {
                        mips_move (code, mips_a0 + i, mips_a0 + i + 1);
@@ -579,8 +579,13 @@ get_delegate_invoke_impl (gboolean has_target, gboolean param_count, guint32 *co
                mono_arch_flush_icache (start, size);
        }
 
-       if (code_size)
-               *code_size = code - start;
+       if (has_target) {
+               *info = mono_tramp_info_create ("delegate_invoke_impl_has_target", start, code - start, NULL, NULL);
+       } else {
+               char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", param_count);
+               *info = mono_tramp_info_create (name, start, code - start, NULL, NULL);
+               g_free (name);
+       }
 
        return start;
 }
@@ -595,16 +600,15 @@ GSList*
 mono_arch_get_delegate_invoke_impls (void)
 {
        GSList *res = NULL;
-       guint8 *code;
-       guint32 code_len;
+       MonoTrampInfo *info;
        int i;
 
-       code = get_delegate_invoke_impl (TRUE, 0, &code_len);
-       res = g_slist_prepend (res, mono_tramp_info_create (g_strdup ("delegate_invoke_impl_has_target"), code, code_len, NULL, NULL));
+       get_delegate_invoke_impl (&info, TRUE, 0);
+       res = g_slist_prepend (res, info);
 
        for (i = 0; i <= MAX_ARCH_DELEGATE_PARAMS; ++i) {
-               code = get_delegate_invoke_impl (FALSE, i, &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));
+               get_delegate_invoke_impl (&info, FALSE, i);
+               res = g_slist_prepend (res, info);
        }
 
        return res;
@@ -627,10 +631,13 @@ mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_targe
                        return cached;
                }
 
-               if (mono_aot_only)
+               if (mono_aot_only) {
                        start = mono_aot_get_trampoline ("delegate_invoke_impl_has_target");
-               else
-                       start = get_delegate_invoke_impl (TRUE, 0, NULL);
+               } else {
+                       MonoTrampInfo *info;
+                       start = get_delegate_invoke_impl (&info, TRUE, 0);
+                       mono_tramp_info_register (info, NULL);
+               }
                cached = start;
                mono_mini_arch_unlock ();
                return cached;
@@ -656,7 +663,9 @@ mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_targe
                        start = mono_aot_get_trampoline (name);
                        g_free (name);
                } else {
-                       start = get_delegate_invoke_impl (FALSE, sig->param_count, NULL);
+                       MonoTrampInfo *info;
+                       start = get_delegate_invoke_impl (&info, FALSE, sig->param_count);
+                       mono_tramp_info_register (info, NULL);
                }
                cache [sig->param_count] = start;
                mono_mini_arch_unlock ();
@@ -666,6 +675,12 @@ mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_targe
        return NULL;
 }
 
+gpointer
+mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method, int offset, gboolean load_imt_reg)
+{
+       return NULL;
+}
+
 gpointer
 mono_arch_get_this_arg_from_call (mgreg_t *regs, guint8 *code)
 {
@@ -698,7 +713,7 @@ mono_arch_cpu_init (void)
 void
 mono_arch_init (void)
 {
-       InitializeCriticalSection (&mini_arch_mutex);
+       mono_mutex_init_recursive (&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);
@@ -711,14 +726,14 @@ mono_arch_init (void)
 void
 mono_arch_cleanup (void)
 {
-       DeleteCriticalSection (&mini_arch_mutex);
+       mono_mutex_destroy (&mini_arch_mutex);
 }
 
 /*
  * This function returns the optimizations supported on this cpu.
  */
 guint32
-mono_arch_cpu_optimizazions (guint32 *exclude_mask)
+mono_arch_cpu_optimizations (guint32 *exclude_mask)
 {
        guint32 opts = 0;
 
@@ -727,6 +742,19 @@ mono_arch_cpu_optimizazions (guint32 *exclude_mask)
        return opts;
 }
 
+/*
+ * This function test for all SIMD functions supported.
+ *
+ * Returns a bitmask corresponding to all supported versions.
+ *
+ */
+guint32
+mono_arch_cpu_enumerate_simd_versions (void)
+{
+       /* SIMD is currently unimplemented */
+       return 0;
+}
+
 GList *
 mono_arch_get_allocatable_int_vars (MonoCompile *cfg)
 {
@@ -1032,7 +1060,7 @@ add_float64_arg (CallInfo *info, ArgInfo *ainfo) {
 #endif
 
 static CallInfo*
-get_call_info (MonoGenericSharingContext *gsctx, MonoMemPool *mp, MonoMethodSignature *sig)
+get_call_info (MonoMemPool *mp, MonoMethodSignature *sig)
 {
        guint i;
        int n = sig->hasthis + sig->param_count;
@@ -1074,7 +1102,7 @@ get_call_info (MonoGenericSharingContext *gsctx, MonoMemPool *mp, MonoMethodSign
         * 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 (cinfo->vtype_retaddr && !is_pinvoke && (sig->hasthis || (sig->param_count > 0 && MONO_TYPE_IS_REFERENCE (mini_get_underlying_type (sig->params [0]))))) {
                if (sig->hasthis) {
                        add_int32_arg (cinfo, cinfo->args + n);
                        n ++;
@@ -1109,7 +1137,7 @@ get_call_info (MonoGenericSharingContext *gsctx, MonoMemPool *mp, MonoMethodSign
                        add_int32_arg (cinfo, &cinfo->sig_cookie);
                }
                DEBUG(printf("param %d: ", i));
-               simpletype = mini_type_get_underlying_type (gsctx, sig->params [i]);
+               simpletype = mini_get_underlying_type (sig->params [i]);
                switch (simpletype->type) {
                case MONO_TYPE_BOOLEAN:
                case MONO_TYPE_I1:
@@ -1256,7 +1284,7 @@ get_call_info (MonoGenericSharingContext *gsctx, MonoMemPool *mp, MonoMethodSign
        }
 
        {
-               simpletype = mini_type_get_underlying_type (gsctx, sig->ret);
+               simpletype = mini_get_underlying_type (sig->ret);
                switch (simpletype->type) {
                case MONO_TYPE_BOOLEAN:
                case MONO_TYPE_I1:
@@ -1309,36 +1337,11 @@ get_call_info (MonoGenericSharingContext *gsctx, MonoMemPool *mp, MonoMethodSign
        return cinfo;
 }
 
-G_GNUC_UNUSED static void
-break_count (void)
-{
-}
-
-G_GNUC_UNUSED static gboolean
-debug_count (void)
-{
-       static int count = 0;
-       count ++;
-
-       if (!getenv ("COUNT"))
-               return TRUE;
-
-       if (count == atoi (getenv ("COUNT"))) {
-               break_count ();
-       }
-
-       if (count > atoi (getenv ("COUNT"))) {
-               return FALSE;
-       }
-
-       return TRUE;
-}
-
 static gboolean
 debug_omit_fp (void)
 {
 #if 0
-       return debug_count ();
+       return mono_debug_count ();
 #else
        return TRUE;
 #endif
@@ -1365,7 +1368,7 @@ mono_arch_compute_omit_fp (MonoCompile *cfg)
        sig = mono_method_signature (cfg->method);
 
        if (!cfg->arch.cinfo)
-               cfg->arch.cinfo = get_call_info (cfg->generic_sharing_context, cfg->mempool, sig);
+               cfg->arch.cinfo = get_call_info (cfg->mempool, sig);
        cinfo = cfg->arch.cinfo;
 
        /*
@@ -1430,7 +1433,7 @@ mono_arch_allocate_vars (MonoCompile *cfg)
        sig = mono_method_signature (cfg->method);
 
        if (!cfg->arch.cinfo)
-               cfg->arch.cinfo = get_call_info (cfg->generic_sharing_context, cfg->mempool, sig);
+               cfg->arch.cinfo = get_call_info (cfg->mempool, sig);
        cinfo = cfg->arch.cinfo;
 
        mono_arch_compute_omit_fp (cfg);
@@ -1473,7 +1476,7 @@ mono_arch_allocate_vars (MonoCompile *cfg)
        curinst = 0;
        if (!MONO_TYPE_ISSTRUCT (sig->ret)) {
                /* FIXME: handle long and FP values */
-               switch (mini_type_get_underlying_type (cfg->generic_sharing_context, sig->ret)->type) {
+               switch (mini_get_underlying_type (sig->ret)->type) {
                case MONO_TYPE_VOID:
                        break;
                case MONO_TYPE_R4:
@@ -1538,11 +1541,6 @@ mono_arch_allocate_vars (MonoCompile *cfg)
                offset += size;
        }                       
 
-       /*
-        * FIXME: - Saved S-regs seem to be getting clobbered by some calls with struct
-        * args or return vals.  Extra stack space avoids this in a lot of cases.
-        */
-       offset += EXTRA_STACK_SPACE;
        offset += SIZEOF_REGISTER - 1;
        offset &= ~(SIZEOF_REGISTER - 1);
 
@@ -1713,7 +1711,7 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
        sig = call->signature;
        n = sig->param_count + sig->hasthis;
        
-       cinfo = get_call_info (NULL, cfg->mempool, sig);
+       cinfo = get_call_info (cfg->mempool, sig);
        if (cinfo->struct_ret)
                call->used_iregs |= 1 << cinfo->struct_ret;
 
@@ -1725,7 +1723,7 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
                        t = sig->params [i - sig->hasthis];
                else
                        t = &mono_defaults.int_class->byval_arg;
-               t = mini_type_get_underlying_type (cfg->generic_sharing_context, t);
+               t = mini_get_underlying_type (t);
 
                if ((sig->call_convention == MONO_CALL_VARARG) && (i == sig->sentinelpos)) {
                        /* Emit the signature cookie just before the implicit arguments */
@@ -1943,7 +1941,7 @@ mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src)
                        size = mono_type_native_stack_size (&src->klass->byval_arg, NULL);
                        vtcopy->backend.is_pinvoke = 1;
                } else {
-                       size = mini_type_stack_size (cfg->generic_sharing_context, &src->klass->byval_arg, NULL);
+                       size = mini_type_stack_size (&src->klass->byval_arg, NULL);
                }
                if (size > 0)
                        g_assert (ovf_size > 0);
@@ -1961,8 +1959,7 @@ mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src)
 void
 mono_arch_emit_setret (MonoCompile *cfg, MonoMethod *method, MonoInst *val)
 {
-       MonoType *ret = mini_type_get_underlying_type (cfg->generic_sharing_context,
-                       mono_method_signature (method)->ret);
+       MonoType *ret = mini_get_underlying_type (mono_method_signature (method)->ret);
 
        if (!ret->byref) {
 #if (SIZEOF_REGISTER == 4)
@@ -3218,7 +3215,7 @@ emit_load_volatile_arguments(MonoCompile *cfg, guint8 *code)
        sig = mono_method_signature (method);
 
        if (!cfg->arch.cinfo)
-               cfg->arch.cinfo = get_call_info (cfg->generic_sharing_context, cfg->mempool, sig);
+               cfg->arch.cinfo = get_call_info (cfg->mempool, sig);
        cinfo = cfg->arch.cinfo;
 
        if (cinfo->struct_ret) {
@@ -3313,8 +3310,8 @@ emit_reserve_param_area (MonoCompile *cfg, guint8 *code)
        if (ppc_is_imm16 (-size)) {
                ppc_stwu (code, ppc_r0, -size, ppc_sp);
        } else {
-               ppc_load (code, ppc_r11, -size);
-               ppc_stwux (code, ppc_r0, ppc_sp, ppc_r11);
+               ppc_load (code, ppc_r12, -size);
+               ppc_stwux (code, ppc_r0, ppc_sp, ppc_r12);
        }
 #endif
        return code;
@@ -3335,8 +3332,8 @@ emit_unreserve_param_area (MonoCompile *cfg, guint8 *code)
        if (ppc_is_imm16 (size)) {
                ppc_stwu (code, ppc_r0, size, ppc_sp);
        } else {
-               ppc_load (code, ppc_r11, size);
-               ppc_stwux (code, ppc_r0, ppc_sp, ppc_r11);
+               ppc_load (code, ppc_r12, size);
+               ppc_stwux (code, ppc_r0, ppc_sp, ppc_r12);
        }
 #endif
        return code;
@@ -3402,6 +3399,9 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                case OP_NOT_REACHED:
                case OP_NOT_NULL:
                        break;
+               case OP_IL_SEQ_POINT:
+                       mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
+                       break;
                case OP_SEQ_POINT: {
                        if (ins->flags & MONO_INST_SINGLE_STEP_LOC) {
                                guint32 addr = (guint32)ss_trigger_page;
@@ -3439,9 +3439,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        mips_mfhi (code, ins->dreg+1);
                        break;
                case OP_MEMORY_BARRIER:
-#if 0
-                       ppc_sync (code);
-#endif
+                       mips_sync (code, 0);
                        break;
                case OP_STOREI1_MEMBASE_IMM:
                        mips_load_const (code, mips_temp, ins->inst_imm);
@@ -3727,8 +3725,8 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                case OP_DIV_IMM:
                        g_assert_not_reached ();
 #if 0
-                       ppc_load (code, ppc_r11, ins->inst_imm);
-                       ppc_divwod (code, ins->dreg, ins->sreg1, ppc_r11);
+                       ppc_load (code, ppc_r12, ins->inst_imm);
+                       ppc_divwod (code, ins->dreg, ins->sreg1, ppc_r12);
                        ppc_mfspr (code, ppc_r0, ppc_xer);
                        ppc_andisd (code, ppc_r0, ppc_r0, (1<<14));
                        /* FIXME: use OverflowException for 0x80000000/-1 */
@@ -3920,6 +3918,14 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                                mips_fmovd (code, ins->dreg, ins->sreg1);
                        }
                        break;
+               case OP_MOVE_F_TO_I4:
+                       mips_cvtsd (code, mips_ftemp, ins->sreg1);
+                       mips_mfc1 (code, ins->dreg, mips_ftemp);
+                       break;
+               case OP_MOVE_I4_TO_F:
+                       mips_mtc1 (code, ins->dreg, ins->sreg1);
+                       mips_cvtds (code, ins->dreg, ins->dreg);
+                       break;
                case OP_MIPS_CVTSD:
                        /* Convert from double to float and leave it there */
                        mips_cvtsd (code, ins->dreg, ins->sreg1);
@@ -4044,11 +4050,19 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        mips_addiu (code, ins->dreg, mips_sp, area_offset);
 
                        if (ins->flags & MONO_INST_INIT) {
+                               guint32 *buf;
+
+                               buf = (guint32*)(void*)code;
+                               mips_beq (code, mips_at, mips_zero, 0);
+                               mips_nop (code);
+
                                mips_move (code, mips_temp, ins->dreg);
                                mips_sb (code, mips_zero, mips_temp, 0);
                                mips_addiu (code, mips_at, mips_at, -1);
                                mips_bne (code, mips_at, mips_zero, -3);
                                mips_addiu (code, mips_temp, mips_temp, 1);
+
+                               mips_patch (buf, (guint32)code);
                        }
                        break;
                }
@@ -4654,7 +4668,7 @@ mono_arch_register_lowlevel_calls (void)
 }
 
 void
-mono_arch_patch_code (MonoMethod *method, MonoDomain *domain, guint8 *code, MonoJumpInfo *ji, MonoCodeManager *dyn_code_mp, gboolean run_cctors)
+mono_arch_patch_code (MonoCompile *cfg, MonoMethod *method, MonoDomain *domain, guint8 *code, MonoJumpInfo *ji, gboolean run_cctors)
 {
        MonoJumpInfo *patch_info;
 
@@ -4710,20 +4724,6 @@ mono_arch_patch_code (MonoMethod *method, MonoDomain *domain, guint8 *code, Mono
        }
 }
 
-#if 0
-static
-void
-mono_trace_lmf_prolog (MonoLMF *new_lmf)
-{
-}
-
-static
-void
-mono_trace_lmf_epilog (MonoLMF *old_lmf)
-{
-}
-#endif
-
 /*
  * Allow tracing to work with this interface (with an optional argument)
  *
@@ -4742,33 +4742,37 @@ mono_arch_instrument_prolog (MonoCompile *cfg, void *func, void *p, gboolean ena
        mips_nop (code);
        mips_nop (code);
 
-       /* For N32, need to know for each stack slot if it's an integer
-        * or float argument, and save/restore the appropriate register
-        */
        MIPS_SW (code, mips_a0, mips_sp, offset + 0*SIZEOF_REGISTER);
        MIPS_SW (code, mips_a1, mips_sp, offset + 1*SIZEOF_REGISTER);
        MIPS_SW (code, mips_a2, mips_sp, offset + 2*SIZEOF_REGISTER);
        MIPS_SW (code, mips_a3, mips_sp, offset + 3*SIZEOF_REGISTER);
 #if _MIPS_SIM == _ABIN32
+       NOT_IMPLEMENTED;
+       /* FIXME: Need a separate region for these */
        MIPS_SW (code, mips_a4, mips_sp, offset + 4*SIZEOF_REGISTER);
        MIPS_SW (code, mips_a5, mips_sp, offset + 5*SIZEOF_REGISTER);
        MIPS_SW (code, mips_a6, mips_sp, offset + 6*SIZEOF_REGISTER);
        MIPS_SW (code, mips_a7, mips_sp, offset + 7*SIZEOF_REGISTER);
+       */
 #endif
 
        mips_load_const (code, mips_a0, cfg->method);
        mips_addiu (code, mips_a1, mips_sp, offset);
        mips_call (code, mips_t9, func);
+       mips_nop (code);
 
        MIPS_LW (code, mips_a0, mips_sp, offset + 0*SIZEOF_REGISTER);
        MIPS_LW (code, mips_a1, mips_sp, offset + 1*SIZEOF_REGISTER);
        MIPS_LW (code, mips_a2, mips_sp, offset + 2*SIZEOF_REGISTER);
        MIPS_LW (code, mips_a3, mips_sp, offset + 3*SIZEOF_REGISTER);
 #if _MIPS_SIM == _ABIN32
+       NOT_IMPLEMENTED;
+       /*
        MIPS_LW (code, mips_a4, mips_sp, offset + 4*SIZEOF_REGISTER);
        MIPS_LW (code, mips_a5, mips_sp, offset + 5*SIZEOF_REGISTER);
        MIPS_LW (code, mips_a6, mips_sp, offset + 6*SIZEOF_REGISTER);
        MIPS_LW (code, mips_a7, mips_sp, offset + 7*SIZEOF_REGISTER);
+       */
 #endif
 
        mips_nop (code);
@@ -4976,16 +4980,6 @@ mono_arch_emit_prolog (MonoCompile *cfg)
        if (max_offset > 0xffff)
                cfg->arch.long_branch = TRUE;
 
-       if (tracing) {
-#if _MIPS_SIM == _ABIO32
-               cfg->arch.tracing_offset = cfg->stack_offset;
-#elif _MIPS_SIM == _ABIN32
-               /* no stack slots by default for argument regs, reserve a special block */
-               cfg->arch.tracing_offset = cfg->stack_offset;
-               cfg->stack_offset += 8 * SIZEOF_REGISTER;
-#endif
-       }
-
        /*
         * Currently, fp points to the bottom of the frame on MIPS, unlike other platforms.
         * This means that we have to adjust the offsets inside instructions which reference
@@ -5098,13 +5092,6 @@ mono_arch_emit_prolog (MonoCompile *cfg)
                }
        }
 
-       /* Do instrumentation before assigning regvars to registers.  Because they may be assigned
-        * to the t* registers, which would be clobbered by the instrumentation calls.
-        */
-       if (tracing) {
-               code = mono_arch_instrument_prolog (cfg, mono_trace_enter_method, code, TRUE);
-       }
-
        /* store runtime generic context */
        if (cfg->rgctx_var) {
                MonoInst *ins = cfg->rgctx_var;
@@ -5119,7 +5106,7 @@ mono_arch_emit_prolog (MonoCompile *cfg)
        pos = 0;
 
        if (!cfg->arch.cinfo)
-               cfg->arch.cinfo = get_call_info (cfg->generic_sharing_context, cfg->mempool, sig);
+               cfg->arch.cinfo = get_call_info (cfg->mempool, sig);
        cinfo = cfg->arch.cinfo;
 
        if (MONO_TYPE_ISSTRUCT (sig->ret)) {
@@ -5269,11 +5256,6 @@ mono_arch_emit_prolog (MonoCompile *cfg)
                pos++;
        }
 
-       if (method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) {
-               mips_load_const (code, mips_a0, cfg->domain);
-               mips_call (code, mips_t9, (gpointer)mono_jit_thread_attach);
-       }
-
        if (method->save_lmf) {
                mips_load_const (code, mips_at, MIPS_LMF_MAGIC1);
                mips_sw (code, mips_at, mips_sp, lmf_offset + G_STRUCT_OFFSET(MonoLMF, magic));
@@ -5332,6 +5314,16 @@ mono_arch_emit_prolog (MonoCompile *cfg)
                        mono_emit_unwind_op_def_cfa_offset (cfg, code, cfa_offset);
        }
 
+       if (tracing) {
+#if _MIPS_SIM == _ABIO32
+               cfg->arch.tracing_offset = cfg->stack_offset;
+#elif _MIPS_SIM == _ABIN32
+               /* no stack slots by default for argument regs, reserve a special block */
+               g_assert_not_reached ();
+#endif
+               code = mono_arch_instrument_prolog (cfg, mono_trace_enter_method, code, TRUE);
+       }
+
        cfg->code_len = code - cfg->native_code;
        g_assert (cfg->code_len < cfg->code_size);
 
@@ -5353,7 +5345,7 @@ mono_arch_instrument_epilog_full (MonoCompile *cfg, void *func, void *p, gboolea
        int save_mode = SAVE_NONE;
        int offset;
        MonoMethod *method = cfg->method;
-       int rtype = mini_type_get_underlying_type (cfg->generic_sharing_context, mono_method_signature (method)->ret)->type;
+       int rtype = mini_get_underlying_type (mono_method_signature (method)->ret)->type;
        int save_offset = MIPS_STACK_PARAM_OFFSET;
 
        g_assert ((save_offset & (MIPS_STACK_ALIGNMENT-1)) == 0);
@@ -5784,11 +5776,6 @@ setup_tls_access (void)
                }
 #endif
        }
-       if (monodomain_key == -1) {
-               ptk = mono_domain_get_tls_key ();
-               if (ptk < 1024)
-                       monodomain_key = ptk;
-       }
        if (lmf_pthread_key == -1) {
                ptk = mono_jit_tls_id;
                if (ptk < 1024) {
@@ -5812,7 +5799,7 @@ setup_tls_access (void)
 }
 
 void
-mono_arch_setup_jit_tls_data (MonoJitTlsData *tls)
+mono_arch_finish_init (void)
 {
        setup_tls_access ();
 }
@@ -5832,13 +5819,13 @@ mono_arch_emit_this_vret_args (MonoCompile *cfg, MonoCallInst *inst, int this_re
 
        /* add the this argument */
        if (this_reg != -1) {
-               MonoInst *this;
-               MONO_INST_NEW (cfg, this, OP_MOVE);
-               this->type = this_type;
-               this->sreg1 = this_reg;
-               this->dreg = mono_alloc_ireg (cfg);
-               mono_bblock_add_inst (cfg->cbb, this);
-               mono_call_inst_add_outarg_reg (cfg, inst, this->dreg, this_dreg, FALSE);
+               MonoInst *this_ins;
+               MONO_INST_NEW (cfg, this_ins, OP_MOVE);
+               this_ins->type = this_type;
+               this_ins->sreg1 = this_reg;
+               this_ins->dreg = mono_alloc_ireg (cfg);
+               mono_bblock_add_inst (cfg->cbb, this_ins);
+               mono_call_inst_add_outarg_reg (cfg, inst, this_ins->dreg, this_dreg, FALSE);
        }
 
        if (vt_reg != -1) {
@@ -5872,27 +5859,12 @@ mono_arch_print_tree (MonoInst *tree, int arity)
        return 0;
 }
 
-MonoInst* mono_arch_get_domain_intrinsic (MonoCompile* cfg)
-{
-       MonoInst* ins;
-
-       setup_tls_access ();
-       if (monodomain_key == -1)
-               return NULL;
-       
-       MONO_INST_NEW (cfg, ins, OP_TLS_GET);
-       ins->inst_offset = monodomain_key;
-       return ins;
-}
-
 mgreg_t
 mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
 {
        return ctx->sc_regs [reg];
 }
 
-#ifdef MONO_ARCH_HAVE_IMT
-
 #define ENABLE_WRONG_METHOD_CHECK 0
 
 #define MIPS_LOAD_SEQUENCE_LENGTH      8
@@ -6038,6 +6010,9 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI
                mono_stats.imt_thunks_size += code - start;
        g_assert (code - start <= size);
        mono_arch_flush_icache (start, size);
+
+       mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, NULL), domain);
+
        return start;
 }
 
@@ -6046,7 +6021,6 @@ mono_arch_find_imt_method (mgreg_t *regs, guint8 *code)
 {
        return (MonoMethod*) regs [MONO_ARCH_IMT_REG];
 }
-#endif
 
 MonoVTable*
 mono_arch_find_static_call_vtable (mgreg_t *regs, guint8 *code)
@@ -6179,4 +6153,19 @@ mono_arch_get_seq_point_info (MonoDomain *domain, guint8 *code)
        return NULL;
 }
 
+void
+mono_arch_init_lmf_ext (MonoLMFExt *ext, gpointer prev_lmf)
+{
+       ext->lmf.previous_lmf = prev_lmf;
+       /* Mark that this is a MonoLMFExt */
+       ext->lmf.previous_lmf = (gpointer)(((gssize)ext->lmf.previous_lmf) | 2);
+       ext->lmf.iregs [mips_sp] = (gssize)ext;
+}
+
 #endif /* MONO_ARCH_SOFT_DEBUG_SUPPORTED */
+
+gboolean
+mono_arch_opcode_supported (int opcode)
+{
+       return FALSE;
+}