From 148cbdcb33296fcb207678e2ac19cee078136650 Mon Sep 17 00:00:00 2001 From: Lionel Flandrin Date: Tue, 17 Nov 2015 18:43:37 +0100 Subject: [PATCH] Fix GTE sign extention issues --- src/cpu/gte/mod.rs | 41 ++- src/cpu/gte/tests.rs | 702 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 727 insertions(+), 16 deletions(-) diff --git a/src/cpu/gte/mod.rs b/src/cpu/gte/mod.rs index 8e49110..31aa8e2 100644 --- a/src/cpu/gte/mod.rs +++ b/src/cpu/gte/mod.rs @@ -658,7 +658,9 @@ impl Gte { // Compute the sum in 64bits to detect overflows let sum = a as i64 + b as i64 + c as i64; - self.mac[0] = self.i64_to_i32_result(sum); + self.check_mac_overflow(sum); + + self.mac[0] = sum as i32; } /// Outer Product @@ -725,18 +727,18 @@ impl Gte { let shading = (col * ir) as i64; - let product = fc - shading; + let tmp = fc - shading; - let tmp = self.i64_to_i32_result(product) >> config.shift; + let tmp = (self.i64_to_i44(i as u8, tmp) >> config.shift) as i32; let ir0 = self.ir[0] as i64; let res = self.i32_to_i16_saturate(CommandConfig::from_command(0), i as u8, tmp) as i64; - let res = self.i64_to_i32_result(shading + ir0 * res); + let res = self.i64_to_i44(i as u8, shading + ir0 * res); - self.mac[i + 1] = res >> config.shift; + self.mac[i + 1] = (res >> config.shift) as i32; } self.mac_to_ir(config); @@ -894,7 +896,9 @@ impl Gte { let average = zsf3 * sum as i64; - self.mac[0] = self.i64_to_i32_result(average); + self.check_mac_overflow(average); + + self.mac[0] = average as i32; self.otz = self.i64_to_otz(average); } @@ -915,7 +919,9 @@ impl Gte { let average = zsf4 * sum as i64; - self.mac[0] = self.i64_to_i32_result(average); + self.check_mac_overflow(average); + + self.mac[0] = average as i32; self.otz = self.i64_to_otz(average); } @@ -1254,8 +1260,14 @@ impl Gte { let ofy = self.ofy as i64; // Project X and Y onto the plane - let screen_x = self.i64_to_i32_result(x * factor + ofx) >> 16; - let screen_y = self.i64_to_i32_result(y * factor + ofy) >> 16; + let screen_x = x * factor + ofx; + let screen_y = y * factor + ofy; + + self.check_mac_overflow(screen_x); + self.check_mac_overflow(screen_y); + + let screen_x = (screen_x >> 16) as i32; + let screen_y = (screen_y >> 16) as i32; // Push onto the XY FIFO self.xy_fifo[3] = (self.i32_to_i11_saturate(0, screen_x), @@ -1279,7 +1291,9 @@ impl Gte { let depth = dqb + dqa * factor; - self.mac[0] = self.i64_to_i32_result(depth); + self.check_mac_overflow(depth); + + self.mac[0] = depth as i32; // Compute 16bit IR value let depth = depth >> 12; @@ -1356,16 +1370,13 @@ impl Gte { } } - /// Convert i64 to i32, in case of a truncation set the result - /// overflow flags (but don't saturate the result) - fn i64_to_i32_result(&mut self, val: i64) -> i32 { + /// Check for 32bit overflow in the accumulator + fn check_mac_overflow(&mut self, val: i64) { if val < -0x80000000 { self.set_flag(15); } else if val > 0x7fffffff { self.set_flag(16); } - - val as i32 } /// Convert a 64bit signed average value to an unsigned halfword diff --git a/src/cpu/gte/tests.rs b/src/cpu/gte/tests.rs index d94f9a2..9fec945 100644 --- a/src/cpu/gte/tests.rs +++ b/src/cpu/gte/tests.rs @@ -2165,6 +2165,706 @@ static TESTS: &'static [Test] = &[ ], }, }, - + Test { + desc: "GTE_OP GTE_DCPL, lm=0, cv=0, v=0, mx=0, sf=1 full 0xffffffff", + initial: Config { + controls: &[ + (0, 0xffffffff), + (1, 0xffffffff), + (2, 0xffffffff), + (3, 0xffffffff), + (4, 0xffffffff), + (5, 0xffffffff), + (6, 0xffffffff), + (7, 0xffffffff), + (8, 0xffffffff), + (9, 0xffffffff), + (10, 0xffffffff), + (11, 0xffffffff), + (12, 0xffffffff), + (13, 0xffffffff), + (14, 0xffffffff), + (15, 0xffffffff), + (16, 0xffffffff), + (17, 0xffffffff), + (18, 0xffffffff), + (19, 0xffffffff), + (20, 0xffffffff), + (21, 0xffffffff), + (22, 0xffffffff), + (23, 0xffffffff), + (24, 0xffffffff), + (25, 0xffffffff), + (26, 0xffffffff), + (27, 0xffffffff), + (28, 0xffffffff), + (29, 0xffffffff), + (30, 0xffffffff), + (31, 0xfffff000), + ], + data: &[ + (0, 0xffffffff), + (1, 0xffffffff), + (2, 0xffffffff), + (3, 0xffffffff), + (4, 0xffffffff), + (5, 0xffffffff), + (6, 0xffffffff), + (7, 0x0000ffff), + (8, 0xffffffff), + (9, 0x00000f80), + (10, 0x00000f80), + (11, 0x00000f80), + (12, 0xffffffff), + (13, 0xffffffff), + (14, 0xffffffff), + (15, 0xffffffff), + (16, 0x0000ffff), + (17, 0x0000ffff), + (18, 0x0000ffff), + (19, 0x0000ffff), + (20, 0xffffffff), + (21, 0xffffffff), + (22, 0xffffffff), + (23, 0xffffffff), + (24, 0xffffffff), + (25, 0xffffffff), + (26, 0xffffffff), + (27, 0xffffffff), + (28, 0x00007fff), + (29, 0x00007fff), + (30, 0xffffffff), + (31, 0x00000020), + ], + }, + command: 0x00080029, + result: Config { + controls: &[ + (0, 0xffffffff), + (1, 0xffffffff), + (2, 0xffffffff), + (3, 0xffffffff), + (4, 0xffffffff), + (5, 0xffffffff), + (6, 0xffffffff), + (7, 0xffffffff), + (8, 0xffffffff), + (9, 0xffffffff), + (10, 0xffffffff), + (11, 0xffffffff), + (12, 0xffffffff), + (13, 0xffffffff), + (14, 0xffffffff), + (15, 0xffffffff), + (16, 0xffffffff), + (17, 0xffffffff), + (18, 0xffffffff), + (19, 0xffffffff), + (20, 0xffffffff), + (21, 0xffffffff), + (22, 0xffffffff), + (23, 0xffffffff), + (24, 0xffffffff), + (25, 0xffffffff), + (26, 0xffffffff), + (27, 0xffffffff), + (28, 0xffffffff), + (29, 0xffffffff), + (30, 0xffffffff), + ], + data: &[ + (0, 0xffffffff), + (1, 0xffffffff), + (2, 0xffffffff), + (3, 0xffffffff), + (4, 0xffffffff), + (5, 0xffffffff), + (6, 0xffffffff), + (7, 0x0000ffff), + (8, 0xffffffff), + (9, 0x00000f71), + (10, 0x00000f71), + (11, 0x00000f71), + (12, 0xffffffff), + (13, 0xffffffff), + (14, 0xffffffff), + (15, 0xffffffff), + (16, 0x0000ffff), + (17, 0x0000ffff), + (18, 0x0000ffff), + (19, 0x0000ffff), + (20, 0xffffffff), + (21, 0xffffffff), + (22, 0xfff7f7f7), + (23, 0xffffffff), + (24, 0xffffffff), + (25, 0x00000f71), + (26, 0x00000f71), + (27, 0x00000f71), + (28, 0x00007bde), + (29, 0x00007bde), + (30, 0xffffffff), + (31, 0x00000020), + ], + }, + }, + Test { + desc: "GTE_OP GTE_MVMVA, lm=0, cv=0, v=0, mx=0, sf=1 random", + initial: Config { + controls: &[ + (0, 0xff35cdf4), + (1, 0xf8acd6a6), + (2, 0x1954aa70), + (3, 0xae7b5062), + (4, 0x00000c63), + (5, 0xcad4cc39), + (6, 0xb9c11958), + (7, 0xa942b312), + (8, 0xaf436779), + (9, 0x3c2d507a), + (10, 0x95f99741), + (11, 0x72413224), + (12, 0x0000499d), + (13, 0x0a37d280), + (14, 0xdbe8feec), + (15, 0x2395909a), + (16, 0x47364c98), + (17, 0x795c2ed7), + (18, 0x637e48f4), + (19, 0x89557da5), + (20, 0xffff997a), + (21, 0x690eb551), + (22, 0x3dfb368e), + (23, 0x2bbe355f), + (24, 0xb07c9d22), + (25, 0x030c876b), + (26, 0x00003b7d), + (27, 0x0000765a), + (28, 0x228c2901), + (29, 0xffffe86f), + (30, 0xffffaf93), + (31, 0xc741f000), + ], + data: &[ + (0, 0x91d5c574), + (1, 0xffffdf9c), + (2, 0xcea213bc), + (3, 0x0000143e), + (4, 0x2360a947), + (5, 0x00003248), + (6, 0x1747e72e), + (7, 0x0000cc08), + (8, 0x0000381d), + (9, 0xffffe2ff), + (10, 0xffffe0f8), + (11, 0xffffe1b6), + (12, 0x9da7438d), + (13, 0xff60f0ed), + (14, 0xbf5961ab), + (15, 0xbf5961ab), + (16, 0x0000b1c1), + (17, 0x0000dda6), + (18, 0x0000ce75), + (19, 0x0000b2d1), + (20, 0xdb01b77a), + (21, 0x19cd28cd), + (22, 0x1a75d97a), + (23, 0xe91dc0ad), + (24, 0x764e464f), + (25, 0x4aa5a1e5), + (26, 0x3b1a1977), + (27, 0x39fb3f5f), + (30, 0xfe8de0c9), + (31, 0x00000007), + ], + }, + command: 0x00080012, + result: Config { + controls: &[ + (0, 0xff35cdf4), + (1, 0xf8acd6a6), + (2, 0x1954aa70), + (3, 0xae7b5062), + (4, 0x00000c63), + (5, 0xcad4cc39), + (6, 0xb9c11958), + (7, 0xa942b312), + (8, 0xaf436779), + (9, 0x3c2d507a), + (10, 0x95f99741), + (11, 0x72413224), + (12, 0x0000499d), + (13, 0x0a37d280), + (14, 0xdbe8feec), + (15, 0x2395909a), + (16, 0x47364c98), + (17, 0x795c2ed7), + (18, 0x637e48f4), + (19, 0x89557da5), + (20, 0xffff997a), + (21, 0x690eb551), + (22, 0x3dfb368e), + (23, 0x2bbe355f), + (24, 0xb07c9d22), + (25, 0x030c876b), + (26, 0x00003b7d), + (27, 0x0000765a), + (28, 0x228c2901), + (29, 0xffffe86f), + (30, 0xffffaf93), + (31, 0x81c00000), + ], + data: &[ + (0, 0x91d5c574), + (1, 0xffffdf9c), + (2, 0xcea213bc), + (3, 0x0000143e), + (4, 0x2360a947), + (5, 0x00003248), + (6, 0x1747e72e), + (7, 0x0000cc08), + (8, 0x0000381d), + (9, 0xffff8000), + (10, 0xffff8000), + (11, 0xffff8000), + (12, 0x9da7438d), + (13, 0xff60f0ed), + (14, 0xbf5961ab), + (15, 0xbf5961ab), + (16, 0x0000b1c1), + (17, 0x0000dda6), + (18, 0x0000ce75), + (19, 0x0000b2d1), + (20, 0xdb01b77a), + (21, 0x19cd28cd), + (22, 0x1a75d97a), + (23, 0xe91dc0ad), + (24, 0x764e464f), + (25, 0xcad5dc86), + (26, 0xb9c34e06), + (27, 0xa943a529), + (30, 0xfe8de0c9), + (31, 0x00000007), + ], + }, + }, + Test { + desc: "GTE_OP GTE_RTPS, lm=0, cv=0, v=0, mx=0, sf=1 random", + initial: Config { + controls: &[ + (0, 0xff35cdf4), + (1, 0xf8acd6a6), + (2, 0x1954aa70), + (3, 0xae7b5062), + (4, 0x00000c63), + (5, 0xcad4cc39), + (6, 0xb9c11958), + (7, 0xa942b312), + (8, 0xaf436779), + (9, 0x3c2d507a), + (10, 0x95f99741), + (11, 0x72413224), + (12, 0x0000499d), + (13, 0x0a37d280), + (14, 0xdbe8feec), + (15, 0x2395909a), + (16, 0x47364c98), + (17, 0x795c2ed7), + (18, 0x637e48f4), + (19, 0x89557da5), + (20, 0xffff997a), + (21, 0x690eb551), + (22, 0x3dfb368e), + (23, 0x2bbe355f), + (24, 0x307c9d22), + (25, 0x030c876b), + (26, 0x00003b7d), + (27, 0x0000765a), + (28, 0x228c2901), + (29, 0xffffe86f), + (30, 0xffffaf93), + (31, 0xc741f000), + ], + data: &[ + (0, 0x91d5c574), + (1, 0xffffdf9c), + (2, 0xcea213bc), + (3, 0x0000143e), + (4, 0x2360a947), + (5, 0x00003248), + (6, 0x1747e72e), + (7, 0x0000cc08), + (8, 0x0000381d), + (9, 0xffffe2ff), + (10, 0xffffe0f8), + (11, 0xffffe1b6), + (12, 0x9da7438d), + (13, 0xff60f0ed), + (14, 0xbf5961ab), + (15, 0xbf5961ab), + (16, 0x0000b1c1), + (17, 0x0000dda6), + (18, 0x0000ce75), + (19, 0x0000b2d1), + (20, 0xdb01b77a), + (21, 0x19cd28cd), + (22, 0x1a75d97a), + (23, 0xe91dc0ad), + (24, 0x764e464f), + (25, 0x4aa5a1e5), + (26, 0x3b1a1977), + (27, 0x39fb3f5f), + (30, 0xfe8de0c9), + (31, 0x00000007), + ], + }, + command: 0x00080001, + result: Config { + controls: &[ + (0, 0xff35cdf4), + (1, 0xf8acd6a6), + (2, 0x1954aa70), + (3, 0xae7b5062), + (4, 0x00000c63), + (5, 0xcad4cc39), + (6, 0xb9c11958), + (7, 0xa942b312), + (8, 0xaf436779), + (9, 0x3c2d507a), + (10, 0x95f99741), + (11, 0x72413224), + (12, 0x0000499d), + (13, 0x0a37d280), + (14, 0xdbe8feec), + (15, 0x2395909a), + (16, 0x47364c98), + (17, 0x795c2ed7), + (18, 0x637e48f4), + (19, 0x89557da5), + (20, 0xffff997a), + (21, 0x690eb551), + (22, 0x3dfb368e), + (23, 0x2bbe355f), + (24, 0x307c9d22), + (25, 0x030c876b), + (26, 0x00003b7d), + (27, 0x0000765a), + (28, 0x228c2901), + (29, 0xffffe86f), + (30, 0xffffaf93), + (31, 0x81c7f000), + ], + data: &[ + (0, 0x91d5c574), + (1, 0xffffdf9c), + (2, 0xcea213bc), + (3, 0x0000143e), + (4, 0x2360a947), + (5, 0x00003248), + (6, 0x1747e72e), + (7, 0x0000cc08), + (8, 0x00001000), + (9, 0xffff8000), + (10, 0xffff8000), + (11, 0xffff8000), + (12, 0xff60f0ed), + (13, 0xbf5961ab), + (14, 0xfc00fc00), + (15, 0xfc00fc00), + (16, 0x0000dda6), + (17, 0x0000ce75), + (18, 0x0000b2d1), + (20, 0xdb01b77a), + (21, 0x19cd28cd), + (22, 0x1a75d97a), + (23, 0xe91dc0ad), + (24, 0x0f3fb2a7), + (25, 0xcad5dc86), + (26, 0xb9c34e06), + (27, 0xa943a529), + (30, 0xfe8de0c9), + (31, 0x00000007), + ], + }, + }, + Test { + desc: "GTE_OP GTE_RTPT, lm=0, cv=0, v=0, mx=0, sf=1 random", + initial: Config { + controls: &[ + (0, 0xff35cdf4), + (1, 0xf8acd6a6), + (2, 0x1954aa70), + (3, 0xae7b5062), + (4, 0x00000c63), + (5, 0xcad4cc39), + (6, 0xb9c11958), + (7, 0xa942b312), + (8, 0xaf436779), + (9, 0x3c2d507a), + (10, 0x95f99741), + (11, 0x72413224), + (12, 0x0000499d), + (13, 0x0a37d280), + (14, 0xdbe8feec), + (15, 0x2395909a), + (16, 0x47364c98), + (17, 0x795c2ed7), + (18, 0x637e48f4), + (19, 0x89557da5), + (20, 0xffff997a), + (21, 0x690eb551), + (22, 0x3dfb368e), + (23, 0x2bbe355f), + (24, 0x307c9d22), + (25, 0x030c876b), + (26, 0x00003b7d), + (27, 0x0000765a), + (28, 0x228c2901), + (29, 0xffffe86f), + (30, 0xffffaf93), + (31, 0xc741f000), + ], + data: &[ + (0, 0x91d5c574), + (1, 0xffffdf9c), + (2, 0xcea213bc), + (3, 0x0000143e), + (4, 0x2360a947), + (5, 0x00003248), + (6, 0x1747e72e), + (7, 0x0000cc08), + (8, 0x0000381d), + (9, 0xffffe2ff), + (10, 0xffffe0f8), + (11, 0xffffe1b6), + (12, 0x9da7438d), + (13, 0xff60f0ed), + (14, 0xbf5961ab), + (15, 0xbf5961ab), + (16, 0x0000b1c1), + (17, 0x0000dda6), + (18, 0x0000ce75), + (19, 0x0000b2d1), + (20, 0xdb01b77a), + (21, 0x19cd28cd), + (22, 0x1a75d97a), + (23, 0xe91dc0ad), + (24, 0x764e464f), + (25, 0x4aa5a1e5), + (26, 0x3b1a1977), + (27, 0x39fb3f5f), + (30, 0xfe8de0c9), + (31, 0x00000007), + ], + }, + command: 0x00080030, + result: Config { + controls: &[ + (0, 0xff35cdf4), + (1, 0xf8acd6a6), + (2, 0x1954aa70), + (3, 0xae7b5062), + (4, 0x00000c63), + (5, 0xcad4cc39), + (6, 0xb9c11958), + (7, 0xa942b312), + (8, 0xaf436779), + (9, 0x3c2d507a), + (10, 0x95f99741), + (11, 0x72413224), + (12, 0x0000499d), + (13, 0x0a37d280), + (14, 0xdbe8feec), + (15, 0x2395909a), + (16, 0x47364c98), + (17, 0x795c2ed7), + (18, 0x637e48f4), + (19, 0x89557da5), + (20, 0xffff997a), + (21, 0x690eb551), + (22, 0x3dfb368e), + (23, 0x2bbe355f), + (24, 0x307c9d22), + (25, 0x030c876b), + (26, 0x00003b7d), + (27, 0x0000765a), + (28, 0x228c2901), + (29, 0xffffe86f), + (30, 0xffffaf93), + (31, 0x81c7f000), + ], + data: &[ + (0, 0x91d5c574), + (1, 0xffffdf9c), + (2, 0xcea213bc), + (3, 0x0000143e), + (4, 0x2360a947), + (5, 0x00003248), + (6, 0x1747e72e), + (7, 0x0000cc08), + (8, 0x00001000), + (9, 0xffff8000), + (10, 0xffff8000), + (11, 0xffff8000), + (12, 0xfc00fc00), + (13, 0xfc00fc00), + (14, 0xfc00fc00), + (15, 0xfc00fc00), + (16, 0x0000b2d1), + (20, 0xdb01b77a), + (21, 0x19cd28cd), + (22, 0x1a75d97a), + (23, 0xe91dc0ad), + (24, 0x0f3fb2a7), + (25, 0xcad557c8), + (26, 0xb9c0d37c), + (27, 0xa9407212), + (30, 0xfe8de0c9), + (31, 0x00000007), + ], + }, + }, + Test { + desc: "GTE_OP GTE_DCPL, lm=0, cv=0, v=0, mx=0, sf=1 random", + initial: Config { + controls: &[ + (0, 0xff35cdf4), + (1, 0xf8acd6a6), + (2, 0x1954aa70), + (3, 0xae7b5062), + (4, 0x00000c63), + (5, 0xcad4cc39), + (6, 0xb9c11958), + (7, 0xa942b312), + (8, 0xaf436779), + (9, 0x3c2d507a), + (10, 0x95f99741), + (11, 0x72413224), + (12, 0x0000499d), + (13, 0x0a37d280), + (14, 0xdbe8feec), + (15, 0x2395909a), + (16, 0x47364c98), + (17, 0x795c2ed7), + (18, 0x637e48f4), + (19, 0x89557da5), + (20, 0xffff997a), + (21, 0x690eb551), + (22, 0x3dfb368e), + (23, 0x2bbe355f), + (24, 0xb07c9d22), + (25, 0x030c876b), + (26, 0x00003b7d), + (27, 0x0000765a), + (28, 0x228c2901), + (29, 0xffffe86f), + (30, 0xffffaf93), + (31, 0xc741f000), + ], + data: &[ + (0, 0x91d5c574), + (1, 0xffffdf9c), + (2, 0xcea213bc), + (3, 0x0000143e), + (4, 0x2360a947), + (5, 0x00003248), + (6, 0x1747e72e), + (7, 0x0000cc08), + (8, 0x0000381d), + (9, 0xffffe2ff), + (10, 0xffffe0f8), + (11, 0xffffe1b6), + (12, 0x9da7438d), + (13, 0xff60f0ed), + (14, 0xbf5961ab), + (15, 0xbf5961ab), + (16, 0x0000b1c1), + (17, 0x0000dda6), + (18, 0x0000ce75), + (19, 0x0000b2d1), + (20, 0xdb01b77a), + (21, 0x19cd28cd), + (22, 0x1a75d97a), + (23, 0xe91dc0ad), + (24, 0x764e464f), + (25, 0x4aa5a1e5), + (26, 0x3b1a1977), + (27, 0x39fb3f5f), + (30, 0xfe8de0c9), + (31, 0x00000007), + ], + }, + command: 0x00080029, + result: Config { + controls: &[ + (0, 0xff35cdf4), + (1, 0xf8acd6a6), + (2, 0x1954aa70), + (3, 0xae7b5062), + (4, 0x00000c63), + (5, 0xcad4cc39), + (6, 0xb9c11958), + (7, 0xa942b312), + (8, 0xaf436779), + (9, 0x3c2d507a), + (10, 0x95f99741), + (11, 0x72413224), + (12, 0x0000499d), + (13, 0x0a37d280), + (14, 0xdbe8feec), + (15, 0x2395909a), + (16, 0x47364c98), + (17, 0x795c2ed7), + (18, 0x637e48f4), + (19, 0x89557da5), + (20, 0xffff997a), + (21, 0x690eb551), + (22, 0x3dfb368e), + (23, 0x2bbe355f), + (24, 0xb07c9d22), + (25, 0x030c876b), + (26, 0x00003b7d), + (27, 0x0000765a), + (28, 0x228c2901), + (29, 0xffffe86f), + (30, 0xffffaf93), + (31, 0x81f80000), + ], + data: &[ + (0, 0x91d5c574), + (1, 0xffffdf9c), + (2, 0xcea213bc), + (3, 0x0000143e), + (4, 0x2360a947), + (5, 0x00003248), + (6, 0x1747e72e), + (7, 0x0000cc08), + (8, 0x0000381d), + (9, 0x00007fff), + (10, 0x00007fff), + (11, 0x00007fff), + (12, 0x9da7438d), + (13, 0xff60f0ed), + (14, 0xbf5961ab), + (15, 0xbf5961ab), + (16, 0x0000b1c1), + (17, 0x0000dda6), + (18, 0x0000ce75), + (19, 0x0000b2d1), + (20, 0x19cd28cd), + (21, 0x1a75d97a), + (22, 0x17ffffff), + (23, 0xe91dc0ad), + (24, 0x764e464f), + (25, 0x0001bbae), + (26, 0x0001a4e4), + (27, 0x0001b87d), + (28, 0x00007fff), + (29, 0x00007fff), + (30, 0xfe8de0c9), + (31, 0x00000007), + ], + }, + }, ];