Bugzilla – Bug 315084
[PATCH] BIGMUL does not handle signs correctly
Last modified: 2007-09-15 21:24:46 UTC
---- Reported by sebastien@ximian.com 2004-06-11 16:12:05 MST ---- Description of Problem: Multiplying a long with a negative integer results in a big positive integer. There are no (visible) overflow involved. Steps to reproduce the problem: 1. Compile the following source using System; class T { static void Main () { int seconds = -59; Console.Out.WriteLine ("{0} * {1} == {2}", TimeSpan.TicksPerSecond, seconds, (TimeSpan.TicksPerSecond * seconds)); } } 2. Execute Actual Results (Mono): 10000000 * -59 == 42949672370000000 Expected Results: 10000000 * -59 == -590000000 How often does this happen? Always Additional Information: The same binary gives the right result when executed by the MS runtime. ---- Additional Comments From bmaurer@users.sf.net 2004-06-12 00:11:30 MST ---- Simpler: class T { static void Main () { const long a = 1; int b = -59; System.Console.WriteLine (a * b); } } Gives: 4294967237 ---- Additional Comments From bmaurer@users.sf.net 2004-06-12 00:12:51 MST ---- nb: 4294967237 == 0xFFFFFFC5. We want 0xFFFFFFFFFFFFFFC5. I think we need cdq in here somewhere... ---- Additional Comments From bmaurer@users.sf.net 2004-06-12 00:19:27 MST ---- converting method T:Main () creating vars creating locals locals done method to IR T:Main () converting (in B2: stack: 0) IL_0000: ldc.i4.s -59 converting (in B2: stack: 1) IL_0002: stloc.1 converting (in B2: stack: 0) IL_0003: ldc.i4.1 converting (in B2: stack: 1) IL_0004: conv.u8 converting (in B2: stack: 1) IL_0005: ldloc.1 converting (in B2: stack: 2) IL_0006: conv.i8 converting (in B2: stack: 2) IL_0007: mul converting (in B2: stack: 1) IL_0008: call 0x0a000002 converting (in B2: stack: 0) IL_000d: ret REGION BB0 IL_0000 ID_FFFFFFFF REGION BB3 IL_0000 ID_FFFFFFFF REGION BB2 IL_000d ID_FFFFFFFF REGION BB1 IL_0000 ID_FFFFFFFF block merge triggered 3 -> 2 br removal triggered 3 -> 1 REGVAR 1 C3 R7 DUMP BLOCK 0: DUMP BLOCK 3: (stind.i8 regoffset[-0x10(%ebp)] i8const[0]) (stind.i4 regvar[%edi] iconst[0]) (stind.i4 regvar[%edi] iconst[-59]) (stind.i8 regoffset[-0x18(%ebp)] (op_bigmul_un iconst[1] (ldind.i4 regvar[%edi]))) (outarg (ldind.i8 regoffset[-0x18(%ebp)])) voidcall[WriteLine] nop ... 15: bf 00 00 00 00 mov edi,0x0 1a: bf c5 ff ff ff mov edi,0xffffffc5 1f: b8 01 00 00 00 mov eax,0x1 24: 8b cf mov ecx,edi 26: f7 e1 mul ecx ---- Additional Comments From bmaurer@users.sf.net 2004-06-12 00:25:59 MST ---- Created an attachment (id=166244) Patch ---- Additional Comments From bmaurer@users.sf.net 2004-06-12 00:27:46 MST ---- This patch makes the BIGMUL code require that the two operands of the multiply use the same conversion op. E.g, ((ulong) x) * ((long) y) will need to use the long path. ---- Additional Comments From bmaurer@users.sf.net 2004-06-12 12:55:45 MST ---- FIXED in cvs. Imported an attachment (id=166244)