}
lreg: OP_LADD (lreg, i8con) {
+ int tmp1 = mono_regstate_next_int (s->rs);
+
MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, state->left->reg1, state->right->tree->inst_ls_word);
- MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, mips_temp, state->reg1, state->left->reg1);
+ MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, tmp1, state->reg1, state->left->reg1);
MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg2, state->left->reg2, state->right->tree->inst_ms_word);
- MONO_EMIT_BIALU (s, tree, CEE_ADD, state->reg2, mips_temp, state->reg2);
+ MONO_EMIT_BIALU (s, tree, CEE_ADD, state->reg2, tmp1, state->reg2);
+}
+
+lreg: OP_LADD (lreg, lreg) {
+ int tmp1 = mono_regstate_next_int (s->rs);
+
+ MONO_EMIT_NEW_BIALU (s, CEE_ADD, state->reg1, state->left->reg1, state->right->reg1);
+ MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, tmp1, state->reg1, state->left->reg1);
+ MONO_EMIT_NEW_BIALU (s, CEE_ADD, state->reg2, state->left->reg2, state->right->reg2);
+ MONO_EMIT_BIALU (s, tree, CEE_ADD, state->reg2, tmp1, state->reg2);
+}
+
+lreg: OP_LADD_OVF (lreg, lreg) {
+ int tmp1 = mono_regstate_next_int (s->rs);
+ int tmp2 = mono_regstate_next_int (s->rs);
+ int tmp3 = mono_regstate_next_int (s->rs);
+ int tmp4 = mono_regstate_next_int (s->rs);
+ int tmp5 = mono_regstate_next_int (s->rs);
+
+ MONO_EMIT_NEW_BIALU (s, CEE_ADD, state->reg1, state->left->reg1, state->right->reg1);
+
+ /* tmp1 holds the carry from the low 32-bit to the high 32-bits */
+
+ MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, tmp5, state->reg1, state->left->reg1);
+
+ /* add the high 32-bits, and add in the carry from the low 32-bits */
+
+ MONO_EMIT_NEW_BIALU (s, CEE_ADD, state->reg2, state->left->reg2, state->right->reg2);
+ MONO_EMIT_NEW_BIALU (s, CEE_ADD, state->reg2, tmp5, state->reg2);
+
+ /* Overflow happens if
+ * neg + neg = pos or
+ * pos + pos = neg
+ * XOR of the high bits returns 0 if the signs match
+ * XOR of that with the high bit of the result return 1 if overflow.
+ */
+
+ /* tmp1 = 0 if the signs of the two inputs match, 1 otherwise */
+ MONO_EMIT_NEW_BIALU (s, CEE_XOR, tmp1, state->left->reg2, state->right->reg2);
+
+ /* set tmp2 = 0 if bit31 of results matches is different than the operands */
+ MONO_EMIT_NEW_BIALU (s, CEE_XOR, tmp2, state->reg2, state->right->reg2);
+ MONO_EMIT_NEW_UNALU (s, CEE_NOT, tmp2, tmp2);
+
+ /* OR(tmp1, tmp2) = 0 if both conditions are true */
+ MONO_EMIT_NEW_BIALU (s, CEE_OR, tmp3, tmp2, tmp1);
+
+ MONO_EMIT_NEW_BIALU_IMM (s, OP_SHR_IMM, tmp4, tmp3, 31);
+
+ /* Now, if (tmp4 == 0) then overflow */
+ MONO_EMIT_NEW_COMPARE_EXC (s, EQ, tmp4, mips_zero, "OverflowException");
}
-lreg: OP_LADD (lreg, lreg),
-lreg: OP_LADD_OVF (lreg, lreg),
lreg: OP_LADD_OVF_UN (lreg, lreg) {
+ int tmp1 = mono_regstate_next_int (s->rs);
+ int tmp2 = mono_regstate_next_int (s->rs);
+
MONO_EMIT_NEW_BIALU (s, CEE_ADD, state->reg1, state->left->reg1, state->right->reg1);
- MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, mips_at, state->reg1, state->left->reg1);
- /* MONO_EMIT_NEW_COND_EXC (s, OV, "OverflowException"); */
+ MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, tmp1, state->reg1, state->left->reg1);
MONO_EMIT_NEW_BIALU (s, CEE_ADD, state->reg2, state->left->reg2, state->right->reg2);
- MONO_EMIT_BIALU (s, tree, CEE_ADD, state->reg2, mips_at, state->reg2);
+ MONO_EMIT_NEW_BIALU (s, CEE_ADD, state->reg2, tmp1, state->reg2);
+ MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, tmp2, state->reg2, state->left->reg2);
+ MONO_EMIT_NEW_COMPARE_EXC (s, NE_UN, tmp2, mips_zero, "OverflowException");
}
lreg: OP_LSUB (lreg, i8con) {
+ int tmp1 = mono_regstate_next_int (s->rs);
+
MONO_EMIT_NEW_BIALU_IMM (s, OP_SUB_IMM, state->reg1, state->left->reg1, state->right->tree->inst_ls_word);
- MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, mips_temp, state->left->reg1, state->reg1);
+ MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, tmp1, state->left->reg1, state->reg1);
MONO_EMIT_NEW_BIALU_IMM (s, OP_SUB_IMM, state->reg2, state->left->reg2, state->right->tree->inst_ms_word);
- MONO_EMIT_BIALU (s, tree, CEE_SUB, state->reg2, state->reg2, mips_temp);
+ MONO_EMIT_BIALU (s, tree, CEE_SUB, state->reg2, state->reg2, tmp1);
+}
+
+lreg: OP_LSUB (lreg, lreg) {
+ int tmp1 = mono_regstate_next_int (s->rs);
+
+ MONO_EMIT_NEW_BIALU (s, CEE_SUB, state->reg1, state->left->reg1, state->right->reg1);
+ MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, tmp1, state->left->reg1, state->reg1);
+ MONO_EMIT_NEW_BIALU (s, CEE_SUB, state->reg2, state->left->reg2, state->right->reg2);
+ MONO_EMIT_BIALU (s, tree, CEE_SUB, state->reg2, state->reg2, tmp1);
+}
+
+lreg: OP_LSUB_OVF (lreg, lreg) {
+ int tmp1 = mono_regstate_next_int (s->rs);
+ int tmp2 = mono_regstate_next_int (s->rs);
+ int tmp3 = mono_regstate_next_int (s->rs);
+ int tmp4 = mono_regstate_next_int (s->rs);
+ int tmp5 = mono_regstate_next_int (s->rs);
+
+ MONO_EMIT_NEW_BIALU (s, CEE_SUB, state->reg1, state->left->reg1, state->right->reg1);
+ MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, tmp5, state->left->reg1, state->reg1);
+ MONO_EMIT_NEW_BIALU (s, CEE_SUB, state->reg2, state->left->reg2, state->right->reg2);
+ MONO_EMIT_NEW_BIALU (s, CEE_SUB, state->reg2, state->reg2, tmp5);
+
+ /* Overflow happens if
+ * neg - pos = pos or
+ * pos - neg = neg
+ * XOR of bit31 of the lhs & rhs = 1 if the signs are different
+ *
+ * tmp1 = (lhs ^ rhs)
+ * tmp2 = (lhs ^ result)
+ * if ((tmp1 < 0) & (tmp2 < 0)) then overflow
+ */
+
+ MONO_EMIT_NEW_BIALU (s, CEE_XOR, tmp1, state->left->reg2, state->right->reg2);
+ MONO_EMIT_NEW_BIALU (s, CEE_XOR, tmp2, state->left->reg2, state->reg2);
+ MONO_EMIT_NEW_BIALU (s, CEE_AND, tmp3, tmp2, tmp1);
+ MONO_EMIT_NEW_BIALU_IMM (s, OP_SHR_IMM, tmp4, tmp3, 31);
+
+ /* Now, if (tmp4 == 1) then overflow */
+ MONO_EMIT_NEW_COMPARE_EXC (s, NE_UN, tmp4, mips_zero, "OverflowException");
}
-lreg: OP_LSUB (lreg, lreg),
-lreg: OP_LSUB_OVF (lreg, lreg),
lreg: OP_LSUB_OVF_UN (lreg, lreg) {
+ int tmp1 = mono_regstate_next_int (s->rs);
+ int tmp2 = mono_regstate_next_int (s->rs);
+
MONO_EMIT_NEW_BIALU (s, CEE_SUB, state->reg1, state->left->reg1, state->right->reg1);
- MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, mips_at, state->left->reg1, state->reg1);
- /* MONO_EMIT_NEW_COND_EXC (s, OV, "OverflowException"); */
+ MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, tmp1, state->left->reg1, state->reg1);
MONO_EMIT_NEW_BIALU (s, CEE_SUB, state->reg2, state->left->reg2, state->right->reg2);
- MONO_EMIT_BIALU (s, tree, CEE_SUB, state->reg2, state->reg2, mips_at);
+ MONO_EMIT_NEW_BIALU (s, CEE_SUB, state->reg2, state->reg2, tmp1);
+
+ MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, tmp2, state->left->reg2, state->reg2);
+ MONO_EMIT_NEW_COMPARE_EXC (s, NE_UN, tmp2, mips_zero, "OverflowException");
}
lreg: OP_LAND (lreg, lreg) {
MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, mips_at, rreg1, lreg1);
MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, mips_at, mips_zero, tree->inst_false_bb);
- MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BR, tree->inst_true_bb);
+ MONO_EMIT_NEW_BRANCH_BLOCK (s, OP_BR, tree->inst_true_bb);
}
stmt: CEE_BLE (OP_LCOMPARE (lreg, i8con)) {
MONO_EMIT_NEW_ICONST (s, rreg1, state->left->right->tree->inst_ls_word);
MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, mips_at, rreg1, lreg1);
MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, mips_at, mips_zero, tree->inst_false_bb);
- MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BR, tree->inst_true_bb);
+ MONO_EMIT_NEW_BRANCH_BLOCK (s, OP_BR, tree->inst_true_bb);
}
stmt: CEE_BLE_UN (OP_LCOMPARE (lreg, lreg)) {
MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, mips_at, rreg1, lreg1);
MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, mips_at, mips_zero, tree->inst_false_bb);
- MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BR, tree->inst_true_bb);
+ MONO_EMIT_NEW_BRANCH_BLOCK (s, OP_BR, tree->inst_true_bb);
}
stmt: CEE_BLE_UN (OP_LCOMPARE (lreg, i8con)) {
MONO_EMIT_NEW_ICONST (s, rreg1, state->left->right->tree->inst_ls_word);
MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, mips_at, rreg1, lreg1);
MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, mips_at, mips_zero, tree->inst_false_bb);
- MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BR, tree->inst_true_bb);
+ MONO_EMIT_NEW_BRANCH_BLOCK (s, OP_BR, tree->inst_true_bb);
}
stmt: CEE_BGE (OP_LCOMPARE (lreg, lreg)) {
/* (rreg2 == lreg2), so if (lreg1 < rreg1) -> false */
MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLT, mips_at, lreg1, rreg1);
MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, mips_at, mips_zero, tree->inst_false_bb);
- MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BR, tree->inst_true_bb);
+ MONO_EMIT_NEW_BRANCH_BLOCK (s, OP_BR, tree->inst_true_bb);
}
stmt: CEE_BGE (OP_LCOMPARE (lreg, i8con)) {
/* (rreg2 == lreg2), so if (lreg1 < rreg1) -> false */
MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLT, mips_at, lreg1, rreg1);
MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, mips_at, mips_zero, tree->inst_false_bb);
- MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BR, tree->inst_true_bb);
+ MONO_EMIT_NEW_BRANCH_BLOCK (s, OP_BR, tree->inst_true_bb);
}
stmt: CEE_BGE_UN (OP_LCOMPARE (lreg, lreg)) {
/* (rreg2 == lreg2), so if (lreg1 < rreg1) -> false */
MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLT, mips_at, lreg1, rreg1);
MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, mips_at, mips_zero, tree->inst_false_bb);
- MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BR, tree->inst_true_bb);
+ MONO_EMIT_NEW_BRANCH_BLOCK (s, OP_BR, tree->inst_true_bb);
}
stmt: CEE_BGE_UN (OP_LCOMPARE (lreg, i8con)) {
/* (rreg2 == lreg2), so if (lreg1 < rreg1) -> false */
MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLT, mips_at, lreg1, rreg1);
MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, mips_at, mips_zero, tree->inst_false_bb);
- MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BR, tree->inst_true_bb);
+ MONO_EMIT_NEW_BRANCH_BLOCK (s, OP_BR, tree->inst_true_bb);
}
stmt: CEE_BLT (OP_LCOMPARE (lreg, lreg)) {
/* (lreg2 == rreg2), if (lreg1 < rreg1) -> true */
MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, mips_at, lreg1, rreg1);
MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, mips_at, mips_zero, tree->inst_true_bb);
- MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BR, tree->inst_false_bb);
+ MONO_EMIT_NEW_BRANCH_BLOCK (s, OP_BR, tree->inst_false_bb);
}
stmt: CEE_BLT (OP_LCOMPARE (lreg, i8con)) {
/* (lreg2 == rreg2), if (lreg1 < rreg1) -> true */
MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, mips_at, lreg1, rreg1);
MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, mips_at, mips_zero, tree->inst_true_bb);
- MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BR, tree->inst_false_bb);
+ MONO_EMIT_NEW_BRANCH_BLOCK (s, OP_BR, tree->inst_false_bb);
}
stmt: CEE_BLT_UN (OP_LCOMPARE (lreg, lreg)) {
/* (lreg2 == rreg2), if (lreg1 < rreg1) -> true */
MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, mips_at, lreg1, rreg1);
MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, mips_at, mips_zero, tree->inst_true_bb);
- MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BR, tree->inst_false_bb);
+ MONO_EMIT_NEW_BRANCH_BLOCK (s, OP_BR, tree->inst_false_bb);
}
stmt: CEE_BLT_UN (OP_LCOMPARE (lreg, i8con)) {
/* (lreg2 == rreg2), if (lreg1 < rreg1) -> true */
MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, mips_at, lreg1, rreg1);
MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, mips_at, mips_zero, tree->inst_true_bb);
- MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BR, tree->inst_false_bb);
+ MONO_EMIT_NEW_BRANCH_BLOCK (s, OP_BR, tree->inst_false_bb);
}
stmt: CEE_BGT (OP_LCOMPARE (lreg, lreg)) {
/* (rreg2 == lreg2), so if (lreg1 > rreg1) -> true */
MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, mips_at, rreg1, lreg1);
MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, mips_at, mips_zero, tree->inst_true_bb);
- MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BR, tree->inst_false_bb);
+ MONO_EMIT_NEW_BRANCH_BLOCK (s, OP_BR, tree->inst_false_bb);
}
stmt: CEE_BGT (OP_LCOMPARE (lreg, i8con)) {
/* (rreg2 == lreg2), so if (lreg1 > rreg1) -> true */
MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, mips_at, rreg1, lreg1);
MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, mips_at, mips_zero, tree->inst_true_bb);
- MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BR, tree->inst_false_bb);
+ MONO_EMIT_NEW_BRANCH_BLOCK (s, OP_BR, tree->inst_false_bb);
}
stmt: CEE_BGT_UN (OP_LCOMPARE (lreg, lreg)) {
/* (rreg2 == lreg2), so if (lreg1 > rreg1) -> true */
MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, mips_at, rreg1, lreg1);
MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, mips_at, mips_zero, tree->inst_true_bb);
- MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BR, tree->inst_false_bb);
+ MONO_EMIT_NEW_BRANCH_BLOCK (s, OP_BR, tree->inst_false_bb);
}
stmt: CEE_BGT_UN (OP_LCOMPARE (lreg, i8con)) {
/* (rreg2 == lreg2), so if (lreg1 > rreg1) -> true */
MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, mips_at, rreg1, lreg1);
MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, mips_at, mips_zero, tree->inst_true_bb);
- MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BR, tree->inst_false_bb);
+ MONO_EMIT_NEW_BRANCH_BLOCK (s, OP_BR, tree->inst_false_bb);
}
lreg: CEE_CONV_I8 (OP_ICONST) {
}
lreg: CEE_CONV_OVF_U8 (reg) {
- MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 0);
- MONO_EMIT_NEW_COND_EXC (s, LT, "OverflowException");
+ MONO_EMIT_NEW_COMPARE_IMM_EXC (s, LT, state->left->reg1, 0, "OverflowException");
MONO_EMIT_NEW_ICONST (s, state->reg2, 0);
MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
}
}
reg: OP_LCONV_TO_OVF_I1_UN (lreg) {
- MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, 0);
- MONO_EMIT_NEW_COND_EXC (s, NE_UN, "OverflowException");
+ MONO_EMIT_NEW_COMPARE_IMM_EXC (s, NE_UN, state->left->reg2, 0, "OverflowException");
- MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 127);
- MONO_EMIT_NEW_COND_EXC (s, GT, "OverflowException");
- MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, -128);
- MONO_EMIT_NEW_COND_EXC (s, LT, "OverflowException");
+ MONO_EMIT_NEW_COMPARE_IMM_EXC (s, GT, state->left->reg1, 127, "OverflowException");
+ MONO_EMIT_NEW_COMPARE_IMM_EXC (s, LT, state->left->reg1, -128, "OverflowException");
MONO_EMIT_UNALU (s, tree, CEE_CONV_I1, state->reg1, state->left->reg1);
}
MONO_NEW_LABEL (s, is_negative);
MONO_NEW_LABEL (s, end_label);
- MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, 0);
- MONO_EMIT_NEW_COND_EXC (s, GT, "OverflowException");
- MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, -1);
- MONO_EMIT_NEW_COND_EXC (s, LT, "OverflowException");
+ MONO_EMIT_NEW_COMPARE_IMM_EXC (s, GT, state->left->reg2, 0, "OverflowException");
+ MONO_EMIT_NEW_COMPARE_IMM_EXC (s, LT, state->left->reg2, -1, "OverflowException");
MONO_EMIT_NEW_COMPARE_BRANCH_LABEL (s, CEE_BLT, state->left->reg2, mips_zero, is_negative);
/* Positive */
- MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 127);
- MONO_EMIT_NEW_COND_EXC (s, GT_UN, "OverflowException");
- MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BR, end_label);
+ MONO_EMIT_NEW_COMPARE_IMM_EXC (s, GT_UN, state->left->reg1, 127, "OverflowException");
+ MONO_EMIT_NEW_BRANCH_LABEL (s, OP_BR, end_label);
/* Negative */
mono_bblock_add_inst (s->cbb, is_negative);
- MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, -128);
- MONO_EMIT_NEW_COND_EXC (s, LT_UN, "OverflowException");
+ MONO_EMIT_NEW_COMPARE_IMM_EXC (s, LT_UN, state->left->reg1, -128, "OverflowException");
mono_bblock_add_inst (s->cbb, end_label);
MONO_EMIT_UNALU (s, tree, CEE_CONV_I1, state->reg1, state->left->reg1);
reg: OP_LCONV_TO_OVF_U1_UN (lreg),
reg: OP_LCONV_TO_OVF_U1 (lreg) {
- MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, 0);
- MONO_EMIT_NEW_COND_EXC (s, NE_UN, "OverflowException");
+ MONO_EMIT_NEW_COMPARE_IMM_EXC (s, NE_UN, state->left->reg2, 0, "OverflowException");
/* probe value to be within 0 to 255 */
- MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 255);
- MONO_EMIT_NEW_COND_EXC (s, GT_UN, "OverflowException");
+ MONO_EMIT_NEW_COMPARE_IMM_EXC (s, GT_UN, state->left->reg1, 255, "OverflowException");
MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->reg1, state->left->reg1, 0xff);
}
MONO_NEW_LABEL (s, is_negative);
MONO_NEW_LABEL (s, end_label);
- MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, 0);
- MONO_EMIT_NEW_COND_EXC (s, GT, "OverflowException");
- MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, -1);
- MONO_EMIT_NEW_COND_EXC (s, LT, "OverflowException");
+ MONO_EMIT_NEW_COMPARE_IMM_EXC (s, GT, state->left->reg2, 0, "OverflowException");
+ MONO_EMIT_NEW_COMPARE_IMM_EXC (s, LT, state->left->reg2, -1, "OverflowException");
MONO_EMIT_NEW_COMPARE_BRANCH_LABEL (s, CEE_BLT, state->left->reg2, mips_zero, is_negative);
/* Positive */
- MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 32767);
- MONO_EMIT_NEW_COND_EXC (s, GT_UN, "OverflowException");
- MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BR, end_label);
+ MONO_EMIT_NEW_COMPARE_IMM_EXC (s, GT_UN, state->left->reg1, 32767, "OverflowException");
+ MONO_EMIT_NEW_BRANCH_LABEL (s, OP_BR, end_label);
/* Negative */
mono_bblock_add_inst (s->cbb, is_negative);
- MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, -32768);
- MONO_EMIT_NEW_COND_EXC (s, LT_UN, "OverflowException");
+ MONO_EMIT_NEW_COMPARE_IMM_EXC (s, LT_UN, state->left->reg1, -32768, "OverflowException");
mono_bblock_add_inst (s->cbb, end_label);
MONO_EMIT_UNALU (s, tree, CEE_CONV_I2, state->reg1, state->left->reg1);
}
reg: OP_LCONV_TO_OVF_I2_UN (lreg) {
- MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, 0);
- MONO_EMIT_NEW_COND_EXC (s, NE_UN, "OverflowException");
+ MONO_EMIT_NEW_COMPARE_IMM_EXC (s, NE_UN, state->left->reg2, 0, "OverflowException");
/* Probe value to be within -32768 and 32767 */
- MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 32767);
- MONO_EMIT_NEW_COND_EXC (s, GT, "OverflowException");
- MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, -32768);
- MONO_EMIT_NEW_COND_EXC (s, LT, "OverflowException");
+ MONO_EMIT_NEW_COMPARE_IMM_EXC (s, GT, state->left->reg1, 32767, "OverflowException");
+ MONO_EMIT_NEW_COMPARE_IMM_EXC (s, LT, state->left->reg1, -32768, "OverflowException");
MONO_EMIT_UNALU (s, tree, CEE_CONV_I2, state->reg1, state->left->reg1);
}
reg: OP_LCONV_TO_OVF_U2_UN (lreg),
reg: OP_LCONV_TO_OVF_U2 (lreg) {
- MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, 0);
- MONO_EMIT_NEW_COND_EXC (s, NE_UN, "OverflowException");
+ MONO_EMIT_NEW_COMPARE_IMM_EXC (s, NE_UN, state->left->reg2, 0, "OverflowException");
/* Probe value to be within 0 and 65535 */
- MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 0xffff);
- MONO_EMIT_NEW_COND_EXC (s, GT_UN, "OverflowException");
+ MONO_EMIT_NEW_COMPARE_IMM_EXC (s, GT_UN, state->left->reg1, 0xffff, "OverflowException");
MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->reg1, state->left->reg1, 0xffff);
}
reg: OP_LCONV_TO_OVF_U4_UN (lreg) {
- MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, 0);
- MONO_EMIT_NEW_COND_EXC (s, NE_UN, "OverflowException");
+ MONO_EMIT_NEW_COMPARE_IMM_EXC (s, NE_UN, state->left->reg2, 0, "OverflowException");
MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
}
reg: OP_LCONV_TO_OVF_I_UN (lreg) {
- MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, 0);
- MONO_EMIT_NEW_COND_EXC (s, NE_UN, "OverflowException");
+ MONO_EMIT_NEW_COMPARE_IMM_EXC (s, NE_UN, state->left->reg2, 0, "OverflowException");
MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
}
reg: OP_LCONV_TO_OVF_U4 (lreg) {
- MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, 0);
- MONO_EMIT_NEW_COND_EXC (s, NE_UN, "OverflowException");
+ MONO_EMIT_NEW_COMPARE_IMM_EXC (s, NE_UN, state->left->reg2, 0, "OverflowException");
MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
}
-reg: OP_LCONV_TO_OVF_I (lreg) {
- tree->dreg = state->reg1;
- tree->sreg1 = state->left->reg1;
- tree->sreg2 = state->left->reg2;
- mono_bblock_add_inst (s->cbb, tree);
-}
-
reg: OP_LCONV_TO_OVF_I4_UN (lreg) {
- MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, 0);
- MONO_EMIT_NEW_COND_EXC (s, NE_UN, "OverflowException");
- MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg1, 0);
- MONO_EMIT_NEW_COND_EXC (s, LT, "OverflowException");
+ MONO_EMIT_NEW_COMPARE_IMM_EXC (s, NE_UN, state->left->reg2, 0, "OverflowException");
+ MONO_EMIT_NEW_COMPARE_IMM_EXC (s, LT, state->left->reg1, 0, "OverflowException");
MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->reg1);
}
+reg: OP_LCONV_TO_OVF_I (lreg),
reg: OP_LCONV_TO_OVF_I4 (lreg) {
- tree->dreg = state->reg1;
- tree->sreg1 = state->left->reg1;
- tree->sreg2 = state->left->reg2;
- tree->opcode = OP_LCONV_TO_OVF_I;
- mono_bblock_add_inst (s->cbb, tree);
+ int tmp_reg = mono_regstate_next_int (s->rs);
+
+ /* Overflows if reg2 != sign extension of reg1 */
+ MONO_EMIT_BIALU_IMM (s, tree, OP_SHR_IMM, tmp_reg, state->left->reg1, 31);
+
+ MONO_EMIT_NEW_COMPARE_EXC (s, NE_UN, state->left->reg2, tmp_reg, "OverflowException");
+ MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->reg1);
}
lreg: OP_LCONV_TO_OVF_I8_UN (lreg) {
- MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, 0);
- MONO_EMIT_NEW_COND_EXC (s, LT, "OverflowException");
+ MONO_EMIT_NEW_COMPARE_IMM_EXC (s, LT, state->left->reg2, 0, "OverflowException");
MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->reg1);
MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg2, state->left->reg2);
}
lreg: OP_LCONV_TO_OVF_U8 (lreg) {
- MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, 0);
- MONO_EMIT_NEW_COND_EXC (s, LT, "OverflowException");
+ MONO_EMIT_NEW_COMPARE_IMM_EXC (s, LT, state->left->reg2, 0, "OverflowException");
MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->reg1);
MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg2, state->left->reg2);