Thu Nov 23 20:01:12 CET 2006 Paolo Molaro <lupus@ximian.com>
[mono.git] / mono / mini / inssel-long32.brg
index 7d6d03c7853dbda581c3f655bdb7b3fe2d4798fd..d12c34c08996fba6fa5a5ae68d9e04ffd53041e7 100644 (file)
@@ -101,6 +101,28 @@ reg: CEE_SUB_OVF_UN (reg, reg) {
        MONO_EMIT_NEW_COND_EXC (s, C, "OverflowException");
 }
 
+reg: CEE_DIV (reg, OP_ICONST) {
+       int p2 = mono_is_power_of_two (state->right->tree->inst_c0);
+       int r = mono_regstate_next_int (s->rs);
+       if (p2 <= 0) {
+               MONO_EMIT_NEW_ICONST (s, r, state->right->tree->inst_c0);
+               MONO_EMIT_BIALU (s, tree, CEE_DIV, state->reg1, state->left->reg1, r);
+       } else if (p2 == 1) {
+               int r2 = mono_regstate_next_int (s->rs);
+               MONO_EMIT_NEW_BIALU_IMM (s, OP_SHR_UN_IMM, r, state->left->reg1, 31);
+               MONO_EMIT_NEW_BIALU (s, CEE_ADD, r2, r, state->left->reg1);
+               MONO_EMIT_NEW_BIALU_IMM (s, OP_SHR_IMM, state->reg1, r2, 1);
+       } else {
+               int r2 = mono_regstate_next_int (s->rs);
+               int r3 = mono_regstate_next_int (s->rs);
+               int r4 = mono_regstate_next_int (s->rs);
+               MONO_EMIT_NEW_BIALU_IMM (s, OP_SHR_IMM, r2, state->left->reg1, 31);
+               MONO_EMIT_NEW_BIALU_IMM (s, OP_SHR_UN_IMM, r3, r2, (32 - p2));
+               MONO_EMIT_NEW_BIALU (s, CEE_ADD, r4, r3, state->left->reg1);
+               MONO_EMIT_NEW_BIALU_IMM (s, OP_SHR_IMM, state->reg1, r4, p2);
+       }
+}
+
 cflags: OP_COMPARE (reg, reg) {
        tree->sreg1 = state->left->reg1;
        tree->sreg2 = state->right->reg1;
@@ -851,7 +873,14 @@ reg: OP_LCONV_TO_OVF_I (lreg) {
        mono_bblock_add_inst (s->cbb, tree);
 }
 
-reg: OP_LCONV_TO_OVF_I4_UN (lreg),
+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_UNALU (s, OP_MOVE, state->reg1, state->left->reg1);
+}
+
 reg: OP_LCONV_TO_OVF_I4 (lreg) {
        tree->dreg = state->reg1;
        tree->sreg1 = state->left->reg1;