mirror of
https://github.com/FranLMSP/snes.git
synced 2026-08-03 08:30:01 -04:00
SBC opcodes
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 = (self.registers.a & 0x00FF) | (result as u16);
|
||||
self.registers.a = (self.registers.a & 0xFF00) | (result as u16);
|
||||
self.registers.set_carry_flag(is_carry);
|
||||
self.registers.set_negative_flag(is_negative);
|
||||
self.registers.set_zero_flag(is_zero);
|
||||
@@ -57,6 +57,39 @@ impl CPU {
|
||||
};
|
||||
}
|
||||
|
||||
fn sbc(&mut self, bus: &Bus, addressing_mode: AddressingMode) {
|
||||
// if the M flag is set, perform 8 bit addition.
|
||||
// Otherwise, 16 bit addition
|
||||
let carry_flag = self.registers.get_carry_flag();
|
||||
let is_decimal_mode = self.registers.get_decimal_mode_flag();
|
||||
let is_8bit = self.registers.get_memory_select_flag();
|
||||
let target = self.registers.a;
|
||||
match is_8bit {
|
||||
true => {
|
||||
let value = self.get_8bit_from_address(bus, addressing_mode);
|
||||
let (result, is_carry, is_negative, is_zero) = match is_decimal_mode {
|
||||
true => alu::sbc8bcd(target as u8, value, carry_flag),
|
||||
false => alu::sbc8bin(target as u8, value, carry_flag),
|
||||
};
|
||||
self.registers.a = (self.registers.a & 0xFF00) | (result as u16);
|
||||
self.registers.set_carry_flag(is_carry);
|
||||
self.registers.set_negative_flag(is_negative);
|
||||
self.registers.set_zero_flag(is_zero);
|
||||
},
|
||||
false => {
|
||||
let value = self.get_16bit_from_address(bus, addressing_mode);
|
||||
let (result, is_carry, is_negative, is_zero) = match is_decimal_mode {
|
||||
true => alu::sbc16bcd(target, value, carry_flag),
|
||||
false => alu::sbc16bin(target, value, carry_flag),
|
||||
};
|
||||
self.registers.a = result;
|
||||
self.registers.set_carry_flag(is_carry);
|
||||
self.registers.set_negative_flag(is_negative);
|
||||
self.registers.set_zero_flag(is_zero);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub fn execute_opcode(&mut self, opcode: u8, bus: &Bus) {
|
||||
type A = AddressingMode;
|
||||
type I = IndexRegister;
|
||||
@@ -77,6 +110,22 @@ impl CPU {
|
||||
0x77 => self.adc(bus, A::DirectPageIndirectLongIndexed(I::Y)),
|
||||
0x63 => self.adc(bus, A::StackRelative),
|
||||
0x73 => self.adc(bus, A::StackRelativeIndirectIndexed(I::Y)),
|
||||
// SBC
|
||||
0xE9 => self.sbc(bus, A::Immediate),
|
||||
0xED => self.sbc(bus, A::Absolute),
|
||||
0xEF => self.sbc(bus, A::AbsoluteLong),
|
||||
0xE5 => self.sbc(bus, A::DirectPage),
|
||||
0xF2 => self.sbc(bus, A::DirectPageIndirect),
|
||||
0xE7 => self.sbc(bus, A::DirectPageIndirectLong),
|
||||
0xFD => self.sbc(bus, A::AbsoluteIndexed(I::X)),
|
||||
0xFF => self.sbc(bus, A::AbsoluteLongIndexed(I::X)),
|
||||
0xF9 => self.sbc(bus, A::AbsoluteIndexed(I::Y)),
|
||||
0xF5 => self.sbc(bus, A::DirectPageIndexed(I::X)),
|
||||
0xE1 => self.sbc(bus, A::DirectPageIndexedIndirect(I::X)),
|
||||
0xF1 => self.sbc(bus, A::DirectPageIndirectIndexed(I::Y)),
|
||||
0xF7 => self.sbc(bus, A::DirectPageIndirectLongIndexed(I::Y)),
|
||||
0xE3 => self.sbc(bus, A::StackRelative),
|
||||
0xF3 => self.sbc(bus, A::StackRelativeIndirectIndexed(I::Y)),
|
||||
_ => println!("Invalid opcode: {:02X}", opcode),
|
||||
}
|
||||
}
|
||||
@@ -101,19 +150,17 @@ mod cpu_instructions_tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dec() {
|
||||
/*
|
||||
fn test_sbc() {
|
||||
let mut cpu = CPU::new();
|
||||
let mut bus = Bus::new();
|
||||
cpu.registers.a = 0x0000;
|
||||
cpu.registers.a = 0x0001;
|
||||
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);
|
||||
cpu.sbc(&bus, AddressingMode::Immediate);
|
||||
assert_eq!(cpu.registers.a, 0);
|
||||
assert!(!cpu.registers.get_carry_flag());
|
||||
assert!(!cpu.registers.get_zero_flag());
|
||||
*/
|
||||
assert!(cpu.registers.get_zero_flag());
|
||||
}
|
||||
}
|
||||
|
||||
+14
-14
@@ -68,7 +68,7 @@ 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) {
|
||||
pub fn sbc8bin(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) {
|
||||
@@ -84,7 +84,7 @@ pub fn dec8bin(target: u8, value: u8, carry: bool) -> (u8, bool, bool, bool) {
|
||||
(result, is_carry, is_negative, is_zero)
|
||||
}
|
||||
|
||||
pub fn dec16bin(target: u16, value: u16, carry: bool) -> (u16, bool, bool, bool) {
|
||||
pub fn sbc16bin(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) {
|
||||
@@ -100,7 +100,7 @@ pub fn dec16bin(target: u16, value: u16, carry: bool) -> (u16, bool, bool, bool)
|
||||
(result, is_carry, is_negative, is_zero)
|
||||
}
|
||||
|
||||
pub fn dec8bcd(target: u8, value: u8, carry: bool) -> (u8, bool, bool, bool) {
|
||||
pub fn sbc8bcd(target: u8, value: u8, carry: bool) -> (u8, bool, bool, bool) {
|
||||
let mut is_carry = carry;
|
||||
let target = target as u16;
|
||||
let value = !(value as u16);
|
||||
@@ -120,7 +120,7 @@ pub fn dec8bcd(target: u8, value: u8, carry: bool) -> (u8, bool, bool, bool) {
|
||||
(result, is_carry, is_negative, is_zero)
|
||||
}
|
||||
|
||||
pub fn dec16bcd(target: u16, value: u16, carry: bool) -> (u16, bool, bool, bool) {
|
||||
pub fn sbc16bcd(target: u16, value: u16, carry: bool) -> (u16, bool, bool, bool) {
|
||||
let mut is_carry = carry;
|
||||
let target = target as u32;
|
||||
let value = !(value as u32);
|
||||
@@ -307,19 +307,19 @@ mod alu_tests {
|
||||
|
||||
#[test]
|
||||
fn test_dec8bin() {
|
||||
let (result, carry, negative, zero) = dec8bin(1, 1, false);
|
||||
let (result, carry, negative, zero) = sbc8bin(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);
|
||||
let (result, carry, negative, zero) = sbc8bin(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);
|
||||
let (result, carry, negative, zero) = sbc8bin(0, 1, true);
|
||||
assert_eq!(result, 0b11111110);
|
||||
assert_eq!(carry, true);
|
||||
assert_eq!(negative, true);
|
||||
@@ -328,19 +328,19 @@ mod alu_tests {
|
||||
|
||||
#[test]
|
||||
fn test_dec16bin() {
|
||||
let (result, carry, negative, zero) = dec16bin(1, 1, false);
|
||||
let (result, carry, negative, zero) = sbc16bin(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);
|
||||
let (result, carry, negative, zero) = sbc16bin(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);
|
||||
let (result, carry, negative, zero) = sbc16bin(0, 1, true);
|
||||
assert_eq!(result, 0b11111111_11111110);
|
||||
assert_eq!(carry, true);
|
||||
assert_eq!(negative, true);
|
||||
@@ -349,13 +349,13 @@ mod alu_tests {
|
||||
|
||||
#[test]
|
||||
fn test_dec8bcd() {
|
||||
let (result, carry, negative, zero) = dec8bcd(0x49, 0x48, false);
|
||||
let (result, carry, negative, zero) = sbc8bcd(0x49, 0x48, false);
|
||||
assert_eq!(result, 0x00);
|
||||
assert_eq!(carry, true);
|
||||
assert_eq!(negative, false);
|
||||
assert_eq!(zero, true);
|
||||
|
||||
let (result, carry, negative, zero) = dec8bcd(0x49, 0x50, true);
|
||||
let (result, carry, negative, zero) = sbc8bcd(0x49, 0x50, true);
|
||||
assert_eq!(result, 0x99);
|
||||
assert_eq!(carry, false);
|
||||
assert_eq!(negative, true);
|
||||
@@ -364,13 +364,13 @@ mod alu_tests {
|
||||
|
||||
#[test]
|
||||
fn test_dec16bcd() {
|
||||
let (result, carry, negative, zero) = dec16bcd(0x4999, 0x4998, false);
|
||||
let (result, carry, negative, zero) = sbc16bcd(0x4999, 0x4998, false);
|
||||
assert_eq!(result, 0x0000);
|
||||
assert_eq!(carry, true);
|
||||
assert_eq!(negative, false);
|
||||
assert_eq!(zero, true);
|
||||
|
||||
let (result, carry, negative, zero) = dec16bcd(0x4999, 0x5000, true);
|
||||
let (result, carry, negative, zero) = sbc16bcd(0x4999, 0x5000, true);
|
||||
assert_eq!(result, 0x9999);
|
||||
assert_eq!(carry, false);
|
||||
assert_eq!(negative, true);
|
||||
|
||||
Reference in New Issue
Block a user