gboolean emulate = FALSE;
/* FIXME: Instead of = NOP, don't emit the original ins at all */
-
-#ifdef MONO_ARCH_HAVE_DECOMPOSE_OPTS
mono_arch_decompose_opts (cfg, ins);
-#endif
/*
* The code below assumes that we are called immediately after emitting
cfg->exception_message = g_strdup_printf ("float conv.ovf.un opcodes not supported.");
break;
-#if defined(MONO_ARCH_EMULATE_DIV) && defined(MONO_ARCH_HAVE_OPCODE_NEEDS_EMULATION)
+#if defined(MONO_ARCH_EMULATE_DIV)
case OP_IDIV:
case OP_IREM:
case OP_IDIV_UN:
MONO_EMIT_NEW_UNALU (cfg, OP_ICEQ, 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, "DivideByZeroException");
+ MONO_EMIT_NEW_COND_EXC (cfg, IEQ, "OverflowException");
}
#endif
MONO_EMIT_NEW_BIALU (cfg, ins->opcode, ins->dreg, ins->sreg1, ins->sreg2);
- ins->opcode = OP_NOP;
+ NULLIFY_INS (ins);
} else {
emulate = TRUE;
}
ins->opcode = OP_ICONST;
MONO_INST_NULLIFY_SREGS (ins);
ins->inst_c0 = 0;
- } else if ((ins->inst_imm > 0) && (ins->inst_imm < (1L << 32)) && (power != -1)) {
+#if __s390__
+ }
+#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;
if (power > 1) {
intermediate_reg = compensator_reg;
- MONO_EMIT_NEW_BIALU_IMM (cfg, is_long ? OP_LSHR_IMM : OP_SHR_IMM, intermediate_reg, ins->sreg1, is_long ? 63 : 31);
+ 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;
}
- MONO_EMIT_NEW_BIALU_IMM (cfg, is_long ? OP_LSHR_UN_IMM : OP_SHR_UN_IMM, compensator_reg, intermediate_reg, (is_long ? 64 : 32) - power);
+ 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);
NULLIFY_INS (ins);
}
+#endif
break;
}
}
}
- call = mono_emit_native_call (cfg, mono_icall_get_wrapper (info), info->sig, args);
+ call = mono_emit_jit_icall_by_info (cfg, info, args);
call->dreg = ins->dreg;
NULLIFY_INS (ins);
first_bb = cfg->cbb;
for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
- MonoInst *tree = bb->code;
+ MonoInst *tree = mono_bb_first_inst(bb, FILTER_IL_SEQ_POINT);
MonoInst *prev = NULL;
/*
mono_print_bb (bb, "BEFORE LOWER_LONG_OPTS");
*/
- tree = bb->code;
cfg->cbb->code = cfg->cbb->last_ins = NULL;
while (tree) {
-
-#ifdef MONO_ARCH_HAVE_DECOMPOSE_LONG_OPTS
mono_arch_decompose_long_opts (cfg, tree);
-#endif
switch (tree->opcode) {
case OP_I8CONST:
break;
case OP_LCOMPARE: {
- MonoInst *next = tree->next;
+ MonoInst *next = mono_inst_next (tree, FILTER_IL_SEQ_POINT);
g_assert (next);
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);
- next->opcode = OP_NOP;
+ NULLIFY_INS (next);
break;
}
case OP_LBGE:
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_BRANCH_BLOCK2 (cfg, lbr_decomp [next->opcode - OP_LBEQ][1], next->inst_true_bb, next->inst_false_bb);
- next->opcode = OP_NOP;
+ NULLIFY_INS (next);
break;
case OP_LCEQ: {
int d1, d2;
MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, d1, 0);
MONO_EMIT_NEW_UNALU (cfg, OP_ICEQ, next->dreg, -1);
- next->opcode = OP_NOP;
+ NULLIFY_INS (next);
break;
}
case OP_LCLT:
MONO_START_BB (cfg, set_to_1);
MONO_EMIT_NEW_ICONST (cfg, next->dreg, 1);
MONO_START_BB (cfg, set_to_0);
- next->opcode = OP_NOP;
+ NULLIFY_INS (next);
break;
}
default:
/* Not yet used, since lcompare is decomposed before local cprop */
case OP_LCOMPARE_IMM: {
- MonoInst *next = tree->next;
+ 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;
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);
- next->opcode = OP_NOP;
+ NULLIFY_INS (next);
break;
}
MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBNE_UN, next->inst_false_bb);
MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, low_reg, low_imm);
MONO_EMIT_NEW_BRANCH_BLOCK2 (cfg, lbr_decomp [next->opcode - OP_LBEQ][1], next->inst_true_bb, next->inst_false_bb);
- next->opcode = OP_NOP;
+ NULLIFY_INS (next);
break;
case OP_LCEQ: {
int d1, d2;
MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, d1, 0);
MONO_EMIT_NEW_UNALU (cfg, OP_ICEQ, next->dreg, -1);
- next->opcode = OP_NOP;
+ NULLIFY_INS (next);
break;
}
case OP_LCLT:
MONO_START_BB (cfg, set_to_1);
MONO_EMIT_NEW_ICONST (cfg, next->dreg, 1);
MONO_START_BB (cfg, set_to_0);
- next->opcode = OP_NOP;
+ NULLIFY_INS (next);
break;
}
default:
/* Process the newly added ops again since they can be long ops too */
if (prev)
- tree = prev->next;
+ tree = mono_inst_next (prev, FILTER_IL_SEQ_POINT);
else
- tree = bb->code;
+ tree = mono_bb_first_inst (bb, FILTER_IL_SEQ_POINT);
first_bb->code = first_bb->last_ins = NULL;
first_bb->in_count = first_bb->out_count = 0;
}
else {
prev = tree;
- tree = tree->next;
+ tree = mono_inst_next (tree, FILTER_IL_SEQ_POINT);
}
}
}
if (call->vret_in_reg) {
MonoCallInst *call2;
- /* Replace the vcall with an integer call */
+ /* Replace the vcall with a scalar call */
MONO_INST_NEW_CALL (cfg, call2, OP_NOP);
memcpy (call2, call, sizeof (MonoCallInst));
switch (ins->opcode) {
case OP_VCALL:
- call2->inst.opcode = OP_CALL;
+ call2->inst.opcode = call->vret_in_reg_fp ? OP_FCALL : OP_CALL;
break;
case OP_VCALL_REG:
- call2->inst.opcode = OP_CALL_REG;
+ call2->inst.opcode = call->vret_in_reg_fp ? OP_FCALL_REG : OP_CALL_REG;
break;
case OP_VCALL_MEMBASE:
- call2->inst.opcode = OP_CALL_MEMBASE;
+ call2->inst.opcode = call->vret_in_reg_fp ? OP_FCALL_MEMBASE : OP_CALL_MEMBASE;
break;
}
call2->inst.dreg = alloc_preg (cfg);
break;
case 3:
case 4:
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
+ if (call->vret_in_reg_fp)
+ MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER4_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
+ else
+ MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
break;
case 5:
case 6:
case 7:
case 8:
+ if (call->vret_in_reg_fp) {
+ MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
+ break;
+ }
#if SIZEOF_REGISTER == 4
/*
FIXME Other ABIs might return in different regs than the ones used for LCALL.