*
* (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"
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:
}
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;
}
if (emulate) {
- MonoJitICallInfo *info = NULL;
-
#if SIZEOF_REGISTER == 8
if (decompose_long_opcode (cfg, ins, &repl))
emulate = FALSE;
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) {
* 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.
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: {
* 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;
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 () */
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;
+#ifdef TARGET_POWERPC
+/* FIXME This is normally handled in cprop. Proper fix or remove if no longer needed. */
case OP_LSHR_UN_IMM:
if (tree->inst_c1 == 32) {
* later apply the speedup to the left shift as well
* See BUG# 57957.
*/
- /* 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);
- }
- 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_LS (tree->dreg), MONO_LVREG_MS (tree->sreg1));
+ MONO_EMIT_NEW_ICONST (cfg, MONO_LVREG_MS (tree->dreg), 0);
}
break;
-
+#endif
case OP_LCOMPARE: {
MonoInst *next = mono_inst_next (tree, FILTER_IL_SEQ_POINT);
/* 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);
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;
/* 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);
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);
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);
break;
}
case OP_VZERO:
- if (COMPILE_LLVM (cfg))
+ if (COMPILE_LLVM (cfg) && !mini_is_gsharedvt_klass (ins->klass))
break;
g_assert (ins->klass);
case OP_STOREV_MEMBASE: {
src_var = get_vreg_to_inst (cfg, ins->sreg1);
+ if (COMPILE_LLVM (cfg) && !mini_is_gsharedvt_klass (ins->klass) && !cfg->gen_write_barriers)
+ break;
+
if (!src_var) {
g_assert (ins->klass);
src_var = mono_compile_create_var_for_vreg (cfg, &ins->klass->byval_arg, OP_LOCAL, ins->sreg1);
case OP_OUTARG_VTRETADDR: {
MonoCallInst *call = (MonoCallInst*)ins->inst_p1;
- if (COMPILE_LLVM (cfg))
- break;
-
src_var = get_vreg_to_inst (cfg, call->inst.dreg);
if (!src_var)
src_var = mono_compile_create_var_for_vreg (cfg, call->signature->ret, OP_LOCAL, call->inst.dreg);
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
MONO_INST_NEW (cfg, iargs [2], OP_MOVE);
iargs [2]->dreg = ins->sreg1;
- dest = mono_emit_jit_icall (cfg, mono_array_new, iargs);
+ dest = mono_emit_jit_icall (cfg, ves_icall_array_new, iargs);
dest->dreg = ins->dreg;
} else {
MonoClass *array_class = mono_array_class_get (ins->inst_newa_class, 1);
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;
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:
#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, bb->real_offset, 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 */