[xbuild] Make Engine.DefaultToolsVersion 2.0 .
[mono.git] / mono / mini / mini-mips.h
index db5ac2f0bd4cf4c76635e8190ebf7617d086aead..ce8600ed62908db03a80037a802cf48e943b17cc 100644 (file)
@@ -1,8 +1,22 @@
 #ifndef __MONO_MINI_MIPS_H__
 #define __MONO_MINI_MIPS_H__
 
-#include <mono/arch/mips/mips-codegen.h>
 #include <glib.h>
+#include <mono/arch/mips/mips-codegen.h>
+
+#if _MIPS_SIM == _ABIO32
+/* o32 fully supported */
+#elif _MIPS_SIM == _ABIN32
+/* n32 under development */
+#warning "MIPS using n32 - under development"
+#else
+/* o64 not supported */
+/* n64 not supported */
+#error "MIPS unsupported ABI"
+#endif
+
+
+#define MONO_ARCH_CPU_SPEC mips_desc
 
 #define MONO_MAX_IREGS 32
 #define MONO_MAX_FREGS 32
 #define MONO_SAVED_GREGS 32
 #define MONO_SAVED_FREGS 32
 
+
+#if SIZEOF_REGISTER == 4
+#define IREG_SIZE      4
+typedef guint32                mips_ireg;
+#define FREG_SIZE      4
+typedef gfloat         mips_freg;
+
+#elif SIZEOF_REGISTER == 8
+
+#define IREG_SIZE      8
+typedef guint64                mips_ireg;
+#define FREG_SIZE      8
+typedef gdouble                mips_freg;
+
+#else
+#error Unknown REGISTER_SIZE
+#endif
+
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+#define MSW_OFFSET     sizeof(mips_ireg)
+#define LSW_OFFSET     0
+#else
+#define MSW_OFFSET     0
+#define LSW_OFFSET     sizeof(mips_ireg)
+#endif
+
 /*
  * at and t0 used internally
  * v0, v1 aren't here for clarity reasons
@@ -19,6 +59,7 @@
 
 #define MIPS_V_REGS    ((1 << mips_v0) | \
                         (1 << mips_v1))
+#if _MIPS_SIM == _ABIO32
 #define MIPS_T_REGS    ((1 << mips_t0) | \
                         (1 << mips_t1) | \
                         (1 << mips_t2) | \
                         (1 << mips_t5) | \
                         (1 << mips_t6) | \
                         (1 << mips_t7))
+#elif _MIPS_SIM == _ABIN32
+#define MIPS_T_REGS    ((1 << mips_t0) | \
+                        (1 << mips_t1) | \
+                        (1 << mips_t2) | \
+                        (1 << mips_t3))
+#endif
+
+
 #define MIPS_S_REGS    ((1 << mips_s0) | \
                         (1 << mips_s1) | \
                         (1 << mips_s2) | \
                         (1 << mips_s6) | \
                         (1 << mips_s7) | \
                         (1 << mips_fp))
+#if _MIPS_SIM == _ABIO32
 #define MIPS_A_REGS    ((1 << mips_a0) | \
                         (1 << mips_a1) | \
                         (1 << mips_a2) | \
                         (1 << mips_a3))
+#elif _MIPS_SIM == _ABIN32
+#define MIPS_A_REGS    ((1 << mips_a0) | \
+                        (1 << mips_a1) | \
+                        (1 << mips_a2) | \
+                        (1 << mips_a3) | \
+                        (1 << mips_a4) | \
+                        (1 << mips_a5) | \
+                        (1 << mips_a6) | \
+                        (1 << mips_a7))
+#endif
 
 #define mips_temp mips_t8
 
 #define MIPS_FP_PAIR(reg)      (1 << (reg))
 #endif
 
+#if _MIPS_SIM == _ABIO32
 #define MONO_ARCH_CALLEE_FREGS         (MIPS_FP_PAIR(mips_f0) |        \
                                         MIPS_FP_PAIR(mips_f2) |        \
                                         MIPS_FP_PAIR(mips_f4) |        \
                                         MIPS_FP_PAIR(mips_f26) |       \
                                         MIPS_FP_PAIR(mips_f28) |       \
                                         MIPS_FP_PAIR(mips_f30))
+#elif _MIPS_SIM == _ABIN32
+#define MONO_ARCH_CALLEE_FREGS         (MIPS_FP_PAIR(mips_f0) |        \
+                                        MIPS_FP_PAIR(mips_f1) |        \
+                                        MIPS_FP_PAIR(mips_f2) |        \
+                                        MIPS_FP_PAIR(mips_f3) |        \
+                                        MIPS_FP_PAIR(mips_f4) |        \
+                                        MIPS_FP_PAIR(mips_f5) |        \
+                                        MIPS_FP_PAIR(mips_f6) |        \
+                                        MIPS_FP_PAIR(mips_f7) |        \
+                                        MIPS_FP_PAIR(mips_f8) |        \
+                                        MIPS_FP_PAIR(mips_f9) |        \
+                                        MIPS_FP_PAIR(mips_f10) |       \
+                                        MIPS_FP_PAIR(mips_f11) |       \
+                                        MIPS_FP_PAIR(mips_f12) |       \
+                                        MIPS_FP_PAIR(mips_f13) |       \
+                                        MIPS_FP_PAIR(mips_f14) |       \
+                                        MIPS_FP_PAIR(mips_f15) |       \
+                                        MIPS_FP_PAIR(mips_f16) |       \
+                                        MIPS_FP_PAIR(mips_f17) |       \
+                                        MIPS_FP_PAIR(mips_f18) |       \
+                                        MIPS_FP_PAIR(mips_f19))
+
+#define MONO_ARCH_CALLEE_SAVED_FREGS   (MIPS_FP_PAIR(mips_f20) |       \
+                                        MIPS_FP_PAIR(mips_f21) |       \
+                                        MIPS_FP_PAIR(mips_f22) |       \
+                                        MIPS_FP_PAIR(mips_f23) |       \
+                                        MIPS_FP_PAIR(mips_f24) |       \
+                                        MIPS_FP_PAIR(mips_f25) |       \
+                                        MIPS_FP_PAIR(mips_f26) |       \
+                                        MIPS_FP_PAIR(mips_f27) |       \
+                                        MIPS_FP_PAIR(mips_f28) |       \
+                                        MIPS_FP_PAIR(mips_f29) |       \
+                                        MIPS_FP_PAIR(mips_f30) |       \
+                                        MIPS_FP_PAIR(mips_f31))
+#endif
 
 #define mips_ftemp mips_f18
 
 #define MONO_ARCH_FPSTACK_SIZE 0
 
 /* Parameters used by the register allocator */
