Author: markmason
Date: 2007-01-17 15:17:41 -0500 (Wed, 17 Jan 2007)
New Revision: 71227
Modified:
trunk/mono/mono/mini/ChangeLog
trunk/mono/mono/mini/cpu-mips.md
trunk/mono/mono/mini/exceptions-mips.c
trunk/mono/mono/mini/inssel-long.brg
trunk/mono/mono/mini/inssel-long32-mips.brg
trunk/mono/mono/mini/inssel-mips.brg
trunk/mono/mono/mini/mini-mips.c
trunk/mono/mono/mini/mini-mips.h
trunk/mono/mono/mini/mini-ops.h
Log:
* inssel-long.brg: patch to deal with mips missing flags
* inssel-long32-mips.brg: implement overflow checks
* insset-mips.brg: implement overflow checks
* mini-mips.h: implement conditional exception handling
* mini-mips.c: add mips_emit_exc_by_name(), implement
conditional exception handling.
Remove unused code, minor cleanups.
* exceptions-mips.c: minor cleanups
* mini-ops.h: add mips conditional exception ops
* cpu-mips.md: add mips conditional exception ops
These changes contributed under the MIT/X11 license.
Modified: trunk/mono/mono/mini/ChangeLog
===================================================================
--- trunk/mono/mono/mini/ChangeLog 2007-01-17 20:03:33 UTC (rev 71226)
+++ trunk/mono/mono/mini/ChangeLog 2007-01-17 20:17:41 UTC (rev 71227)
@@ -1,4 +1,16 @@
+2007-01-17 Mark Mason <[EMAIL PROTECTED]>
+ * inssel-long.brg: patch to deal with mips missing flags
+ * inssel-long32-mips.brg: implement overflow checks
+ * insset-mips.brg: implement overflow checks
+ * mini-mips.h: implement conditional exception handling
+ * mini-mips.c: add mips_emit_exc_by_name(), implement conditional
exception handling.
+ Remove unused code, minor cleanups.
+ * exceptions-mips.c: minor cleanups
+ * mini-ops.h: add mips conditional exception ops
+ * cpu-mips.md: add mips conditional exception ops
+
+
Wed Jan 17 19:22:34 CET 2007 Paolo Molaro <[EMAIL PROTECTED]>
* inssel.brg: patch from Mark Mason <[EMAIL PROTECTED]>
Modified: trunk/mono/mono/mini/cpu-mips.md
===================================================================
--- trunk/mono/mono/mini/cpu-mips.md 2007-01-17 20:03:33 UTC (rev 71226)
+++ trunk/mono/mono/mini/cpu-mips.md 2007-01-17 20:17:41 UTC (rev 71227)
@@ -142,10 +142,10 @@
add: dest:i src1:i src2:i len:4
sub: dest:i src1:i src2:i len:4
mul: dest:i src1:i src2:i len:20
-div: dest:i src1:i src2:i len:40
-div.un: dest:i src1:i src2:i len:40
-rem: dest:i src1:i src2:i len:48
-rem.un: dest:i src1:i src2:i len:28
+div: dest:i src1:i src2:i len:72
+div.un: dest:i src1:i src2:i len:72
+rem: dest:i src1:i src2:i len:72
+rem.un: dest:i src1:i src2:i len:72
and: dest:i src1:i src2:i len:4
or: dest:i src1:i src2:i len:4
xor: dest:i src1:i src2:i len:4
@@ -563,3 +563,31 @@
mips_sltiu: dest:i src1:i len:4
mips_sltu: dest:i src1:i src2:i len:4
mips_xori: dest:i src1:i len:4
+mips_cond_exc_eq: src1:i src2:i len:40
+mips_cond_exc_ge: src1:i src2:i len:40
+mips_cond_exc_gt: src1:i src2:i len:40
+mips_cond_exc_le: src1:i src2:i len:40
+mips_cond_exc_lt: src1:i src2:i len:40
+mips_cond_exc_ne_un: src1:i src2:i len:40
+mips_cond_exc_ge_un: src1:i src2:i len:40
+mips_cond_exc_gt_un: src1:i src2:i len:40
+mips_cond_exc_le_un: src1:i src2:i len:40
+mips_cond_exc_lt_un: src1:i src2:i len:40
+mips_cond_exc_ov: src1:i src2:i len:40
+mips_cond_exc_no: src1:i src2:i len:40
+mips_cond_exc_c: src1:i src2:i len:40
+mips_cond_exc_nc: src1:i src2:i len:40
+mips_cond_exc_ieq: src1:i src2:i len:40
+mips_cond_exc_ige: src1:i src2:i len:40
+mips_cond_exc_igt: src1:i src2:i len:40
+mips_cond_exc_ile: src1:i src2:i len:40
+mips_cond_exc_ilt: src1:i src2:i len:40
+mips_cond_exc_ine_un: src1:i src2:i len:40
+mips_cond_exc_ige_un: src1:i src2:i len:40
+mips_cond_exc_igt_un: src1:i src2:i len:40
+mips_cond_exc_ile_un: src1:i src2:i len:40
+mips_cond_exc_ilt_un: src1:i src2:i len:40
+mips_cond_exc_iov: src1:i src2:i len:40
+mips_cond_exc_ino: src1:i src2:i len:40
+mips_cond_exc_ic: src1:i src2:i len:40
+mips_cond_exc_inc: src1:i src2:i len:40
Modified: trunk/mono/mono/mini/exceptions-mips.c
===================================================================
--- trunk/mono/mono/mini/exceptions-mips.c 2007-01-17 20:03:33 UTC (rev
71226)
+++ trunk/mono/mono/mini/exceptions-mips.c 2007-01-17 20:17:41 UTC (rev
71227)
@@ -120,13 +120,12 @@
static int inited = 0;
guint8 *code;
int alloc_size;
- int offset = 16;
+ int offset;
if (inited)
return start;
inited = 1;
-
code = start;
alloc_size = 64;
@@ -136,6 +135,7 @@
mips_sw (code, mips_ra, mips_sp, alloc_size + MIPS_RET_ADDR_OFFSET);
/* Save global registers on stack (s0 - s7) */
+ offset = 16;
mips_sw (code, mips_s0, mips_sp, offset); offset += 4;
mips_sw (code, mips_s1, mips_sp, offset); offset += 4;
mips_sw (code, mips_s2, mips_sp, offset); offset += 4;
@@ -146,7 +146,7 @@
mips_sw (code, mips_s7, mips_sp, offset); offset += 4;
mips_sw (code, mips_fp, mips_sp, offset); offset += 4;
- /* Restore global registers (s0-s7) */
+ /* Restore global registers from MonoContext, including the frame
pointer */
mips_lw (code, mips_s0, mips_a0, G_STRUCT_OFFSET (MonoContext,
sc_regs[mips_s0]));
mips_lw (code, mips_s1, mips_a0, G_STRUCT_OFFSET (MonoContext,
sc_regs[mips_s1]));
mips_lw (code, mips_s2, mips_a0, G_STRUCT_OFFSET (MonoContext,
sc_regs[mips_s2]));
Modified: trunk/mono/mono/mini/inssel-long.brg
===================================================================
--- trunk/mono/mono/mini/inssel-long.brg 2007-01-17 20:03:33 UTC (rev
71226)
+++ trunk/mono/mono/mini/inssel-long.brg 2007-01-17 20:17:41 UTC (rev
71227)
@@ -228,103 +228,83 @@
}
reg: OP_LCONV_TO_OVF_I1 (reg) {
- 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);
}
reg: OP_LCONV_TO_OVF_I1_UN (reg) {
- MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 127);
- MONO_EMIT_NEW_COND_EXC (s, GT_UN, "OverflowException");
+ MONO_EMIT_NEW_COMPARE_IMM_EXC (s, GT_UN, state->left->reg1, 127,
"OverflowException");
MONO_EMIT_UNALU (s, tree, CEE_CONV_I1, state->reg1, state->left->reg1);
}
reg: OP_LCONV_TO_OVF_U1 (reg) {
/* 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);
}
reg: OP_LCONV_TO_OVF_U1_UN (reg) {
/* 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);
}
reg: OP_LCONV_TO_OVF_I2 (reg) {
/* 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_I2_UN (reg) {
/* Probe value to be within 0 and 32767 */
- MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 32767);
- MONO_EMIT_NEW_COND_EXC (s, GT_UN, "OverflowException");
+ MONO_EMIT_NEW_COMPARE_IMM_EXC (s, GT_UN, state->left->reg1, 32767,
"OverflowException");
MONO_EMIT_UNALU (s, tree, CEE_CONV_I2, state->reg1, state->left->reg1);
}
reg: OP_LCONV_TO_OVF_U2 (reg) {
/* 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_U2_UN (reg) {
/* 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_I4 (reg) {
- MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 0x7fffffff);
- MONO_EMIT_NEW_COND_EXC (s, GT, "OverflowException");
- MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, -2147483648);
- MONO_EMIT_NEW_COND_EXC (s, LT, "OverflowException");
+ MONO_EMIT_NEW_COMPARE_IMM_EXC (s, GT, state->left->reg1, 0x7fffffff,
"OverflowException");
+ MONO_EMIT_NEW_COMPARE_IMM_EXC (s, LT, state->left->reg1, -2147483648,
"OverflowException");
MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
}
reg: OP_LCONV_TO_OVF_I4_UN (reg) {
- MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 0x7fffffff);
- MONO_EMIT_NEW_COND_EXC (s, GT_UN, "OverflowException");
+ MONO_EMIT_NEW_COMPARE_IMM_EXC (s, GT_UN, state->left->reg1, 0x7fffffff,
"OverflowException");
MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
}
reg: OP_LCONV_TO_OVF_U4 (reg) {
- MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 0xffffffffUL);
- MONO_EMIT_NEW_COND_EXC (s, GT, "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, GT, state->left->reg1, 0xffffffffUL,
"OverflowException");
+ MONO_EMIT_NEW_COMPARE_IMM_EXC (s, LT, state->left->reg1, 0,
"OverflowException");
MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
}
reg: OP_LCONV_TO_OVF_U4_UN (reg) {
- MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 0xffffffff);
- MONO_EMIT_NEW_COND_EXC (s, GT_UN, "OverflowException");
+ MONO_EMIT_NEW_COMPARE_IMM_EXC (s, GT_UN, state->left->reg1, 0xffffffff,
"OverflowException");
MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
}
reg: OP_LCONV_TO_OVF_I_UN (reg),
reg: OP_LCONV_TO_OVF_I8_UN (reg) {
- 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, LT, state->left->reg1, 0,
"OverflowException");
MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
}
reg: OP_LCONV_TO_OVF_U8 (reg) {
- 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, LT, state->left->reg1, 0,
"OverflowException");
MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
}
@@ -357,8 +337,7 @@
}
reg: 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_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
}
Modified: trunk/mono/mono/mini/inssel-long32-mips.brg
===================================================================
--- trunk/mono/mono/mini/inssel-long32-mips.brg 2007-01-17 20:03:33 UTC (rev
71226)
+++ trunk/mono/mono/mini/inssel-long32-mips.brg 2007-01-17 20:17:41 UTC (rev
71227)
@@ -272,37 +272,136 @@
}
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),
-lreg: OP_LADD_OVF (lreg, lreg),
+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_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),
-lreg: OP_LSUB_OVF (lreg, lreg),
+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_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) {
@@ -868,8 +967,7 @@
}
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);
}
@@ -947,13 +1045,10 @@
}
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);
}
@@ -963,22 +1058,18 @@
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_COMPARE_IMM_EXC (s, GT_UN, state->left->reg1, 127,
"OverflowException");
MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_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);
@@ -986,12 +1077,10 @@
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);
}
@@ -1001,103 +1090,83 @@
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_COMPARE_IMM_EXC (s, GT_UN, state->left->reg1, 32767,
"OverflowException");
MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_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);
Modified: trunk/mono/mono/mini/inssel-mips.brg
===================================================================
--- trunk/mono/mono/mini/inssel-mips.brg 2007-01-17 20:03:33 UTC (rev
71226)
+++ trunk/mono/mono/mini/inssel-mips.brg 2007-01-17 20:17:41 UTC (rev
71227)
@@ -618,6 +618,7 @@
int soffset = vt->inst_offset;
int doffset = ai->offset;
+ //g_printf ("OP_OUTARG_VT: LDOBJ\n");
for (i = 0; i < nregs; ++i) {
dreg = mono_regstate_next_int (s->rs);
MONO_EMIT_NEW_LOAD_MEMBASE (s, dreg, vt->inst_basereg, soffset);
@@ -625,7 +626,7 @@
soffset += sizeof (gpointer);
doffset += sizeof (gpointer);
}
- //g_print ("vt size: %d at R%d + %d\n", ai->offset, vt->inst_basereg,
vt->inst_offset);
+ //g_printf ("vt size: %d at R%d + %d\n", ai->offset, vt->inst_basereg,
vt->inst_offset);
if (ovf_size != 0) {
mini_emit_memcpy (s, vt->inst_basereg, doffset,
vt->inst_basereg, soffset, ovf_size * sizeof (gpointer), 0);
}
@@ -636,6 +637,8 @@
MonoMIPSArgInfo *ai = tree->backend.data;
int start_reg = ai->reg;
int nregs = ai->size;
+
+ //g_printf ("OP_OUTARG_VT: ICONST\n");
if (nregs) {
tree->opcode = OP_SETREGIMM;
tree->dreg = mono_regstate_next_int (s->rs);
@@ -652,6 +655,8 @@
MonoMIPSArgInfo *ai = tree->backend.data;
int start_reg = ai->reg;
int nregs = ai->size;
+
+ //g_printf ("OP_OUTARG_VT: reg\n");
if (nregs) {
tree->opcode = OP_SETREG;
tree->dreg = mono_regstate_next_int (s->rs);
@@ -783,19 +788,84 @@
}
reg: CEE_ADD_OVF (reg, reg) "0" {
- MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1,
state->right->reg1);
+ 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);
+
+ /* add the operands */
+
+ MONO_EMIT_NEW_BIALU (s, CEE_ADD, state->reg1, state->left->reg1,
state->right->reg1);
+
+ /* Overflow happens if
+ * neg + neg = pos or
+ * pos + pos = neg
+ *
+ * (bit31s of operands match) AND (bit31 of operand != bit31 of result)
+ * XOR of the high bit 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->reg1,
state->right->reg1);
+
+ /* set tmp2 = 0 if bit31 of results matches is different than the
operands */
+ MONO_EMIT_NEW_BIALU (s, CEE_XOR, tmp2, state->reg1, state->right->reg1);
+ MONO_EMIT_NEW_UNALU (s, CEE_NOT, tmp3, tmp2);
+
+ /* OR(tmp1, tmp2) = 0 if both conditions are true */
+ MONO_EMIT_NEW_BIALU (s, CEE_OR, tmp4, tmp3, tmp1);
+
+ MONO_EMIT_NEW_BIALU_IMM (s, OP_SHR_IMM, tmp5, tmp4, 31);
+
+ /* Now, if (tmp4 == 0) then overflow */
+ MONO_EMIT_NEW_COMPARE_EXC (s, EQ, tmp5, mips_zero, "OverflowException");
}
reg: CEE_ADD_OVF_UN (reg, reg) "0" {
- MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1,
state->right->reg1);
+ 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_COMPARE_EXC (s, NE_UN, tmp1, mips_zero,
"OverflowException"); */
}
reg: CEE_SUB_OVF (reg, reg) "0" {
- MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1,
state->right->reg1);
+ 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);
+
+ /* 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
+ */
+
+ /* tmp3 = 1 if the signs of the two inputs differ */
+ MONO_EMIT_NEW_BIALU (s, CEE_XOR, tmp1, state->left->reg1,
state->right->reg1);
+ MONO_EMIT_NEW_BIALU (s, CEE_XOR, tmp2, state->left->reg1, state->reg1);
+ MONO_EMIT_NEW_BIALU_IMM (s, OP_MIPS_SLTI, tmp3, tmp1, 0);
+ MONO_EMIT_NEW_BIALU_IMM (s, OP_MIPS_SLTI, tmp4, tmp2, 0);
+ MONO_EMIT_NEW_BIALU (s, CEE_AND, tmp5, tmp4, tmp3);
+
+ MONO_EMIT_NEW_COMPARE_EXC (s, NE_UN, tmp5, mips_zero,
"OverflowException");
}
reg: CEE_SUB_OVF_UN (reg, reg) "0" {
- MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1,
state->right->reg1);
+ 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_COMPARE_EXC (s, NE_UN, tmp1, mips_zero,
"OverflowException");
}
Modified: trunk/mono/mono/mini/mini-mips.c
===================================================================
--- trunk/mono/mono/mini/mini-mips.c 2007-01-17 20:03:33 UTC (rev 71226)
+++ trunk/mono/mono/mini/mini-mips.c 2007-01-17 20:17:41 UTC (rev 71227)
@@ -57,42 +57,13 @@
* to cfg->bb_exit as far as the big branch handling is concerned
*/
-#define EMIT_SYSTEM_EXCEPTION_NAME_LEN 5
#define EMIT_SYSTEM_EXCEPTION_NAME(exc_name) \
do { \
- mono_add_patch_info (cfg, code - cfg->native_code, \
- MONO_PATCH_INFO_EXC, exc_name); \
- mips_lui (code, mips_t9, mips_zero, 0); \
- mips_addiu (code, mips_t9, mips_t9, 0); \
- mips_jalr (code, mips_t9, mips_ra); \
- mips_nop (code); \
+ code = mips_emit_exc_by_name (code, exc_name); \
cfg->bb_exit->max_offset += 16; \
} while (0)
-/* XXX - need to actually test the condition - not just bne */
-#define EMIT_COND_SYSTEM_EXCEPTION_FLAGS(b0,b1,exc_name) \
- do { \
- mips_bne (code, mips_at, mips_zero, 5); \
- mips_nop (code); \
- EMIT_SYSTEM_EXCEPTION_NAME(exc_name); \
- cfg->bb_exit->max_offset += 8; \
- } while (0)
-
-#define EMIT_COND_SYSTEM_EXCEPTION(cond,exc_name) \
- do { \
- switch (cond) { \
- case CEE_BEQ: \
- mips_bne (code, mips_at, mips_zero, 5); \
- break; \
- default: \
- g_assert_not_reached(); \
- } \
- mips_nop (code); \
- EMIT_SYSTEM_EXCEPTION_NAME(exc_name); \
- cfg->bb_exit->max_offset += 8; \
- } while (0)
-
#define emit_linuxthreads_tls(code,dreg,key) do {\
int off1, off2; \
off1 = offsets_from_pthread_key ((key), &off2); \
@@ -169,6 +140,20 @@
}
#endif
+static guint8 *
+mips_emit_exc_by_name(guint8 *code, char *name)
+{
+ guint32 addr;
+
+ mips_load_const (code, mips_a0, name);
+ addr = (guint32) mono_arch_get_throw_exception_by_name ();
+ mips_load_const (code, mips_t9, addr);
+ mips_jalr (code, mips_t9, mips_ra);
+ mips_nop (code);
+
+ return code;
+}
+
/* XXX - big-endian dependent? */
void
patch_lui_addiu(guint32 *ip, guint32 val)
@@ -1503,8 +1488,8 @@
ins->opcode = map_to_reg_reg_op (ins->opcode);
}
break;
- case OP_SUB_IMM:
#if 0
+ case OP_SUB_IMM:
if (!mips_is_imm16 (-ins->inst_imm)) {
NEW_INS (cfg, temp, OP_ICONST);
temp->inst_c0 = ins->inst_imm;
@@ -1512,12 +1497,12 @@
ins->sreg2 = temp->dreg;
ins->opcode = map_to_reg_reg_op (ins->opcode);
}
-#endif
break;
+#endif
+#if 0
case OP_AND_IMM:
case OP_OR_IMM:
case OP_XOR_IMM:
-#if 0
if ((ins->inst_imm & 0xffff0000) && (ins->inst_imm &
0xffff)) {
NEW_INS (cfg, temp, OP_ICONST);
temp->inst_c0 = ins->inst_imm;
@@ -1525,12 +1510,12 @@
ins->sreg2 = temp->dreg;
ins->opcode = map_to_reg_reg_op (ins->opcode);
}
-#endif
break;
+#endif
+#if 0
case OP_SBB_IMM:
case OP_SUBCC_IMM:
case OP_ADC_IMM:
-#if 0
NEW_INS (cfg, temp, OP_ICONST);
temp->inst_c0 = ins->inst_imm;
temp->dreg = mono_regstate_next_int (cfg->rs);
@@ -1538,8 +1523,8 @@
ins->opcode = map_to_reg_reg_op (ins->opcode);
break;
#endif
- case OP_COMPARE_IMM:
#if 0
+ case OP_COMPARE_IMM:
if (compare_opcode_is_unsigned (ins->next->opcode)) {
if (!ppc_is_uimm16 (ins->inst_imm)) {
NEW_INS (cfg, temp, OP_ICONST);
@@ -1557,10 +1542,10 @@
ins->opcode = map_to_reg_reg_op
(ins->opcode);
}
}
-#endif
break;
- case OP_MUL_IMM:
+#endif
#if 0
+ case OP_MUL_IMM:
if (ins->inst_imm == 1) {
ins->opcode = OP_MOVE;
break;
@@ -1583,8 +1568,9 @@
ins->sreg2 = temp->dreg;
ins->opcode = map_to_reg_reg_op (ins->opcode);
}
-#endif
break;
+#endif
+#if 0
case OP_LOAD_MEMBASE:
case OP_LOADI4_MEMBASE:
case OP_LOADU4_MEMBASE:
@@ -1600,7 +1586,6 @@
case OP_STOREI1_MEMBASE_REG:
case OP_STORER4_MEMBASE_REG:
case OP_STORER8_MEMBASE_REG:
-#if 0
/* we can do two things: load the immed in a register
* and use an indexed load, or see if the immed can be
* represented as an ad_imm + a load with a smaller
offset
@@ -1613,13 +1598,13 @@
temp->dreg = mono_regstate_next_int (cfg->rs);
ins->sreg2 = temp->dreg;
ins->opcode = map_to_reg_reg_op (ins->opcode);
-#endif
break;
+#endif
+#if 0
case OP_STORE_MEMBASE_IMM:
case OP_STOREI1_MEMBASE_IMM:
case OP_STOREI2_MEMBASE_IMM:
case OP_STOREI4_MEMBASE_IMM:
-#if 0
NEW_INS (cfg, temp, OP_ICONST);
temp->inst_c0 = ins->inst_imm;
temp->dreg = mono_regstate_next_int (cfg->rs);
@@ -1627,10 +1612,8 @@
ins->opcode = map_to_reg_reg_op (ins->opcode);
last_ins = temp;
goto loop_start; /* make it handle the possibly big
ins->inst_offset */
+ break;
#endif
-#if 1
- ;
-#endif
}
last_ins = ins;
ins = ins->next;
@@ -1924,7 +1907,6 @@
imm = ins->inst_imm & 0xffff;
}
}
-
#if 0
if (ins->next) {
switch (ins->next->opcode) {
@@ -2073,10 +2055,24 @@
mips_and (code, ins->dreg, ins->sreg1, mips_at);
}
break;
- case CEE_DIV: {
- guint32 *divisor_is_zero = (guint32 *)(void *)code;
+ case CEE_DIV:
+ case CEE_REM: {
+ guint32 *divisor_is_m1;
+ guint32 *divisor_is_zero;
+ /* */
+ mips_addiu (code, mips_at, mips_zero, 0xffff);
+ divisor_is_m1 = (guint32 *)code;
+ mips_bne (code, ins->sreg2, mips_at, 0);
+ mips_nop (code);
+
+ /* Divide by -1 -- throw exception */
+ EMIT_SYSTEM_EXCEPTION_NAME("ArithmeticException");
+
+ mips_patch (divisor_is_m1, (guint32)code);
+
/* Put divide in branch delay slot */
+ divisor_is_zero = (guint32 *)code;
mips_bne (code, ins->sreg2, mips_zero, 0);
mips_div (code, ins->sreg1, ins->sreg2);
@@ -2084,7 +2080,10 @@
EMIT_SYSTEM_EXCEPTION_NAME("DivideByZeroException");
mips_patch (divisor_is_zero, (guint32)code);
- mips_mflo (code, ins->dreg);
+ if (ins->opcode == CEE_DIV)
+ mips_mflo (code, ins->dreg);
+ else
+ mips_mfhi (code, ins->dreg);
break;
}
case CEE_DIV_UN: {
@@ -2113,40 +2112,6 @@
#endif
g_assert_not_reached();
break;
- case CEE_REM: {
- /* XXX */
-#if 1
- guint32 *divisor_is_zero = (guint32 *)(void *)code;
-
- /* Put divide in branch delay slot */
- mips_bne (code, ins->sreg2, mips_zero, 0);
- mips_div (code, ins->sreg1, ins->sreg2);
-
- /* Divide by zero -- throw exception */
- EMIT_SYSTEM_EXCEPTION_NAME("DivideByZeroException");
-
- mips_patch (divisor_is_zero, (guint32)code);
- mips_mfhi (code, ins->dreg);
- break;
-#else
- guint32 *divisor_is_m1;
- ppc_cmpi (code, 0, 0, ins->sreg2, -1);
- divisor_is_m1 = (guint32 *)(void *)code;
- ppc_bc (code, PPC_BR_FALSE | PPC_BR_LIKELY, PPC_BR_EQ,
0);
- ppc_lis (code, ppc_r11, 0x8000);
- ppc_cmp (code, 0, 0, ins->sreg1, ppc_r11);
- EMIT_COND_SYSTEM_EXCEPTION_FLAGS (PPC_BR_TRUE,
PPC_BR_EQ, "ArithmeticException");
- mips_patch (divisor_is_m1, (guint32)code);
- ppc_divwod (code, ppc_r11, ins->sreg1, ins->sreg2);
- ppc_mfspr (code, ppc_r0, ppc_xer);
- ppc_andisd (code, ppc_r0, ppc_r0, (1<<14));
- /* FIXME: use OverflowException for 0x80000000/-1 */
- EMIT_COND_SYSTEM_EXCEPTION_FLAGS (PPC_BR_FALSE,
PPC_BR_EQ, "DivideByZeroException");
- ppc_mullw (code, ppc_r11, ppc_r11, ins->sreg2);
- ppc_subf (code, ins->dreg, ppc_r11, ins->sreg1);
-#endif
- break;
- }
case CEE_REM_UN: {
guint32 *divisor_is_zero = (guint32 *)(void *)code;
@@ -2235,20 +2200,23 @@
mips_nop (code);
#endif
break;
- case CEE_MUL_OVF:
-#if 1
- mips_mul (code, ins->dreg, ins->sreg1, ins->sreg2);
-#else
+ case CEE_MUL_OVF: {
+ guint32 *patch;
mips_mult (code, ins->sreg1, ins->sreg2);
mips_mflo (code, ins->dreg);
mips_mfhi (code, mips_at);
mips_nop (code);
mips_nop (code);
-#endif
- /* XXX - Throw exception if we overflowed */
+ mips_sra (code, mips_temp, ins->dreg, 31);
+ patch = (guint32 *)(void *)code;
+ mips_beq (code, mips_temp, mips_at, 0);
+ mips_nop (code);
+ EMIT_SYSTEM_EXCEPTION_NAME("OverflowException");
+ mips_patch (patch, (guint32)code);
break;
+ }
case CEE_MUL_OVF_UN:
-#if 1
+#if 0
mips_mul (code, ins->dreg, ins->sreg1, ins->sreg2);
#else
mips_mult (code, ins->sreg1, ins->sreg2);
@@ -2349,12 +2317,14 @@
ppc_add (code, ppc_sp, cfg->frame_reg, ppc_r11);
}
if (!cfg->method->save_lmf) {
- /*for (i = 31; i >= 14; --i) {
+#if 0
+ for (i = 31; i >= 14; --i) {
if (cfg->used_float_regs & (1 << i)) {
pos += sizeof (double);
ppc_lfd (code, i, -pos,
cfg->frame_reg);
}
- }*/
+ }
+#endif
for (i = 31; i >= 13; --i) {
if (cfg->used_int_regs & (1 << i)) {
pos += sizeof (gulong);
@@ -2599,72 +2569,109 @@
mips_nop (code);
mips_move (code, ins->dreg, mips_zero);
break;
+
case OP_COND_EXC_EQ:
- case OP_COND_EXC_NE_UN:
- case OP_COND_EXC_LT:
- case OP_COND_EXC_LT_UN:
- case OP_COND_EXC_GT:
- case OP_COND_EXC_GT_UN:
case OP_COND_EXC_GE:
- case OP_COND_EXC_GE_UN:
+ case OP_COND_EXC_GT:
case OP_COND_EXC_LE:
+ case OP_COND_EXC_LT:
+ case OP_COND_EXC_NE_UN:
+ case OP_COND_EXC_GE_UN:
+ case OP_COND_EXC_GT_UN:
case OP_COND_EXC_LE_UN:
-#if 0 /* Don't raise conditional exceptions at the moment */
+ case OP_COND_EXC_LT_UN:
+
+ case OP_COND_EXC_OV:
+ case OP_COND_EXC_NO:
+ case OP_COND_EXC_C:
+ case OP_COND_EXC_NC:
+
+ case OP_COND_EXC_IEQ:
+ case OP_COND_EXC_IGE:
+ case OP_COND_EXC_IGT:
+ case OP_COND_EXC_ILE:
+ case OP_COND_EXC_ILT:
+ case OP_COND_EXC_INE_UN:
+ case OP_COND_EXC_IGE_UN:
+ case OP_COND_EXC_IGT_UN:
+ case OP_COND_EXC_ILE_UN:
+ case OP_COND_EXC_ILT_UN:
+
+ case OP_COND_EXC_IOV:
+ case OP_COND_EXC_INO:
+ case OP_COND_EXC_IC:
+ case OP_COND_EXC_INC:
+ /* Should be re-mapped to OP_MIPS_B* by
*.inssel-mips.brg */
+ g_warning ("unsupported conditional exception %s\n",
mono_inst_name (ins->opcode));
+ g_assert_not_reached ();
+ break;
+
+ case OP_MIPS_COND_EXC_EQ:
+ case OP_MIPS_COND_EXC_GE:
+ case OP_MIPS_COND_EXC_GT:
+ case OP_MIPS_COND_EXC_LE:
+ case OP_MIPS_COND_EXC_LT:
+ case OP_MIPS_COND_EXC_NE_UN:
+ case OP_MIPS_COND_EXC_GE_UN:
+ case OP_MIPS_COND_EXC_GT_UN:
+ case OP_MIPS_COND_EXC_LE_UN:
+ case OP_MIPS_COND_EXC_LT_UN:
+
+ case OP_MIPS_COND_EXC_OV:
+ case OP_MIPS_COND_EXC_NO:
+ case OP_MIPS_COND_EXC_C:
+ case OP_MIPS_COND_EXC_NC:
+
+ case OP_MIPS_COND_EXC_IEQ:
+ case OP_MIPS_COND_EXC_IGE:
+ case OP_MIPS_COND_EXC_IGT:
+ case OP_MIPS_COND_EXC_ILE:
+ case OP_MIPS_COND_EXC_ILT:
+ case OP_MIPS_COND_EXC_INE_UN:
+ case OP_MIPS_COND_EXC_IGE_UN:
+ case OP_MIPS_COND_EXC_IGT_UN:
+ case OP_MIPS_COND_EXC_ILE_UN:
+ case OP_MIPS_COND_EXC_ILT_UN:
+
+ case OP_MIPS_COND_EXC_IOV:
+ case OP_MIPS_COND_EXC_INO:
+ case OP_MIPS_COND_EXC_IC:
+ case OP_MIPS_COND_EXC_INC: {
+ guint32 *skip;
+ guint32 *throw;
+
+ /* If the condition is true, raise the exception */
+
+ /* need to reverse test to skip around exception
raising */
+
+ /* For the moment, branch around a branch to avoid
reversing
+ the tests. */
+
+ /* Remember, an unpatched branch to 0 branches to the
delay slot */
+ throw = (guint32 *)(void *)code;
switch (ins->opcode) {
- case OP_COND_EXC_EQ:
- mips_bne (code, mips_at, mips_zero, 5);
+ case OP_MIPS_COND_EXC_EQ:
+ mips_beq (code, ins->sreg1, ins->sreg2, 0);
+ mips_nop (code);
break;
- case OP_COND_EXC_NE_UN:
- mips_beq (code, mips_at, mips_zero, 5);
+ case OP_MIPS_COND_EXC_NE_UN:
+ mips_bne (code, ins->sreg1, ins->sreg2, 0);
+ mips_nop (code);
break;
- case OP_COND_EXC_LT:
- case OP_COND_EXC_LT_UN:
- mips_bgez (code, mips_at, 5);
- break;
- case OP_COND_EXC_GT:
- case OP_COND_EXC_GT_UN:
- mips_blez (code, mips_at, 5);
- break;
- case OP_COND_EXC_GE:
- case OP_COND_EXC_GE_UN:
- mips_bltz (code, mips_at, 5);
- break;
- case OP_COND_EXC_LE:
- case OP_COND_EXC_LE_UN:
- mips_bgtz (code, mips_at, 5);
- break;
+ default:
+ /* Not yet implemented */
+ g_warning ("NYI conditional exception %s\n",
mono_inst_name (ins->opcode));
+ g_assert_not_reached ();
}
+ skip = (guint32 *)(void *)code;
+ mips_beq (code, mips_zero, mips_zero, 0);
mips_nop (code);
- mono_add_patch_info (cfg, code - cfg->native_code,
- MONO_PATCH_INFO_EXC, ins->inst_p1);
- mips_lui (code, mips_t9, mips_zero, 0);
- mips_addiu (code, mips_t9, mips_t9, 0);
- mips_jalr (code, mips_t9, mips_ra);
- mips_nop (code);
+ mips_patch (throw, (guint32)code);
+ code = mips_emit_exc_by_name (code, ins->inst_p1);
+ mips_patch (skip, (guint32)code);
cfg->bb_exit->max_offset += 24;
-#endif
break;
- case OP_COND_EXC_C:
- g_assert_not_reached();
-#if 0
- /* check XER [0-3] (SO, OV, CA): we can't use mcrxr
- */
- ppc_mfspr (code, ppc_r0, ppc_xer);
- ppc_andisd (code, ppc_r0, ppc_r0, (1<<14));
- EMIT_COND_SYSTEM_EXCEPTION_FLAGS (PPC_BR_FALSE,
PPC_BR_EQ, "OverflowException");
-#endif
- break;
- case OP_COND_EXC_OV:
- g_assert_not_reached();
-#if 0
- ppc_mcrxr (code, 0);
- EMIT_COND_SYSTEM_EXCEPTION (CEE_BGT - CEE_BEQ,
ins->inst_p1);
-#endif
- break;
- case OP_COND_EXC_NC:
- case OP_COND_EXC_NO:
- g_assert_not_reached ();
- break;
+ }
case CEE_BEQ:
case CEE_BNE_UN:
case CEE_BLT:
@@ -2676,6 +2683,7 @@
case CEE_BLE:
case CEE_BLE_UN:
/* Should be re-mapped to OP_MIPS_B* by
*.inssel-mips.brg */
+ g_warning ("unsupported conditional set %s\n",
mono_inst_name (ins->opcode));
g_assert_not_reached ();
break;
case OP_MIPS_BEQ:
@@ -2805,17 +2813,17 @@
mips_cvtds (code, ins->dreg, ins->dreg);
break;
case CEE_CONV_R_UN: {
- g_assert_not_reached();
-#if 0
- static const guint64 adjust_val = 0x4330000000000000ULL;
- ppc_addis (code, ppc_r0, ppc_r0, 0x4330);
- ppc_stw (code, ppc_r0, -8, ppc_sp);
- ppc_stw (code, ins->sreg1, -4, ppc_sp);
- ppc_load (code, ppc_r11, &adjust_val);
- ppc_lfd (code, ins->dreg, -8, ppc_sp);
- ppc_lfd (code, ppc_f0, 0, ppc_r11);
- ppc_fsub (code, ins->dreg, ins->dreg, ppc_f0);
-#endif
+ static const guint64 adjust_val = 0x41F0000000000000ULL;
+
+ /* convert unsigned int to double */
+ mips_mtc1 (code, mips_ftemp, ins->sreg1);
+ mips_bgez (code, ins->sreg1, 5);
+ mips_cvtdw (code, ins->dreg, mips_ftemp);
+
+ mips_load (code, mips_at, (guint32) &adjust_val);
+ mips_ldc1 (code, mips_ftemp, mips_at, 0);
+ mips_faddd (code, ins->dreg, ins->dreg, mips_ftemp);
+ /* target is here */
break;
}
case CEE_CONV_R4:
@@ -2856,37 +2864,10 @@
g_assert_not_reached ();
/* Implemented as helper calls */
break;
- case OP_LCONV_TO_OVF_I: {
-#if 1
- if (ins->dreg != ins->sreg1)
- mips_move (code, ins->dreg, ins->sreg1);
-#else
- guint32 *negative_branch, *msword_positive_branch,
*msword_negative_branch, *ovf_ex_target;
- g_assert_not_reached();
- // Check if its negative
- ppc_cmpi (code, 0, 0, ins->sreg1, 0);
- negative_branch = (guint32 *)(void *)code;
- ppc_bc (code, PPC_BR_TRUE, PPC_BR_LT, 0);
- // Its positive msword == 0
- ppc_cmpi (code, 0, 0, ins->sreg2, 0);
- msword_positive_branch = (guint32 *)(void *)code;
- ppc_bc (code, PPC_BR_TRUE, PPC_BR_EQ, 0);
-
- ovf_ex_target = (guint32 *)(void *)code;
- EMIT_COND_SYSTEM_EXCEPTION_FLAGS (PPC_BR_ALWAYS, 0,
"OverflowException");
- // Negative
- mips_patch (negative_branch, (guint32)code);
- ppc_cmpi (code, 0, 0, ins->sreg2, -1);
- msword_negative_branch = (guint32 *)(void *)code;
- ppc_bc (code, PPC_BR_FALSE, PPC_BR_EQ, 0);
- mips_patch (msword_negative_branch,
(guint32)ovf_ex_target);
-
- mips_patch (msword_positive_branch, (guint32)code);
- if (ins->dreg != ins->sreg1)
- ppc_mr (code, ins->dreg, ins->sreg1);
-#endif
+ case OP_LCONV_TO_OVF_I:
+ g_assert_not_reached ();
+ /* split up by brg file */
break;
- }
case OP_SQRT:
mips_fsqrtd (code, ins->dreg, ins->sreg1);
break;
@@ -3133,13 +3114,13 @@
/* from OP_AOTCONST : lui + addiu */
patch_lui_addiu ((guint32 *)(void *)ip,
(guint32)target);
continue;
+#if 0
case MONO_PATCH_INFO_EXC_NAME:
g_assert_not_reached ();
*((gconstpointer *)(void *)(ip + 1)) =
patch_info->data.name;
continue;
+#endif
case MONO_PATCH_INFO_NONE:
- case MONO_PATCH_INFO_BB_OVF:
- case MONO_PATCH_INFO_EXC_OVF:
/* everything is dealt with at epilog output time */
continue;
default:
@@ -3763,6 +3744,7 @@
void
mono_arch_emit_exceptions (MonoCompile *cfg)
{
+#if 0
MonoJumpInfo *patch_info;
int i;
guint8 *code;
@@ -3777,6 +3759,7 @@
* 24 is the simulated call to throw_exception_by_name
*/
for (patch_info = cfg->patch_info; patch_info; patch_info =
patch_info->next) {
+#if 0
if (patch_info->type == MONO_PATCH_INFO_EXC) {
i = exception_id_by_name (patch_info->data.target);
g_assert (i < MONO_EXC_INTRINS_NUM);
@@ -3784,18 +3767,6 @@
max_epilog_size += 12;
exc_throw_found [i] = TRUE;
}
- } else if (patch_info->type == MONO_PATCH_INFO_BB_OVF)
- max_epilog_size += 12;
-#if 0
- else if (patch_info->type == MONO_PATCH_INFO_EXC_OVF) {
- MonoOvfJump *ovfj = (MonoOvfJump
*)patch_info->data.target;
- i = exception_id_by_name (ovfj->data.exception);
- g_assert (i < MONO_EXC_INTRINS_NUM);
- if (!exc_throw_found [i]) {
- max_epilog_size += 12;
- exc_throw_found [i] = TRUE;
- }
- max_epilog_size += 8;
}
#endif
}
@@ -3811,52 +3782,8 @@
/* add code to raise exceptions */
for (patch_info = cfg->patch_info; patch_info; patch_info =
patch_info->next) {
switch (patch_info->type) {
-#if 0
- case MONO_PATCH_INFO_BB_OVF: {
- MonoOvfJump *ovfj = (MonoOvfJump
*)patch_info->data.target;
- guint32 *ip = (guint32 *)(void *)(patch_info->ip.i +
cfg->native_code);
- /* patch the initial jump */
- mips_patch (ip, (guint32)code);
- mips_bne (code, ovfj->b0_cond, ovfj->b1_cond, 2);
- mips_nop (code);
- mips_lui (code, mips_at, mips_zero, 0);
- mips_addiu (code, mips_at, mips_at, 0);
- mips_jr (code, mips_at);
- mips_patch ((guint32 *)(void *)(code - 4), (guint32)(ip
+ 1)); /* jump back after the initial branch */
- mips_nop (code);
- /* jump back to the true target */
- mips_jump (code, 0);
- ip = (guint32 *)(void *)(ovfj->data.bb->native_offset +
cfg->native_code);
- mips_patch ((guint32 *)(void *)(code - 4), (guint32)ip);
- mips_nop (code);
- break;
- }
- case MONO_PATCH_INFO_EXC_OVF: {
- MonoOvfJump *ovfj = (MonoOvfJump
*)patch_info->data.target;
- MonoJumpInfo *newji;
- guint32 *ip = (guint32 *)(void *)(patch_info->ip.i +
cfg->native_code);
- unsigned char *bcl = code;
-
- /* patch the initial jump: we arrived here with a call
*/
- mips_patch (ip, (guint32)code);
- mips_bne (code, ovfj->b0_cond, ovfj->b1_cond, 0);
- mips_nop (code);
- mips_jump (code, 0);
- /* jump back after the initial branch */
- mips_patch ((guint32 *)(void *)(code - 4), (guint32)(ip
+ 1));
- mips_nop (code);
- /* patch the conditional jump to the right handler */
- /* make it processed next */
- newji = mono_mempool_alloc (cfg->mempool, sizeof
(MonoJumpInfo));
- newji->type = MONO_PATCH_INFO_EXC;
- newji->ip.i = bcl - cfg->native_code;
- newji->data.target = ovfj->data.exception;
- newji->next = patch_info->next;
- patch_info->next = newji;
- break;
- }
-#endif
case MONO_PATCH_INFO_EXC: {
+#if 0
//unsigned char *ip = patch_info->ip.i +
cfg->native_code;
i = exception_id_by_name (patch_info->data.target);
@@ -3877,6 +3804,9 @@
/* Turn into a Relative patch, pointing at code stub */
patch_info->type = MONO_PATCH_INFO_METHOD_REL;
patch_info->data.offset = exc_throw_pos[i] -
cfg->native_code;
+#else
+ g_assert_not_reached();
+#endif
break;
}
default:
@@ -3888,7 +3818,7 @@
cfg->code_len = code - cfg->native_code;
g_assert (cfg->code_len < cfg->code_size);
-
+#endif
}
/*
Modified: trunk/mono/mono/mini/mini-mips.h
===================================================================
--- trunk/mono/mono/mini/mini-mips.h 2007-01-17 20:03:33 UTC (rev 71226)
+++ trunk/mono/mono/mini/mini-mips.h 2007-01-17 20:17:41 UTC (rev 71227)
@@ -354,17 +354,17 @@
do { \
switch (cmp_op) { \
case CEE_BEQ: \
- MONO_EMIT_NEW_BRANCH_BIREG_BLOCK(cfg, OP_MIPS_BEQ,
sreg1, sreg2, block); \
+ MONO_EMIT_NEW_BRANCH_BIREG_BLOCK (cfg, OP_MIPS_BEQ,
sreg1, sreg2, block); \
break; \
case CEE_BNE_UN: \
- MONO_EMIT_NEW_BRANCH_BIREG_BLOCK(cfg, OP_MIPS_BNE,
sreg1, sreg2, block); \
+ MONO_EMIT_NEW_BRANCH_BIREG_BLOCK (cfg, OP_MIPS_BNE,
sreg1, sreg2, block); \
break; \
case CEE_BLT_UN: \
MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLTU, mips_at, sreg1,
sreg2); \
- MONO_EMIT_NEW_BRANCH_BIREG_BLOCK(cfg, OP_MIPS_BNE,
mips_at, mips_zero, block); \
+ MONO_EMIT_NEW_BRANCH_BIREG_BLOCK (cfg, OP_MIPS_BNE,
mips_at, mips_zero, block); \
break; \
default: \
- g_assert_not_reached(); \
+ g_assert_not_reached (); \
} \
} while (0)
#endif
@@ -384,6 +384,76 @@
} while (0)
#endif
+#define MONO_EMIT_NEW_MIPS_COND_EXC(cfg,cond,sr1,sr2,name) do { \
+ MonoInst *inst; \
+ inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst));
\
+ inst->opcode = cond; \
+ inst->inst_p1 = (char*)name; \
+ inst->sreg1 = sr1; \
+ inst->sreg2 = sr2; \
+ mono_bblock_add_inst ((cfg)->cbb, inst); \
+ } while (0)
+
+#ifndef MONO_EMIT_NEW_COMPARE_EXC
+#define MONO_EMIT_NEW_COMPARE_EXC(cfg, cmp_op, sreg1, sreg2, exc) do { \
+ switch (OP_MIPS_COND_EXC_##cmp_op) { \
+ case OP_MIPS_COND_EXC_EQ: \
+ MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_EQ,
sreg1, sreg2, exc); \
+ break; \
+ case OP_MIPS_COND_EXC_NE_UN: \
+ MONO_EMIT_NEW_MIPS_COND_EXC (cfg,
OP_MIPS_COND_EXC_NE_UN, sreg1, sreg2, exc); \
+ break; \
+ case OP_MIPS_COND_EXC_GT: \
+ MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLT, mips_at, sreg2,
sreg1); \
+ MONO_EMIT_NEW_MIPS_COND_EXC (cfg,
OP_MIPS_COND_EXC_NE_UN, mips_at, mips_zero, exc); \
+ break; \
+ case OP_MIPS_COND_EXC_GT_UN: \
+ MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLTU, mips_at, sreg2,
sreg1); \
+ MONO_EMIT_NEW_MIPS_COND_EXC (cfg,
OP_MIPS_COND_EXC_NE_UN, mips_at, mips_zero, exc); \
+ break; \
+ case OP_MIPS_COND_EXC_LE: \
+ MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLT, mips_at, sreg2,
sreg1); \
+ MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_EQ,
mips_at, mips_zero, exc); \
+ break; \
+ case OP_MIPS_COND_EXC_LE_UN: \
+ MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLTU, mips_at, sreg2,
sreg1); \
+ MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_EQ,
mips_at, mips_zero, exc); \
+ break; \
+ case OP_MIPS_COND_EXC_LT: \
+ MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLT, mips_at, sreg1,
sreg2); \
+ MONO_EMIT_NEW_MIPS_COND_EXC (cfg,
OP_MIPS_COND_EXC_NE_UN, mips_at, mips_zero, exc); \
+ break; \
+ case OP_MIPS_COND_EXC_LT_UN: \
+ MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLTU, mips_at, sreg1,
sreg2); \
+ MONO_EMIT_NEW_MIPS_COND_EXC (cfg,
OP_MIPS_COND_EXC_NE_UN, mips_at, mips_zero, exc); \
+ break; \
+ default: \
+ g_warning ("unknown comparison %s\n", #cmp_op); \
+ g_assert_not_reached (); \
+ } \
+ } while (0)
+#endif
+
+#ifndef MONO_EMIT_NEW_COMPARE_IMM_EXC
+#define MONO_EMIT_NEW_COMPARE_IMM_EXC(cfg, cmp_op, sreg1, imm, exc) do { \
+ guint32 cmp_reg; \
+ if (!(imm)) { \
+ cmp_reg = mips_zero; \
+ } \
+ else { \
+ cmp_reg = mips_at; \
+ MONO_EMIT_NEW_ICONST (cfg, cmp_reg, (imm)); \
+ } \
+ MONO_EMIT_NEW_COMPARE_EXC (cfg, cmp_op, sreg1, cmp_reg, exc); \
+ } while (0)
+#endif
+
+#ifndef MONO_EMIT_NEW_ICOMPARE_IMM_EXC
+#define MONO_EMIT_NEW_ICOMPARE_IMM_EXC(cfg, cmp_op, sreg1, imm, exc) do { \
+ MONO_EMIT_NEW_COMPARE_IMM_EXC(cfg, cmp_op, sreg1, imm, exc); \
+ } while (0)
+#endif
+
typedef struct {
gint8 reg;
gint8 size;
Modified: trunk/mono/mono/mini/mini-ops.h
===================================================================
--- trunk/mono/mono/mini/mini-ops.h 2007-01-17 20:03:33 UTC (rev 71226)
+++ trunk/mono/mono/mini/mini-ops.h 2007-01-17 20:17:41 UTC (rev 71227)
@@ -770,4 +770,37 @@
MINI_OP(OP_MIPS_SLTIU, "mips_sltiu")
MINI_OP(OP_MIPS_SLTU, "mips_sltu")
MINI_OP(OP_MIPS_XORI, "mips_xori")
+
+MINI_OP(OP_MIPS_COND_EXC_EQ, "mips_cond_exc_eq")
+MINI_OP(OP_MIPS_COND_EXC_GE, "mips_cond_exc_ge")
+MINI_OP(OP_MIPS_COND_EXC_GT, "mips_cond_exc_gt")
+MINI_OP(OP_MIPS_COND_EXC_LE, "mips_cond_exc_le")
+MINI_OP(OP_MIPS_COND_EXC_LT, "mips_cond_exc_lt")
+MINI_OP(OP_MIPS_COND_EXC_NE_UN, "mips_cond_exc_ne_un")
+MINI_OP(OP_MIPS_COND_EXC_GE_UN, "mips_cond_exc_ge_un")
+MINI_OP(OP_MIPS_COND_EXC_GT_UN, "mips_cond_exc_gt_un")
+MINI_OP(OP_MIPS_COND_EXC_LE_UN, "mips_cond_exc_le_un")
+MINI_OP(OP_MIPS_COND_EXC_LT_UN, "mips_cond_exc_lt_un")
+
+MINI_OP(OP_MIPS_COND_EXC_OV, "mips_cond_exc_ov")
+MINI_OP(OP_MIPS_COND_EXC_NO, "mips_cond_exc_no")
+MINI_OP(OP_MIPS_COND_EXC_C, "mips_cond_exc_c")
+MINI_OP(OP_MIPS_COND_EXC_NC, "mips_cond_exc_nc")
+
+MINI_OP(OP_MIPS_COND_EXC_IEQ, "mips_cond_exc_ieq")
+MINI_OP(OP_MIPS_COND_EXC_IGE, "mips_cond_exc_ige")
+MINI_OP(OP_MIPS_COND_EXC_IGT, "mips_cond_exc_igt")
+MINI_OP(OP_MIPS_COND_EXC_ILE, "mips_cond_exc_ile")
+MINI_OP(OP_MIPS_COND_EXC_ILT, "mips_cond_exc_ilt")
+MINI_OP(OP_MIPS_COND_EXC_INE_UN, "mips_cond_exc_ine_un")
+MINI_OP(OP_MIPS_COND_EXC_IGE_UN, "mips_cond_exc_ige_un")
+MINI_OP(OP_MIPS_COND_EXC_IGT_UN, "mips_cond_exc_igt_un")
+MINI_OP(OP_MIPS_COND_EXC_ILE_UN, "mips_cond_exc_ile_un")
+MINI_OP(OP_MIPS_COND_EXC_ILT_UN, "mips_cond_exc_ilt_un")
+
+MINI_OP(OP_MIPS_COND_EXC_IOV, "mips_cond_exc_iov")
+MINI_OP(OP_MIPS_COND_EXC_INO, "mips_cond_exc_ino")
+MINI_OP(OP_MIPS_COND_EXC_IC, "mips_cond_exc_ic")
+MINI_OP(OP_MIPS_COND_EXC_INC, "mips_cond_exc_inc")
+
#endif
_______________________________________________
Mono-patches maillist - [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches