From bdc24dcf24db1650372e1c11ac3ae23ed319ceae Mon Sep 17 00:00:00 2001 From: Franco Colmenarez Date: Sun, 21 Jan 2024 20:46:30 -0500 Subject: [PATCH] fix overflow flag --- snes-core/src/utils/alu.rs | 30 +++++++++++++++++++----------- snes-core/src/utils/num_trait.rs | 8 ++++---- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/snes-core/src/utils/alu.rs b/snes-core/src/utils/alu.rs index 1de606f..f16db07 100644 --- a/snes-core/src/utils/alu.rs +++ b/snes-core/src/utils/alu.rs @@ -170,11 +170,11 @@ mod alu_tests { let (result, affected_flags) = adc_bin(200_u8, 155_u8, false); assert_eq!(result, 99); - assert_eq!(affected_flags, [Negative(false), Overflow(false), Zero(false), Carry(true)]); + assert_eq!(affected_flags, [Negative(false), Overflow(true), Zero(false), Carry(true)]); let (result, affected_flags) = adc_bin(200_u8, 155_u8, true); assert_eq!(result, 100); - assert_eq!(affected_flags, [Negative(false), Overflow(false), Zero(false), Carry(true)]); + assert_eq!(affected_flags, [Negative(false), Overflow(true), Zero(false), Carry(true)]); let (result, affected_flags) = adc_bin(200_u8, 54_u8, true); assert_eq!(result, 255); @@ -184,6 +184,14 @@ mod alu_tests { assert_eq!(result, 255); assert_eq!(affected_flags, [Negative(true), Overflow(false), Zero(false), Carry(false)]); + let (result, affected_flags) = adc_bin(0x7F_u8, 0x81_u8, false); + assert_eq!(result, 0x00); + assert_eq!(affected_flags, [Negative(false), Overflow(false), Zero(true), Carry(true)]); + + let (result, affected_flags) = adc_bin(0x7F_u8, 0x7F_u8, true); + assert_eq!(result, 0xFF); + assert_eq!(affected_flags, [Negative(true), Overflow(true), Zero(false), Carry(false)]); + // 16 bits let (result, affected_flags) = adc_bin(0_u16, 0_u16, false); assert_eq!(result, 0); @@ -195,11 +203,11 @@ mod alu_tests { let (result, affected_flags) = adc_bin(65530_u16, 10_u16, false); assert_eq!(result, 4); - assert_eq!(affected_flags, [Negative(false), Overflow(true), Zero(false), Carry(true)]); + assert_eq!(affected_flags, [Negative(false), Overflow(false), Zero(false), Carry(true)]); let (result, affected_flags) = adc_bin(65530_u16, 10_u16, true); assert_eq!(result, 5); - assert_eq!(affected_flags, [Negative(false), Overflow(true), Zero(false), Carry(true)]); + assert_eq!(affected_flags, [Negative(false), Overflow(false), Zero(false), Carry(true)]); let (result, affected_flags) = adc_bin(65530_u16, 4_u16, true); assert_eq!(result, 65535); @@ -272,16 +280,16 @@ mod alu_tests { let (result, affected_flags) = sbc_bin(0_u8, 1_u8, false); assert_eq!(result, 0b11111111); - assert_eq!(affected_flags, [Negative(true), Overflow(false), Zero(false), Carry(true)]); + assert_eq!(affected_flags, [Negative(true), Overflow(true), Zero(false), Carry(true)]); let (result, affected_flags) = sbc_bin(0_u8, 1_u8, true); assert_eq!(result, 0b11111110); - assert_eq!(affected_flags, [Negative(true), Overflow(false), Zero(false), Carry(true)]); + assert_eq!(affected_flags, [Negative(true), Overflow(true), Zero(false), Carry(true)]); // overflow let (result, affected_flags) = sbc_bin(0x50_u8, 0xB0_u8, false); assert_eq!(result, 0xA0); - assert_eq!(affected_flags, [Negative(true), Overflow(true), Zero(false), Carry(true)]); + assert_eq!(affected_flags, [Negative(true), Overflow(false), Zero(false), Carry(true)]); // 16 bit let (result, affected_flags) = sbc_bin(1_u16, 1_u16, false); @@ -290,11 +298,11 @@ mod alu_tests { let (result, affected_flags) = sbc_bin(0_u16, 1_u16, false); assert_eq!(result, 0b11111111_11111111); - assert_eq!(affected_flags, [Negative(true), Overflow(false), Zero(false), Carry(true)]); + assert_eq!(affected_flags, [Negative(true), Overflow(true), Zero(false), Carry(true)]); let (result, affected_flags) = sbc_bin(0_u16, 1_u16, true); assert_eq!(result, 0b11111111_11111110); - assert_eq!(affected_flags, [Negative(true), Overflow(false), Zero(false), Carry(true)]); + assert_eq!(affected_flags, [Negative(true), Overflow(true), Zero(false), Carry(true)]); } #[test] @@ -306,7 +314,7 @@ mod alu_tests { let (result, affected_flags) = sbc_bcd(0x49_u8, 0x50_u8, true); assert_eq!(result, 0x99); - assert_eq!(affected_flags, [Negative(true), Overflow(false), Zero(false), Carry(false)]); + assert_eq!(affected_flags, [Negative(true), Overflow(true), Zero(false), Carry(false)]); // 16 bit let (result, affected_flags) = sbc_bcd(0x4999_u16, 0x4998_u16, false); @@ -315,7 +323,7 @@ mod alu_tests { let (result, affected_flags) = sbc_bcd(0x4999_u16, 0x5000_u16, true); assert_eq!(result, 0x9999); - assert_eq!(affected_flags, [Negative(true), Overflow(false), Zero(false), Carry(false)]); + assert_eq!(affected_flags, [Negative(true), Overflow(true), Zero(false), Carry(false)]); } #[test] diff --git a/snes-core/src/utils/num_trait.rs b/snes-core/src/utils/num_trait.rs index 0630f24..a965a79 100644 --- a/snes-core/src/utils/num_trait.rs +++ b/snes-core/src/utils/num_trait.rs @@ -46,10 +46,10 @@ macro_rules! define_operation { macro_rules! define_is_overflow { ($t:ty) => { fn is_overflow(&self, v: $t, r: $t) -> bool { - let target = (*self).is_negative(); - let value = v.is_negative(); - let result = r.is_negative(); - (target ^ result) && (target ^ value) + let target_msb = (*self).is_negative(); + let value_msb = v.is_negative(); + let result_msb = r.is_negative(); + (target_msb ^ result_msb) && !(target_msb ^ value_msb) } } }