-#define MONO_ARCH_HAS_XP_LOCAL_REGALLOC
 
 /* On Mips, for regpairs, the lower-numbered reg is most significant
  * This is true in both big and little endian
  */
 
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+#define RET_REG1 mips_v0
+#define RET_REG2 mips_v1
+#else
+#define RET_REG1 mips_v1
+#define RET_REG2 mips_v0
+#endif
+
 #define MONO_ARCH_INST_SREG2_MASK(ins)         (0)
 #define MONO_ARCH_INST_IS_REGPAIR(desc)                ((desc) == 'V' || (desc) == 'l')
-#define MONO_ARCH_INST_REGPAIR_REG2(desc,hreg1) (((desc) == 'l') ? ((hreg1) + 1) : (((desc) == 'V') ? ((hreg1) - 1) : -1))
+#define MONO_ARCH_INST_REGPAIR_REG2(desc,hreg1) (((desc) == 'l') ? ((hreg1) + 1) : (((desc) == 'V') ? RET_REG2 : -1))
 #define MONO_ARCH_INST_IS_FLOAT(desc)          ((desc == 'f') || (desc == 'g'))
 
 // This define is called to get specific dest register as defined
 // by md file (letter after "dest"). Overwise return -1
 
-#define MONO_ARCH_INST_FIXED_REG(desc)         (((desc) == '0') ? mips_zero : (((desc) == 'a') ? mips_at : ((((desc) == 'v')) ? mips_v0 : (((desc) == 'V') ? mips_v1 : (((desc) == 'g') ? mips_f0 : -1)))))
+#define MONO_ARCH_INST_FIXED_REG(desc)         (((desc) == '0') ? mips_zero : (((desc) == 'a') ? mips_at : ((((desc) == 'v')) ? mips_v0 : (((desc) == 'V') ? RET_REG1 : (((desc) == 'g') ? mips_f0 : -1)))))
 
 #define MONO_ARCH_FRAME_ALIGNMENT 8
 
 
 void mips_patch (guint32 *code, guint32 target);
 
