#include <mono/arch/mips/mips-codegen.h>
#include <glib.h>
+#define MONO_ARCH_CPU_SPEC mips_desc
+
#define MONO_MAX_IREGS 32
#define MONO_MAX_FREGS 32
#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
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;
gulong eip;
gulong iregs [MONO_SAVED_GREGS];
gfloat fregs [MONO_SAVED_FREGS];
- gulong pad;
+ gulong magic;
};
/* we define our own structure and we'll copy the data
#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 {
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
+#if 0
#define mono_find_jit_info mono_arch_find_jit_info
#define CUSTOM_STACK_WALK
#endif
/* re-attaches with gdb - sometimes causes executable to hang */
#undef HAVE_BACKTRACE_SYMBOLS
-#define CUSTOM_EXCEPTION_HANDLING
+#undef DEBUG_EXCEPTIONS
+#undef CUSTOM_EXCEPTION_HANDLING
#define MONO_ZERO_REG mips_zero
MonoInst *target_label; \
target_label = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
target_label->opcode = OP_LABEL; \
- target_label->next = (targetbb)->code; \
+ MONO_INST_LIST_ADD (&target_label->node, \
+ &(targetbb)->ins_list); \
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; \
MonoInst *target_label; \
target_label = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
target_label->opcode = OP_LABEL; \
- target_label->next = (targetbb)->code; \
+ MONO_INST_LIST_ADD (&target_label->node, \
+ &(targetbb)->ins_list); \
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; \
do { \
switch (cmp_op) { \
case CEE_BEQ: \
- MONO_EMIT_NEW_BRANCH_BIREG_BLOCK(cfg, OP_MIPS_BEQ, sreg1, sreg2, block); \
+ 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); \
+ 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); \
+ MONO_EMIT_NEW_BRANCH_BIREG_BLOCK (cfg, OP_MIPS_BNE, mips_at, mips_zero, block); \
break; \
default: \
- g_assert_not_reached(); \
+ g_assert_not_reached (); \
} \
} while (0)
#endif
} while (0)
#endif
+#define MONO_EMIT_NEW_MIPS_COND_EXC(cfg,cond,sr1,sr2,name) do { \
+ MonoInst *inst; \
+ inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
+ inst->opcode = cond; \
+ inst->inst_p1 = (char*)name; \
+ inst->sreg1 = sr1; \
+ inst->sreg2 = sr2; \
+ mono_bblock_add_inst ((cfg)->cbb, inst); \
+ } while (0)
+
+#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 OP_MIPS_COND_EXC_NE_UN: \
+ MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_NE_UN, sreg1, sreg2, exc); \
+ break; \
+ 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 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 OP_MIPS_COND_EXC_LE: \
+ MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLT, mips_at, sreg2, sreg1); \
+ MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_EQ, mips_at, mips_zero, exc); \
+ break; \
+ case OP_MIPS_COND_EXC_LE_UN: \
+ MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLTU, mips_at, sreg2, sreg1); \
+ MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_EQ, mips_at, mips_zero, exc); \
+ break; \
+ case OP_MIPS_COND_EXC_LT: \
+ MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLT, mips_at, sreg1, sreg2); \
+ MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_NE_UN, mips_at, mips_zero, exc); \
+ break; \
+ case OP_MIPS_COND_EXC_LT_UN: \
+ MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLTU, mips_at, sreg1, sreg2); \
+ MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_NE_UN, mips_at, mips_zero, exc); \
+ break; \
+ default: \
+ g_warning ("unknown comparison %s\n", #cmp_op); \
+ g_assert_not_reached (); \
+ } \
+ } while (0)
+#endif
+
+#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; \
+ } \
+ else { \
+ cmp_reg = mips_at; \
+ MONO_EMIT_NEW_ICONST (cfg, cmp_reg, (imm)); \
+ } \
+ MONO_EMIT_NEW_COMPARE_EXC (cfg, cmp_op, sreg1, cmp_reg, exc); \
+ } while (0)
+#endif
+
+#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
+
typedef struct {
gint8 reg;
gint8 size;