mirror of
https://github.com/FranLMSP/snes.git
synced 2026-01-01 07:21:35 -05:00
WIP DEC functions
This commit is contained in:
@@ -38,7 +38,7 @@ impl CPU {
|
||||
true => alu::adc8bcd(target as u8, value, carry_flag),
|
||||
false => alu::adc8bin(target as u8, value, carry_flag),
|
||||
};
|
||||
self.registers.a = result as u16;
|
||||
self.registers.a = (self.registers.a & 0x00FF) | (result as u16);
|
||||
self.registers.set_carry_flag(is_carry);
|
||||
self.registers.set_negative_flag(is_negative);
|
||||
self.registers.set_zero_flag(is_zero);
|
||||
@@ -99,4 +99,21 @@ mod cpu_instructions_tests {
|
||||
assert_eq!(cpu.registers.a, 0x40);
|
||||
assert!(!cpu.registers.get_carry_flag());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dec() {
|
||||
/*
|
||||
let mut cpu = CPU::new();
|
||||
let mut bus = Bus::new();
|
||||
cpu.registers.a = 0x0000;
|
||||
cpu.registers.pbr = 0x00;
|
||||
cpu.registers.pc = 0x0000;
|
||||
cpu.registers.set_memory_select_flag(true);
|
||||
bus.write(0x000001, 1);
|
||||
cpu.dec(&bus, AddressingMode::Immediate);
|
||||
assert_eq!(cpu.registers.a, 1);
|
||||
assert!(!cpu.registers.get_carry_flag());
|
||||
assert!(!cpu.registers.get_zero_flag());
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
/// TODO: refactor functions to work with generic types (either u8 or 16) to reduce duplication
|
||||
|
||||
pub fn adc8bin(target: u8, value: u8, carry: bool) -> (u8, bool, bool, bool) {
|
||||
let is_carry = match target.checked_add(value) {
|
||||
None => true,
|
||||
@@ -66,6 +68,72 @@ pub fn adc16bcd(target: u16, value: u16, carry: bool) -> (u16, bool, bool, bool)
|
||||
(result, is_carry, is_negative, is_zero)
|
||||
}
|
||||
|
||||
pub fn dec8bin(target: u8, value: u8, carry: bool) -> (u8, bool, bool, bool) {
|
||||
let is_carry = match target.checked_sub(value) {
|
||||
None => true,
|
||||
Some(res) => match res.checked_sub(carry as u8) {
|
||||
None => true,
|
||||
Some(_) => false,
|
||||
},
|
||||
};
|
||||
let result = target
|
||||
.wrapping_sub(value)
|
||||
.wrapping_sub(carry as u8);
|
||||
let is_negative = (result >> 7) == 1;
|
||||
let is_zero = result == 0;
|
||||
(result, is_carry, is_negative, is_zero)
|
||||
}
|
||||
|
||||
pub fn dec16bin(target: u16, value: u16, carry: bool) -> (u16, bool, bool, bool) {
|
||||
let is_carry = match target.checked_sub(value) {
|
||||
None => true,
|
||||
Some(res) => match res.checked_sub(carry as u16) {
|
||||
None => true,
|
||||
Some(_) => false,
|
||||
},
|
||||
};
|
||||
let result = target
|
||||
.wrapping_sub(value)
|
||||
.wrapping_sub(carry as u16);
|
||||
let is_negative = (result >> 15) == 1;
|
||||
let is_zero = result == 0;
|
||||
(result, is_carry, is_negative, is_zero)
|
||||
}
|
||||
|
||||
pub fn dec8bcd(target: u8, value: u8, carry: bool) -> (u8, bool, bool, bool) {
|
||||
let mut is_carry = carry;
|
||||
let value = (!value).wrapping_add(1); // complement of value
|
||||
let six_complement = (!6 as u8).wrapping_add(1);
|
||||
let mut result = (target & 0xF) + (value & 0xF) + (is_carry as u8) + 1;
|
||||
if result > 0xF {
|
||||
result = result.wrapping_add(six_complement);
|
||||
}
|
||||
result = result.wrapping_add(target & 0xF0).wrapping_add(value & 0xF0).wrapping_add(1);
|
||||
is_carry = result < 0xFF;
|
||||
let is_negative = (result >> 7) == 1;
|
||||
let is_zero = result == 0;
|
||||
(result, is_carry, is_negative, is_zero)
|
||||
}
|
||||
|
||||
pub fn dec16bcd(target: u16, value: u16, carry: bool) -> (u16, bool, bool, bool) {
|
||||
let mut is_carry = carry;
|
||||
let mut result = (target & 0xF) + (value & 0xF) + (is_carry as u16);
|
||||
if result > 9 {
|
||||
result += 6;
|
||||
}
|
||||
result += (target & 0xF0) + (value & 0xF0);
|
||||
if result > 0x9F {
|
||||
result += 0x60;
|
||||
}
|
||||
result += (target & 0xF00) + (value & 0xF00);
|
||||
if result > 0x9FF {
|
||||
result += 0x600;
|
||||
}
|
||||
is_carry = result > 0x9FFF;
|
||||
let is_negative = (result >> 15) == 1;
|
||||
let is_zero = result == 0;
|
||||
(result, is_carry, is_negative, is_zero)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod alu_tests {
|
||||
@@ -220,4 +288,64 @@ mod alu_tests {
|
||||
assert_eq!(negative, false);
|
||||
assert_eq!(zero, false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dec8bin() {
|
||||
let (result, carry, negative, zero) = dec8bin(1, 1, false);
|
||||
assert_eq!(result, 0);
|
||||
assert_eq!(carry, false);
|
||||
assert_eq!(negative, false);
|
||||
assert_eq!(zero, true);
|
||||
|
||||
let (result, carry, negative, zero) = dec8bin(0, 1, false);
|
||||
assert_eq!(result, 0b11111111);
|
||||
assert_eq!(carry, true);
|
||||
assert_eq!(negative, true);
|
||||
assert_eq!(zero, false);
|
||||
|
||||
let (result, carry, negative, zero) = dec8bin(0, 1, true);
|
||||
assert_eq!(result, 0b11111110);
|
||||
assert_eq!(carry, true);
|
||||
assert_eq!(negative, true);
|
||||
assert_eq!(zero, false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dec16bin() {
|
||||
let (result, carry, negative, zero) = dec16bin(1, 1, false);
|
||||
assert_eq!(result, 0);
|
||||
assert_eq!(carry, false);
|
||||
assert_eq!(negative, false);
|
||||
assert_eq!(zero, true);
|
||||
|
||||
let (result, carry, negative, zero) = dec16bin(0, 1, false);
|
||||
assert_eq!(result, 0b11111111_11111111);
|
||||
assert_eq!(carry, true);
|
||||
assert_eq!(negative, true);
|
||||
assert_eq!(zero, false);
|
||||
|
||||
let (result, carry, negative, zero) = dec16bin(0, 1, true);
|
||||
assert_eq!(result, 0b11111111_11111110);
|
||||
assert_eq!(carry, true);
|
||||
assert_eq!(negative, true);
|
||||
assert_eq!(zero, false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dec8bcd() {
|
||||
let (result, carry, negative, zero) = dec8bcd(0b0100_0111, 0b0010_1000, false);
|
||||
assert_eq!(result, 0b0001_1001);
|
||||
assert_eq!(carry, false);
|
||||
assert_eq!(negative, false);
|
||||
assert_eq!(zero, false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dec16bcd() {
|
||||
let (result, carry, negative, zero) = dec16bcd(0b0100_0111, 0b0010_1000, false);
|
||||
assert_eq!(result, 0b0001_1001);
|
||||
assert_eq!(carry, false);
|
||||
assert_eq!(negative, false);
|
||||
assert_eq!(zero, false);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user