+#define MIPS_LMF_MAGIC1        0xa5a5a5a5
+#define MIPS_LMF_MAGIC2        0xc3c3c3c3
+
 struct MonoLMF {
-       gpointer    previous_lmf;
-       gpointer    lmf_addr;
-       MonoMethod *method;
-       gulong     ebp;
-       gulong     eip;
-       gulong     iregs [MONO_SAVED_GREGS];
-       gfloat     fregs [MONO_SAVED_FREGS];
-       gulong     pad;
+       gpointer        previous_lmf;
+       gpointer        lmf_addr;
+       MonoMethod      *method;
+       mips_ireg       ebp;
+       gpointer        eip;
+       mips_ireg       iregs [MONO_SAVED_GREGS];
+       mips_freg       fregs [MONO_SAVED_FREGS];
+       gulong          magic;
 };
 
 /* we define our own structure and we'll copy the data
@@ -120,37 +226,63 @@ struct MonoLMF {
  * the original context from the signal handler.
  */
 typedef struct {
-       gulong sc_pc;
-       gulong sc_regs [MONO_SAVED_GREGS];
-       gfloat sc_fpregs [MONO_SAVED_FREGS];
+       gpointer        sc_pc;
+       mips_ireg       sc_regs [MONO_SAVED_GREGS];
+       mips_freg       sc_fpregs [MONO_SAVED_FREGS];
 } MonoContext;
 
 typedef struct MonoCompileArch {
        guint           iregs_offset;
        guint           lmf_offset;
+       guint           local_alloc_offset;
        guint           spillvar_offset;
        guint           spillvar_offset_float;
+       guint           tracing_offset;
+       guint           long_branch;
 } MonoCompileArch;
 
+#if SIZEOF_REGISTER == 4
 #define MONO_ARCH_EMULATE_FCONV_TO_I8 1
 #define MONO_ARCH_EMULATE_LCONV_TO_R8 1
 #define MONO_ARCH_EMULATE_LCONV_TO_R4 1
 #define MONO_ARCH_EMULATE_LCONV_TO_R8_UN 1
 #define MONO_ARCH_EMULATE_FREM 1
 #define MONO_ARCH_BIGMUL_INTRINS 1
+#endif
 
-#define MIPS_RET_ADDR_OFFSET   (-4)
+#if SIZEOF_REGISTER == 8
+#define MONO_ARCH_NO_EMULATE_LONG_MUL_OPTS
+#endif
+
+#define MIPS_RET_ADDR_OFFSET   (-sizeof(gpointer))
 #define MIPS_FP_ADDR_OFFSET    (-8)
 #define MIPS_STACK_ALIGNMENT   16
 #define MIPS_STACK_PARAM_OFFSET 16             /* from sp to first parameter */
-#define MIPS_MINIMAL_STACK_SIZE (4*4 + 4*4)
+#define MIPS_MINIMAL_STACK_SIZE (4*sizeof(mips_ireg) + 4*sizeof(mips_ireg))
 #define MIPS_EXTRA_STACK_SIZE  16              /* from last parameter to top of frame */
+
+#if _MIPS_SIM == _ABIO32
 #define MIPS_FIRST_ARG_REG     mips_a0
 #define MIPS_LAST_ARG_REG      mips_a3
 #define MIPS_FIRST_FPARG_REG   mips_f12
 #define MIPS_LAST_FPARG_REG    mips_f14
+#elif _MIPS_SIM == _ABIN32
+#define MIPS_FIRST_ARG_REG     mips_a0
+#define MIPS_LAST_ARG_REG      mips_t3
+#define MIPS_FIRST_FPARG_REG   mips_f12
+#define MIPS_LAST_FPARG_REG    mips_f19
+#endif
+
+#define MONO_ARCH_HAVE_IMT     1
+#define MONO_ARCH_IMT_REG      mips_t0
+
+#define MONO_ARCH_VTABLE_REG   mips_t0
+#define MONO_ARCH_RGCTX_REG    mips_t0
 
+#define MONO_ARCH_HAVE_DECOMPOSE_OPTS 1
+#define MONO_ARCH_HAVE_DECOMPOSE_LONG_OPTS 1
 
+#define MONO_ARCH_HAVE_GENERALIZED_IMT_THUNK 1
 
 /* XXX - a mystery, but it works */
 #define MONO_GET_CONTEXT \
@@ -162,17 +294,20 @@ typedef struct MonoCompileArch {
 
 #define MONO_ARCH_USE_SIGACTION
 #define MONO_ARCH_NEED_DIV_CHECK 1
+#define MONO_ARCH_NO_IOV_CHECK 1
+
+#define MONO_ARCH_THIS_AS_FIRST_ARG 1
 
 #define MIPS_NUM_REG_ARGS (MIPS_LAST_ARG_REG-MIPS_FIRST_ARG_REG+1)
 #define MIPS_NUM_REG_FPARGS (MIPS_LAST_FPARG_REG-MIPS_FIRST_FPARG_REG+1)
 
 /* we have the stack pointer, not the base pointer in sigcontext */
-#define MONO_CONTEXT_SET_IP(ctx,ip) do { (ctx)->sc_pc = (int)ip; } while (0); 
-#define MONO_CONTEXT_SET_BP(ctx,bp) do { (ctx)->sc_regs[mips_sp] = (int)bp; } while (0); 
-#define MONO_CONTEXT_SET_SP(ctx,sp) do { (ctx)->sc_regs[mips_sp] = (int)sp; } while (0); 
+#define MONO_CONTEXT_SET_IP(ctx,ip) do { (ctx)->sc_pc = (int)(ip); } while (0); 
+#define MONO_CONTEXT_SET_BP(ctx,bp) do { (ctx)->sc_regs[mips_fp] = (int)(bp); } while (0); 
+#define MONO_CONTEXT_SET_SP(ctx,sp) do { (ctx)->sc_regs[mips_sp] = (int)(sp); } while (0); 
 
 #define MONO_CONTEXT_GET_IP(ctx) ((gpointer)((ctx)->sc_pc))
-#define MONO_CONTEXT_GET_BP(ctx) ((gpointer)((ctx)->sc_regs[mips_sp]))
+#define MONO_CONTEXT_GET_BP(ctx) ((gpointer)((ctx)->sc_regs[mips_fp]))
 #define MONO_CONTEXT_GET_SP(ctx) ((gpointer)((ctx)->sc_regs[mips_sp]))
 
 typedef struct {
@@ -223,120 +358,69 @@ typedef struct {
                MONO_CONTEXT_SET_BP ((ctx), sp + (-imm));       \
                ra = *(guint32 *)(sp + (-imm) + MIPS_RET_ADDR_OFFSET);  \
                MONO_CONTEXT_SET_IP ((ctx),ra); \
+               MONO_CONTEXT_SET_SP ((ctx), MONO_CONTEXT_GET_BP (ctx)); \
        } while (0)
 
-#if 1
-#define mono_find_jit_info mono_arch_find_jit_info
-#define CUSTOM_STACK_WALK
-#endif
+#define MONO_ARCH_INIT_TOP_LMF_ENTRY(lmf) do { (lmf)->ebp = -1; } while (0)
 
 /* re-attaches with gdb - sometimes causes executable to hang */
 #undef HAVE_BACKTRACE_SYMBOLS
 
-#define CUSTOM_EXCEPTION_HANDLING
+#undef DEBUG_EXCEPTIONS
 
 #define MONO_ZERO_REG          mips_zero
 
-#define        MONO_EMIT_NEW_BRANCH_UNREG_LABEL(cfg,op,sr1,label) do { \
-                MonoInst *inst; \
-               inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
-               inst->opcode = op;      \
-               inst->sreg1 = sr1;      \
-               inst->inst_i0 = label;  \
-               inst->flags = MONO_INST_BRLABEL;        \
-               mono_bblock_add_inst ((cfg)->cbb, inst); \
-       } while (0)
-
-#define        MONO_EMIT_NEW_BRANCH_BIREG_LABEL(cfg,op,sr1,sr2,label) do {     \
-                MonoInst *inst; \
-               inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
-               inst->opcode = op;      \
-               inst->sreg1 = sr1;      \
-               inst->sreg2 = sr2;      \
-               inst->inst_i0 = label;  \
-               inst->flags = MONO_INST_BRLABEL;        \
-               mono_bblock_add_inst ((cfg)->cbb, inst); \
-       } while (0)
-
-#define        MONO_EMIT_NEW_BRANCH_NONZERO_LABEL(cfg,op,sr1,targetbb) do {    \
-                MonoInst *inst; \
-               MonoInst *target_label; \
-               target_label = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
-               target_label->opcode = OP_LABEL;        \
-               target_label->next = (targetbb)->code; \
-               target_label->inst_c0 = (targetbb)->native_offset; \
-               (targetbb)->code = target_label; \
-               inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
-               inst->opcode = op;      \
-                (inst)->sreg1 = sr1; \
-                (inst)->sreg2 = sr2; \
-               inst->inst_i0 = target_label;   \
-               inst->flags = MONO_INST_BRLABEL;        \
-               mono_bblock_add_inst ((cfg)->cbb, inst); \
-       } while (0)
-
-#define        MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK(cfg,op,sr1,sr2,targetbb) do {        \
+#define        MONO_EMIT_NEW_MIPS_COND_EXC(cfg,cond,sr1,sr2,name) do { \
                 MonoInst *inst; \
