2008-02-07 Zoltan Varga <vargaz@gmail.com>
+ * mini.c (mono_normalize_opcodes): New mini pass to convert CEE_ opcodes to
+ the corresponding OP_I/OP_L opcodes.
+
+ * mini-amd64.c mini-amd64.h cpu-amd64.md: Get rid of CEE_ opcodes.
+
* mini-sparc.c (mono_arch_output_basic_block): Fix the sparc build.
2008-02-06 Zoltan Varga <vargaz@gmail.com>
ble.un: len:8
blt.un: len:8
label: len:0
-add: dest:i src1:i src2:i len:3 clob:1
-sub: dest:i src1:i src2:i len:3 clob:1
-mul: dest:i src1:i src2:i len:4 clob:1
-div: dest:a src1:a src2:i len:16 clob:d
-div.un: dest:a src1:a src2:i len:16 clob:d
-rem: dest:d src1:a src2:i len:16 clob:a
-rem.un: dest:d src1:a src2:i len:16 clob:a
-and: dest:i src1:i src2:i len:3 clob:1
-or: dest:i src1:i src2:i len:3 clob:1
-xor: dest:i src1:i src2:i len:3 clob:1
-shl: dest:i src1:i src2:s clob:1 len:3
-shr: dest:i src1:i src2:s clob:1 len:3
-shr.un: dest:i src1:i src2:s clob:1 len:3
-neg: dest:i src1:i len:3 clob:1
-not: dest:i src1:i len:3 clob:1
-conv.i1: dest:i src1:i len:4
-conv.i2: dest:i src1:i len:4
-conv.i4: dest:i src1:i len:3
-conv.i8: dest:i src1:i len:3
-conv.r4: dest:f src1:i len:9
-conv.r8: dest:f src1:i len:9
-conv.u4: dest:i src1:i len:3
-conv.u8: dest:i src1:i len:3
-conv.r.un: dest:f src1:i len:8
+
+long_add: dest:i src1:i src2:i len:3 clob:1
+long_sub: dest:i src1:i src2:i len:3 clob:1
+long_mul: dest:i src1:i src2:i len:4 clob:1
+long_div: dest:a src1:a src2:i len:16 clob:d
+long_div_un: dest:a src1:a src2:i len:16 clob:d
+long_rem: dest:d src1:a src2:i len:16 clob:a
+long_rem_un: dest:d src1:a src2:i len:16 clob:a
+long_and: dest:i src1:i src2:i len:3 clob:1
+long_or: dest:i src1:i src2:i len:3 clob:1
+long_xor: dest:i src1:i src2:i len:3 clob:1
+long_shl: dest:i src1:i src2:s clob:1 len:3
+long_shr: dest:i src1:i src2:s clob:1 len:3
+long_shr_un: dest:i src1:i src2:s clob:1 len:3
+long_neg: dest:i src1:i len:3 clob:1
+long_not: dest:i src1:i len:3 clob:1
+long_conv_to_i1: dest:i src1:i len:4
+long_conv_to_i2: dest:i src1:i len:4
+long_conv_to_i4: dest:i src1:i len:3
+long_conv_to_i8: dest:i src1:i len:3
+long_conv_to_r4: dest:f src1:i len:9
+long_conv_to_r8: dest:f src1:i len:9
+long_conv_to_u4: dest:i src1:i len:3
+long_conv_to_u8: dest:i src1:i len:3
+long_conv_to_r_un: dest:f src1:i len:64
+long_conv_to_ovf_i4_un: dest:i src1:i len:16
+long_conv_to_ovf_u4: dest:i src1:i len:15
+long_conv_to_u2: dest:i src1:i len:4
+long_conv_to_u1: dest:i src1:i len:4
+zext_i4: dest:i src1:i len:4
+
+long_mul_imm: dest:i src1:i clob:1 len:12
+long_min: dest:i src1:i src2:i len:16 clob:1
+long_max: dest:i src1:i src2:i len:16 clob:1
throw: src1:i len:18
rethrow: src1:i len:18
start_handler: len:9
endfinally: len:9
endfilter: src1:a len:9
-
-conv.ovf.i4.un: dest:i src1:i len:16
-conv.ovf.u4.un:
-conv.ovf.u4: dest:i src1:i len:15
ckfinite: dest:f src1:f len:43
-conv.u2: dest:i src1:i len:4
-conv.u1: dest:i src1:i len:4
-conv.i: dest:i src1:i len:4
mul.ovf: dest:i src1:i src2:i clob:1 len:10
# this opcode is handled specially in the code generator
mul.ovf.un: dest:i src1:i src2:i len:18
-conv.u: dest:i src1:i len:4
ceq: dest:c len:8
cgt: dest:c len:8
cgt.un: dest:c len:8
cond_exc_iov: len:8
cond_exc_ic: len:8
-long_add: dest:i src1:i src2:i len:3 clob:1
-long_mul: dest:i src1:i src2:i clob:1 len:4
-long_mul_imm: dest:i src1:i clob:1 len:12
-long_div: dest:a src1:a src2:i len:16 clob:d
-long_div_un: dest:a src1:a src2:i len:16 clob:d
-long_rem: dest:d src1:a src2:i len:16 clob:a
-long_rem_un: dest:d src1:a src2:i len:16 clob:a
-long_and: dest:i src1:i src2:i len:3 clob:1
-long_or: dest:i src1:i src2:i len:3 clob:1
-long_xor: dest:i src1:i src2:i len:3 clob:1
-long_shl: dest:i src1:i src2:s clob:1 len:31
-long_shr: dest:i src1:i src2:s clob:1 len:32
-long_shr_un: dest:i src1:i src2:s clob:1 len:32
-long_min: dest:i src1:i src2:i len:16 clob:1
-long_max: dest:i src1:i src2:i len:16 clob:1
-
-long_conv_to_r4: dest:f src1:i len:8
-long_conv_to_r8: dest:f src1:i len:8
long_conv_to_ovf_i: dest:i src1:i src2:i len:40
long_mul_ovf: dest:i src1:i src2:i clob:1 len:16
long_mul_ovf_un: dest:i src1:i src2:i len:22
-long_conv_to_r_un: dest:f src1:i len:64
long_shr_imm: dest:i src1:i clob:1 len:11
long_shr_un_imm: dest:i src1:i clob:1 len:11
long_shl_imm: dest:i src1:i clob:1 len:11
int_neg: dest:i src1:i clob:1 len:4
int_not: dest:i src1:i clob:1 len:4
+int_conv_to_r4: dest:f src1:i len:9
+int_conv_to_r8: dest:f src1:i len:9
int_ceq: dest:c len:8
int_cgt: dest:c len:8
int_cgt_un: dest:c len:8
}
else
break;
- case CEE_XOR:
+ case OP_LXOR:
+ case OP_IXOR:
if ((ins->sreg1 == ins->sreg2) && (ins->sreg1 == ins->dreg)) {
MonoInst *ins2;
}
}
break;
- case CEE_CONV_I4:
- case CEE_CONV_U4:
case OP_MOVE:
case OP_FMOVE:
/*
break;
}
}
- case CEE_XOR:
case OP_LXOR:
/*
* Use IXOR to avoid a rex prefix if possible. The cpu will sign extend the
if (last_ins && (last_ins->opcode == OP_STOREI1_MEMBASE_REG) &&
ins->inst_basereg == last_ins->inst_destbasereg &&
ins->inst_offset == last_ins->inst_offset) {
- ins->opcode = (ins->opcode == OP_LOADI1_MEMBASE) ? CEE_CONV_I1 : CEE_CONV_U1;
+ ins->opcode = (ins->opcode == OP_LOADI1_MEMBASE) ? OP_PCONV_TO_I1 : OP_PCONV_TO_U1;
ins->sreg1 = last_ins->sreg1;
}
break;
if (last_ins && (last_ins->opcode == OP_STOREI2_MEMBASE_REG) &&
ins->inst_basereg == last_ins->inst_destbasereg &&
ins->inst_offset == last_ins->inst_offset) {
- ins->opcode = (ins->opcode == OP_LOADI2_MEMBASE) ? CEE_CONV_I2 : CEE_CONV_U2;
+ ins->opcode = (ins->opcode == OP_LOADI2_MEMBASE) ? OP_PCONV_TO_I2 : OP_PCONV_TO_U2;
ins->sreg1 = last_ins->sreg1;
}
break;
- case CEE_CONV_I4:
- case CEE_CONV_U4:
case OP_MOVE:
case OP_FMOVE:
/*
case OP_AMD64_LOADI8_MEMINDEX:
amd64_mov_reg_memindex_size (code, ins->dreg, ins->inst_basereg, 0, ins->inst_indexreg, 0, 8);
break;
- case CEE_CONV_I1:
+ case OP_LCONV_TO_I1:
case OP_SEXT_I1:
amd64_widen_reg (code, ins->dreg, ins->sreg1, TRUE, FALSE);
break;
- case CEE_CONV_I2:
+ case OP_LCONV_TO_I2:
case OP_SEXT_I2:
amd64_widen_reg (code, ins->dreg, ins->sreg1, TRUE, TRUE);
break;
- case CEE_CONV_U1:
+ case OP_LCONV_TO_U1:
amd64_widen_reg (code, ins->dreg, ins->sreg1, FALSE, FALSE);
break;
- case CEE_CONV_U2:
+ case OP_LCONV_TO_U2:
amd64_widen_reg (code, ins->dreg, ins->sreg1, FALSE, TRUE);
break;
- case CEE_CONV_U8:
- case CEE_CONV_U:
+ case OP_ZEXT_I4:
/* Clean out the upper word */
amd64_mov_reg_reg_size (code, ins->dreg, ins->sreg1, 4);
break;
- case CEE_CONV_I8:
- case CEE_CONV_I:
case OP_SEXT_I4:
amd64_movsxd_reg_reg (code, ins->dreg, ins->sreg1);
break;
amd64_breakpoint (code);
break;
case OP_ADDCC:
- case CEE_ADD:
case OP_LADD:
amd64_alu_reg_reg (code, X86_ADD, ins->sreg1, ins->sreg2);
break;
amd64_alu_reg_imm (code, X86_ADC, ins->dreg, ins->inst_imm);
break;
case OP_SUBCC:
- case CEE_SUB:
+ case OP_LSUB:
amd64_alu_reg_reg (code, X86_SUB, ins->sreg1, ins->sreg2);
break;
case OP_SBB:
g_assert (amd64_is_imm32 (ins->inst_imm));
amd64_alu_reg_imm (code, X86_SBB, ins->dreg, ins->inst_imm);
break;
- case CEE_AND:
+ case OP_LAND:
amd64_alu_reg_reg (code, X86_AND, ins->sreg1, ins->sreg2);
break;
case OP_AND_IMM:
g_assert (amd64_is_imm32 (ins->inst_imm));
amd64_alu_reg_imm (code, X86_AND, ins->sreg1, ins->inst_imm);
break;
- case CEE_MUL:
case OP_LMUL:
amd64_imul_reg_reg (code, ins->sreg1, ins->sreg2);
break;
}
break;
}
- case CEE_DIV:
case OP_LDIV:
- case CEE_REM:
case OP_LREM:
/* Regalloc magic makes the div/rem cases the same */
if (ins->sreg2 == AMD64_RDX) {
amd64_div_reg (code, ins->sreg2, TRUE);
}
break;
- case CEE_DIV_UN:
case OP_LDIV_UN:
- case CEE_REM_UN:
case OP_LREM_UN:
if (ins->sreg2 == AMD64_RDX) {
amd64_mov_membase_reg (code, AMD64_RSP, -8, AMD64_RDX, 8);
amd64_imul_reg_reg (code, ins->sreg1, ins->sreg2);
EMIT_COND_SYSTEM_EXCEPTION (X86_CC_O, FALSE, "OverflowException");
break;
- case CEE_OR:
+ case OP_LOR:
amd64_alu_reg_reg (code, X86_OR, ins->sreg1, ins->sreg2);
break;
case OP_OR_IMM:
g_assert (amd64_is_imm32 (ins->inst_imm));
amd64_alu_reg_imm (code, X86_OR, ins->sreg1, ins->inst_imm);
break;
- case CEE_XOR:
case OP_LXOR:
amd64_alu_reg_reg (code, X86_XOR, ins->sreg1, ins->sreg2);
break;
g_assert (amd64_is_imm32 (ins->inst_imm));
amd64_alu_reg_imm (code, X86_XOR, ins->sreg1, ins->inst_imm);
break;
- case CEE_SHL:
case OP_LSHL:
g_assert (ins->sreg2 == AMD64_RCX);
amd64_shift_reg (code, X86_SHL, ins->dreg);
break;
- case CEE_SHR:
case OP_LSHR:
g_assert (ins->sreg2 == AMD64_RCX);
amd64_shift_reg (code, X86_SAR, ins->dreg);
g_assert (amd64_is_imm32 (ins->inst_imm));
amd64_shift_reg_imm (code, X86_SHR, ins->dreg, ins->inst_imm);
break;
- case CEE_SHR_UN:
- g_assert (ins->sreg2 == AMD64_RCX);
- amd64_shift_reg_size (code, X86_SHR, ins->dreg, 4);
- break;
case OP_LSHR_UN:
g_assert (ins->sreg2 == AMD64_RCX);
amd64_shift_reg (code, X86_SHR, ins->dreg);
case OP_IBLE_UN:
EMIT_COND_BRANCH (ins, cc_table [mono_opcode_to_cond (ins->opcode)], cc_signed_table [mono_opcode_to_cond (ins->opcode)]);
break;
- case CEE_NOT:
+ case OP_LNOT:
amd64_not_reg (code, ins->sreg1);
break;
- case CEE_NEG:
+ case OP_LNEG:
amd64_neg_reg (code, ins->sreg1);
break;
mono_add_patch_info (cfg, offset, (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
amd64_mov_reg_membase (code, ins->dreg, AMD64_RIP, 0, 8);
break;
- case CEE_CONV_I4:
- case CEE_CONV_U4:
case OP_MOVE:
amd64_mov_reg_reg (code, ins->dreg, ins->sreg1, sizeof (gpointer));
break;
EMIT_COND_SYSTEM_EXCEPTION (branch_cc_table [ins->opcode - OP_COND_EXC_IEQ],
(ins->opcode < OP_COND_EXC_INE_UN), ins->inst_p1);
break;
- case CEE_BEQ:
- case CEE_BNE_UN:
- case CEE_BLT:
- case CEE_BLT_UN:
- case CEE_BGT:
- case CEE_BGT_UN:
- case CEE_BGE:
- case CEE_BGE_UN:
- case CEE_BLE:
- case CEE_BLE_UN:
+ case OP_LBEQ:
+ case OP_LBLT:
+ case OP_LBGT:
+ case OP_LBGE:
+ case OP_LBLE:
+ case OP_LBNE_UN:
+ case OP_LBLT_UN:
+ case OP_LBGT_UN:
+ case OP_LBGE_UN:
+ case OP_LBLE_UN:
EMIT_COND_BRANCH (ins, cc_table [mono_opcode_to_cond (ins->opcode)], cc_signed_table [mono_opcode_to_cond (ins->opcode)]);
break;
else
amd64_fld_membase (code, ins->inst_basereg, ins->inst_offset, FALSE);
break;
- case CEE_CONV_R4: /* FIXME: change precision */
- case CEE_CONV_R8:
+ case OP_ICONV_TO_R4: /* FIXME: change precision */
+ case OP_ICONV_TO_R8:
if (use_sse2)
amd64_sse_cvtsi2sd_reg_reg_size (code, ins->dreg, ins->sreg1, 4);
else {
amd64_alu_reg_imm (code, X86_ADD, AMD64_RSP, 8);
}
break;
- case CEE_CONV_R_UN:
- /* Emulated */
- g_assert_not_reached ();
- break;
case OP_LCONV_TO_R4: /* FIXME: change precision */
case OP_LCONV_TO_R8:
if (use_sse2)
break;
}
- case CEE_CONV_OVF_U4:
+ case OP_LCONV_TO_OVF_U4:
amd64_alu_reg_imm (code, X86_CMP, ins->sreg1, 0);
EMIT_COND_SYSTEM_EXCEPTION (X86_CC_LT, TRUE, "OverflowException");
amd64_mov_reg_reg (code, ins->dreg, ins->sreg1, 8);
break;
- case CEE_CONV_OVF_I4_UN:
+ case OP_LCONV_TO_OVF_I4_UN:
amd64_alu_reg_imm (code, X86_CMP, ins->sreg1, 0x7fffffff);
EMIT_COND_SYSTEM_EXCEPTION (X86_CC_GT, FALSE, "OverflowException");
amd64_mov_reg_reg (code, ins->dreg, ins->sreg1, 8);
#define MONO_ARCH_VTABLE_REG AMD64_R11
#define MONO_ARCH_COMMON_VTABLE_TRAMPOLINE 1
#define MONO_ARCH_HAVE_NOTIFY_PENDING_EXC 1
+#define MONO_ARCH_ENABLE_NORMALIZE_OPCODES 1
#define MONO_ARCH_AOT_SUPPORTED 1
mono_mempool_destroy (cfg->state_pool);
}
+/*
+ * mono_normalize_opcodes:
+ *
+ * Replace CEE_ and OP_ opcodes with the corresponding OP_I or OP_L opcodes.
+ */
+
+static gint16 *remap_table;
+
+#if SIZEOF_VOID_P == 8
+#define REMAP_OPCODE(opcode) OP_L ## opcode
+#else
+#define REMAP_OPCODE(opcode) OP_I ## opcode
+#endif
+
+static G_GNUC_UNUSED void
+mono_normalize_opcodes (MonoCompile *cfg, MonoBasicBlock *bb)
+{
+ MonoInst *ins;
+
+ if (!remap_table) {
+ remap_table = g_new0 (gint16, OP_LAST);
+
+#if SIZEOF_VOID_P == 8
+ remap_table [CEE_CONV_U8] = OP_ZEXT_I4;
+ remap_table [CEE_CONV_U] = OP_ZEXT_I4;
+ remap_table [CEE_CONV_I8] = OP_SEXT_I4;
+ remap_table [CEE_CONV_I] = OP_SEXT_I4;
+ remap_table [CEE_CONV_OVF_U4] = OP_LCONV_TO_OVF_U4;
+ remap_table [CEE_CONV_OVF_I4_UN] = OP_LCONV_TO_OVF_I4_UN;
+#else
+#endif
+ remap_table [CEE_CONV_R4] = OP_ICONV_TO_R4;
+ remap_table [CEE_CONV_R8] = OP_ICONV_TO_R8;
+ remap_table [CEE_CONV_I4] = OP_MOVE;
+ remap_table [CEE_CONV_U4] = OP_MOVE;
+ remap_table [CEE_CONV_I1] = REMAP_OPCODE (CONV_TO_I1);
+ remap_table [CEE_CONV_I2] = REMAP_OPCODE (CONV_TO_I2);
+ remap_table [CEE_CONV_U1] = REMAP_OPCODE (CONV_TO_U1);
+ remap_table [CEE_CONV_U2] = REMAP_OPCODE (CONV_TO_U2);
+ remap_table [CEE_ADD] = REMAP_OPCODE (ADD);
+ remap_table [CEE_SUB] = REMAP_OPCODE (SUB);
+ remap_table [CEE_MUL] = REMAP_OPCODE (MUL);
+ remap_table [CEE_DIV] = REMAP_OPCODE (DIV);
+ remap_table [CEE_REM] = REMAP_OPCODE (REM);
+ remap_table [CEE_DIV_UN] = REMAP_OPCODE (DIV_UN);
+ remap_table [CEE_REM_UN] = REMAP_OPCODE (REM_UN);
+ remap_table [CEE_AND] = REMAP_OPCODE (AND);
+ remap_table [CEE_OR] = REMAP_OPCODE (OR);
+ remap_table [CEE_XOR] = REMAP_OPCODE (XOR);
+ remap_table [CEE_SHL] = REMAP_OPCODE (SHL);
+ remap_table [CEE_SHR] = REMAP_OPCODE (SHR);
+ remap_table [CEE_SHR_UN] = REMAP_OPCODE (SHR_UN);
+ remap_table [CEE_NOT] = REMAP_OPCODE (NOT);
+ remap_table [CEE_NEG] = REMAP_OPCODE (NEG);
+ remap_table [CEE_CALL] = OP_CALL;
+ remap_table [CEE_BEQ] = REMAP_OPCODE (BEQ);
+ remap_table [CEE_BNE_UN] = REMAP_OPCODE (BNE_UN);
+ remap_table [CEE_BLT] = REMAP_OPCODE (BLT);
+ remap_table [CEE_BLT_UN] = REMAP_OPCODE (BLT_UN);
+ remap_table [CEE_BGT] = REMAP_OPCODE (BGT);
+ remap_table [CEE_BGT_UN] = REMAP_OPCODE (BGT_UN);
+ remap_table [CEE_BGE] = REMAP_OPCODE (BGE);
+ remap_table [CEE_BGE_UN] = REMAP_OPCODE (BGE_UN);
+ remap_table [CEE_BLE] = REMAP_OPCODE (BLE);
+ remap_table [CEE_BLE_UN] = REMAP_OPCODE (BLE_UN);
+ remap_table [CEE_MUL_OVF] = REMAP_OPCODE (MUL_OVF);
+ remap_table [CEE_MUL_OVF_UN] = REMAP_OPCODE (MUL_OVF_UN);
+ }
+
+ MONO_BB_FOR_EACH_INS (bb, ins) {
+ int remapped = remap_table [ins->opcode];
+ if (remapped)
+ ins->opcode = remapped;
+ }
+}
+
void
mono_codegen (MonoCompile *cfg)
{
cfg->spill_count = 0;
/* we reuse dfn here */
/* bb->dfn = bb_count++; */
+#ifdef MONO_ARCH_ENABLE_NORMALIZE_OPCODES
+ mono_normalize_opcodes (cfg, bb);
+#endif
mono_arch_local_regalloc (cfg, bb);
}
#define OP_PCONST OP_I8CONST
#define OP_PADD OP_LADD
#define OP_PNEG OP_LNEG
+#define OP_PCONV_TO_I1 OP_LCONV_TO_I1
+#define OP_PCONV_TO_U1 OP_LCONV_TO_U1
+#define OP_PCONV_TO_I2 OP_LCONV_TO_I2
#define OP_PCONV_TO_U2 OP_LCONV_TO_U2
#define OP_PCONV_TO_OVF_I1_UN OP_LCONV_TO_OVF_I1_UN
#define OP_PCONV_TO_OVF_I1 OP_LCONV_TO_OVF_I1
#define OP_PCONST OP_ICONST
#define OP_PADD CEE_ADD
#define OP_PNEG CEE_NEG
+#define OP_PCONV_TO_I1 OP_ICONV_TO_I1
+#define OP_PCONV_TO_U1 OP_ICONV_TO_U1
+#define OP_PCONV_TO_I2 OP_ICONV_TO_I2
#define OP_PCONV_TO_U2 CEE_CONV_U2
#define OP_PCONV_TO_OVF_I1_UN CEE_CONV_OVF_I1_UN
#define OP_PCONV_TO_OVF_I1 CEE_CONV_OVF_I1