Fix bugs related to 16bit mode, emulation mode and REP instruction

This commit is contained in:
2023-06-19 21:50:52 -05:00
parent ecaaaab4b4
commit 92929af185
4 changed files with 99 additions and 7 deletions
+2 -1
View File
@@ -51,7 +51,7 @@ impl CPU {
match condition {
// Add 1 byte and 1 cycle if m = 0 (16-bit memory/accumulator)
Condition::MemorySelectFlag => {
if !self.registers.get_memory_select_flag() {
if self.registers.is_16bit_mode() {
cycles += 1;
match addressing_mode {
A::Immediate => bytes += 1,
@@ -441,6 +441,7 @@ mod cpu_instructions_tests {
#[test]
fn test_common_conditions() {
let mut cpu = CPU::new();
cpu.registers.emulation_mode = false;
// 16-bit Memory/accumulator flag condition
cpu.registers.pc = 0;
+32 -3
View File
@@ -760,7 +760,8 @@ impl CPU {
}
fn rep(&mut self, bus: &Bus) {
self.registers.p = self.get_8bit_from_address(bus, AddressingMode::Immediate);
let byte = self.get_8bit_from_address(bus, AddressingMode::Immediate);
self.registers.reset_rep_byte(byte);
self.increment_cycles_rep();
}
@@ -1506,6 +1507,7 @@ mod cpu_instructions_tests {
fn test_adc() {
let mut cpu = CPU::new();
let mut bus = Bus::new();
cpu.registers.emulation_mode = false;
cpu.registers.a = 0x0000;
cpu.registers.pbr = 0x00;
cpu.registers.pc = 0x0000;
@@ -1539,6 +1541,7 @@ mod cpu_instructions_tests {
fn test_sbc() {
let mut cpu = CPU::new();
let mut bus = Bus::new();
cpu.registers.emulation_mode = false;
cpu.registers.a = 0x0001;
cpu.registers.pbr = 0x00;
cpu.registers.pc = 0x0000;
@@ -1556,6 +1559,7 @@ mod cpu_instructions_tests {
fn test_and() {
let mut cpu = CPU::new();
let mut bus = Bus::new();
cpu.registers.emulation_mode = false;
cpu.registers.a = 0x0101;
cpu.registers.pbr = 0x00;
cpu.registers.pc = 0x0000;
@@ -1591,6 +1595,7 @@ mod cpu_instructions_tests {
fn test_asl() {
let mut cpu = CPU::new();
let mut bus = Bus::new();
cpu.registers.emulation_mode = false;
cpu.registers.a = 0b01010000_00000000;
cpu.registers.pbr = 0x00;
cpu.registers.pc = 0x0000;
@@ -1608,6 +1613,8 @@ mod cpu_instructions_tests {
fn test_lsr() {
let mut cpu = CPU::new();
let mut bus = Bus::new();
cpu.registers.emulation_mode = false;
cpu.registers.exposed_bit_zero = ModeFlag::Carry;
cpu.registers.a = 0b00000000_00000011;
cpu.registers.pbr = 0x00;
cpu.registers.pc = 0x0000;
@@ -1627,6 +1634,7 @@ mod cpu_instructions_tests {
fn test_bit() {
let mut cpu = CPU::new();
let mut bus = Bus::new();
cpu.registers.emulation_mode = false;
cpu.registers.a = 0b1111_0000;
cpu.registers.pbr = 0x00;
cpu.registers.pc = 0x0000;
@@ -2041,6 +2049,7 @@ mod cpu_instructions_tests {
// store the result nor it affects the overflow flag
let mut cpu = CPU::new();
let mut bus = Bus::new();
cpu.registers.emulation_mode = false;
cpu.registers.x = 0x01;
cpu.registers.pbr = 0x00;
cpu.registers.pc = 0x0000;
@@ -2058,6 +2067,8 @@ mod cpu_instructions_tests {
cpu.registers.x = 0x50;
cpu.registers.pbr = 0x00;
cpu.registers.pc = 0x0000;
cpu.registers.emulation_mode = false;
cpu.registers.exposed_bit_zero = ModeFlag::Carry;
cpu.registers.set_16bit_index(true);
cpu.registers.set_overflow_flag(false);
bus.write(0x000002, 0xB0);
@@ -2077,6 +2088,8 @@ mod cpu_instructions_tests {
// store the result nor it affects the overflow flag
let mut cpu = CPU::new();
let mut bus = Bus::new();
cpu.registers.emulation_mode = false;
cpu.registers.exposed_bit_zero = ModeFlag::Carry;
cpu.registers.y = 0x01;
cpu.registers.pbr = 0x00;
cpu.registers.pc = 0x0000;
@@ -2432,6 +2445,7 @@ mod cpu_instructions_tests {
fn test_phx() {
let mut cpu = CPU::new();
let mut bus = Bus::new();
cpu.registers.emulation_mode = false;
cpu.registers.pc = 0x0000;
cpu.registers.x = 0x1234;
cpu.registers.sp = 0x1FC;
@@ -2447,6 +2461,7 @@ mod cpu_instructions_tests {
fn test_phy() {
let mut cpu = CPU::new();
let mut bus = Bus::new();
cpu.registers.emulation_mode = false;
cpu.registers.pc = 0x0000;
cpu.registers.y = 0x1234;
cpu.registers.sp = 0x1FC;
@@ -2462,6 +2477,7 @@ mod cpu_instructions_tests {
fn test_pla() {
let mut cpu = CPU::new();
let mut bus = Bus::new();
cpu.registers.emulation_mode = false;
cpu.registers.pc = 0x0000;
cpu.registers.y = 0x1234;
cpu.registers.set_16bit_mode(true);
@@ -2537,6 +2553,7 @@ mod cpu_instructions_tests {
fn test_plx() {
let mut cpu = CPU::new();
let mut bus = Bus::new();
cpu.registers.emulation_mode = false;
cpu.registers.pc = 0x0000;
cpu.registers.x = 0x1234;
cpu.registers.set_16bit_index(true);
@@ -2558,6 +2575,7 @@ mod cpu_instructions_tests {
fn test_ply() {
let mut cpu = CPU::new();
let mut bus = Bus::new();
cpu.registers.emulation_mode = false;
cpu.registers.pc = 0x0000;
cpu.registers.y = 0x1234;
cpu.registers.set_16bit_index(true);
@@ -2579,11 +2597,12 @@ mod cpu_instructions_tests {
fn test_rep() {
let mut cpu = CPU::new();
let mut bus = Bus::new();
cpu.registers.emulation_mode = false;
cpu.registers.pc = 0x0000;
cpu.registers.p = 0x00;
cpu.registers.p = 0xFF;
bus.write(0x0001, 0xFF);
cpu.rep(&mut bus);
assert_eq!(cpu.registers.p, 0xFF);
assert_eq!(cpu.registers.p, 0x00);
assert_eq!(cpu.registers.pc, 0x0002);
assert_eq!(cpu.cycles, 3);
}
@@ -2592,6 +2611,7 @@ mod cpu_instructions_tests {
fn test_rol() {
let mut cpu = CPU::new();
let mut bus = Bus::new();
cpu.registers.emulation_mode = false;
cpu.registers.set_16bit_mode(false);
cpu.registers.a = 0b0100_0000;
cpu.registers.pc = 0x0000;
@@ -2607,6 +2627,7 @@ mod cpu_instructions_tests {
fn test_ror() {
let mut cpu = CPU::new();
let mut bus = Bus::new();
cpu.registers.emulation_mode = false;
cpu.registers.set_16bit_mode(false);
cpu.registers.set_carry_flag(true);
cpu.registers.a = 0x00;
@@ -2770,6 +2791,7 @@ mod cpu_instructions_tests {
#[test]
fn test_tax() {
let mut cpu = CPU::new();
cpu.registers.emulation_mode = false;
cpu.registers.pc = 0x0000;
cpu.registers.a = 0xF0F0;
cpu.registers.x = 0x0000;
@@ -2786,6 +2808,7 @@ mod cpu_instructions_tests {
#[test]
fn test_tay() {
let mut cpu = CPU::new();
cpu.registers.emulation_mode = false;
cpu.registers.pc = 0x0000;
cpu.registers.a = 0xF0F0;
cpu.registers.y = 0x0000;
@@ -2850,6 +2873,7 @@ mod cpu_instructions_tests {
#[test]
fn test_tsx() {
let mut cpu = CPU::new();
cpu.registers.emulation_mode = false;
cpu.registers.pc = 0x0000;
cpu.registers.x = 0x0000;
cpu.registers.sp = 0xF0F0;
@@ -2863,6 +2887,7 @@ mod cpu_instructions_tests {
#[test]
fn test_txa() {
let mut cpu = CPU::new();
cpu.registers.emulation_mode = false;
cpu.registers.pc = 0x0000;
cpu.registers.a = 0x0000;
cpu.registers.x = 0xF0F0;
@@ -2876,6 +2901,7 @@ mod cpu_instructions_tests {
#[test]
fn test_txs() {
let mut cpu = CPU::new();
cpu.registers.emulation_mode = false;
cpu.registers.pc = 0x0000;
cpu.registers.sp = 0x0000;
cpu.registers.x = 0xF0F0;
@@ -2889,6 +2915,7 @@ mod cpu_instructions_tests {
#[test]
fn test_txy() {
let mut cpu = CPU::new();
cpu.registers.emulation_mode = false;
cpu.registers.pc = 0x0000;
cpu.registers.y = 0x0000;
cpu.registers.x = 0xF0F0;
@@ -2902,6 +2929,7 @@ mod cpu_instructions_tests {
#[test]
fn test_tya() {
let mut cpu = CPU::new();
cpu.registers.emulation_mode = false;
cpu.registers.pc = 0x0000;
cpu.registers.a = 0x0000;
cpu.registers.y = 0xF0F0;
@@ -2915,6 +2943,7 @@ mod cpu_instructions_tests {
#[test]
fn test_tyx() {
let mut cpu = CPU::new();
cpu.registers.emulation_mode = false;
cpu.registers.pc = 0x0000;
cpu.registers.x = 0x0000;
cpu.registers.y = 0xF0F0;
+64 -2
View File
@@ -27,8 +27,8 @@ impl Registers {
pbr: 0,
dbr: 0,
pc: 0,
exposed_bit_zero: ModeFlag::Carry,
emulation_mode: false,
exposed_bit_zero: ModeFlag::EmulationMode,
emulation_mode: true,
carry: false,
}
}
@@ -154,10 +154,16 @@ impl Registers {
}
pub fn is_16bit_index(&self) -> bool {
if self.emulation_mode {
return false
}
!self.get_index_register_select_flag()
}
pub fn is_16bit_mode(&self) -> bool {
if self.emulation_mode {
return false
}
!self.get_memory_select_flag()
}
@@ -223,6 +229,15 @@ impl Registers {
}
}
}
pub fn reset_rep_byte(&mut self, byte: u8) {
self.p = self.p & !byte;
// Avoid messing up exposed emu mode flag logic
let reset_carry_flag = (byte & 0x01) == 1;
if reset_carry_flag {
self.set_carry_flag(false);
}
}
}
#[cfg(test)]
@@ -232,6 +247,7 @@ mod registers_tests {
#[test]
fn test_is_16bit_mode() {
let mut registers = Registers::new();
registers.emulation_mode = false;
registers.set_memory_select_flag(false);
assert!(registers.is_16bit_mode());
registers.set_memory_select_flag(true);
@@ -241,6 +257,7 @@ mod registers_tests {
#[test]
fn test_set_16bit_mode() {
let mut registers = Registers::new();
registers.emulation_mode = false;
registers.set_16bit_mode(true);
assert!(registers.is_16bit_mode());
registers.set_16bit_mode(false);
@@ -250,6 +267,7 @@ mod registers_tests {
#[test]
fn test_is_16bit_index() {
let mut registers = Registers::new();
registers.emulation_mode = false;
registers.set_index_register_select_flag(false);
assert!(registers.is_16bit_index());
registers.set_index_register_select_flag(true);
@@ -259,6 +277,7 @@ mod registers_tests {
#[test]
fn test_set_16bit_index() {
let mut registers = Registers::new();
registers.emulation_mode = false;
registers.set_16bit_index(true);
assert!(registers.is_16bit_index());
registers.set_16bit_index(false);
@@ -268,6 +287,7 @@ mod registers_tests {
#[test]
fn test_set_low_a() {
let mut registers = Registers::new();
registers.emulation_mode = false;
registers.a = 0xA1A1;
registers.set_low_a(0xFF);
assert_eq!(registers.a, 0xA1FF);
@@ -276,6 +296,7 @@ mod registers_tests {
#[test]
fn test_set_low_x() {
let mut registers = Registers::new();
registers.emulation_mode = false;
registers.x = 0xA1A1;
registers.set_low_x(0xFF);
assert_eq!(registers.x, 0xA1FF);
@@ -284,6 +305,7 @@ mod registers_tests {
#[test]
fn test_set_low_y() {
let mut registers = Registers::new();
registers.emulation_mode = false;
registers.y = 0xA1A1;
registers.set_low_y(0xFF);
assert_eq!(registers.y, 0xA1FF);
@@ -292,6 +314,7 @@ mod registers_tests {
#[test]
fn test_set_low_sp() {
let mut registers = Registers::new();
registers.emulation_mode = false;
registers.sp = 0xA1A1;
registers.set_low_sp(0xFF);
assert_eq!(registers.sp, 0xA1FF);
@@ -319,6 +342,7 @@ mod registers_tests {
#[test]
fn test_status_registers() {
let mut registers = Registers::new();
registers.emulation_mode = false;
registers.p = 0x00;
registers.set_carry_flag(true);
@@ -388,6 +412,7 @@ mod registers_tests {
#[test]
fn test_set_flags() {
let mut registers = Registers::new();
registers.emulation_mode = false;
registers.p = 0x00;
registers .set_flags(&[
@@ -411,6 +436,7 @@ mod registers_tests {
#[test]
fn test_exchange_carry_and_emulation() {
let mut registers = Registers::new();
registers.emulation_mode = false;
registers.exposed_bit_zero = ModeFlag::Carry;
registers .set_flags(&[Flags::Carry(false)]);
registers.exposed_bit_zero = ModeFlag::EmulationMode;
@@ -433,4 +459,40 @@ mod registers_tests {
registers.exchange_carry_and_emulation();
assert_eq!(registers.get_emulation_mode_flag(), false);
}
#[test]
fn test_reset_rep_byte() {
let mut registers = Registers::new();
registers.p = 0xFF;
registers.reset_rep_byte(0b0000_0001);
assert_eq!(registers.p, 0b1111_1110);
registers.p = 0xFF;
registers.reset_rep_byte(0b0000_0010);
assert_eq!(registers.p, 0b1111_1101);
registers.p = 0xFF;
registers.reset_rep_byte(0b0010_0010);
assert_eq!(registers.p, 0b1101_1101);
registers.p = 0xFF;
registers.reset_rep_byte(0b1111_1111);
assert_eq!(registers.p, 0b0000_0000);
registers.p = 0b0000_0010;
registers.reset_rep_byte(0b0000_0001);
assert_eq!(registers.p, 0b0000_0010);
registers.p = 0b0000_0010;
registers.reset_rep_byte(0b0000_0010);
assert_eq!(registers.p, 0b0000_0000);
registers.p = 0x38;
registers.reset_rep_byte(0x38);
assert_eq!(registers.p, 0x00);
registers.p = 0x86;
registers.reset_rep_byte(0x38);
assert_eq!(registers.p, 0b10000110);
}
}