From 0d2da4d195a040bb8d94af74c71b3f2dfaf17163 Mon Sep 17 00:00:00 2001
From: Damien Diederen
Date: Tue, 1 Feb 2011 22:16:59 +0100
Subject: [PATCH 1/4] MIPS: Throw OverflowException if Int32.MinValue is
divided by -1
Without this, the code throws the more general ArithmeticException
when the divisor is -1, independently of the dividend. The check is
necessary because -Int32.MinValue does not fit into a 32-bit two's
complement integer.
Commit contributed under the MIT/X11 license.
---
mono/mini/cpu-mips.md | 6 +++---
mono/mini/mini-mips.c | 12 ++++++++----
2 files changed, 11 insertions(+), 7 deletions(-)
diff --git a/mono/mini/cpu-mips.md b/mono/mini/cpu-mips.md
index 9fd28107c3c9..86449be788e7 100644
--- a/mono/mini/cpu-mips.md
+++ b/mono/mini/cpu-mips.md
@@ -162,10 +162,10 @@ not_null: src1:i len:0
int_add: dest:i src1:i src2:i len:4
int_sub: dest:i src1:i src2:i len:4
int_mul: dest:i src1:i src2:i len:4
-int_div: dest:i src1:i src2:i len:76
+int_div: dest:i src1:i src2:i len:84
int_div_un: dest:i src1:i src2:i len:40
-int_rem: dest:i src1:i src2:i len:76
-int_rem_un: dest:i src1:i src2:i len:76
+int_rem: dest:i src1:i src2:i len:84
+int_rem_un: dest:i src1:i src2:i len:40
int_and: dest:i src1:i src2:i len:4
int_or: dest:i src1:i src2:i len:4
int_xor: dest:i src1:i src2:i len:4
diff --git a/mono/mini/mini-mips.c b/mono/mini/mini-mips.c
index 6dd289c6bb2e..27eba3b88212 100644
--- a/mono/mini/mini-mips.c
+++ b/mono/mini/mini-mips.c
@@ -3370,18 +3370,22 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
case OP_IDIV:
case OP_IREM: {
guint32 *divisor_is_m1;
+ guint32 *dividend_is_minvalue;
guint32 *divisor_is_zero;
- /* */
- mips_addiu (code, mips_at, mips_zero, 0xffff);
+ mips_load_const (code, mips_at, -1);
divisor_is_m1 = (guint32 *)(void *)code;
mips_bne (code, ins->sreg2, mips_at, 0);
+ mips_lui (code, mips_at, mips_zero, 0x8000);
+ dividend_is_minvalue = (guint32 *)(void *)code;
+ mips_bne (code, ins->sreg1, mips_at, 0);
mips_nop (code);
- /* Divide by -1 -- throw exception */
- EMIT_SYSTEM_EXCEPTION_NAME("ArithmeticException");
+ /* Divide Int32.MinValue by -1 -- throw exception */
+ EMIT_SYSTEM_EXCEPTION_NAME("OverflowException");
mips_patch (divisor_is_m1, (guint32)code);
+ mips_patch (dividend_is_minvalue, (guint32)code);
/* Put divide in branch delay slot (NOT YET) */
divisor_is_zero = (guint32 *)(void *)code;
From 64e3e3174d02acb30203b45a234347fdb3bcf5c5 Mon Sep 17 00:00:00 2001
From: Damien Diederen
Date: Wed, 2 Feb 2011 21:13:38 +0100
Subject: [PATCH 2/4] MIPS: Use SLTU to implement COND_EXC_LE_UN (Exception
when <= unsigned)
The current code generator uses a SUBU/BLEZ combination, but this
breaks for non-zero-based arrays. Given a lower bound 'b', length
'l', and an index 'i', Mini generates:
real_i = i - b;
COND_EXC_LE_UN(l, real_i);
Without this patch, the backend generates for e.g. b=42, l=1 and i=0:
SUBU real_i, 0, 42 => -42
SUBU at, 1, real_i => 43 (U only means "no trap.")
BLEZ at, throw => No throw because at is positive!
This causes the following sequence to be used instead:
SUBU real_i, 0, 42 => -42
SLTU at, real_i, 1 => 0 (Unsigned '<'; real_i is a large value)
BEQ at, zero, throw => Throw.
Commit contributed under the MIT/X11 license.
---
mono/mini/mini-mips.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/mono/mini/mini-mips.c b/mono/mini/mini-mips.c
index 27eba3b88212..1c73cb92d63c 100644
--- a/mono/mini/mini-mips.c
+++ b/mono/mini/mini-mips.c
@@ -3949,9 +3949,9 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
break;
case OP_MIPS_COND_EXC_LE_UN:
- mips_subu (code, mips_at, ins->sreg1, ins->sreg2);
+ mips_sltu (code, mips_at, ins->sreg2, ins->sreg1);
throw = (guint32 *)(void *)code;
- mips_blez (code, mips_at, 0);
+ mips_beq (code, mips_at, mips_zero, 0);
mips_nop (code);
break;
From ba12aeafe5d2d3e91ad61155220ea21f8db3b33b Mon Sep 17 00:00:00 2001
From: Damien Diederen
Date: Thu, 3 Feb 2011 21:50:38 +0100
Subject: [PATCH 3/4] MIPS: Fix unboxing trampolines for functions returning
value types
Generated methods always place 'this' in a0, but unboxing trampolines
currently bump a1 for functions returning value types (the register
assignments for 'this' and return area pointers probably got swapped
at some point, but the trampoline generator was not updated).
Fix that by always bumping a0.
Commit contributed under the MIT/X11 license.
---
mono/mini/tramp-mips.c | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/mono/mini/tramp-mips.c b/mono/mini/tramp-mips.c
index 3cc54ce4c2dd..8699082adcbc 100644
--- a/mono/mini/tramp-mips.c
+++ b/mono/mini/tramp-mips.c
@@ -38,16 +38,13 @@ gpointer
mono_arch_get_unbox_trampoline (MonoGenericSharingContext *gsctx, MonoMethod *m, gpointer addr)
{
guint8 *code, *start;
- int this_pos = mips_a0;
MonoDomain *domain = mono_domain_get ();
-
- if (MONO_TYPE_ISSTRUCT (mono_method_signature (m)->ret))
- this_pos = mips_a1;
start = code = mono_domain_code_reserve (domain, 20);
mips_load (code, mips_t9, addr);
- mips_addiu (code, this_pos, this_pos, sizeof (MonoObject));
+ /* The this pointer is kept in a0 */
+ mips_addiu (code, mips_a0, mips_a0, sizeof (MonoObject));
mips_jr (code, mips_t9);
mips_nop (code);
From d1c7b1add25dd905d03c3045b4ed85335b90d766 Mon Sep 17 00:00:00 2001
From: Damien Diederen
Date: Mon, 7 Feb 2011 23:22:40 +0100
Subject: [PATCH 4/4] MIPS: Ignore float->int overflow behaviour, as on PPC,
ARM, and SPARC
From the comment:
$TARGET handles overflow by clipping, but this test assumes no overflow
handling. According to ECMA the result of float->int conversion is undefined
if overflow occurs, so both behaviours are valid.
Commit contributed under the MIT/X11 license.
---
mono/mini/iltests.il.in | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mono/mini/iltests.il.in b/mono/mini/iltests.il.in
index b2d88a7878eb..2c89d976a1a8 100644
--- a/mono/mini/iltests.il.in
+++ b/mono/mini/iltests.il.in
@@ -963,7 +963,7 @@ COND: ldloc.0
ret
}
-#if !defined(__ppc__) && !defined(__powerpc__) && !defined(__arm__) && !defined(__sparc__)
+#if !defined(__ppc__) && !defined(__powerpc__) && !defined(__arm__) && !defined(__sparc__) && !defined(__mips__)
// PPC handles overflow by clipping, but this test assumes
// no overflow handling. According to ECMA the result of
// float->int conversion is undefined if overflow occurs, so