X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fmini-mips.c;h=e2487779fde15282ddbd1add8a6357b340475a41;hb=e96b1271fd0f67dc198a28378f433a9c318640f4;hp=2ed52ac483e73668a768965388810bcb565a3c99;hpb=50ae304d5c6b7947def396f26138a77afd52646e;p=mono.git diff --git a/mono/mini/mini-mips.c b/mono/mini/mini-mips.c index 2ed52ac483e..e2487779fde 100644 --- a/mono/mini/mini-mips.c +++ b/mono/mini/mini-mips.c @@ -18,24 +18,24 @@ #include #include +#include + #include "mini-mips.h" #include "cpu-mips.h" #include "trace.h" #include "ir-emit.h" -#warning "The mips backend is still being ported to the linear IR." - #define SAVE_FP_REGS 0 #define SAVE_ALL_REGS 0 #define EXTRA_STACK_SPACE 0 /* suppresses some s-reg corruption issues */ -#define LONG_BRANCH 0 /* needed for yyparse in mcs */ +#define LONG_BRANCH 1 /* needed for yyparse in mcs */ #define SAVE_LMF 1 #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_LDC_SDC 0 /* use ldc/sdc to load/store doubles */ +#define USE_MUL 1 /* use mul instead of mult/mflo for multiply */ enum { TLS_MODE_DETECT, @@ -94,8 +94,12 @@ static int monodomain_key = -1; mono_bblock_add_inst (cfg->cbb, inst); \ } while (0) -#define ins_is_compare(ins) ((ins) && (((ins)->opcode == OP_COMPARE) || ((ins)->opcode == OP_ICOMPARE))) -#define ins_is_compare_imm(ins) ((ins) && (((ins)->opcode == OP_COMPARE_IMM) || ((ins)->opcode == OP_ICOMPARE_IMM))) +#define ins_is_compare(ins) ((ins) && (((ins)->opcode == OP_COMPARE) \ + || ((ins)->opcode == OP_ICOMPARE) \ + || ((ins)->opcode == OP_LCOMPARE))) +#define ins_is_compare_imm(ins) ((ins) && (((ins)->opcode == OP_COMPARE_IMM) \ + || ((ins)->opcode == OP_ICOMPARE_IMM) \ + || ((ins)->opcode == OP_LCOMPARE_IMM))) #define INS_REWRITE(ins, op, _s1, _s2) do { \ int s1 = _s1; \ @@ -153,6 +157,11 @@ typedef struct { void patch_lui_addiu(guint32 *ip, guint32 val); guint8 *mono_arch_emit_epilog_sub (MonoCompile *cfg, guint8 *code); +guint8 *mips_emit_cond_branch (MonoCompile *cfg, guint8 *code, int op, MonoInst *ins); +void mips_adjust_stackframe(MonoCompile *cfg); +void mono_arch_emit_this_vret_args (MonoCompile *cfg, MonoCallInst *inst, int this_reg, int this_type, int vt_reg); +MonoInst *mono_arch_get_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args); + void mono_arch_flush_icache (guint8 *code, gint size) @@ -176,9 +185,13 @@ static guint8 * mips_emit_exc_by_name(guint8 *code, const char *name) { guint32 addr; + MonoClass *exc_class; + + exc_class = mono_class_from_name (mono_defaults.corlib, "System", name); + g_assert (exc_class); - mips_load_const (code, mips_a0, name); - addr = (guint32) mono_arch_get_throw_exception_by_name (); + mips_load_const (code, mips_a0, exc_class->type_token); + addr = (guint32) mono_arch_get_throw_corlib_exception (); mips_load_const (code, mips_t9, addr); mips_jalr (code, mips_t9, mips_ra); mips_nop (code); @@ -187,10 +200,42 @@ mips_emit_exc_by_name(guint8 *code, const char *name) } +guint8 * +mips_emit_load_const(guint8 *code, int dreg, mgreg_t v) +{ + if (mips_is_imm16 (v)) + mips_addiu (code, dreg, mips_zero, ((guint32)v) & 0xffff); + else { +#ifdef SIZEOF_REGISTER == 8 + if (v != (long) v) { + /* v is not a sign-extended 32-bit value */ + mips_lui (code, dreg, mips_zero, (guint32)((v >> (32+16)) & 0xffff)); + mips_ori (code, dreg, dreg, (guint32)((v >> (32)) & 0xffff)); + mips_dsll (code, dreg, dreg, 16); + mips_ori (code, dreg, dreg, (guint32)((v >> (16)) & 0xffff)); + mips_dsll (code, dreg, dreg, 16); + mips_ori (code, dreg, dreg, (guint32)(v & 0xffff)); + return code; + } +#endif + if (((guint32)v) & (1 << 15)) { + mips_lui (code, dreg, mips_zero, (((guint32)v)>>16)+1); + } + else { + mips_lui (code, dreg, mips_zero, (((guint32)v)>>16)); + } + if (((guint32)v) & 0xffff) + mips_addiu (code, dreg, dreg, ((guint32)v) & 0xffff); + } + return code; +} + guint8 * mips_emit_cond_branch (MonoCompile *cfg, guint8 *code, int op, MonoInst *ins) { +#if LONG_BRANCH int br_offset = 5; +#endif g_assert (ins); #if LONG_BRANCH @@ -223,23 +268,15 @@ mips_emit_cond_branch (MonoCompile *cfg, guint8 *code, int op, MonoInst *ins) default: g_assert_not_reached (); } - if (ins->flags & MONO_INST_BRLABEL) - mono_add_patch_info (cfg, code - cfg->native_code, - MONO_PATCH_INFO_LABEL, ins->inst_i0); - else - mono_add_patch_info (cfg, code - cfg->native_code, - MONO_PATCH_INFO_BB, ins->inst_true_bb); + mono_add_patch_info (cfg, code - cfg->native_code, + MONO_PATCH_INFO_BB, ins->inst_true_bb); mips_lui (code, mips_at, mips_zero, 0); mips_addiu (code, mips_at, mips_at, 0); mips_jr (code, mips_at); mips_nop (code); #else - if (ins->flags & MONO_INST_BRLABEL) - mono_add_patch_info (cfg, code - cfg->native_code, - MONO_PATCH_INFO_LABEL, ins->inst_i0); - else - mono_add_patch_info (cfg, code - cfg->native_code, - MONO_PATCH_INFO_BB, ins->inst_true_bb); + mono_add_patch_info (cfg, code - cfg->native_code, + MONO_PATCH_INFO_BB, ins->inst_true_bb); switch (op) { case OP_MIPS_BEQ: mips_beq (code, ins->sreg1, ins->sreg2, 0); @@ -341,6 +378,7 @@ mips_patch (guint32 *code, guint32 target) } } +#if 0 static int offsets_from_pthread_key (guint32 key, int *offset2) { @@ -349,9 +387,11 @@ offsets_from_pthread_key (guint32 key, int *offset2) *offset2 = idx2 * sizeof (gpointer); return 284 + idx1 * sizeof (gpointer); } +#endif const char* mono_arch_regname (int reg) { +#if _MIPS_SIM == _ABIO32 static const char * rnames[] = { "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3", @@ -362,6 +402,18 @@ mono_arch_regname (int reg) { "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra" }; +#elif _MIPS_SIM == _ABIN32 + static const char * rnames[] = { + "zero", "at", "v0", "v1", + "a0", "a1", "a2", "a3", + "a4", "a5", "a6", "a7", + "t0", "t1", "t2", "t3", + "s0", "s1", "s2", "s3", + "s4", "s5", "s6", "s7", + "t8", "t9", "k0", "k1", + "gp", "sp", "fp", "ra" + }; +#endif if (reg >= 0 && reg < 32) return rnames [reg]; return "unknown"; @@ -456,7 +508,7 @@ mono_arch_get_argument_info (MonoMethodSignature *csig, int param_count, MonoJit gpointer -mono_arch_get_this_arg_from_call (MonoGenericSharingContext *gsctx, MonoMethodSignature *sig, gssize *regs, guint8 *code) +mono_arch_get_this_arg_from_call (MonoGenericSharingContext *gsctx, MonoMethodSignature *sig, mgreg_t *regs, guint8 *code) { /* FIXME: handle returning a struct */ if (MONO_TYPE_ISSTRUCT (sig->ret)) @@ -511,6 +563,10 @@ is_regsize_var (MonoType *t) { switch (t->type) { case MONO_TYPE_I4: case MONO_TYPE_U4: +#if (SIZEOF_REGISTER == 8) + case MONO_TYPE_I8: + case MONO_TYPE_U8: +#endif case MONO_TYPE_I: case MONO_TYPE_U: case MONO_TYPE_PTR: @@ -594,12 +650,13 @@ mono_arch_regalloc_cost (MonoCompile *cfg, MonoMethodVar *vmv) static void args_onto_stack (CallInfo *info) { - g_assert(!info->on_stack); - g_assert(info->stack_size <= MIPS_STACK_PARAM_OFFSET); + g_assert (!info->on_stack); + g_assert (info->stack_size <= MIPS_STACK_PARAM_OFFSET); info->on_stack = TRUE; info->stack_size = MIPS_STACK_PARAM_OFFSET; } +#if _MIPS_SIM == _ABIO32 /* * O32 calling convention version */ @@ -633,7 +690,7 @@ add_int64_arg (CallInfo *info, ArgInfo *ainfo) { /* Now, place the argument */ if (info->on_stack) { - g_assert(info->stack_size % 4 == 0); + g_assert (info->stack_size % 4 == 0); info->stack_size += (info->stack_size % 8); ainfo->regtype = RegTypeBase; @@ -727,13 +784,120 @@ add_float64_arg (CallInfo *info, ArgInfo *ainfo) { } info->stack_size += 8; } +#elif _MIPS_SIM == _ABIN32 +/* + * N32 calling convention version + */ + +static void +add_int32_arg (CallInfo *info, ArgInfo *ainfo) { + /* First, see if we need to drop onto the stack */ + if (!info->on_stack && info->gr > MIPS_LAST_ARG_REG) + args_onto_stack (info); + + /* Now, place the argument */ + if (info->on_stack) { + ainfo->regtype = RegTypeBase; + ainfo->reg = mips_sp; /* in the caller */ + ainfo->offset = info->stack_size; + info->stack_size += SIZEOF_REGISTER; + } + else { + ainfo->regtype = RegTypeGeneral; + ainfo->reg = info->gr; + info->gr += 1; + info->gr_passed = TRUE; + } +} + +static void +add_int64_arg (CallInfo *info, ArgInfo *ainfo) { + /* First, see if we need to drop onto the stack */ + if (!info->on_stack && info->gr > MIPS_LAST_ARG_REG) + args_onto_stack (info); + + /* Now, place the argument */ + if (info->on_stack) { + g_assert (info->stack_size % 4 == 0); + info->stack_size += (info->stack_size % 8); + + ainfo->regtype = RegTypeBase; + ainfo->reg = mips_sp; /* in the caller */ + ainfo->offset = info->stack_size; + info->stack_size += SIZEOF_REGISTER; + } + else { + g_assert (info->gr <= MIPS_LAST_ARG_REG); + + ainfo->regtype = RegTypeGeneral; + ainfo->reg = info->gr; + info->gr += 1; + info->gr_passed = TRUE; + } +} + +static void +add_float32_arg (CallInfo *info, ArgInfo *ainfo) { + /* First, see if we need to drop onto the stack */ + if (!info->on_stack) { + if (info->gr > MIPS_LAST_ARG_REG) + args_onto_stack (info); + else if (info->fr > MIPS_LAST_FPARG_REG) + args_onto_stack (info); + } + + /* Now, place the argument */ + if (info->on_stack) { + ainfo->regtype = RegTypeBase; + ainfo->reg = mips_sp; /* in the caller */ + ainfo->offset = info->stack_size; + info->stack_size += FREG_SIZE; + } + else { + ainfo->regtype = RegTypeFP; + ainfo->reg = info->fr; + info->fr += 1; + /* FP and GP slots do not overlap */ + info->gr += 1; + } +} + +static void +add_float64_arg (CallInfo *info, ArgInfo *ainfo) { + /* First, see if we need to drop onto the stack */ + if (!info->on_stack) { + if (info->gr > MIPS_LAST_ARG_REG) + args_onto_stack (info); + else if (info->fr > MIPS_LAST_FPARG_REG) + args_onto_stack (info); + } + + /* Now, place the argument */ + if (info->on_stack) { + g_assert(info->stack_size % 4 == 0); + info->stack_size += (info->stack_size % 8); + + ainfo->regtype = RegTypeBase; + ainfo->reg = mips_sp; /* in the caller */ + ainfo->offset = info->stack_size; + info->stack_size += FREG_SIZE; + } + else { + ainfo->regtype = RegTypeFP; + ainfo->reg = info->fr; + info->fr += 1; + /* FP and GP slots do not overlap */ + info->gr += 1; + } +} +#endif static CallInfo* calculate_sizes (MonoMethodSignature *sig, gboolean is_pinvoke) { guint i; int n = sig->hasthis + sig->param_count; - guint32 simpletype; + MonoType* simpletype; CallInfo *cinfo = g_malloc0 (sizeof (CallInfo) + sizeof (ArgInfo) * n); cinfo->fr = MIPS_FIRST_FPARG_REG; @@ -769,8 +933,8 @@ calculate_sizes (MonoMethodSignature *sig, gboolean is_pinvoke) n++; continue; } - simpletype = mono_type_get_underlying_type (sig->params [i])->type; - switch (simpletype) { + simpletype = mono_type_get_underlying_type (sig->params [i]); + switch (simpletype->type) { case MONO_TYPE_BOOLEAN: case MONO_TYPE_I1: case MONO_TYPE_U1: @@ -808,7 +972,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_int32_arg (cinfo, &cinfo->args[n]); n++; @@ -932,8 +1096,8 @@ calculate_sizes (MonoMethodSignature *sig, gboolean is_pinvoke) } { - simpletype = mono_type_get_underlying_type (sig->ret)->type; - switch (simpletype) { + simpletype = mono_type_get_underlying_type (sig->ret); + switch (simpletype->type) { case MONO_TYPE_BOOLEAN: case MONO_TYPE_I1: case MONO_TYPE_U1: @@ -963,7 +1127,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 = mips_v0; break; } @@ -999,7 +1163,9 @@ mono_arch_allocate_vars (MonoCompile *cfg) int i, offset, size, align, curinst; int frame_reg = mips_sp; guint32 iregs_to_save = 0; +#if SAVE_FP_REGS guint32 fregs_to_restore; +#endif /* spill down, we'll fix it in a separate pass */ // cfg->flags |= MONO_CFG_HAS_SPILLUP; @@ -1124,7 +1290,7 @@ mono_arch_allocate_vars (MonoCompile *cfg) if (iregs_to_save) { for (i = MONO_MAX_IREGS-1; i >= 0; --i) { if (iregs_to_save & (1 << i)) { - offset += sizeof (gulong); + offset += SIZEOF_REGISTER; } } } @@ -1140,19 +1306,21 @@ mono_arch_allocate_vars (MonoCompile *cfg) if (fregs_to_restore) { for (i = MONO_MAX_FREGS-1; i >= 0; --i) { if (fregs_to_restore & (1 << i)) { - offset += sizeof (double); + offset += sizeof(double); } } } #endif +#if _MIPS_SIM == _ABIO32 /* Now add space for saving the ra */ - offset += 4; + offset += SIZEOF_VOID_P; /* change sign? */ offset = (offset + MIPS_STACK_ALIGNMENT - 1) & ~(MIPS_STACK_ALIGNMENT - 1); cfg->stack_offset = offset; cfg->arch.local_alloc_offset = cfg->stack_offset; +#endif /* * Now allocate stack slots for the int arg regs (a0 - a3) @@ -1166,7 +1334,7 @@ mono_arch_allocate_vars (MonoCompile *cfg) cfg->vret_addr->inst_c0 = mips_a0; cfg->vret_addr->inst_offset = offset; cfg->vret_addr->inst_basereg = frame_reg; - offset += 4; + offset += SIZEOF_REGISTER; } for (i = 0; i < sig->param_count + sig->hasthis; ++i) { @@ -1182,9 +1350,9 @@ mono_arch_allocate_vars (MonoCompile *cfg) inst->opcode = OP_REGOFFSET; size = mono_type_size (arg_type, &align); - if (size < 4) { - size = 4; - align = 4; + if (size < SIZEOF_REGISTER) { + size = SIZEOF_REGISTER; + align = SIZEOF_REGISTER; } inst->inst_basereg = frame_reg; offset = (offset + align - 1) & ~(align - 1); @@ -1195,9 +1363,10 @@ mono_arch_allocate_vars (MonoCompile *cfg) // g_print ("allocating param %d to %d\n", i, inst->inst_offset); } else { - /* Even a0-a3 get stack slots */ - size = sizeof (gpointer); - align = sizeof (gpointer); +#if _MIPS_SIM == _ABIO32 + /* o32: Even a0-a3 get stack slots */ + size = SIZEOF_REGISTER; + align = SIZEOF_REGISTER; inst->inst_basereg = frame_reg; offset = (offset + align - 1) & ~(align - 1); inst->inst_offset = offset; @@ -1205,8 +1374,18 @@ mono_arch_allocate_vars (MonoCompile *cfg) if ((sig->call_convention == MONO_CALL_VARARG) && (i < sig->sentinelpos)) cfg->sig_cookie += size; // g_print ("allocating param %d to %d\n", i, inst->inst_offset); +#endif } } +#if _MIPS_SIM == _ABIN32 + /* Now add space for saving the ra */ + offset += SIZEOF_VOID_P; + + /* change sign? */ + offset = (offset + MIPS_STACK_ALIGNMENT - 1) & ~(MIPS_STACK_ALIGNMENT - 1); + cfg->stack_offset = offset; + cfg->arch.local_alloc_offset = cfg->stack_offset; +#endif } void @@ -1282,6 +1461,7 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) } in = call->args [i]; if (ainfo->regtype == RegTypeGeneral) { +#if SIZEOF_REGISTER == 4 if (!t->byref && ((t->type == MONO_TYPE_I8) || (t->type == MONO_TYPE_U8))) { MONO_INST_NEW (cfg, ins, OP_MOVE); ins->dreg = mono_alloc_ireg (cfg); @@ -1294,7 +1474,9 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) ins->sreg1 = in->dreg + 2; MONO_ADD_INS (cfg->cbb, ins); mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, ainfo->reg, FALSE); - } else if (!t->byref && (t->type == MONO_TYPE_R4)) { + } else +#endif + if (!t->byref && (t->type == MONO_TYPE_R4)) { int freg; #if PROMOTE_R4_TO_R8 @@ -1374,7 +1556,7 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) int dreg = mono_alloc_freg (cfg); if (ainfo->size == 4) { - MONO_EMIT_NEW_UNALU (cfg, OP_FCONV_TO_R4, dreg, in->dreg); + MONO_EMIT_NEW_UNALU (cfg, OP_MIPS_CVTSD, dreg, in->dreg); } else { MONO_INST_NEW (cfg, ins, OP_FMOVE); ins->dreg = dreg; @@ -1422,7 +1604,10 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) #endif call->stack_usage = cinfo->stack_usage; cfg->param_area = MAX (cfg->param_area, cinfo->stack_usage); - cfg->param_area = MAX (cfg->param_area, 16); /* a0-a3 always present */ +#if _MIPS_SIM == _ABIO32 + /* a0-a3 always present */ + cfg->param_area = MAX (cfg->param_area, 4 * SIZEOF_REGISTER); +#endif cfg->param_area = (cfg->param_area + MIPS_STACK_ALIGNMENT - 1) & ~(MIPS_STACK_ALIGNMENT - 1); cfg->flags |= MONO_CFG_HAS_CALLS; /* @@ -1457,7 +1642,7 @@ mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src) dreg = mono_alloc_ireg (cfg); MONO_EMIT_NEW_LOAD_MEMBASE (cfg, dreg, src->dreg, soffset); mono_call_inst_add_outarg_reg (cfg, call, dreg, ainfo->reg + i, FALSE); - soffset += sizeof (gpointer); + soffset += SIZEOF_REGISTER; } if (ovf_size != 0) { mini_emit_memcpy (cfg, mips_fp, doffset, src->dreg, soffset, ovf_size * sizeof (gpointer), 0); @@ -1504,6 +1689,7 @@ mono_arch_emit_setret (MonoCompile *cfg, MonoMethod *method, MonoInst *val) mono_method_signature (method)->ret); if (!ret->byref) { +#if (SIZEOF_REGISTER == 4) if (ret->type == MONO_TYPE_I8 || ret->type == MONO_TYPE_U8) { MonoInst *ins; @@ -1513,12 +1699,13 @@ mono_arch_emit_setret (MonoCompile *cfg, MonoMethod *method, MonoInst *val) MONO_ADD_INS (cfg->cbb, ins); return; } +#endif if (ret->type == MONO_TYPE_R8) { MONO_EMIT_NEW_UNALU (cfg, OP_FMOVE, cfg->ret->dreg, val->dreg); return; } if (ret->type == MONO_TYPE_R4) { - MONO_EMIT_NEW_UNALU (cfg, OP_FCONV_TO_R4, cfg->ret->dreg, val->dreg); + MONO_EMIT_NEW_UNALU (cfg, OP_MIPS_CVTSD, cfg->ret->dreg, val->dreg); return; } } @@ -2074,73 +2261,6 @@ mono_arch_decompose_opts (MonoCompile *cfg, MonoInst *ins) MONO_EMIT_NEW_COMPARE_EXC (cfg, NE_UN, tmp1, mips_zero, "OverflowException"); ins->opcode = OP_NOP; break; - - case OP_ICONV_TO_R_UN: { - static const guint64 adjust_val = 0x4330000000000000ULL; - int msw_reg = mono_alloc_ireg (cfg); - int adj_reg = mono_alloc_freg (cfg); - int tmp_reg = mono_alloc_freg (cfg); - int basereg = mips_sp; - int offset = -8; - - MONO_EMIT_NEW_ICONST (cfg, msw_reg, 0x43300000); - if (!mips_is_imm16 (offset + 4)) { - basereg = mono_alloc_ireg (cfg); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IADD_IMM, basereg, cfg->frame_reg, offset); - } - MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, basereg, offset, msw_reg); - MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, basereg, offset + 4, ins->sreg1); - MONO_EMIT_NEW_LOAD_R8 (cfg, adj_reg, &adjust_val); - MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR8_MEMBASE, tmp_reg, basereg, offset); - MONO_EMIT_NEW_BIALU (cfg, OP_FSUB, ins->dreg, tmp_reg, adj_reg); - ins->opcode = OP_NOP; - break; - } - case OP_ICONV_TO_R4: - case OP_ICONV_TO_R8: { - /* FIXME: change precision for OP_ICONV_TO_R4 */ - static const guint64 adjust_val = 0x4330000080000000ULL; - int msw_reg = mono_alloc_ireg (cfg); - int xored = mono_alloc_ireg (cfg); - int adj_reg = mono_alloc_freg (cfg); - int tmp_reg = mono_alloc_freg (cfg); - int basereg = mips_sp; - int offset = -8; - - if (!mips_is_imm16 (offset + 4)) { - basereg = mono_alloc_ireg (cfg); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IADD_IMM, basereg, cfg->frame_reg, offset); - } - MONO_EMIT_NEW_ICONST (cfg, msw_reg, 0x43300000); - MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, basereg, offset, msw_reg); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_XOR_IMM, xored, ins->sreg1, 0x80000000); - MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, basereg, offset + 4, xored); - MONO_EMIT_NEW_LOAD_R8 (cfg, adj_reg, (gpointer)&adjust_val); - MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR8_MEMBASE, tmp_reg, basereg, offset); - MONO_EMIT_NEW_BIALU (cfg, OP_FSUB, ins->dreg, tmp_reg, adj_reg); - if (ins->opcode == OP_ICONV_TO_R4) - MONO_EMIT_NEW_UNALU (cfg, OP_FCONV_TO_R4, ins->dreg, ins->dreg); - ins->opcode = OP_NOP; - break; - } -#if 0 - case OP_CKFINITE: { - int msw_reg = mono_alloc_ireg (cfg); - int basereg = mips_sp; - int offset = -8; - - if (!mips_is_imm16 (offset + 4)) { - basereg = mono_alloc_ireg (cfg); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IADD_IMM, basereg, cfg->frame_reg, offset); - } - MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG, basereg, offset, ins->sreg1); - MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI4_MEMBASE, msw_reg, basereg, offset); - MONO_EMIT_NEW_UNALU (cfg, OP_CHECK_FINITE, -1, msw_reg); - MONO_EMIT_NEW_UNALU (cfg, OP_FMOVE, ins->dreg, ins->sreg1); - ins->opcode = OP_NOP; - break; - } -#endif } } @@ -2159,6 +2279,8 @@ map_to_reg_reg_op (int op) return OP_COMPARE; case OP_ICOMPARE_IMM: return OP_ICOMPARE; + case OP_LCOMPARE_IMM: + return OP_LCOMPARE; case OP_ADDCC_IMM: return OP_IADDCC; case OP_ADC_IMM: @@ -2211,6 +2333,8 @@ map_to_reg_reg_op (int op) return OP_STOREI2_MEMBASE_REG; case OP_STOREI4_MEMBASE_IMM: return OP_STOREI4_MEMBASE_REG; + case OP_STOREI8_MEMBASE_IMM: + return OP_STOREI8_MEMBASE_REG; } return mono_op_imm_to_op (op); } @@ -2304,6 +2428,7 @@ loop_start: switch (ins->opcode) { case OP_COMPARE: case OP_ICOMPARE: + case OP_LCOMPARE: next = ins->next; /* Branch opts can eliminate the branch */ if (!next || (!(MONO_IS_COND_BRANCH_OP (next) || MONO_IS_COND_EXC (next) || MONO_IS_SETCC (next)))) { @@ -2314,6 +2439,7 @@ loop_start: case OP_COMPARE_IMM: case OP_ICOMPARE_IMM: + case OP_LCOMPARE_IMM: next = ins->next; /* Branch opts can eliminate the branch */ if (!next || (!(MONO_IS_COND_BRANCH_OP (next) || MONO_IS_COND_EXC (next) || MONO_IS_SETCC (next)))) { @@ -2334,6 +2460,8 @@ loop_start: ins->opcode = OP_COMPARE; else if (ins->opcode == OP_ICOMPARE_IMM) ins->opcode = OP_ICOMPARE; + else if (ins->opcode == OP_LCOMPARE_IMM) + ins->opcode = OP_LCOMPARE; goto loop_start; case OP_IDIV_UN_IMM: @@ -2398,26 +2526,8 @@ loop_start: } break; - case OP_FCOMPARE: - next = ins->next; - /* Branch opts can eliminate the branch */ - if (!next || (!(MONO_IS_COND_BRANCH_OP (next) || MONO_IS_COND_EXC (next) || MONO_IS_SETCC (next)))) { - ins->opcode = OP_NOP; - break; - } - g_assert(next); - - /* - * remap compare/branch and compare/set - * to MIPS specific opcodes. - */ - ins->opcode = OP_NOP; - next->opcode = map_to_mips_op (next->opcode); - next->sreg1 = ins->sreg1; - next->sreg2 = ins->sreg2; - break; - case OP_SUB_IMM: + case OP_ISUB_IMM: if (!mips_is_imm16 (-ins->inst_imm)) { NEW_INS (cfg, last_ins, temp, OP_ICONST); temp->inst_c0 = ins->inst_imm; @@ -2427,17 +2537,8 @@ loop_start: } break; - case OP_SBB_IMM: - case OP_SUBCC_IMM: - case OP_ADC_IMM: - NEW_INS (cfg, last_ins, temp, OP_ICONST); - temp->inst_c0 = ins->inst_imm; - temp->dreg = mono_alloc_ireg (cfg); - ins->sreg2 = temp->dreg; - ins->opcode = map_to_reg_reg_op (ins->opcode); - break; - case OP_MUL_IMM: + case OP_IMUL_IMM: if (ins->inst_imm == 1) { ins->opcode = OP_MOVE; break; @@ -2453,13 +2554,19 @@ loop_start: ins->inst_imm = imm; break; } - if (!mips_is_imm16 (ins->inst_imm)) { - NEW_INS (cfg, last_ins, temp, OP_ICONST); - temp->inst_c0 = ins->inst_imm; - temp->dreg = mono_alloc_ireg (cfg); - ins->sreg2 = temp->dreg; - ins->opcode = map_to_reg_reg_op (ins->opcode); - } + NEW_INS (cfg, last_ins, temp, OP_ICONST); + temp->inst_c0 = ins->inst_imm; + temp->dreg = mono_alloc_ireg (cfg); + ins->sreg2 = temp->dreg; + ins->opcode = map_to_reg_reg_op (ins->opcode); + break; + + case OP_LOCALLOC_IMM: + NEW_INS (cfg, last_ins, temp, OP_ICONST); + temp->inst_c0 = ins->inst_imm; + temp->dreg = mono_alloc_ireg (cfg); + ins->sreg1 = temp->dreg; + ins->opcode = OP_LOCALLOC; break; case OP_LOAD_MEMBASE: @@ -2495,6 +2602,7 @@ loop_start: case OP_STOREI1_MEMBASE_IMM: case OP_STOREI2_MEMBASE_IMM: case OP_STOREI4_MEMBASE_IMM: + case OP_STOREI8_MEMBASE_IMM: if (!ins->inst_imm) { ins->sreg1 = mips_zero; ins->opcode = map_to_reg_reg_op (ins->opcode); @@ -2510,6 +2618,26 @@ loop_start: } break; + case OP_FCOMPARE: + next = ins->next; + /* Branch opts can eliminate the branch */ + if (!next || (!(MONO_IS_COND_BRANCH_OP (next) || MONO_IS_COND_EXC (next) || MONO_IS_SETCC (next)))) { + ins->opcode = OP_NOP; + break; + } + g_assert(next); + + /* + * remap compare/branch and compare/set + * to MIPS specific opcodes. + */ + ins->opcode = OP_NOP; + next->opcode = map_to_mips_op (next->opcode); + next->sreg1 = ins->sreg1; + next->sreg2 = ins->sreg2; + break; + +#if 0 case OP_R8CONST: case OP_R4CONST: NEW_INS (cfg, last_ins, temp, OP_ICONST); @@ -2523,7 +2651,7 @@ loop_start: * later optimize to use lis + load_membase */ goto loop_start; - +#endif case OP_IBEQ: g_assert (ins_is_compare(last_ins)); INS_REWRITE(ins, OP_MIPS_BEQ, last_ins->sreg1, last_ins->sreg2); @@ -2775,7 +2903,7 @@ loop_start: static guchar* emit_float_to_int (MonoCompile *cfg, guchar *code, int dreg, int sreg, int size, gboolean is_signed) { - /* sreg is a float, dreg is an integer reg. mips_at is used a scratch */ + /* sreg is a float, dreg is an integer reg. mips_at is used as scratch */ #if 1 mips_truncwd (code, mips_ftemp, sreg); #else @@ -2805,7 +2933,7 @@ emit_float_to_int (MonoCompile *cfg, guchar *code, int dreg, int sreg, int size, /* * emit_load_volatile_arguments: * - * Load volatile arguments from the stack to the original input registers. + * Load volatile arguments from the stack to the original input registers. * Required before a tail call. */ static guint8 * @@ -2830,7 +2958,7 @@ emit_load_volatile_arguments(MonoCompile *cfg, guint8 *code) inst = cfg->args [i]; if (inst->opcode == OP_REGVAR) { if (ainfo->regtype == RegTypeGeneral) - mips_move (code, ainfo->reg, inst->dreg); + MIPS_MOVE (code, ainfo->reg, inst->dreg); else if (ainfo->regtype == RegTypeFP) g_assert_not_reached(); else if (ainfo->regtype == RegTypeBase) { @@ -2864,11 +2992,11 @@ emit_load_volatile_arguments(MonoCompile *cfg, guint8 *code) } else if (ainfo->regtype == RegTypeFP) { g_assert (mips_is_imm16 (inst->inst_offset)); if (ainfo->size == 8) { -#if USE_LDC_SDC - mips_ldc1 (code, ainfo->reg, inst->inst_basereg, inst->inst_offset); -#else +#if _MIPS_SIM == _ABIO32 mips_lwc1 (code, ainfo->reg, inst->inst_basereg, inst->inst_offset+4); mips_lwc1 (code, ainfo->reg+1, inst->inst_basereg, inst->inst_offset); +#elif _MIPS_SIM == _ABIN32 + mips_ldc1 (code, ainfo->reg, inst->inst_basereg, inst->inst_offset); #endif } else if (ainfo->size == 4) @@ -2883,7 +3011,7 @@ emit_load_volatile_arguments(MonoCompile *cfg, guint8 *code) g_assert (mips_is_imm16 (inst->inst_offset + ainfo->size * sizeof (gpointer))); for (i = 0; i < ainfo->size; ++i) { mips_lw (code, ainfo->reg + i, inst->inst_basereg, doffset); - doffset += sizeof (gpointer); + doffset += SIZEOF_REGISTER; } } else if (ainfo->regtype == RegTypeStructByAddr) { g_assert (mips_is_imm16 (inst->inst_offset)); @@ -3041,6 +3169,15 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) mips_sh (code, mips_temp, mips_at, ins->inst_destbasereg); } break; + case OP_STOREI8_MEMBASE_IMM: + mips_load_const (code, mips_temp, ins->inst_imm); + if (mips_is_imm16 (ins->inst_offset)) { + mips_sd (code, mips_temp, ins->inst_destbasereg, ins->inst_offset); + } else { + mips_load_const (code, mips_at, ins->inst_offset); + mips_sd (code, mips_temp, mips_at, ins->inst_destbasereg); + } + break; case OP_STORE_MEMBASE_IMM: case OP_STOREI4_MEMBASE_IMM: mips_load_const (code, mips_temp, ins->inst_imm); @@ -3079,11 +3216,29 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) mips_sw (code, ins->sreg1, mips_at, 0); } break; + case OP_STOREI8_MEMBASE_REG: + if (mips_is_imm16 (ins->inst_offset)) { + mips_sd (code, ins->sreg1, ins->inst_destbasereg, ins->inst_offset); + } else { + mips_load_const (code, mips_at, ins->inst_offset); + mips_addu (code, mips_at, mips_at, ins->inst_destbasereg); + mips_sd (code, ins->sreg1, mips_at, 0); + } + break; case OP_LOADU4_MEM: g_assert_not_reached (); //x86_mov_reg_imm (code, ins->dreg, ins->inst_p0); //x86_mov_reg_membase (code, ins->dreg, ins->dreg, 0, 4); break; + case OP_LOADI8_MEMBASE: + if (mips_is_imm16 (ins->inst_offset)) { + mips_ld (code, ins->dreg, ins->inst_basereg, ins->inst_offset); + } else { + mips_load_const (code, mips_at, ins->inst_offset); + mips_addu (code, mips_at, mips_at, ins->inst_basereg); + mips_ld (code, ins->dreg, mips_at, 0); + } + break; case OP_LOAD_MEMBASE: case OP_LOADI4_MEMBASE: case OP_LOADU4_MEMBASE: @@ -3166,40 +3321,52 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) case OP_IADD: mips_addu (code, ins->dreg, ins->sreg1, ins->sreg2); break; + case OP_LADD: + mips_daddu (code, ins->dreg, ins->sreg1, ins->sreg2); + break; + case OP_ADD_IMM: case OP_IADD_IMM: - if (mips_is_imm16 (ins->inst_imm)) { - mips_addiu (code, ins->dreg, ins->sreg1, ins->inst_imm); - } else { - mips_load_const (code, mips_at, ins->inst_imm); - mips_addu (code, ins->dreg, ins->sreg1, mips_at); - } + g_assert (mips_is_imm16 (ins->inst_imm)); + mips_addiu (code, ins->dreg, ins->sreg1, ins->inst_imm); + break; + case OP_LADD_IMM: + g_assert (mips_is_imm16 (ins->inst_imm)); + mips_daddiu (code, ins->dreg, ins->sreg1, ins->inst_imm); break; + case OP_ISUB: mips_subu (code, ins->dreg, ins->sreg1, ins->sreg2); break; + case OP_LSUB: + mips_dsubu (code, ins->dreg, ins->sreg1, ins->sreg2); + break; + case OP_ISUB_IMM: case OP_SUB_IMM: // we add the negated value - if (mips_is_imm16 (-ins->inst_imm)) - mips_addi (code, ins->dreg, ins->sreg1, -ins->inst_imm); - else { - mips_load_const (code, mips_at, ins->inst_imm); - mips_subu (code, ins->dreg, ins->sreg1, mips_at); - } + g_assert (mips_is_imm16 (-ins->inst_imm)); + mips_addiu (code, ins->dreg, ins->sreg1, -ins->inst_imm); break; + + case OP_LSUB_IMM: + // we add the negated value + g_assert (mips_is_imm16 (-ins->inst_imm)); + mips_daddiu (code, ins->dreg, ins->sreg1, -ins->inst_imm); + break; + case OP_IAND: + case OP_LAND: mips_and (code, ins->dreg, ins->sreg1, ins->sreg2); break; + case OP_AND_IMM: case OP_IAND_IMM: - if (mips_is_imm16 (ins->inst_imm)) { - mips_andi (code, ins->dreg, ins->sreg1, ins->inst_imm); - } else { - mips_load_const (code, mips_at, ins->inst_imm); - mips_and (code, ins->dreg, ins->sreg1, mips_at); - } + case OP_LAND_IMM: + g_assert (!(ins->inst_imm & 0xffff0000)); + mips_andi (code, ins->dreg, ins->sreg1, ins->inst_imm); break; + case OP_IDIV: case OP_IREM: { guint32 *divisor_is_m1; @@ -3207,7 +3374,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) /* */ mips_addiu (code, mips_at, mips_zero, 0xffff); - divisor_is_m1 = (guint32 *)code; + divisor_is_m1 = (guint32 *)(void *)code; mips_bne (code, ins->sreg2, mips_at, 0); mips_nop (code); @@ -3217,7 +3384,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) mips_patch (divisor_is_m1, (guint32)code); /* Put divide in branch delay slot (NOT YET) */ - divisor_is_zero = (guint32 *)code; + divisor_is_zero = (guint32 *)(void *)code; mips_bne (code, ins->sreg2, mips_zero, 0); mips_nop (code); @@ -3292,25 +3459,41 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) case OP_ISHR: mips_srav (code, ins->dreg, ins->sreg1, ins->sreg2); break; + case OP_LSHR: + mips_dsrav (code, ins->dreg, ins->sreg1, ins->sreg2); + break; case OP_SHR_IMM: case OP_ISHR_IMM: mips_sra (code, ins->dreg, ins->sreg1, ins->inst_imm & 0x1f); break; + case OP_LSHR_IMM: + mips_dsra (code, ins->dreg, ins->sreg1, ins->inst_imm & 0x3f); + break; case OP_SHR_UN_IMM: case OP_ISHR_UN_IMM: mips_srl (code, ins->dreg, ins->sreg1, ins->inst_imm & 0x1f); break; + case OP_LSHR_UN_IMM: + mips_dsrl (code, ins->dreg, ins->sreg1, ins->inst_imm & 0x3f); + break; case OP_ISHR_UN: mips_srlv (code, ins->dreg, ins->sreg1, ins->sreg2); break; + case OP_LSHR_UN: + mips_dsrlv (code, ins->dreg, ins->sreg1, ins->sreg2); + break; case OP_INOT: + case OP_LNOT: mips_nor (code, ins->dreg, mips_zero, ins->sreg1); break; case OP_INEG: mips_subu (code, ins->dreg, mips_zero, ins->sreg1); break; + case OP_LNEG: + mips_dsubu (code, ins->dreg, mips_zero, ins->sreg1); + break; case OP_IMUL: -#if 1 +#if USE_MUL mips_mul (code, ins->dreg, ins->sreg1, ins->sreg2); #else mips_mult (code, ins->sreg1, ins->sreg2); @@ -3319,18 +3502,12 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) mips_nop (code); #endif break; - case OP_MUL_IMM: - case OP_IMUL_IMM: - mips_load_const (code, mips_at, ins->inst_imm); -#if 1 - mips_mul (code, ins->dreg, ins->sreg1, mips_at); -#else - mips_mult (code, ins->sreg1, mips_at); +#if SIZEOF_REGISTER == 8 + case OP_LMUL: + mips_dmult (code, ins->sreg1, ins->sreg2); mips_mflo (code, ins->dreg); - mips_nop (code); - mips_nop (code); -#endif break; +#endif case OP_IMUL_OVF: { guint32 *patch; mips_mult (code, ins->sreg1, ins->sreg2); @@ -3361,6 +3538,11 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) case OP_ICONST: mips_load_const (code, ins->dreg, ins->inst_c0); break; +#if SIZEOF_REGISTER == 8 + case OP_I8CONST: + mips_load_const (code, ins->dreg, ins->inst_c0); + break; +#endif case OP_AOTCONST: mono_add_patch_info (cfg, offset, (MonoJumpInfoType)ins->inst_i1, ins->inst_p0); mips_load (code, ins->dreg, 0); @@ -3369,6 +3551,10 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) case OP_MIPS_MTC1S: mips_mtc1 (code, ins->dreg, ins->sreg1); break; + case OP_MIPS_MTC1S_2: + mips_mtc1 (code, ins->dreg, ins->sreg1); + mips_mtc1 (code, ins->dreg+1, ins->sreg2); + break; case OP_MIPS_MFC1S: mips_mfc1 (code, ins->dreg, ins->sreg1); break; @@ -3376,30 +3562,45 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) mips_dmtc1 (code, ins->dreg, ins->sreg1); break; case OP_MIPS_MFC1D: +#if 0 mips_dmfc1 (code, ins->dreg, ins->sreg1); +#else + mips_mfc1 (code, ins->dreg+1, ins->sreg1); + mips_mfc1 (code, ins->dreg, ins->sreg1+1); +#endif break; case OP_ICONV_TO_I4: case OP_ICONV_TO_U4: case OP_MOVE: if (ins->dreg != ins->sreg1) - mips_move (code, ins->dreg, ins->sreg1); + MIPS_MOVE (code, ins->dreg, ins->sreg1); + break; +#if SIZEOF_REGISTER == 8 + case OP_ZEXT_I4: + mips_dsll (code, ins->dreg, ins->sreg1, 32); + mips_dsrl (code, ins->dreg, ins->dreg, 32); break; + case OP_SEXT_I4: + mips_dsll (code, ins->dreg, ins->sreg1, 32); + mips_dsra (code, ins->dreg, ins->dreg, 32); + break; +#endif case OP_SETLRET: /* Get sreg1 into v1, sreg2 into v0 */ if (ins->sreg1 == mips_v0) { if (ins->sreg1 != mips_at) - mips_move (code, mips_at, ins->sreg1); + MIPS_MOVE (code, mips_at, ins->sreg1); if (ins->sreg2 != mips_v0) - mips_move (code, mips_v0, ins->sreg2); - mips_move (code, mips_v1, mips_at); + MIPS_MOVE (code, mips_v0, ins->sreg2); + MIPS_MOVE (code, mips_v1, mips_at); } else { if (ins->sreg2 != mips_v0) - mips_move (code, mips_v0, ins->sreg2); + MIPS_MOVE (code, mips_v0, ins->sreg2); if (ins->sreg1 != mips_v1) - mips_move (code, mips_v1, ins->sreg1); + MIPS_MOVE (code, mips_v1, ins->sreg1); } break; case OP_FMOVE: @@ -3412,11 +3613,13 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) mips_cvtsd (code, ins->dreg, ins->sreg1); break; case OP_FCONV_TO_R4: - /* Convert from double to float */ - mips_cvtsd (code, ins->dreg, ins->sreg1); #if 0 - /* and back again */ - mips_cvtds (code, ins->dreg, ins->dreg); + mips_cvtsd (code, ins->dreg, ins->sreg1); +#else + /* Just a move, no precision change */ + if (ins->dreg != ins->sreg1) { + mips_fmovd (code, ins->dreg, ins->sreg1); + } #endif break; case OP_JMP: @@ -3493,7 +3696,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) case OP_VCALL2_REG: case OP_VOIDCALL_REG: case OP_CALL_REG: - mips_move (code, mips_t9, ins->sreg1); + MIPS_MOVE (code, mips_t9, ins->sreg1); break; case OP_FCALL_MEMBASE: case OP_LCALL_MEMBASE: @@ -3520,16 +3723,18 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) /* Round up ins->sreg1, mips_at ends up holding size */ mips_addiu (code, mips_at, ins->sreg1, 31); - mips_andi (code, mips_at, mips_at, ~31); + mips_addiu (code, mips_temp, mips_zero, ~31); + mips_and (code, mips_at, mips_at, mips_temp); mips_subu (code, mips_sp, mips_sp, mips_at); + g_assert (mips_is_imm16 (area_offset)); mips_addiu (code, ins->dreg, mips_sp, area_offset); if (ins->flags & MONO_INST_INIT) { 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, -4); + mips_bne (code, mips_at, mips_zero, -3); mips_addiu (code, mips_temp, mips_temp, 1); } break; @@ -3581,7 +3786,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) code = emit_unreserve_param_area (cfg, code); if (ins->sreg1 != mips_v0) - mips_move (code, mips_v0, ins->sreg1); + MIPS_MOVE (code, mips_v0, ins->sreg1); if (mips_is_imm16 (spvar->inst_offset)) { mips_lw (code, mips_ra, spvar->inst_basereg, spvar->inst_offset); } else { @@ -3613,11 +3818,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) ins->inst_c0 = code - cfg->native_code; break; case OP_BR: - if (ins->flags & MONO_INST_BRLABEL) { - mono_add_patch_info (cfg, offset, MONO_PATCH_INFO_LABEL, ins->inst_i0); - } else { - mono_add_patch_info (cfg, offset, MONO_PATCH_INFO_BB, ins->inst_target_bb); - } + mono_add_patch_info (cfg, offset, MONO_PATCH_INFO_BB, ins->inst_target_bb); #if LONG_BRANCH mips_lui (code, mips_at, mips_zero, 0); mips_addiu (code, mips_at, mips_at, 0); @@ -3645,13 +3846,13 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) g_assert (ins->sreg1 != -1); mips_sll (code, mips_at, ins->sreg1, 2); if (1 || !(cfg->flags & MONO_CFG_HAS_CALLS)) - mips_move (code, mips_t8, mips_ra); + MIPS_MOVE (code, mips_t8, mips_ra); mips_bgezal (code, mips_zero, 1); /* bal */ mips_nop (code); mips_addu (code, mips_t9, mips_ra, mips_at); /* Table is 16 or 20 bytes from target of bal above */ if (1 || !(cfg->flags & MONO_CFG_HAS_CALLS)) { - mips_move (code, mips_ra, mips_t8); + MIPS_MOVE (code, mips_ra, mips_t8); mips_lw (code, mips_t9, mips_t9, 20); } else @@ -3667,7 +3868,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) mips_addiu (code, ins->dreg, mips_zero, 1); mips_beq (code, mips_at, mips_zero, 2); mips_nop (code); - mips_move (code, ins->dreg, mips_zero); + MIPS_MOVE (code, ins->dreg, mips_zero); break; case OP_CLT: case OP_CLT_UN: @@ -3676,7 +3877,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) mips_addiu (code, ins->dreg, mips_zero, 1); mips_bltz (code, mips_at, 2); mips_nop (code); - mips_move (code, ins->dreg, mips_zero); + MIPS_MOVE (code, ins->dreg, mips_zero); break; case OP_CGT: case OP_CGT_UN: @@ -3685,7 +3886,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) mips_addiu (code, ins->dreg, mips_zero, 1); mips_bgtz (code, mips_at, 2); mips_nop (code); - mips_move (code, ins->dreg, mips_zero); + MIPS_MOVE (code, ins->dreg, mips_zero); break; case OP_MIPS_COND_EXC_EQ: @@ -3803,11 +4004,17 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) /* floating point opcodes */ case OP_R8CONST: +#if 0 if (((guint32)ins->inst_p0) & (1 << 15)) mips_lui (code, mips_at, mips_zero, (((guint32)ins->inst_p0)>>16)+1); else mips_lui (code, mips_at, mips_zero, (((guint32)ins->inst_p0)>>16)); mips_ldc1 (code, ins->dreg, mips_at, ((guint32)ins->inst_p0) & 0xffff); +#else + mips_load_const (code, mips_at, ins->inst_p0); + mips_lwc1 (code, ins->dreg, mips_at, 4); + mips_lwc1 (code, ins->dreg+1, mips_at, 0); +#endif break; case OP_R4CONST: if (((guint32)ins->inst_p0) & (1 << 15)) @@ -3821,11 +4028,11 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) break; case OP_STORER8_MEMBASE_REG: if (mips_is_imm16 (ins->inst_offset)) { -#if USE_LDC_SDC - mips_sdc1 (code, ins->sreg1, ins->inst_destbasereg, ins->inst_offset); -#else +#if _MIPS_SIM == _ABIO32 mips_swc1 (code, ins->sreg1, ins->inst_destbasereg, ins->inst_offset+4); mips_swc1 (code, ins->sreg1+1, ins->inst_destbasereg, ins->inst_offset); +#elif _MIPS_SIM == _ABIN32 + mips_sdc1 (code, ins->sreg1, ins->inst_destbasereg, ins->inst_offset); #endif } else { mips_load_const (code, mips_at, ins->inst_offset); @@ -3836,11 +4043,11 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) break; case OP_LOADR8_MEMBASE: if (mips_is_imm16 (ins->inst_offset)) { -#if USE_LDC_SDC - mips_ldc1 (code, ins->dreg, ins->inst_basereg, ins->inst_offset); -#else +#if _MIPS_SIM == _ABIO32 mips_lwc1 (code, ins->dreg, ins->inst_basereg, ins->inst_offset+4); mips_lwc1 (code, ins->dreg+1, ins->inst_basereg, ins->inst_offset); +#elif _MIPS_SIM == _ABIN32 + mips_ldc1 (code, ins->dreg, ins->inst_basereg, ins->inst_offset); #endif } else { mips_load_const (code, mips_at, ins->inst_offset); @@ -3850,35 +4057,20 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) } break; case OP_STORER4_MEMBASE_REG: + g_assert (mips_is_imm16 (ins->inst_offset)); #if PROMOTE_R4_TO_R8 /* Need to convert ins->sreg1 to single-precision first */ mips_cvtsd (code, mips_ftemp, ins->sreg1); #endif - if (mips_is_imm16 (ins->inst_offset)) { - mips_swc1 (code, mips_ftemp, ins->inst_destbasereg, ins->inst_offset); - } else { - mips_load_const (code, mips_at, ins->inst_offset); - mips_addu (code, mips_at, mips_at, ins->inst_destbasereg); - mips_swc1 (code, mips_ftemp, mips_at, 0); - } + mips_swc1 (code, mips_ftemp, ins->inst_destbasereg, ins->inst_offset); break; case OP_MIPS_LWC1: - if (mips_is_imm16 (ins->inst_offset)) { - mips_lwc1 (code, ins->dreg, ins->inst_basereg, ins->inst_offset); - } else { - mips_load_const (code, mips_at, ins->inst_offset); - mips_addu (code, mips_at, mips_at, ins->inst_basereg); - mips_lwc1 (code, ins->dreg, mips_at, 0); - } + g_assert (mips_is_imm16 (ins->inst_offset)); + mips_lwc1 (code, ins->dreg, ins->inst_basereg, ins->inst_offset); break; case OP_LOADR4_MEMBASE: - if (mips_is_imm16 (ins->inst_offset)) { - mips_lwc1 (code, ins->dreg, ins->inst_basereg, ins->inst_offset); - } else { - mips_load_const (code, mips_at, ins->inst_offset); - mips_addu (code, mips_at, mips_at, ins->inst_basereg); - mips_lwc1 (code, ins->dreg, mips_at, 0); - } + g_assert (mips_is_imm16 (ins->inst_offset)); + mips_lwc1 (code, ins->dreg, ins->inst_basereg, ins->inst_offset); #if PROMOTE_R4_TO_R8 /* Convert to double precision in place */ mips_cvtds (code, ins->dreg, ins->dreg); @@ -3950,14 +4142,14 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) mips_addiu (code, ins->dreg, mips_zero, 1); mips_fbtrue (code, 2); mips_nop (code); - mips_move (code, ins->dreg, mips_zero); + MIPS_MOVE (code, ins->dreg, mips_zero); break; case OP_FCLT: mips_fcmpd (code, MIPS_FPU_LT, ins->sreg1, ins->sreg2); mips_addiu (code, ins->dreg, mips_zero, 1); mips_fbtrue (code, 2); mips_nop (code); - mips_move (code, ins->dreg, mips_zero); + MIPS_MOVE (code, ins->dreg, mips_zero); break; case OP_FCLT_UN: /* Less than, or Unordered */ @@ -3965,11 +4157,11 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) mips_addiu (code, ins->dreg, mips_zero, 1); mips_fbtrue (code, 2); mips_nop (code); - mips_move (code, ins->dreg, mips_zero); + MIPS_MOVE (code, ins->dreg, mips_zero); break; case OP_FCGT: mips_fcmpd (code, MIPS_FPU_ULE, ins->sreg1, ins->sreg2); - mips_move (code, ins->dreg, mips_zero); + MIPS_MOVE (code, ins->dreg, mips_zero); mips_fbtrue (code, 2); mips_nop (code); mips_addiu (code, ins->dreg, mips_zero, 1); @@ -3977,7 +4169,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) case OP_FCGT_UN: /* Greater than, or Unordered */ mips_fcmpd (code, MIPS_FPU_OLE, ins->sreg1, ins->sreg2); - mips_move (code, ins->dreg, mips_zero); + MIPS_MOVE (code, ins->dreg, mips_zero); mips_fbtrue (code, 2); mips_nop (code); mips_addiu (code, ins->dreg, mips_zero, 1); @@ -3985,117 +4177,92 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) case OP_MIPS_FBEQ: mips_fcmpd (code, MIPS_FPU_EQ, ins->sreg1, ins->sreg2); mips_nop (code); - if (ins->flags & MONO_INST_BRLABEL) - mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_LABEL, ins->inst_i0); - else - mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_BB, ins->inst_true_bb); + mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_BB, ins->inst_true_bb); mips_fbtrue (code, 0); mips_nop (code); break; case OP_MIPS_FBNE: mips_fcmpd (code, MIPS_FPU_EQ, ins->sreg1, ins->sreg2); mips_nop (code); - if (ins->flags & MONO_INST_BRLABEL) - mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_LABEL, ins->inst_i0); - else - mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_BB, ins->inst_true_bb); + mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_BB, ins->inst_true_bb); mips_fbfalse (code, 0); mips_nop (code); break; case OP_MIPS_FBLT: mips_fcmpd (code, MIPS_FPU_LT, ins->sreg1, ins->sreg2); mips_nop (code); - if (ins->flags & MONO_INST_BRLABEL) - mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_LABEL, ins->inst_i0); - else - mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_BB, ins->inst_true_bb); + mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_BB, ins->inst_true_bb); mips_fbtrue (code, 0); mips_nop (code); break; - case OP_FBLT_UN: + case OP_MIPS_FBLT_UN: mips_fcmpd (code, MIPS_FPU_ULT, ins->sreg1, ins->sreg2); mips_nop (code); - if (ins->flags & MONO_INST_BRLABEL) - mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_LABEL, ins->inst_i0); - else - mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_BB, ins->inst_true_bb); + mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_BB, ins->inst_true_bb); mips_fbtrue (code, 0); mips_nop (code); break; case OP_MIPS_FBGT: mips_fcmpd (code, MIPS_FPU_LE, ins->sreg1, ins->sreg2); mips_nop (code); - if (ins->flags & MONO_INST_BRLABEL) - mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_LABEL, ins->inst_i0); - else - mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_BB, ins->inst_true_bb); + mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_BB, ins->inst_true_bb); mips_fbfalse (code, 0); mips_nop (code); break; case OP_MIPS_FBGT_UN: mips_fcmpd (code, MIPS_FPU_OLE, ins->sreg1, ins->sreg2); mips_nop (code); - if (ins->flags & MONO_INST_BRLABEL) - mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_LABEL, ins->inst_i0); - else - mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_BB, ins->inst_true_bb); + mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_BB, ins->inst_true_bb); mips_fbfalse (code, 0); mips_nop (code); break; case OP_MIPS_FBGE: mips_fcmpd (code, MIPS_FPU_LT, ins->sreg1, ins->sreg2); mips_nop (code); - if (ins->flags & MONO_INST_BRLABEL) - mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_LABEL, ins->inst_i0); - else - mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_BB, ins->inst_true_bb); + mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_BB, ins->inst_true_bb); mips_fbfalse (code, 0); mips_nop (code); break; case OP_MIPS_FBGE_UN: mips_fcmpd (code, MIPS_FPU_OLT, ins->sreg1, ins->sreg2); mips_nop (code); - if (ins->flags & MONO_INST_BRLABEL) - mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_LABEL, ins->inst_i0); - else - mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_BB, ins->inst_true_bb); + mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_BB, ins->inst_true_bb); mips_fbfalse (code, 0); mips_nop (code); break; case OP_MIPS_FBLE: mips_fcmpd (code, MIPS_FPU_OLE, ins->sreg1, ins->sreg2); mips_nop (code); - if (ins->flags & MONO_INST_BRLABEL) - mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_LABEL, ins->inst_i0); - else - mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_BB, ins->inst_true_bb); + mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_BB, ins->inst_true_bb); mips_fbtrue (code, 0); mips_nop (code); break; case OP_MIPS_FBLE_UN: mips_fcmpd (code, MIPS_FPU_ULE, ins->sreg1, ins->sreg2); mips_nop (code); - if (ins->flags & MONO_INST_BRLABEL) - mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_LABEL, ins->inst_i0); - else - mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_BB, ins->inst_true_bb); + mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_BB, ins->inst_true_bb); mips_fbtrue (code, 0); mips_nop (code); break; case OP_CKFINITE: { - g_assert_not_reached(); -#if 0 - ppc_stfd (code, ins->sreg1, -8, ppc_sp); - ppc_lwz (code, ppc_r11, -8, ppc_sp); - ppc_rlwinm (code, ppc_r11, ppc_r11, 0, 1, 31); - ppc_addis (code, ppc_r11, ppc_r11, -32752); - ppc_rlwinmd (code, ppc_r11, ppc_r11, 1, 31, 31); - EMIT_COND_SYSTEM_EXCEPTION (CEE_BEQ - CEE_BEQ, "ArithmeticException"); -#endif + guint32 *branch_patch; + + mips_mfc1 (code, mips_at, ins->sreg1+1); + mips_srl (code, mips_at, mips_at, 16+4); + mips_andi (code, mips_at, mips_at, 2047); + mips_addiu (code, mips_at, mips_at, -2047); + + branch_patch = (guint32 *)(void *)code; + mips_bne (code, mips_at, mips_zero, 0); + mips_nop (code); + + EMIT_SYSTEM_EXCEPTION_NAME("ArithmeticException"); + mips_patch (branch_patch, (guint32)code); + mips_fmovd (code, ins->dreg, ins->sreg1); 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); mips_load (code, ins->dreg, 0x0f0f0f0f); break; @@ -4132,9 +4299,7 @@ mono_arch_patch_code (MonoMethod *method, MonoDomain *domain, guint8 *code, Mono for (patch_info = ji; patch_info; patch_info = patch_info->next) { unsigned char *ip = patch_info->ip.i + code; - const unsigned char *target; - - target = mono_resolve_patch_target (method, domain, code, patch_info, run_cctors); + const unsigned char *target = NULL; switch (patch_info->type) { case MONO_PATCH_INFO_IP: @@ -4164,6 +4329,7 @@ mono_arch_patch_code (MonoMethod *method, MonoDomain *domain, guint8 *code, Mono case MONO_PATCH_INFO_R4: case MONO_PATCH_INFO_R8: /* from OP_AOTCONST : lui + addiu */ + target = mono_resolve_patch_target (method, domain, code, patch_info, run_cctors); patch_lui_addiu ((guint32 *)(void *)ip, (guint32)target); continue; #if 0 @@ -4176,12 +4342,14 @@ mono_arch_patch_code (MonoMethod *method, MonoDomain *domain, guint8 *code, Mono /* everything is dealt with at epilog output time */ continue; default: + target = mono_resolve_patch_target (method, domain, code, patch_info, run_cctors); + mips_patch ((guint32 *)(void *)ip, (guint32)target); break; } - mips_patch ((guint32 *)(void *)ip, (guint32)target); } } +#if 0 static void mono_trace_lmf_prolog (MonoLMF *new_lmf) @@ -4193,6 +4361,7 @@ void mono_trace_lmf_epilog (MonoLMF *old_lmf) { } +#endif /* * Allow tracing to work with this interface (with an optional argument) @@ -4206,55 +4375,43 @@ void* mono_arch_instrument_prolog (MonoCompile *cfg, void *func, void *p, gboolean enable_arguments) { guchar *code = p; - int fp_stack_offset = 0; + int offset = cfg->arch.tracing_offset; mips_nop (code); mips_nop (code); mips_nop (code); - mips_sw (code, mips_a0, mips_sp, cfg->stack_offset + 0); - mips_sw (code, mips_a1, mips_sp, cfg->stack_offset + 4); - mips_sw (code, mips_a2, mips_sp, cfg->stack_offset + 8); - mips_sw (code, mips_a3, mips_sp, cfg->stack_offset + 12); -#if 0 -#if 0 - fp_stack_offset = MIPS_STACK_PARAM_OFFSET; - mips_addiu (code, mips_sp, mips_sp, -64); - mips_swc1 (code, mips_f12, mips_sp, fp_stack_offset + 16); - mips_swc1 (code, mips_f13, mips_sp, fp_stack_offset + 20); - mips_swc1 (code, mips_f14, mips_sp, fp_stack_offset + 24); - mips_swc1 (code, mips_f15, mips_sp, fp_stack_offset + 28); -#else - mips_fmovs (code, mips_f22, mips_f12); - mips_fmovs (code, mips_f23, mips_f13); - mips_fmovs (code, mips_f24, mips_f14); - mips_fmovs (code, mips_f25, mips_f15); -#endif + /* 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 + 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, cfg->stack_offset + fp_stack_offset); + mips_addiu (code, mips_a1, mips_sp, offset); mips_load_const (code, mips_t9, func); mips_jalr (code, mips_t9, mips_ra); mips_nop (code); - mips_lw (code, mips_a0, mips_sp, cfg->stack_offset + 0); - mips_lw (code, mips_a1, mips_sp, cfg->stack_offset + 4); - mips_lw (code, mips_a2, mips_sp, cfg->stack_offset + 8); - mips_lw (code, mips_a3, mips_sp, cfg->stack_offset + 12); -#if 0 -#if 0 - mips_lwc1 (code, mips_f12, mips_sp, fp_stack_offset + 16); - mips_lwc1 (code, mips_f13, mips_sp, fp_stack_offset + 20); - mips_lwc1 (code, mips_f14, mips_sp, fp_stack_offset + 24); - mips_lwc1 (code, mips_f15, mips_sp, fp_stack_offset + 28); - mips_addiu (code, mips_sp, mips_sp, 64); -#else - mips_fmovs (code, mips_f12, mips_f22); - mips_fmovs (code, mips_f13, mips_f23); - mips_fmovs (code, mips_f14, mips_f24); - mips_fmovs (code, mips_f15, mips_f25); -#endif + 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 + 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); mips_nop (code); mips_nop (code); @@ -4273,7 +4430,7 @@ mips_adjust_stackframe(MonoCompile *cfg) return; /* adjust cfg->stack_offset for account for down-spilling */ - cfg->stack_offset += 4; + cfg->stack_offset += SIZEOF_REGISTER; /* re-align cfg->stack_offset if needed (due to var spilling) */ cfg->stack_offset = (cfg->stack_offset + MIPS_STACK_ALIGNMENT - 1) & ~(MIPS_STACK_ALIGNMENT - 1); @@ -4283,7 +4440,7 @@ mips_adjust_stackframe(MonoCompile *cfg) g_print ("\tspillvars allocated 0x%x -> 0x%x\n", cfg->arch.local_alloc_offset, cfg->stack_offset); } threshold = cfg->arch.local_alloc_offset; - ra_offset = cfg->stack_offset - 4; + ra_offset = cfg->stack_offset - sizeof(gpointer); if (cfg->verbose_level > 2) { g_print ("\tra_offset %d/0x%x delta %d/0x%x\n", ra_offset, ra_offset, delta, delta); } @@ -4321,10 +4478,24 @@ mips_adjust_stackframe(MonoCompile *cfg) g_print ("BASIC BLOCK %d:\n", bb->block_num); } MONO_BB_FOR_EACH_INS (bb, ins) { + int adj_c0 = 0; + int adj_imm = 0; + if (cfg->verbose_level > 2) { mono_print_ins_index (ins_cnt, ins); } - if ((MONO_IS_LOAD_MEMBASE(ins) && (ins->inst_basereg == mips_fp)) || (MONO_IS_STORE_MEMBASE(ins) && (ins->dreg == mips_fp))) { + if (MONO_IS_LOAD_MEMBASE(ins) && (ins->inst_basereg == mips_fp)) + adj_c0 = 1; + if (MONO_IS_STORE_MEMBASE(ins) && (ins->dreg == mips_fp)) + adj_c0 = 1; + /* The following two catch FP spills */ + if (MONO_IS_LOAD_MEMBASE(ins) && (ins->inst_basereg == mips_sp)) + adj_c0 = 1; + if (MONO_IS_STORE_MEMBASE(ins) && (ins->dreg == mips_sp)) + adj_c0 = 1; + if (((ins->opcode == OP_ADD_IMM) || (ins->opcode == OP_IADD_IMM)) && (ins->sreg1 == mips_fp)) + adj_imm = 1; + if (adj_c0) { if (ins->inst_c0 >= threshold) { ins->inst_c0 += delta; if (cfg->verbose_level > 2) { @@ -4341,6 +4512,17 @@ mips_adjust_stackframe(MonoCompile *cfg) } g_assert (ins->inst_c0 != ra_offset); } + if (adj_imm) { + if (ins->inst_imm >= threshold) { + ins->inst_imm += delta; + if (cfg->verbose_level > 2) { + g_print ("adj"); + mono_print_ins_index (ins_cnt, ins); + } + } + g_assert (ins->inst_c0 != ra_offset); + } + ++ins_cnt; } } @@ -4400,6 +4582,16 @@ mono_arch_emit_prolog (MonoCompile *cfg) cfg->code_size = 768 + sig->param_count * 20; code = cfg->native_code = g_malloc (cfg->code_size); + 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 + } + /* adjust stackframe assignments for spillvars if needed */ mips_adjust_stackframe (cfg); @@ -4439,16 +4631,16 @@ mono_arch_emit_prolog (MonoCompile *cfg) pos = cfg->arch.iregs_offset; for (i = MONO_MAX_IREGS-1; i >= 0; --i) { if (iregs_to_save & (1 << i)) { - g_assert (pos < cfg->stack_usage - 4); - mips_sw (code, i, mips_sp, pos); - pos += sizeof (gulong); + g_assert (pos < cfg->stack_usage - sizeof(gpointer)); + MIPS_SW (code, i, mips_sp, pos); + pos += SIZEOF_REGISTER; } } } #if SAVE_LMF if (method->save_lmf) { for (i = MONO_MAX_IREGS-1; i >= 0; --i) { - mips_sw (code, i, mips_sp, lmf_offset + G_STRUCT_OFFSET(MonoLMF, iregs[i])); + MIPS_SW (code, i, mips_sp, lmf_offset + G_STRUCT_OFFSET(MonoLMF, iregs[i])); } } #endif @@ -4473,10 +4665,10 @@ mono_arch_emit_prolog (MonoCompile *cfg) #endif #endif if (cfg->frame_reg != mips_sp) { - mips_move (code, cfg->frame_reg, mips_sp); + MIPS_MOVE (code, cfg->frame_reg, mips_sp); #if SAVE_LMF if (method->save_lmf) - mips_sw (code, cfg->frame_reg, mips_sp, + MIPS_SW (code, cfg->frame_reg, mips_sp, lmf_offset + G_STRUCT_OFFSET(MonoLMF, iregs[cfg->frame_reg])); #endif } @@ -4484,8 +4676,9 @@ 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) + if (tracing) { code = mono_arch_instrument_prolog (cfg, mono_trace_enter_method, code, TRUE); + } /* load arguments allocated to register from the stack */ @@ -4497,7 +4690,7 @@ mono_arch_emit_prolog (MonoCompile *cfg) ArgInfo *ainfo = &cinfo->ret; inst = cfg->vret_addr; if (inst->opcode == OP_REGVAR) - mips_move (code, inst->dreg, ainfo->reg); + MIPS_MOVE (code, inst->dreg, ainfo->reg); else if (mips_is_imm16 (inst->inst_offset)) { mips_sw (code, ainfo->reg, inst->inst_basereg, inst->inst_offset); } else { @@ -4516,7 +4709,7 @@ mono_arch_emit_prolog (MonoCompile *cfg) if (inst->opcode == OP_REGVAR) { /* Argument ends up in a register */ if (ainfo->regtype == RegTypeGeneral) - mips_move (code, inst->dreg, ainfo->reg); + MIPS_MOVE (code, inst->dreg, ainfo->reg); else if (ainfo->regtype == RegTypeFP) { g_assert_not_reached(); #if 0 @@ -4550,8 +4743,12 @@ mono_arch_emit_prolog (MonoCompile *cfg) mips_sw (code, ainfo->reg, inst->inst_basereg, inst->inst_offset); break; case 8: +#if (SIZEOF_REGISTER == 4) mips_sw (code, ainfo->reg, inst->inst_basereg, inst->inst_offset); mips_sw (code, ainfo->reg + 1, inst->inst_basereg, inst->inst_offset + 4); +#elif (SIZEOF_REGISTER == 8) + mips_sd (code, ainfo->reg, inst->inst_basereg, inst->inst_offset); +#endif break; default: g_assert_not_reached (); @@ -4583,11 +4780,11 @@ mono_arch_emit_prolog (MonoCompile *cfg) } else if (ainfo->regtype == RegTypeFP) { g_assert (mips_is_imm16 (inst->inst_offset)); if (ainfo->size == 8) { -#if USE_LDC_SDC - mips_sdc1 (code, ainfo->reg, inst->inst_basereg, inst->inst_offset); -#else +#if _MIPS_SIM == _ABIO32 mips_swc1 (code, ainfo->reg, inst->inst_basereg, inst->inst_offset+4); mips_swc1 (code, ainfo->reg+1, inst->inst_basereg, inst->inst_offset); +#elif _MIPS_SIM == _ABIN32 + mips_sdc1 (code, ainfo->reg, inst->inst_basereg, inst->inst_offset); #endif } else if (ainfo->size == 4) @@ -4602,8 +4799,8 @@ mono_arch_emit_prolog (MonoCompile *cfg) g_assert (mips_is_imm16 (inst->inst_offset + ainfo->size * sizeof (gpointer))); /* Push the argument registers into their stack slots */ for (i = 0; i < ainfo->size; ++i) { - mips_sw (code, ainfo->reg + i, inst->inst_basereg, doffset); - doffset += sizeof (gpointer); + MIPS_SW (code, ainfo->reg + i, inst->inst_basereg, doffset); + doffset += SIZEOF_REGISTER; } } else if (ainfo->regtype == RegTypeStructByAddr) { g_assert (mips_is_imm16 (inst->inst_offset)); @@ -4659,7 +4856,7 @@ mono_arch_emit_prolog (MonoCompile *cfg) /* save method info */ mips_load_const (code, mips_at, method); mips_sw (code, mips_at, mips_sp, lmf_offset + G_STRUCT_OFFSET(MonoLMF, method)); - mips_sw (code, mips_sp, mips_sp, lmf_offset + G_STRUCT_OFFSET(MonoLMF, ebp)); + MIPS_SW (code, mips_sp, mips_sp, lmf_offset + G_STRUCT_OFFSET(MonoLMF, ebp)); /* save the current IP */ mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_IP, NULL); @@ -4684,7 +4881,7 @@ enum { }; void* -mono_arch_instrument_epilog (MonoCompile *cfg, void *func, void *p, gboolean enable_arguments) +mono_arch_instrument_epilog_full (MonoCompile *cfg, void *func, void *p, gboolean enable_arguments, gboolean preserve_argument_registers) { guchar *code = p; int save_mode = SAVE_NONE; @@ -4712,10 +4909,6 @@ mono_arch_instrument_epilog (MonoCompile *cfg, void *func, void *p, gboolean ena else save_mode = SAVE_NONE; break; - case MONO_TYPE_I8: - case MONO_TYPE_U8: - save_mode = SAVE_TWO; - break; case MONO_TYPE_R4: case MONO_TYPE_R8: save_mode = SAVE_FP; @@ -4723,6 +4916,14 @@ mono_arch_instrument_epilog (MonoCompile *cfg, void *func, void *p, gboolean ena case MONO_TYPE_VALUETYPE: save_mode = SAVE_STRUCT; break; + case MONO_TYPE_I8: + case MONO_TYPE_U8: +#if SIZEOF_REGISTER == 4 + save_mode = SAVE_TWO; +#elif SIZEOF_REGISTER == 8 + save_mode = SAVE_ONE; +#endif + break; default: save_mode = SAVE_ONE; break; @@ -4732,23 +4933,23 @@ mono_arch_instrument_epilog (MonoCompile *cfg, void *func, void *p, gboolean ena switch (save_mode) { case SAVE_TWO: mips_sw (code, mips_v0, mips_sp, save_offset); - mips_sw (code, mips_v1, mips_sp, save_offset + 4); + mips_sw (code, mips_v1, mips_sp, save_offset + SIZEOF_REGISTER); if (enable_arguments) { - mips_move (code, mips_a1, mips_v0); - mips_move (code, mips_a2, mips_v1); + MIPS_MOVE (code, mips_a1, mips_v0); + MIPS_MOVE (code, mips_a2, mips_v1); } break; case SAVE_ONE: - mips_sw (code, mips_v0, mips_sp, save_offset); + MIPS_SW (code, mips_v0, mips_sp, save_offset); if (enable_arguments) { - mips_move (code, mips_a1, mips_v0); + MIPS_MOVE (code, mips_a1, mips_v0); } break; case SAVE_FP: mips_sdc1 (code, mips_f0, mips_sp, save_offset); mips_ldc1 (code, mips_f12, mips_sp, save_offset); mips_lw (code, mips_a0, mips_sp, save_offset); - mips_lw (code, mips_a1, mips_sp, save_offset+4); + mips_lw (code, mips_a1, mips_sp, save_offset + SIZEOF_REGISTER); break; case SAVE_STRUCT: case SAVE_NONE: @@ -4763,10 +4964,10 @@ mono_arch_instrument_epilog (MonoCompile *cfg, void *func, void *p, gboolean ena switch (save_mode) { case SAVE_TWO: mips_lw (code, mips_v0, mips_sp, save_offset); - mips_lw (code, mips_v1, mips_sp, save_offset + 4); + mips_lw (code, mips_v1, mips_sp, save_offset + SIZEOF_REGISTER); break; case SAVE_ONE: - mips_lw (code, mips_v0, mips_sp, save_offset); + MIPS_LW (code, mips_v0, mips_sp, save_offset); break; case SAVE_FP: mips_ldc1 (code, mips_f0, mips_sp, save_offset); @@ -4786,7 +4987,7 @@ guint8 * mono_arch_emit_epilog_sub (MonoCompile *cfg, guint8 *code) { MonoMethod *method = cfg->method; - int pos, i; + int pos = 0, i; int max_epilog_size = 16 + 20*4; guint32 iregs_to_restore; #if SAVE_FP_REGS @@ -4825,7 +5026,7 @@ mono_arch_emit_epilog_sub (MonoCompile *cfg, guint8 *code) } pos = cfg->arch.iregs_offset; if (cfg->frame_reg != mips_sp) { - mips_move (code, mips_sp, cfg->frame_reg); + MIPS_MOVE (code, mips_sp, cfg->frame_reg); } #if SAVE_ALL_REGS iregs_to_restore = MONO_ARCH_CALLEE_SAVED_REGS; @@ -4835,8 +5036,8 @@ mono_arch_emit_epilog_sub (MonoCompile *cfg, guint8 *code) if (iregs_to_restore) { for (i = MONO_MAX_IREGS-1; i >= 0; --i) { if (iregs_to_restore & (1 << i)) { - mips_lw (code, i, mips_sp, pos); - pos += sizeof (gulong); + MIPS_LW (code, i, mips_sp, pos); + pos += SIZEOF_REGISTER; } } } @@ -4853,7 +5054,7 @@ mono_arch_emit_epilog_sub (MonoCompile *cfg, guint8 *code) if (fregs_to_restore & (1 << i)) { g_assert (pos < cfg->stack_usage - MIPS_STACK_ALIGNMENT); mips_lwc1 (code, i, mips_sp, pos); - pos += sizeof (gulong); + pos += FREG_SIZE } } } @@ -4904,6 +5105,7 @@ mono_arch_emit_epilog (MonoCompile *cfg) } /* remove once throw_exception_by_name is eliminated */ +#if 0 static int exception_id_by_name (const char *name) { @@ -4924,6 +5126,7 @@ exception_id_by_name (const char *name) g_error ("Unknown intrinsic exception %s\n", name); return 0; } +#endif void mono_arch_emit_exceptions (MonoCompile *cfg) @@ -5209,20 +5412,6 @@ MonoInst* mono_arch_get_domain_intrinsic (MonoCompile* cfg) return ins; } -MonoInst* -mono_arch_get_thread_intrinsic (MonoCompile* cfg) -{ - MonoInst* ins; - - setup_tls_access (); - if (monothread_key == -1) - return NULL; - - MONO_INST_NEW (cfg, ins, OP_TLS_GET); - ins->inst_offset = monothread_key; - return ins; -} - gpointer mono_arch_context_get_int_reg (MonoContext *ctx, int reg) { @@ -5282,7 +5471,7 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI } else { /* the initial load of the vtable address */ size += 8; - code = mono_code_manager_reserve (domain->code_mp, size); + code = mono_domain_code_reserve (domain, size); } start = code; if (!fail_tramp) @@ -5362,20 +5551,14 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI } MonoMethod* -mono_arch_find_imt_method (gpointer *regs, guint8 *code) +mono_arch_find_imt_method (mgreg_t *regs, guint8 *code) { return (MonoMethod*) regs [MONO_ARCH_IMT_REG]; } - -MonoObject* -mono_arch_find_this_argument (gpointer *regs, MonoMethod *method, MonoGenericSharingContext *gsctx) -{ - return mono_arch_get_this_arg_from_call (gsctx, mono_method_signature (method), (gssize*)regs, NULL); -} #endif MonoVTable* -mono_arch_find_static_call_vtable (gpointer *regs, guint8 *code) +mono_arch_find_static_call_vtable (mgreg_t *regs, guint8 *code) { NOT_IMPLEMENTED; return (MonoVTable*) regs [MONO_ARCH_RGCTX_REG];