-               MonoInst *target_label; \
-               target_label = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
-               target_label->opcode = OP_LABEL;        \
-               target_label->next = (targetbb)->code; \
-               target_label->inst_c0 = (targetbb)->native_offset; \
-               (targetbb)->code = target_label; \
-               inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
-               inst->opcode = op;      \
-                (inst)->sreg1 = sr1; \
-                (inst)->sreg2 = sr2; \
-               inst->inst_i0 = target_label;   \
-               inst->flags = MONO_INST_BRLABEL;        \
-               mono_bblock_add_inst ((cfg)->cbb, inst); \
+               MONO_INST_NEW ((cfg), (inst), cond); \
+                inst->inst_p1 = (char*)name; \
+               inst->sreg1 = sr1; \
+               inst->sreg2 = sr2; \
+               MONO_ADD_INS ((cfg)->cbb, inst); \
        } while (0)
 
-#ifndef MONO_EMIT_NEW_COMPARE_BRANCH_LABEL
-#define MONO_EMIT_NEW_COMPARE_BRANCH_LABEL(cfg, cmp_op, sreg1, sreg2, label) \
-       do { \
-               switch (cmp_op) { \
-               case CEE_BEQ: \
-                       MONO_EMIT_NEW_BRANCH_BIREG_LABEL(cfg, OP_MIPS_BEQ, sreg1, sreg2, label); \
+#ifndef MONO_EMIT_NEW_COMPARE_EXC
+#define MONO_EMIT_NEW_COMPARE_EXC(cfg, cmp_op, sreg1, sreg2, exc) do { \
+               switch (OP_MIPS_COND_EXC_##cmp_op) { \
+               case OP_MIPS_COND_EXC_EQ: \
+                       MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_EQ, sreg1, sreg2, exc); \
                        break; \
-               case CEE_BNE_UN: \
-                       MONO_EMIT_NEW_BRANCH_BIREG_LABEL(cfg, OP_MIPS_BNE, sreg1, sreg2, label); \
+               case OP_MIPS_COND_EXC_NE_UN: \
+                       MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_NE_UN, sreg1, sreg2, exc); \
                        break; \
-               case CEE_BGE: \
-                       MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLT, mips_at, sreg1, sreg2); \
-                       MONO_EMIT_NEW_BIALU_IMM (s, OP_MIPS_XORI, mips_at, mips_at, 1); \
-                       MONO_EMIT_NEW_BRANCH_BIREG_LABEL(cfg, OP_MIPS_BNE, mips_at, mips_zero, label); \
+               case OP_MIPS_COND_EXC_GT: \
+                       MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLT, mips_at, sreg2, sreg1); \
+                       MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_NE_UN, mips_at, mips_zero, exc); \
                        break; \
-               case CEE_BGE_UN: \
-                       MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLTU, mips_at, sreg1, sreg2); \
-                       MONO_EMIT_NEW_BIALU_IMM (s, OP_MIPS_XORI, mips_at, mips_at, 1); \
-                       MONO_EMIT_NEW_BRANCH_BIREG_LABEL(cfg, OP_MIPS_BNE, mips_at, mips_zero, label); \
+               case OP_MIPS_COND_EXC_GT_UN: \
+                       MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLTU, mips_at, sreg2, sreg1); \
+                       MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_NE_UN, mips_at, mips_zero, exc); \
                        break; \
-               case CEE_BGT: \
+               case OP_MIPS_COND_EXC_LE: \
                        MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLT, mips_at, sreg2, sreg1); \
-                       MONO_EMIT_NEW_BRANCH_BIREG_LABEL(cfg, OP_MIPS_BNE, mips_at, mips_zero, label); \
+                       MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_EQ, mips_at, mips_zero, exc); \
                        break; \
-               case CEE_BGT_UN: \
+               case OP_MIPS_COND_EXC_LE_UN: \
                        MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLTU, mips_at, sreg2, sreg1); \
-                       MONO_EMIT_NEW_BRANCH_BIREG_LABEL(cfg, OP_MIPS_BNE, mips_at, mips_zero, label); \
+                       MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_EQ, mips_at, mips_zero, exc); \
                        break; \
