X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fdecompose.c;h=10a5bdfd5b40a943f3a0b627cd4cb91265ff7121;hb=9444d475a4db5f1f6af1bc4d9955a83ce1be5484;hp=2899a1e91838ffda2f0a30771e3a01e09f2b7e61;hpb=0de646eb4cc29b9ca6b5098d4190ee22afe42536;p=mono.git diff --git a/mono/mini/decompose.c b/mono/mini/decompose.c index 2899a1e9183..10a5bdfd5b4 100644 --- a/mono/mini/decompose.c +++ b/mono/mini/decompose.c @@ -6,6 +6,7 @@ * * (C) 2002 Ximian, Inc. * Copyright 2011 Xamarin, Inc (http://www.xamarin.com) + * Licensed under the MIT license. See LICENSE file in the project root for full license information. */ #include "mini.h" @@ -439,8 +440,7 @@ mono_decompose_opcode (MonoCompile *cfg, MonoInst *ins) case OP_FCONV_TO_OVF_U8_UN: case OP_FCONV_TO_OVF_I_UN: case OP_FCONV_TO_OVF_U_UN: - cfg->exception_type = MONO_EXCEPTION_INVALID_PROGRAM; - cfg->exception_message = g_strdup_printf ("float conv.ovf.un opcodes not supported."); + mono_cfg_set_exception_invalid_program (cfg, g_strdup_printf ("float conv.ovf.un opcodes not supported.")); break; case OP_IDIV: @@ -472,46 +472,67 @@ mono_decompose_opcode (MonoCompile *cfg, MonoInst *ins) } break; -#if SIZEOF_REGISTER == 8 - case OP_LREM_IMM: -#endif - case OP_IREM_IMM: { - int power = mono_is_power_of_two (ins->inst_imm); - if (ins->inst_imm == 1) { - ins->opcode = OP_ICONST; - MONO_INST_NULLIFY_SREGS (ins); - ins->inst_c0 = 0; -#if __s390__ +#if SIZEOF_VOID_P == 8 + case OP_LDIV: + case OP_LREM: + case OP_LDIV_UN: + case OP_LREM_UN: + if (cfg->backend->emulate_div && mono_arch_opcode_needs_emulation (cfg, ins->opcode)) + emulate = TRUE; + if (!emulate) { + if (cfg->backend->need_div_check) { + int reg1 = alloc_ireg (cfg); + int reg2 = alloc_ireg (cfg); + int reg3 = alloc_ireg (cfg); + /* b == 0 */ + MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg2, 0); + MONO_EMIT_NEW_COND_EXC (cfg, IEQ, "DivideByZeroException"); + if (ins->opcode == OP_LDIV || ins->opcode == OP_LREM) { + /* b == -1 && a == 0x80000000 */ + MONO_EMIT_NEW_I8CONST (cfg, reg3, -1); + MONO_EMIT_NEW_BIALU (cfg, OP_LCOMPARE, -1, ins->sreg2, reg3); + MONO_EMIT_NEW_UNALU (cfg, OP_LCEQ, reg1, -1); + MONO_EMIT_NEW_I8CONST (cfg, reg3, 0x8000000000000000L); + MONO_EMIT_NEW_BIALU (cfg, OP_LCOMPARE, -1, ins->sreg1, reg3); + MONO_EMIT_NEW_UNALU (cfg, OP_LCEQ, reg2, -1); + MONO_EMIT_NEW_BIALU (cfg, OP_IAND, reg1, reg1, reg2); + MONO_EMIT_NEW_ICOMPARE_IMM (cfg, reg1, 1); + MONO_EMIT_NEW_COND_EXC (cfg, IEQ, "OverflowException"); + } + } + MONO_EMIT_NEW_BIALU (cfg, ins->opcode, ins->dreg, ins->sreg1, ins->sreg2); + NULLIFY_INS (ins); } -#else - } else if ((ins->inst_imm > 0) && (ins->inst_imm < (1LL << 32)) && (power != -1)) { - gboolean is_long = ins->opcode == OP_LREM_IMM; - int compensator_reg = alloc_ireg (cfg); - int intermediate_reg; - - /* Based on gcc code */ - - /* Add compensation for negative numerators */ + break; +#endif - if (power > 1) { - intermediate_reg = compensator_reg; - MONO_EMIT_NEW_BIALU_IMM (cfg, is_long ? OP_LSHR_IMM : OP_ISHR_IMM, intermediate_reg, ins->sreg1, is_long ? 63 : 31); - } else { - intermediate_reg = ins->sreg1; + case OP_DIV_IMM: + case OP_REM_IMM: + case OP_IDIV_IMM: + case OP_IREM_IMM: + case OP_IDIV_UN_IMM: + case OP_IREM_UN_IMM: + if (cfg->backend->need_div_check) { + int reg1 = alloc_ireg (cfg); + /* b == 0 */ + if (ins->inst_imm == 0) { + // FIXME: Optimize this + MONO_EMIT_NEW_ICONST (cfg, reg1, 0); + MONO_EMIT_NEW_ICOMPARE_IMM (cfg, reg1, 0); + MONO_EMIT_NEW_COND_EXC (cfg, IEQ, "DivideByZeroException"); } - - MONO_EMIT_NEW_BIALU_IMM (cfg, is_long ? OP_LSHR_UN_IMM : OP_ISHR_UN_IMM, compensator_reg, intermediate_reg, (is_long ? 64 : 32) - power); - MONO_EMIT_NEW_BIALU (cfg, is_long ? OP_LADD : OP_IADD, ins->dreg, ins->sreg1, compensator_reg); - /* Compute remainder */ - MONO_EMIT_NEW_BIALU_IMM (cfg, is_long ? OP_LAND_IMM : OP_AND_IMM, ins->dreg, ins->dreg, (1 << power) - 1); - /* Remove compensation */ - MONO_EMIT_NEW_BIALU (cfg, is_long ? OP_LSUB : OP_ISUB, ins->dreg, ins->dreg, compensator_reg); - + if ((ins->opcode == OP_DIV_IMM || ins->opcode == OP_IDIV_IMM || ins->opcode == OP_REM_IMM || ins->opcode == OP_IREM_IMM) && + (ins->inst_imm == -1)) { + /* b == -1 && a == 0x80000000 */ + MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg1, 0x80000000); + MONO_EMIT_NEW_COND_EXC (cfg, IEQ, "OverflowException"); + } + MONO_EMIT_NEW_BIALU_IMM (cfg, ins->opcode, ins->dreg, ins->sreg1, ins->inst_imm); NULLIFY_INS (ins); + } else { + emulate = TRUE; } -#endif break; - } default: emulate = TRUE; @@ -519,8 +540,6 @@ mono_decompose_opcode (MonoCompile *cfg, MonoInst *ins) } if (emulate) { - MonoJitICallInfo *info = NULL; - #if SIZEOF_REGISTER == 8 if (decompose_long_opcode (cfg, ins, &repl)) emulate = FALSE; @@ -529,33 +548,8 @@ mono_decompose_opcode (MonoCompile *cfg, MonoInst *ins) emulate = FALSE; #endif - if (emulate) - info = mono_find_jit_opcode_emulation (ins->opcode); - if (info) { - MonoInst **args; - MonoInst *call; - - /* Create dummy MonoInst's for the arguments */ - g_assert (!info->sig->hasthis); - g_assert (info->sig->param_count <= MONO_MAX_SRC_REGS); - - args = (MonoInst **)mono_mempool_alloc0 (cfg->mempool, sizeof (MonoInst*) * info->sig->param_count); - if (info->sig->param_count > 0) { - int sregs [MONO_MAX_SRC_REGS]; - int num_sregs, i; - num_sregs = mono_inst_get_src_registers (ins, sregs); - g_assert (num_sregs == info->sig->param_count); - for (i = 0; i < num_sregs; ++i) { - MONO_INST_NEW (cfg, args [i], OP_ARG); - args [i]->dreg = sregs [i]; - } - } - - call = mono_emit_jit_icall_by_info (cfg, info, args); - call->dreg = ins->dreg; - - NULLIFY_INS (ins); - } + if (emulate && mono_find_jit_opcode_emulation (ins->opcode)) + cfg->has_emulated_ops = TRUE; } if (ins->opcode == OP_NOP) { @@ -614,8 +608,6 @@ mono_decompose_long_opts (MonoCompile *cfg) * needs to be able to handle long vregs. */ - /* reg + 1 contains the ls word, reg + 2 contains the ms word */ - /** * Create a dummy bblock and emit code into it so we can use the normal * code generation macros. @@ -638,28 +630,28 @@ mono_decompose_long_opts (MonoCompile *cfg) switch (tree->opcode) { case OP_I8CONST: - MONO_EMIT_NEW_ICONST (cfg, tree->dreg + 1, tree->inst_ls_word); - MONO_EMIT_NEW_ICONST (cfg, tree->dreg + 2, tree->inst_ms_word); + MONO_EMIT_NEW_ICONST (cfg, MONO_LVREG_LS (tree->dreg), tree->inst_ls_word); + MONO_EMIT_NEW_ICONST (cfg, MONO_LVREG_MS (tree->dreg), tree->inst_ms_word); break; case OP_DUMMY_I8CONST: - MONO_EMIT_NEW_DUMMY_INIT (cfg, tree->dreg + 1, OP_DUMMY_ICONST); - MONO_EMIT_NEW_DUMMY_INIT (cfg, tree->dreg + 2, OP_DUMMY_ICONST); + MONO_EMIT_NEW_DUMMY_INIT (cfg, MONO_LVREG_LS (tree->dreg), OP_DUMMY_ICONST); + MONO_EMIT_NEW_DUMMY_INIT (cfg, MONO_LVREG_MS (tree->dreg), OP_DUMMY_ICONST); break; case OP_LMOVE: case OP_LCONV_TO_U8: case OP_LCONV_TO_I8: case OP_LCONV_TO_OVF_U8_UN: case OP_LCONV_TO_OVF_I8: - MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 1, tree->sreg1 + 1); - MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 2, tree->sreg1 + 2); + MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1)); + MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1)); break; case OP_STOREI8_MEMBASE_REG: - MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, tree->inst_destbasereg, tree->inst_offset + MINI_MS_WORD_OFFSET, tree->sreg1 + 2); - MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, tree->inst_destbasereg, tree->inst_offset + MINI_LS_WORD_OFFSET, tree->sreg1 + 1); + MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, tree->inst_destbasereg, tree->inst_offset + MINI_MS_WORD_OFFSET, MONO_LVREG_MS (tree->sreg1)); + MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, tree->inst_destbasereg, tree->inst_offset + MINI_LS_WORD_OFFSET, MONO_LVREG_LS (tree->sreg1)); break; case OP_LOADI8_MEMBASE: - MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI4_MEMBASE, tree->dreg + 2, tree->inst_basereg, tree->inst_offset + MINI_MS_WORD_OFFSET); - MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI4_MEMBASE, tree->dreg + 1, tree->inst_basereg, tree->inst_offset + MINI_LS_WORD_OFFSET); + MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI4_MEMBASE, MONO_LVREG_MS (tree->dreg), tree->inst_basereg, tree->inst_offset + MINI_MS_WORD_OFFSET); + MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI4_MEMBASE, MONO_LVREG_LS (tree->dreg), tree->inst_basereg, tree->inst_offset + MINI_LS_WORD_OFFSET); break; case OP_ICONV_TO_I8: { @@ -670,108 +662,114 @@ mono_decompose_long_opts (MonoCompile *cfg) * tmp = low > -1 ? 1: 0; * high = tmp - 1; if low is zero or pos high becomes 0, else -1 */ - MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 1, tree->sreg1); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, tree->dreg + 1, -1); + MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_LS (tree->dreg), tree->sreg1); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, MONO_LVREG_LS (tree->dreg), -1); MONO_EMIT_NEW_BIALU (cfg, OP_ICGT, tmpreg, -1, -1); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISUB_IMM, tree->dreg + 2, tmpreg, 1); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISUB_IMM, MONO_LVREG_MS (tree->dreg), tmpreg, 1); break; } case OP_ICONV_TO_U8: - MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 1, tree->sreg1); - MONO_EMIT_NEW_ICONST (cfg, tree->dreg + 2, 0); + MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_LS (tree->dreg), tree->sreg1); + MONO_EMIT_NEW_ICONST (cfg, MONO_LVREG_MS (tree->dreg), 0); break; case OP_ICONV_TO_OVF_I8: /* a signed 32 bit num always fits in a signed 64 bit one */ - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SHR_IMM, tree->dreg + 2, tree->sreg1, 31); - MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 1, tree->sreg1); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SHR_IMM, MONO_LVREG_MS (tree->dreg), tree->sreg1, 31); + MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_LS (tree->dreg), tree->sreg1); break; case OP_ICONV_TO_OVF_U8: MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1, 0); MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException"); - MONO_EMIT_NEW_ICONST (cfg, tree->dreg + 2, 0); - MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 1, tree->sreg1); + MONO_EMIT_NEW_ICONST (cfg, MONO_LVREG_MS (tree->dreg), 0); + MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_LS (tree->dreg), tree->sreg1); break; case OP_ICONV_TO_OVF_I8_UN: case OP_ICONV_TO_OVF_U8_UN: /* an unsigned 32 bit num always fits in an (un)signed 64 bit one */ - MONO_EMIT_NEW_ICONST (cfg, tree->dreg + 2, 0); - MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 1, tree->sreg1); + MONO_EMIT_NEW_ICONST (cfg, MONO_LVREG_MS (tree->dreg), 0); + MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_LS (tree->dreg), tree->sreg1); break; case OP_LCONV_TO_I1: - MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I1, tree->dreg, tree->sreg1 + 1); + MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I1, tree->dreg, MONO_LVREG_LS (tree->sreg1)); break; case OP_LCONV_TO_U1: - MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_U1, tree->dreg, tree->sreg1 + 1); + MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_U1, tree->dreg, MONO_LVREG_LS (tree->sreg1)); break; case OP_LCONV_TO_I2: - MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I2, tree->dreg, tree->sreg1 + 1); + MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I2, tree->dreg, MONO_LVREG_LS (tree->sreg1)); break; case OP_LCONV_TO_U2: - MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_U2, tree->dreg, tree->sreg1 + 1); + MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_U2, tree->dreg, MONO_LVREG_LS (tree->sreg1)); break; case OP_LCONV_TO_I4: case OP_LCONV_TO_U4: case OP_LCONV_TO_I: case OP_LCONV_TO_U: - MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg, tree->sreg1 + 1); + MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg, MONO_LVREG_LS (tree->sreg1)); break; +#ifndef MONO_ARCH_EMULATE_LCONV_TO_R8 case OP_LCONV_TO_R8: - MONO_EMIT_NEW_BIALU (cfg, OP_LCONV_TO_R8_2, tree->dreg, tree->sreg1 + 1, tree->sreg1 + 2); + MONO_EMIT_NEW_BIALU (cfg, OP_LCONV_TO_R8_2, tree->dreg, MONO_LVREG_LS (tree->sreg1), MONO_LVREG_MS (tree->sreg1)); break; +#endif +#ifndef MONO_ARCH_EMULATE_LCONV_TO_R4 case OP_LCONV_TO_R4: - MONO_EMIT_NEW_BIALU (cfg, OP_LCONV_TO_R4_2, tree->dreg, tree->sreg1 + 1, tree->sreg1 + 2); + MONO_EMIT_NEW_BIALU (cfg, OP_LCONV_TO_R4_2, tree->dreg, MONO_LVREG_LS (tree->sreg1), MONO_LVREG_MS (tree->sreg1)); break; +#endif +#ifndef MONO_ARCH_EMULATE_LCONV_TO_R8_UN case OP_LCONV_TO_R_UN: - MONO_EMIT_NEW_BIALU (cfg, OP_LCONV_TO_R_UN_2, tree->dreg, tree->sreg1 + 1, tree->sreg1 + 2); + MONO_EMIT_NEW_BIALU (cfg, OP_LCONV_TO_R_UN_2, tree->dreg, MONO_LVREG_LS (tree->sreg1), MONO_LVREG_MS (tree->sreg1)); break; +#endif case OP_LCONV_TO_OVF_I1: { MonoBasicBlock *is_negative, *end_label; NEW_BBLOCK (cfg, is_negative); NEW_BBLOCK (cfg, end_label); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, MONO_LVREG_MS (tree->sreg1), 0); MONO_EMIT_NEW_COND_EXC (cfg, GT, "OverflowException"); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, -1); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, MONO_LVREG_MS (tree->sreg1), -1); MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException"); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, MONO_LVREG_MS (tree->sreg1), 0); MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBLT, is_negative); /* Positive */ - MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1 + 1, 127); + MONO_EMIT_NEW_COMPARE_IMM (cfg, MONO_LVREG_LS (tree->sreg1), 127); MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException"); MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_label); /* Negative */ MONO_START_BB (cfg, is_negative); - MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1 + 1, -128); + MONO_EMIT_NEW_COMPARE_IMM (cfg, MONO_LVREG_LS (tree->sreg1), -128); MONO_EMIT_NEW_COND_EXC (cfg, LT_UN, "OverflowException"); MONO_START_BB (cfg, end_label); - MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I1, tree->dreg, tree->sreg1 + 1); + MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I1, tree->dreg, MONO_LVREG_LS (tree->sreg1)); break; } case OP_LCONV_TO_OVF_I1_UN: - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, MONO_LVREG_MS (tree->sreg1), 0); MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "OverflowException"); - MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1 + 1, 127); + MONO_EMIT_NEW_COMPARE_IMM (cfg, MONO_LVREG_LS (tree->sreg1), 127); MONO_EMIT_NEW_COND_EXC (cfg, GT, "OverflowException"); - MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1 + 1, -128); + MONO_EMIT_NEW_COMPARE_IMM (cfg, MONO_LVREG_LS (tree->sreg1), -128); MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException"); - MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I1, tree->dreg, tree->sreg1 + 1); + MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I1, tree->dreg, MONO_LVREG_LS (tree->sreg1)); break; case OP_LCONV_TO_OVF_U1: case OP_LCONV_TO_OVF_U1_UN: - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, MONO_LVREG_MS (tree->sreg1), 0); MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "OverflowException"); /* probe value to be within 0 to 255 */ - MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1 + 1, 255); + MONO_EMIT_NEW_COMPARE_IMM (cfg, MONO_LVREG_LS (tree->sreg1), 255); MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException"); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, tree->dreg, tree->sreg1 + 1, 0xff); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, tree->dreg, MONO_LVREG_LS (tree->sreg1), 0xff); break; case OP_LCONV_TO_OVF_I2: { MonoBasicBlock *is_negative, *end_label; @@ -779,132 +777,132 @@ mono_decompose_long_opts (MonoCompile *cfg) NEW_BBLOCK (cfg, is_negative); NEW_BBLOCK (cfg, end_label); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, MONO_LVREG_MS (tree->sreg1), 0); MONO_EMIT_NEW_COND_EXC (cfg, GT, "OverflowException"); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, -1); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, MONO_LVREG_MS (tree->sreg1), -1); MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException"); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, MONO_LVREG_MS (tree->sreg1), 0); MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBLT, is_negative); /* Positive */ - MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1 + 1, 32767); + MONO_EMIT_NEW_COMPARE_IMM (cfg, MONO_LVREG_LS (tree->sreg1), 32767); MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException"); MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_label); /* Negative */ MONO_START_BB (cfg, is_negative); - MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1 + 1, -32768); + MONO_EMIT_NEW_COMPARE_IMM (cfg, MONO_LVREG_LS (tree->sreg1), -32768); MONO_EMIT_NEW_COND_EXC (cfg, LT_UN, "OverflowException"); MONO_START_BB (cfg, end_label); - MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I2, tree->dreg, tree->sreg1 + 1); + MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I2, tree->dreg, MONO_LVREG_LS (tree->sreg1)); break; } case OP_LCONV_TO_OVF_I2_UN: - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, MONO_LVREG_MS (tree->sreg1), 0); MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "OverflowException"); /* Probe value to be within -32768 and 32767 */ - MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1 + 1, 32767); + MONO_EMIT_NEW_COMPARE_IMM (cfg, MONO_LVREG_LS (tree->sreg1), 32767); MONO_EMIT_NEW_COND_EXC (cfg, GT, "OverflowException"); - MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1 + 1, -32768); + MONO_EMIT_NEW_COMPARE_IMM (cfg, MONO_LVREG_LS (tree->sreg1), -32768); MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException"); - MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I2, tree->dreg, tree->sreg1 + 1); + MONO_EMIT_NEW_UNALU (cfg, OP_ICONV_TO_I2, tree->dreg, MONO_LVREG_LS (tree->sreg1)); break; case OP_LCONV_TO_OVF_U2: case OP_LCONV_TO_OVF_U2_UN: - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, MONO_LVREG_MS (tree->sreg1), 0); MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "OverflowException"); /* Probe value to be within 0 and 65535 */ - MONO_EMIT_NEW_COMPARE_IMM (cfg, tree->sreg1 + 1, 0xffff); + MONO_EMIT_NEW_COMPARE_IMM (cfg, MONO_LVREG_LS (tree->sreg1), 0xffff); MONO_EMIT_NEW_COND_EXC (cfg, GT_UN, "OverflowException"); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, tree->dreg, tree->sreg1 + 1, 0xffff); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, tree->dreg, MONO_LVREG_LS (tree->sreg1), 0xffff); break; case OP_LCONV_TO_OVF_I4: case OP_LCONV_TO_OVF_I: - MONO_EMIT_NEW_BIALU (cfg, OP_LCONV_TO_OVF_I4_2, tree->dreg, tree->sreg1 + 1, tree->sreg1 + 2); + MONO_EMIT_NEW_BIALU (cfg, OP_LCONV_TO_OVF_I4_2, tree->dreg, MONO_LVREG_LS (tree->sreg1), MONO_LVREG_MS (tree->sreg1)); break; case OP_LCONV_TO_OVF_U4: case OP_LCONV_TO_OVF_U: case OP_LCONV_TO_OVF_U4_UN: case OP_LCONV_TO_OVF_U_UN: - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, MONO_LVREG_MS (tree->sreg1), 0); MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "OverflowException"); - MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg, tree->sreg1 + 1); + MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg, MONO_LVREG_LS (tree->sreg1)); break; case OP_LCONV_TO_OVF_I_UN: case OP_LCONV_TO_OVF_I4_UN: - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, MONO_LVREG_MS (tree->sreg1), 0); MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "OverflowException"); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 1, 0); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, MONO_LVREG_LS (tree->sreg1), 0); MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException"); - MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg, tree->sreg1 + 1); + MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg, MONO_LVREG_LS (tree->sreg1)); break; case OP_LCONV_TO_OVF_U8: - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, MONO_LVREG_MS (tree->sreg1), 0); MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException"); - MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 1, tree->sreg1 + 1); - MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 2, tree->sreg1 + 2); + MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1)); + MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1)); break; case OP_LCONV_TO_OVF_I8_UN: - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tree->sreg1 + 2, 0); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, MONO_LVREG_MS (tree->sreg1), 0); MONO_EMIT_NEW_COND_EXC (cfg, LT, "OverflowException"); - MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 1, tree->sreg1 + 1); - MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 2, tree->sreg1 + 2); + MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1)); + MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1)); break; case OP_LADD: - MONO_EMIT_NEW_BIALU (cfg, OP_IADDCC, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1); - MONO_EMIT_NEW_BIALU (cfg, OP_IADC, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2); + MONO_EMIT_NEW_BIALU (cfg, OP_IADDCC, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1), MONO_LVREG_LS (tree->sreg2)); + MONO_EMIT_NEW_BIALU (cfg, OP_IADC, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1), MONO_LVREG_MS (tree->sreg2)); break; case OP_LSUB: - MONO_EMIT_NEW_BIALU (cfg, OP_ISUBCC, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1); - MONO_EMIT_NEW_BIALU (cfg, OP_ISBB, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2); + MONO_EMIT_NEW_BIALU (cfg, OP_ISUBCC, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1), MONO_LVREG_LS (tree->sreg2)); + MONO_EMIT_NEW_BIALU (cfg, OP_ISBB, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1), MONO_LVREG_MS (tree->sreg2)); break; case OP_LADD_OVF: /* ADC sets the condition code */ - MONO_EMIT_NEW_BIALU (cfg, OP_IADDCC, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1); - MONO_EMIT_NEW_BIALU (cfg, OP_IADC, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2); + MONO_EMIT_NEW_BIALU (cfg, OP_IADDCC, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1), MONO_LVREG_LS (tree->sreg2)); + MONO_EMIT_NEW_BIALU (cfg, OP_IADC, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1), MONO_LVREG_MS (tree->sreg2)); MONO_EMIT_NEW_COND_EXC (cfg, OV, "OverflowException"); break; case OP_LADD_OVF_UN: /* ADC sets the condition code */ - MONO_EMIT_NEW_BIALU (cfg, OP_IADDCC, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1); - MONO_EMIT_NEW_BIALU (cfg, OP_IADC, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2); + MONO_EMIT_NEW_BIALU (cfg, OP_IADDCC, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1), MONO_LVREG_LS (tree->sreg2)); + MONO_EMIT_NEW_BIALU (cfg, OP_IADC, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1), MONO_LVREG_MS (tree->sreg2)); MONO_EMIT_NEW_COND_EXC (cfg, C, "OverflowException"); break; case OP_LSUB_OVF: /* SBB sets the condition code */ - MONO_EMIT_NEW_BIALU (cfg, OP_ISUBCC, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1); - MONO_EMIT_NEW_BIALU (cfg, OP_ISBB, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2); + MONO_EMIT_NEW_BIALU (cfg, OP_ISUBCC, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1), MONO_LVREG_LS (tree->sreg2)); + MONO_EMIT_NEW_BIALU (cfg, OP_ISBB, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1), MONO_LVREG_MS (tree->sreg2)); MONO_EMIT_NEW_COND_EXC (cfg, OV, "OverflowException"); break; case OP_LSUB_OVF_UN: /* SBB sets the condition code */ - MONO_EMIT_NEW_BIALU (cfg, OP_ISUBCC, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1); - MONO_EMIT_NEW_BIALU (cfg, OP_ISBB, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2); + MONO_EMIT_NEW_BIALU (cfg, OP_ISUBCC, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1), MONO_LVREG_LS (tree->sreg2)); + MONO_EMIT_NEW_BIALU (cfg, OP_ISBB, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1), MONO_LVREG_MS (tree->sreg2)); MONO_EMIT_NEW_COND_EXC (cfg, C, "OverflowException"); break; case OP_LAND: - MONO_EMIT_NEW_BIALU (cfg, OP_IAND, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1); - MONO_EMIT_NEW_BIALU (cfg, OP_IAND, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2); + MONO_EMIT_NEW_BIALU (cfg, OP_IAND, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1), MONO_LVREG_LS (tree->sreg2)); + MONO_EMIT_NEW_BIALU (cfg, OP_IAND, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1), MONO_LVREG_MS (tree->sreg2)); break; case OP_LOR: - MONO_EMIT_NEW_BIALU (cfg, OP_IOR, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1); - MONO_EMIT_NEW_BIALU (cfg, OP_IOR, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2); + MONO_EMIT_NEW_BIALU (cfg, OP_IOR, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1), MONO_LVREG_LS (tree->sreg2)); + MONO_EMIT_NEW_BIALU (cfg, OP_IOR, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1), MONO_LVREG_MS (tree->sreg2)); break; case OP_LXOR: - MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1); - MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2); + MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1), MONO_LVREG_LS (tree->sreg2)); + MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1), MONO_LVREG_MS (tree->sreg2)); break; case OP_LNOT: - MONO_EMIT_NEW_UNALU (cfg, OP_INOT, tree->dreg + 1, tree->sreg1 + 1); - MONO_EMIT_NEW_UNALU (cfg, OP_INOT, tree->dreg + 2, tree->sreg1 + 2); + MONO_EMIT_NEW_UNALU (cfg, OP_INOT, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1)); + MONO_EMIT_NEW_UNALU (cfg, OP_INOT, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1)); break; case OP_LNEG: /* Handled in mono_arch_decompose_long_opts () */ @@ -916,24 +914,24 @@ mono_decompose_long_opts (MonoCompile *cfg) break; case OP_LADD_IMM: - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADDCC_IMM, tree->dreg + 1, tree->sreg1 + 1, tree->inst_ls_word); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADC_IMM, tree->dreg + 2, tree->sreg1 + 2, tree->inst_ms_word); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADDCC_IMM, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1), tree->inst_ls_word); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADC_IMM, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1), tree->inst_ms_word); break; case OP_LSUB_IMM: - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SUBCC_IMM, tree->dreg + 1, tree->sreg1 + 1, tree->inst_ls_word); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SBB_IMM, tree->dreg + 2, tree->sreg1 + 2, tree->inst_ms_word); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SUBCC_IMM, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1), tree->inst_ls_word); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SBB_IMM, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1), tree->inst_ms_word); break; case OP_LAND_IMM: - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, tree->dreg + 1, tree->sreg1 + 1, tree->inst_ls_word); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, tree->dreg + 2, tree->sreg1 + 2, tree->inst_ms_word); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1), tree->inst_ls_word); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1), tree->inst_ms_word); break; case OP_LOR_IMM: - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_OR_IMM, tree->dreg + 1, tree->sreg1 + 1, tree->inst_ls_word); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_OR_IMM, tree->dreg + 2, tree->sreg1 + 2, tree->inst_ms_word); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_OR_IMM, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1), tree->inst_ls_word); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_OR_IMM, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1), tree->inst_ms_word); break; case OP_LXOR_IMM: - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_XOR_IMM, tree->dreg + 1, tree->sreg1 + 1, tree->inst_ls_word); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_XOR_IMM, tree->dreg + 2, tree->sreg1 + 2, tree->inst_ms_word); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_XOR_IMM, MONO_LVREG_LS (tree->dreg), MONO_LVREG_LS (tree->sreg1), tree->inst_ls_word); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_XOR_IMM, MONO_LVREG_MS (tree->dreg), MONO_LVREG_MS (tree->sreg1), tree->inst_ms_word); break; case OP_LSHR_UN_IMM: if (tree->inst_c1 == 32) { @@ -945,15 +943,15 @@ mono_decompose_long_opts (MonoCompile *cfg) */ /* FIXME: Move this to the strength reduction pass */ /* just move the upper half to the lower and zero the high word */ - MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 1, tree->sreg1 + 2); - MONO_EMIT_NEW_ICONST (cfg, tree->dreg + 2, 0); + MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_LS (tree->dreg), MONO_LVREG_MS (tree->sreg1)); + MONO_EMIT_NEW_ICONST (cfg, MONO_LVREG_MS (tree->dreg), 0); } break; case OP_LSHL_IMM: if (tree->inst_c1 == 32) { /* just move the lower half to the upper and zero the lower word */ - MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 2, tree->sreg1 + 1); - MONO_EMIT_NEW_ICONST (cfg, tree->dreg + 1, 0); + MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_MS (tree->dreg), MONO_LVREG_LS (tree->sreg1)); + MONO_EMIT_NEW_ICONST (cfg, MONO_LVREG_LS (tree->dreg), 0); } break; @@ -970,8 +968,8 @@ mono_decompose_long_opts (MonoCompile *cfg) /* Branchless version based on gcc code */ d1 = alloc_ireg (cfg); d2 = alloc_ireg (cfg); - MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, d1, tree->sreg1 + 1, tree->sreg2 + 1); - MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, d2, tree->sreg1 + 2, tree->sreg2 + 2); + MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, d1, MONO_LVREG_LS (tree->sreg1), MONO_LVREG_LS (tree->sreg2)); + MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, d2, MONO_LVREG_MS (tree->sreg1), MONO_LVREG_MS (tree->sreg2)); MONO_EMIT_NEW_BIALU (cfg, OP_IOR, d1, d1, d2); MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, d1, 0); MONO_EMIT_NEW_BRANCH_BLOCK2 (cfg, next->opcode == OP_LBEQ ? OP_IBEQ : OP_IBNE_UN, next->inst_true_bb, next->inst_false_bb); @@ -987,11 +985,11 @@ mono_decompose_long_opts (MonoCompile *cfg) case OP_LBLE_UN: case OP_LBLT_UN: /* Convert into three comparisons + branches */ - MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, tree->sreg1 + 2, tree->sreg2 + 2); + MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, MONO_LVREG_MS (tree->sreg1), MONO_LVREG_MS (tree->sreg2)); MONO_EMIT_NEW_BRANCH_BLOCK (cfg, lbr_decomp [next->opcode - OP_LBEQ][0], next->inst_true_bb); - MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, tree->sreg1 + 2, tree->sreg2 + 2); + MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, MONO_LVREG_MS (tree->sreg1), MONO_LVREG_MS (tree->sreg2)); MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBNE_UN, next->inst_false_bb); - MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, tree->sreg1 + 1, tree->sreg2 + 1); + MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, MONO_LVREG_LS (tree->sreg1), MONO_LVREG_LS (tree->sreg2)); MONO_EMIT_NEW_BRANCH_BLOCK2 (cfg, lbr_decomp [next->opcode - OP_LBEQ][1], next->inst_true_bb, next->inst_false_bb); NULLIFY_INS (next); break; @@ -1001,8 +999,8 @@ mono_decompose_long_opts (MonoCompile *cfg) /* Branchless version based on gcc code */ d1 = alloc_ireg (cfg); d2 = alloc_ireg (cfg); - MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, d1, tree->sreg1 + 1, tree->sreg2 + 1); - MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, d2, tree->sreg1 + 2, tree->sreg2 + 2); + MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, d1, MONO_LVREG_LS (tree->sreg1), MONO_LVREG_LS (tree->sreg2)); + MONO_EMIT_NEW_BIALU (cfg, OP_IXOR, d2, MONO_LVREG_MS (tree->sreg1), MONO_LVREG_MS (tree->sreg2)); MONO_EMIT_NEW_BIALU (cfg, OP_IOR, d1, d1, d2); MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, d1, 0); @@ -1020,11 +1018,11 @@ mono_decompose_long_opts (MonoCompile *cfg) NEW_BBLOCK (cfg, set_to_1); MONO_EMIT_NEW_ICONST (cfg, next->dreg, 0); - MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, tree->sreg1 + 2, tree->sreg2 + 2); + MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, MONO_LVREG_MS (tree->sreg1), MONO_LVREG_MS (tree->sreg2)); MONO_EMIT_NEW_BRANCH_BLOCK (cfg, lcset_decomp [next->opcode - OP_LCEQ][0], set_to_0); - MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, tree->sreg1 + 2, tree->sreg2 + 2); + MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, MONO_LVREG_MS (tree->sreg1), MONO_LVREG_MS (tree->sreg2)); MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBNE_UN, set_to_1); - MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, tree->sreg1 + 1, tree->sreg2 + 1); + MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, MONO_LVREG_LS (tree->sreg1), MONO_LVREG_LS (tree->sreg2)); MONO_EMIT_NEW_BRANCH_BLOCK (cfg, lcset_decomp [next->opcode - OP_LCEQ][1], set_to_0); MONO_START_BB (cfg, set_to_1); MONO_EMIT_NEW_ICONST (cfg, next->dreg, 1); @@ -1043,8 +1041,8 @@ mono_decompose_long_opts (MonoCompile *cfg) MonoInst *next = mono_inst_next (tree, FILTER_IL_SEQ_POINT); guint32 low_imm = tree->inst_ls_word; guint32 high_imm = tree->inst_ms_word; - int low_reg = tree->sreg1 + 1; - int high_reg = tree->sreg1 + 2; + int low_reg = MONO_LVREG_LS (tree->sreg1); + int high_reg = MONO_LVREG_MS (tree->sreg1); g_assert (next); @@ -1409,8 +1407,8 @@ mono_decompose_vtype_opts (MonoCompile *cfg) break; } call2->inst.dreg = alloc_lreg (cfg); - MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, dest->dreg, MINI_MS_WORD_OFFSET, call2->inst.dreg + 2); - MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, dest->dreg, MINI_LS_WORD_OFFSET, call2->inst.dreg + 1); + MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, dest->dreg, MINI_MS_WORD_OFFSET, MONO_LVREG_MS (call2->inst.dreg)); + MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, dest->dreg, MINI_LS_WORD_OFFSET, MONO_LVREG_LS (call2->inst.dreg)); #else MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI8_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg); #endif @@ -1544,7 +1542,7 @@ mono_decompose_array_access_opts (MonoCompile *cfg) if (managed_alloc) dest = mono_emit_method_call (cfg, managed_alloc, iargs, NULL); else - dest = mono_emit_jit_icall (cfg, mono_array_new_specific, iargs); + dest = mono_emit_jit_icall (cfg, ves_icall_array_new_specific, iargs); dest->dreg = ins->dreg; } break; @@ -1644,19 +1642,19 @@ mono_decompose_soft_float (MonoCompile *cfg) break; case OP_FGETLOW32: ins->opcode = OP_MOVE; - ins->sreg1 = ins->sreg1 + 1; + ins->sreg1 = MONO_LVREG_LS (ins->sreg1); break; case OP_FGETHIGH32: ins->opcode = OP_MOVE; - ins->sreg1 = ins->sreg1 + 2; + ins->sreg1 = MONO_LVREG_MS (ins->sreg1); break; case OP_SETFRET: { int reg = ins->sreg1; ins->opcode = OP_SETLRET; ins->dreg = -1; - ins->sreg1 = reg + 1; - ins->sreg2 = reg + 2; + ins->sreg1 = MONO_LVREG_LS (reg); + ins->sreg2 = MONO_LVREG_MS (reg); break; } case OP_LOADR8_MEMBASE: @@ -1881,4 +1879,89 @@ mono_decompose_soft_float (MonoCompile *cfg) #endif +void +mono_local_emulate_ops (MonoCompile *cfg) +{ + MonoBasicBlock *bb; + gboolean inlined_wrapper = FALSE; + + for (bb = cfg->bb_entry; bb; bb = bb->next_bb) { + MonoInst *ins; + + MONO_BB_FOR_EACH_INS (bb, ins) { + int op_noimm = mono_op_imm_to_op (ins->opcode); + MonoJitICallInfo *info; + + /* + * Emulation can't handle _IMM ops. If this is an imm opcode we need + * to check whether its non-imm counterpart is emulated and, if so, + * decompose it back to its non-imm counterpart. + */ + if (op_noimm != -1) + info = mono_find_jit_opcode_emulation (op_noimm); + else + info = mono_find_jit_opcode_emulation (ins->opcode); + + if (info) { + MonoInst **args; + MonoInst *call; + MonoBasicBlock *first_bb; + + /* Create dummy MonoInst's for the arguments */ + g_assert (!info->sig->hasthis); + g_assert (info->sig->param_count <= MONO_MAX_SRC_REGS); + + if (op_noimm != -1) + mono_decompose_op_imm (cfg, bb, ins); + + args = (MonoInst **)mono_mempool_alloc0 (cfg->mempool, sizeof (MonoInst*) * info->sig->param_count); + if (info->sig->param_count > 0) { + int sregs [MONO_MAX_SRC_REGS]; + int num_sregs, i; + num_sregs = mono_inst_get_src_registers (ins, sregs); + g_assert (num_sregs == info->sig->param_count); + for (i = 0; i < num_sregs; ++i) { + MONO_INST_NEW (cfg, args [i], OP_ARG); + args [i]->dreg = sregs [i]; + } + } + + /* We emit the call on a separate dummy basic block */ + cfg->cbb = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoBasicBlock)); + first_bb = cfg->cbb; + + call = mono_emit_jit_icall_by_info (cfg, info, args); + call->dreg = ins->dreg; + + /* Replace ins with the emitted code and do the necessary bb linking */ + if (cfg->cbb->code || (cfg->cbb != first_bb)) { + MonoInst *saved_prev = ins->prev; + + mono_replace_ins (cfg, bb, ins, &ins->prev, first_bb, cfg->cbb); + first_bb->code = first_bb->last_ins = NULL; + first_bb->in_count = first_bb->out_count = 0; + cfg->cbb = first_bb; + + /* ins is hanging, continue scanning the emitted code */ + ins = saved_prev; + } else { + g_error ("Failed to emit emulation code"); + } + inlined_wrapper = TRUE; + } + } + } + + /* + * Avoid rerunning these passes by emitting directly the exception checkpoint + * at IR level, instead of inlining the icall wrapper. FIXME + */ + if (inlined_wrapper) { + if (!COMPILE_LLVM (cfg)) + mono_decompose_long_opts (cfg); + if (cfg->opt & (MONO_OPT_CONSPROP | MONO_OPT_COPYPROP)) + mono_local_cprop (cfg); + } +} + #endif /* DISABLE_JIT */