}
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 = 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;
case OP_LSHR_UN_IMM:
if (tree->inst_c1 == 32) {
*/
/* 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;
/* 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);
* Create a dummy bblock and emit code into it so we can use the normal
* code generation macros.
*/
- cfg->cbb = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoBasicBlock));
+ cfg->cbb = (MonoBasicBlock *)mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoBasicBlock));
first_bb = cfg->cbb;
+ /* For LLVM, decompose only the OP_STOREV_MEMBASE opcodes, which need write barriers and the gsharedvt opcodes */
+
for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
MonoInst *ins;
MonoInst *prev = NULL;
for (ins = bb->code; ins; ins = ins->next) {
switch (ins->opcode) {
case OP_VMOVE: {
+ g_assert (ins->klass);
+ if (COMPILE_LLVM (cfg) && !mini_is_gsharedvt_klass (ins->klass))
+ break;
src_var = get_vreg_to_inst (cfg, ins->sreg1);
dest_var = get_vreg_to_inst (cfg, ins->dreg);
- g_assert (ins->klass);
-
if (!src_var)
src_var = mono_compile_create_var_for_vreg (cfg, &ins->klass->byval_arg, OP_LOCAL, ins->dreg);
break;
}
case OP_VZERO:
+ if (COMPILE_LLVM (cfg) && !mini_is_gsharedvt_klass (ins->klass))
+ break;
+
g_assert (ins->klass);
EMIT_NEW_VARLOADA_VREG (cfg, dest, ins->dreg, &ins->klass->byval_arg);
}
break;
case OP_DUMMY_VZERO:
+ if (COMPILE_LLVM (cfg))
+ break;
+
NULLIFY_INS (ins);
break;
case OP_STOREV_MEMBASE: {
}
case OP_LOADV_MEMBASE: {
g_assert (ins->klass);
+ if (COMPILE_LLVM (cfg) && !mini_is_gsharedvt_klass (ins->klass))
+ break;
dest_var = get_vreg_to_inst (cfg, ins->dreg);
// FIXME-VT:
break;
}
case OP_OUTARG_VT: {
+ if (COMPILE_LLVM (cfg))
+ break;
+
g_assert (ins->klass);
src_var = get_vreg_to_inst (cfg, ins->sreg1);
MonoCallInst *call = (MonoCallInst*)ins;
int size;
+ if (COMPILE_LLVM (cfg))
+ break;
+
if (call->vret_in_reg) {
MonoCallInst *call2;
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
}
}
-void
-mono_decompose_vtype_opts_llvm (MonoCompile *cfg)
-{
- MonoBasicBlock *bb, *first_bb;
-
- /* Decompose only the OP_STOREV_MEMBASE opcodes, which need write barriers */
-
- cfg->cbb = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoBasicBlock));
- first_bb = cfg->cbb;
-
- for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
- MonoInst *ins;
- MonoInst *prev = NULL;
- MonoInst *src_var, *src, *dest;
- gboolean restart;
- int dreg;
-
- if (cfg->verbose_level > 2) mono_print_bb (bb, "BEFORE LOWER-VTYPE-OPTS(LLVM) ");
-
- cfg->cbb->code = cfg->cbb->last_ins = NULL;
- restart = TRUE;
-
- while (restart) {
- restart = FALSE;
-
- for (ins = bb->code; ins; ins = ins->next) {
- switch (ins->opcode) {
- case OP_STOREV_MEMBASE: {
- src_var = get_vreg_to_inst (cfg, ins->sreg1);
-
- if (!src_var) {
- g_assert (ins->klass);
- src_var = mono_compile_create_var_for_vreg (cfg, &ins->klass->byval_arg, OP_LOCAL, ins->sreg1);
- }
-
- EMIT_NEW_VARLOADA_VREG ((cfg), (src), ins->sreg1, &ins->klass->byval_arg);
-
- dreg = alloc_preg (cfg);
- EMIT_NEW_BIALU_IMM (cfg, dest, OP_ADD_IMM, dreg, ins->inst_destbasereg, ins->inst_offset);
- mini_emit_stobj (cfg, dest, src, src_var->klass, src_var->backend.is_pinvoke);
- break;
- }
- default:
- break;
- }
-
- g_assert (cfg->cbb == first_bb);
-
- if (cfg->cbb->code || (cfg->cbb != first_bb)) {
- /* Replace the original instruction with the new code sequence */
-
- mono_replace_ins (cfg, bb, 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;
- }
- else
- prev = ins;
- }
- }
-
- if (cfg->verbose_level > 2) mono_print_bb (bb, "AFTER LOWER-VTYPE-OPTS(LLVM) ");
- }
-}
-
inline static MonoInst *
mono_get_domainvar (MonoCompile *cfg)
{
* Create a dummy bblock and emit code into it so we can use the normal
* code generation macros.
*/
- cfg->cbb = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoBasicBlock));
+ cfg->cbb = (MonoBasicBlock *)mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoBasicBlock));
first_bb = cfg->cbb;
for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
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, 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 */