-               case CEE_BLT: \
+               case OP_MIPS_COND_EXC_LT: \
                        MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLT, mips_at, sreg1, sreg2); \
-                       MONO_EMIT_NEW_BRANCH_BIREG_LABEL(cfg, OP_MIPS_BNE, mips_at, mips_zero, label); \
+                       MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_NE_UN, mips_at, mips_zero, exc); \
                        break; \
-               case CEE_BLT_UN: \
+               case OP_MIPS_COND_EXC_LT_UN: \
                        MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLTU, mips_at, sreg1, sreg2); \
-                       MONO_EMIT_NEW_BRANCH_BIREG_LABEL(cfg, OP_MIPS_BNE, mips_at, mips_zero, label); \
+                       MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_NE_UN, mips_at, mips_zero, exc); \
                        break; \
                default: \
-                       g_assert_not_reached(); \
+                       g_warning ("unknown comparison %s\n", #cmp_op); \
+                       g_assert_not_reached (); \
                } \
        } while (0)
 #endif
 
-#ifndef MONO_EMIT_NEW_COMPARE_IMM_BRANCH_LABEL
-#define MONO_EMIT_NEW_COMPARE_IMM_BRANCH_LABEL(cfg, cmp_op, sreg1, imm, label) \
-       do { \
+#ifndef MONO_EMIT_NEW_COMPARE_IMM_EXC
+#define MONO_EMIT_NEW_COMPARE_IMM_EXC(cfg, cmp_op, sreg1, imm, exc) do { \
                guint32 cmp_reg; \
                if (!(imm)) { \
                        cmp_reg = mips_zero; \
@@ -345,42 +429,13 @@ typedef struct {
                        cmp_reg = mips_at; \
                        MONO_EMIT_NEW_ICONST (cfg, cmp_reg, (imm)); \
                } \
-               MONO_EMIT_NEW_COMPARE_BRANCH_LABEL(cfg, cmp_op, sreg1, cmp_reg, label); \
-       } while (0)
-#endif
-
-#ifndef MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK
-#define MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK(cfg, cmp_op, sreg1, sreg2, block) \
-       do { \
-               switch (cmp_op) { \
-               case CEE_BEQ: \
-                       MONO_EMIT_NEW_BRANCH_BIREG_BLOCK(cfg, OP_MIPS_BEQ, sreg1, sreg2, block); \
-                       break; \
-               case CEE_BNE_UN: \
-                       MONO_EMIT_NEW_BRANCH_BIREG_BLOCK(cfg, OP_MIPS_BNE, sreg1, sreg2, block); \
-                       break; \
-               case CEE_BLT_UN: \
-                       MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLTU, mips_at, sreg1, sreg2); \
-                       MONO_EMIT_NEW_BRANCH_BIREG_BLOCK(cfg, OP_MIPS_BNE, mips_at, mips_zero, block); \
-                       break; \
-               default: \
-                       g_assert_not_reached(); \
-               } \
+               MONO_EMIT_NEW_COMPARE_EXC (cfg, cmp_op, sreg1, cmp_reg, exc); \
        } while (0)
 #endif
 
-#ifndef MONO_EMIT_NEW_COMPARE_IMM_BRANCH_BLOCK
-#define MONO_EMIT_NEW_COMPARE_IMM_BRANCH_BLOCK(cfg, cmp_op, sreg1, imm, block) \
-       do { \
-               guint32 cmp_reg; \
-               if (!(imm)) { \
-                       cmp_reg = mips_zero; \
-               } \
-               else { \
-                       cmp_reg = mips_at; \
-                       MONO_EMIT_NEW_ICONST (cfg, cmp_reg, (imm)); \
-               } \
-               MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK(cfg, cmp_op, sreg1, cmp_reg, block); \
+#ifndef MONO_EMIT_NEW_ICOMPARE_IMM_EXC
+#define MONO_EMIT_NEW_ICOMPARE_IMM_EXC(cfg, cmp_op, sreg1, imm, exc) do { \
+               MONO_EMIT_NEW_COMPARE_IMM_EXC(cfg, cmp_op, sreg1, imm, exc); \
        } while (0)
 #endif
 
@@ -391,4 +446,6 @@ typedef struct {
        int offset;
 } MonoMIPSArgInfo;
 
+extern guint8 *mips_emit_load_const(guint8 *code, int dreg, mgreg_t v);
+
 #endif /* __MONO_MINI_MIPS_H__ */