decouple cycle increment logic from cpu struct (#1)

This commit is contained in:
2023-12-26 03:42:07 +00:00
committed by GitHub
parent 1642d582cb
commit 2e4dd7b15c
2 changed files with 634 additions and 496 deletions
+234 -197
View File
@@ -1,6 +1,7 @@
use super::cpu::CPU;
use crate::utils::addressing::{AddressingMode, IndexRegister}; use crate::utils::addressing::{AddressingMode, IndexRegister};
use crate::cpu::registers::Registers;
type A = AddressingMode; type A = AddressingMode;
type I = IndexRegister; type I = IndexRegister;
@@ -42,8 +43,7 @@ const COMP_INDEX_CONDITIONS: [Condition; 2] = [
Condition::IndexCrossesPageBoundary, Condition::IndexCrossesPageBoundary,
]; ];
impl CPU { fn common_conditions(cpu_registers: &Registers, addressing_mode: AddressingMode, conditions: &[Condition]) -> (u16, usize) {
fn common_conditions(&mut self, addressing_mode: AddressingMode, conditions: &[Condition]) -> (u16, usize) {
let mut bytes = 0; let mut bytes = 0;
let mut cycles = 0; let mut cycles = 0;
@@ -51,7 +51,7 @@ impl CPU {
match condition { match condition {
// Add 1 byte and 1 cycle if m = 0 (16-bit memory/accumulator) // Add 1 byte and 1 cycle if m = 0 (16-bit memory/accumulator)
Condition::MemorySelectFlag => { Condition::MemorySelectFlag => {
if self.registers.is_16bit_mode() { if cpu_registers.is_16bit_mode() {
cycles += 1; cycles += 1;
match addressing_mode { match addressing_mode {
A::Immediate => bytes += 1, A::Immediate => bytes += 1,
@@ -66,7 +66,7 @@ impl CPU {
A::DirectPageIndexed(_) | A::DirectPageIndexedIndirect(_) | A::DirectPageIndexed(_) | A::DirectPageIndexedIndirect(_) |
A::DirectPageIndirectIndexed(_) | A::DirectPageIndirectIndexed(_) |
A::DirectPageIndirectLongIndexed(_) => { A::DirectPageIndirectLongIndexed(_) => {
if self.registers.direct_page_low() != 0 { if cpu_registers.direct_page_low() != 0 {
cycles += 1; cycles += 1;
} }
}, },
@@ -77,10 +77,10 @@ impl CPU {
Condition::IndexCrossesPageBoundary => { Condition::IndexCrossesPageBoundary => {
match addressing_mode { match addressing_mode {
A::AbsoluteIndexed(index) | A::DirectPageIndirectIndexed(index) => { A::AbsoluteIndexed(index) | A::DirectPageIndirectIndexed(index) => {
let page = self.registers.get_pc_address() & 0xFF; let page = cpu_registers.get_pc_address() & 0xFF;
let index = match index { let index = match index {
I::X => self.registers.x, I::X => cpu_registers.x,
I::Y => self.registers.y, I::Y => cpu_registers.y,
}; };
if (page + index as u32) > 0xFF { if (page + index as u32) > 0xFF {
cycles += 1 cycles += 1
@@ -91,13 +91,13 @@ impl CPU {
}, },
// Add 1 cycle if 65C02 and d = 1 (decimal mode, 65C02) // Add 1 cycle if 65C02 and d = 1 (decimal mode, 65C02)
Condition::DecimalMode => { Condition::DecimalMode => {
if self.registers.get_decimal_mode_flag() { if cpu_registers.get_decimal_mode_flag() {
cycles += 1; cycles += 1;
} }
}, },
// Add 1 byte if <index> = 0 (16-bit index registers) // Add 1 byte if <index> = 0 (16-bit index registers)
Condition::IndexIs16Bit => { Condition::IndexIs16Bit => {
if self.registers.is_16bit_index() { if cpu_registers.is_16bit_index() {
bytes += 1; cycles += 1; bytes += 1; cycles += 1;
} }
}, },
@@ -154,80 +154,107 @@ impl CPU {
} }
} }
pub fn increment_cycles_arithmetic(&mut self, addressing_mode: AddressingMode) { pub fn increment_cycles_arithmetic(cpu_registers: &Registers, addressing_mode: AddressingMode) -> (u16, usize) {
let (bytes, cycles) = CPU::common_bytes_cycles_arithmetic(addressing_mode); let mut total_bytes = 0;
self.registers.increment_pc(bytes); self.cycles += cycles; let mut total_cycles = 0;
let (bytes, cycles) = self.common_conditions(addressing_mode, &ALL_CONDITIONS);
self.registers.increment_pc(bytes); self.cycles += cycles; let (bytes, cycles) = common_bytes_cycles_arithmetic(addressing_mode);
total_bytes += bytes; total_cycles += cycles;
let (bytes, cycles) = common_conditions(cpu_registers, addressing_mode, &ALL_CONDITIONS);
total_bytes += bytes; total_cycles += cycles;
(total_bytes, total_cycles)
} }
pub fn increment_cycles_bitwise(&mut self, addressing_mode: AddressingMode) { pub fn increment_cycles_bitwise(cpu_registers: &Registers, addressing_mode: AddressingMode) -> (u16, usize) {
let (bytes, cycles) = CPU::common_bytes_cycles_arithmetic(addressing_mode); let mut total_bytes = 0;
self.registers.increment_pc(bytes); self.cycles += cycles; let mut total_cycles = 0;
let (bytes, cycles) = self.common_conditions(addressing_mode, &BITWISE_CONDITIONS);
self.registers.increment_pc(bytes); self.cycles += cycles; let (bytes, cycles) = common_bytes_cycles_arithmetic(addressing_mode);
total_bytes += bytes; total_cycles += cycles;
let (bytes, cycles) = common_conditions(cpu_registers, addressing_mode, &BITWISE_CONDITIONS);
total_bytes += bytes; total_cycles += cycles;
(total_bytes, total_cycles)
} }
pub fn increment_cycles_shift(&mut self, addressing_mode: AddressingMode) { pub fn increment_cycles_shift(cpu_registers: &Registers, addressing_mode: AddressingMode) -> (u16, usize) {
let (bytes, cycles) = CPU::common_bytes_cycles_shift(addressing_mode); let mut total_bytes = 0;
self.registers.increment_pc(bytes); self.cycles += cycles; let mut total_cycles = 0;
let (bytes, cycles) = common_bytes_cycles_shift(addressing_mode);
total_bytes += bytes; total_cycles += cycles;
// Add 2 cycles if m = 1 // Add 2 cycles if m = 1
let (_, cycles) = self.common_conditions(addressing_mode, &[Condition::MemorySelectFlag]); let (_, cycles) = common_conditions(cpu_registers, addressing_mode, &[Condition::MemorySelectFlag]);
self.cycles += cycles; total_cycles += cycles;
let (bytes, cycles) = self.common_conditions(addressing_mode, &BITWISE_CONDITIONS); let (bytes, cycles) = common_conditions(cpu_registers, addressing_mode, &BITWISE_CONDITIONS);
self.registers.increment_pc(bytes); self.cycles += cycles; total_bytes += bytes; total_cycles += cycles;
(total_bytes, total_cycles)
} }
pub fn increment_cycles_bit(&mut self, addressing_mode: AddressingMode) { pub fn increment_cycles_bit(cpu_registers: &Registers, addressing_mode: AddressingMode) -> (u16, usize) {
let (bytes, cycles) = CPU::common_bytes_cycles_bit(addressing_mode); let mut total_bytes = 0;
self.registers.increment_pc(bytes); self.cycles += cycles; let mut total_cycles = 0;
let (bytes, cycles) = self.common_conditions(addressing_mode, &BITWISE_CONDITIONS);
self.registers.increment_pc(bytes); self.cycles += cycles; let (bytes, cycles) = common_bytes_cycles_bit(addressing_mode);
total_bytes += bytes; total_cycles += cycles;
let (bytes, cycles) = common_conditions(cpu_registers, addressing_mode, &BITWISE_CONDITIONS);
total_bytes += bytes; total_cycles += cycles;
(total_bytes, total_cycles)
} }
pub fn increment_cycles_clear(&mut self) { pub fn increment_cycles_clear() -> (u16, usize) {
self.registers.increment_pc(1); self.cycles += 2; (1, 2)
} }
pub fn increment_cycles_branch(&mut self) { pub fn increment_cycles_branch() -> (u16, usize) {
self.registers.increment_pc(2); self.cycles += 2; (2, 2)
} }
pub fn increment_cycles_branch_taken(&mut self, page_boundary_crossed: bool) { pub fn increment_cycles_branch_taken(page_boundary_crossed: bool) -> (u16, usize) {
self.cycles += 1; let mut total_cycles = 1;
if page_boundary_crossed { if page_boundary_crossed {
self.cycles += 1; total_cycles += 1;
}
} }
pub fn increment_cycles_branch_long(&mut self) { (0, total_cycles)
self.registers.increment_pc(3); self.cycles += 4;
} }
pub fn increment_cycles_comp_index(&mut self, addressing_mode: AddressingMode) { pub fn increment_cycles_branch_long() -> (u16, usize) {
let (bytes, cycles) = CPU::common_bytes_cycles_arithmetic(addressing_mode); (3, 4)
self.registers.increment_pc(bytes); self.cycles += cycles;
let (bytes, cycles) = self.common_conditions(addressing_mode, &COMP_INDEX_CONDITIONS);
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
pub fn increment_cycles_inc_dec(&mut self, addressing_mode: AddressingMode) { pub fn increment_cycles_comp_index(cpu_registers: &Registers, addressing_mode: AddressingMode) -> (u16, usize) {
self.increment_cycles_shift(addressing_mode); let mut total_bytes = 0;
let mut total_cycles = 0;
let (bytes, cycles) = common_bytes_cycles_arithmetic(addressing_mode);
total_bytes += bytes; total_cycles += cycles;
let (bytes, cycles) = common_conditions(cpu_registers, addressing_mode, &COMP_INDEX_CONDITIONS);
total_bytes += bytes; total_cycles += cycles;
(total_bytes, total_cycles)
} }
pub fn increment_cycles_inc_dec_index(&mut self) { pub fn increment_cycles_inc_dec(cpu_registers: &Registers, addressing_mode: AddressingMode) -> (u16, usize) {
self.registers.increment_pc(1); self.cycles += 2; increment_cycles_shift(cpu_registers, addressing_mode)
} }
pub fn increment_cycles_nop(&mut self) { pub fn increment_cycles_inc_dec_index() -> (u16, usize) {
self.registers.increment_pc(1); self.cycles += 2; (1, 2)
} }
pub fn increment_cycles_wdm(&mut self) { pub fn increment_cycles_nop() -> (u16, usize) {
self.registers.increment_pc(2); self.cycles += 2; (1, 2)
} }
pub fn increment_cycles_jmp(&mut self, addressing_mode: AddressingMode) { pub fn increment_cycles_wdm() -> (u16, usize) {
(2, 2)
}
pub fn increment_cycles_jmp(addressing_mode: AddressingMode) -> (u16, usize) {
let (_, cycles) = match addressing_mode { let (_, cycles) = match addressing_mode {
A::Absolute => (3, 3), A::Absolute => (3, 3),
A::AbsoluteIndirect => (3, 5), A::AbsoluteIndirect => (3, 5),
@@ -240,11 +267,11 @@ impl CPU {
// are performing a JMP anyway. // are performing a JMP anyway.
// However, we have to keep in mind PBR if we happen to increment PC at 0xFFFF // However, we have to keep in mind PBR if we happen to increment PC at 0xFFFF
// self.registers.increment_pc(bytes); // TODO: consider above comment // self.registers.increment_pc(bytes); // TODO: consider above comment
self.cycles += cycles; (0, cycles)
} }
/// Note: the bytes should be incremented *before* pushing onto the stack /// Note: the bytes should be incremented *before* pushing onto the stack
pub fn increment_cycles_jsr(&mut self, addressing_mode: AddressingMode) { pub fn increment_cycles_jsr(addressing_mode: AddressingMode) -> (u16, usize) {
let (bytes, cycles) = match addressing_mode { let (bytes, cycles) = match addressing_mode {
A::Absolute => (3, 6), A::Absolute => (3, 6),
A::AbsoluteIndexedIndirect(_) => (3, 8), A::AbsoluteIndexedIndirect(_) => (3, 8),
@@ -255,183 +282,194 @@ impl CPU {
// are performing a JMP anyway. // are performing a JMP anyway.
// However, we have to keep in mind PBR if we happen to increment PC at 0xFFFF // However, we have to keep in mind PBR if we happen to increment PC at 0xFFFF
// self.registers.increment_pc(bytes); // TODO: consider above comment // self.registers.increment_pc(bytes); // TODO: consider above comment
self.registers.increment_pc(bytes); self.cycles += cycles; (bytes, cycles)
} }
pub fn increment_cycles_lda(&mut self, addressing_mode: AddressingMode) { pub fn increment_cycles_lda(cpu_registers: &Registers, addressing_mode: AddressingMode) -> (u16, usize) {
let (bytes, cycles) = CPU::common_bytes_cycles_arithmetic(addressing_mode); let mut total_bytes = 0;
self.registers.increment_pc(bytes); self.cycles += cycles; let mut total_cycles = 0;
let (bytes, cycles) = self.common_conditions(addressing_mode, &LDA_CONDITIONS);
self.registers.increment_pc(bytes); self.cycles += cycles; let (bytes, cycles) = common_bytes_cycles_arithmetic(addressing_mode);
total_bytes += bytes; total_cycles += cycles;
let (bytes, cycles) = common_conditions(cpu_registers, addressing_mode, &LDA_CONDITIONS);
total_bytes += bytes; total_cycles += cycles;
(total_bytes, total_cycles)
} }
pub fn increment_cycles_ld_index(&mut self, addressing_mode: AddressingMode) { pub fn increment_cycles_ld_index(cpu_registers: &Registers, addressing_mode: AddressingMode) -> (u16, usize) {
let (bytes, cycles) = CPU::common_bytes_cycles_arithmetic(addressing_mode); let mut total_bytes = 0;
self.registers.increment_pc(bytes); self.cycles += cycles; let mut total_cycles = 0;
let (bytes, cycles) = self.common_conditions(addressing_mode, &LD_INDEX_CONDITIONS);
self.registers.increment_pc(bytes); self.cycles += cycles; let (bytes, cycles) = common_bytes_cycles_arithmetic(addressing_mode);
total_bytes += bytes; total_cycles += cycles;
let (bytes, cycles) = common_conditions(cpu_registers, addressing_mode, &LD_INDEX_CONDITIONS);
total_bytes += bytes; total_cycles += cycles;
(total_bytes, total_cycles)
} }
pub fn increment_cycles_pea(&mut self) { pub fn increment_cycles_pea() -> (u16, usize) {
self.registers.increment_pc(3); self.cycles += 5; (3, 5)
} }
pub fn increment_cycles_pei(&mut self) { pub fn increment_cycles_pei(cpu_registers: &Registers) -> (u16, usize) {
self.registers.increment_pc(2); self.cycles += 6; let mut total_bytes = 2;
let (bytes, cycles) = self.common_conditions( let mut total_cycles = 6;
let (bytes, cycles) = common_conditions(
cpu_registers,
AddressingMode::DirectPageIndirect, AddressingMode::DirectPageIndirect,
&[Condition::DirectPageIsZero], &[Condition::DirectPageIsZero],
); );
self.registers.increment_pc(bytes); self.cycles += cycles; total_bytes += bytes; total_cycles += cycles;
(total_bytes, total_cycles)
} }
pub fn increment_cycles_per(&mut self) { pub fn increment_cycles_per() -> (u16, usize) {
self.registers.increment_pc(3); self.cycles += 6; (3, 6)
} }
pub fn increment_cycles_pha(&mut self) { pub fn increment_cycles_pha(is_16bit_mode: bool) -> (u16, usize) {
self.registers.increment_pc(1); self.cycles += 3; (1, if is_16bit_mode {4} else {3})
if self.registers.is_16bit_mode() {
self.cycles += 1;
}
} }
pub fn increment_cycles_phb(&mut self) { pub fn increment_cycles_phb() -> (u16, usize) {
self.registers.increment_pc(1); self.cycles += 3; (1, 3)
} }
pub fn increment_cycles_phd(&mut self) { pub fn increment_cycles_phd() -> (u16, usize) {
self.registers.increment_pc(1); self.cycles += 4; (1, 4)
} }
pub fn increment_cycles_phk(&mut self) { pub fn increment_cycles_phk() -> (u16, usize) {
self.registers.increment_pc(1); self.cycles += 3; (1, 3)
} }
pub fn increment_cycles_php(&mut self) { pub fn increment_cycles_php() -> (u16, usize) {
self.registers.increment_pc(1); self.cycles += 3; (1, 3)
} }
pub fn increment_cycles_push_index(&mut self) { pub fn increment_cycles_push_index(is_16bit_index: bool) -> (u16, usize) {
self.registers.increment_pc(1); self.cycles += 3; (1, if is_16bit_index {4} else {3})
if self.registers.is_16bit_index() {
self.cycles += 1;
}
} }
pub fn increment_cycles_pla(&mut self) { pub fn increment_cycles_pla(is_16bit_mode: bool) -> (u16, usize) {
self.registers.increment_pc(1); self.cycles += 4; (1, if is_16bit_mode {5} else {4})
if self.registers.is_16bit_mode() {
self.cycles += 1;
}
} }
pub fn increment_cycles_plb(&mut self) { pub fn increment_cycles_plb() -> (u16, usize) {
self.registers.increment_pc(1); self.cycles += 4; (1, 4)
} }
pub fn increment_cycles_pld(&mut self) { pub fn increment_cycles_pld() -> (u16, usize) {
self.registers.increment_pc(1); self.cycles += 5; (1, 5)
} }
pub fn increment_cycles_plp(&mut self) { pub fn increment_cycles_plp() -> (u16, usize) {
self.registers.increment_pc(1); self.cycles += 4; (1, 4)
} }
pub fn increment_cycles_pl_index(&mut self) { pub fn increment_cycles_pl_index(is_16bit_index: bool) -> (u16, usize) {
self.registers.increment_pc(1); self.cycles += 4; (1, if is_16bit_index {5} else {4})
if self.registers.is_16bit_index() {
self.cycles += 1;
}
} }
pub fn increment_cycles_rep(&mut self) { pub fn increment_cycles_rep() -> (u16, usize) {
self.registers.increment_pc(2); self.cycles += 3; (2, 3)
} }
pub fn increment_cycles_sep(&mut self) { pub fn increment_cycles_sep() -> (u16, usize) {
self.registers.increment_pc(2); self.cycles += 3; (2, 3)
} }
pub fn increment_cycles_return_subroutine(&mut self) { pub fn increment_cycles_return_subroutine() -> (u16, usize) {
self.cycles += 6; (0, 6)
} }
pub fn increment_cycles_return_interrupt(&mut self) { pub fn increment_cycles_return_interrupt(is_emulation_mode: bool) -> (u16, usize) {
self.cycles += 6; (0, if is_emulation_mode {7} else {6})
if !self.registers.emulation_mode {
self.cycles += 1;
}
} }
pub fn increment_cycles_set_flag(&mut self) { pub fn increment_cycles_set_flag() -> (u16, usize) {
self.registers.increment_pc(1); self.cycles += 2; (1, 2)
} }
pub fn increment_cycles_sta(&mut self, addressing_mode: AddressingMode) { pub fn increment_cycles_sta(cpu_registers: &Registers, addressing_mode: AddressingMode) -> (u16, usize) {
let (bytes, cycles) = CPU::common_bytes_cycles_arithmetic(addressing_mode); let mut total_bytes = 0;
self.registers.increment_pc(bytes); self.cycles += cycles; let mut total_cycles = 0;
let (_, cycles) = self.common_conditions(addressing_mode, &[
let (bytes, cycles) = common_bytes_cycles_arithmetic(addressing_mode);
total_bytes += bytes; total_cycles += cycles;
let (_, cycles) = common_conditions(cpu_registers, addressing_mode, &[
Condition::MemorySelectFlag, Condition::MemorySelectFlag,
Condition::DirectPageIsZero, Condition::DirectPageIsZero,
]); ]);
self.cycles += cycles; total_cycles += cycles;
(total_bytes, total_cycles)
} }
pub fn increment_cycles_st_index(&mut self, addressing_mode: AddressingMode) { pub fn increment_cycles_st_index(cpu_registers: &Registers, addressing_mode: AddressingMode) -> (u16, usize) {
let (bytes, cycles) = CPU::common_bytes_cycles_arithmetic(addressing_mode); let mut total_bytes = 0;
self.registers.increment_pc(bytes); self.cycles += cycles; let mut total_cycles = 0;
let (_, cycles) = self.common_conditions(addressing_mode, &[
let (bytes, cycles) = common_bytes_cycles_arithmetic(addressing_mode);
total_bytes += bytes; total_cycles += cycles;
let (_, cycles) = common_conditions(cpu_registers, addressing_mode, &[
Condition::IndexIs16Bit, Condition::IndexIs16Bit,
Condition::DirectPageIsZero, Condition::DirectPageIsZero,
]); ]);
self.cycles += cycles; total_cycles += cycles;
(total_bytes, total_cycles)
} }
pub fn increment_cycles_transfer(&mut self) { pub fn increment_cycles_transfer() -> (u16, usize) {
self.registers.increment_pc(1); self.cycles += 2; (1, 2)
} }
pub fn increment_cycles_exchange(&mut self) { pub fn increment_cycles_exchange() -> (u16, usize) {
self.registers.increment_pc(1); self.cycles += 2; (1, 2)
} }
pub fn increment_cycles_xba(&mut self) { pub fn increment_cycles_xba() -> (u16, usize) {
self.registers.increment_pc(1); self.cycles += 3; (1, 3)
} }
pub fn increment_cycles_brk(&mut self) { pub fn increment_cycles_brk(is_emulation_mode: bool) -> (u16, usize) {
self.registers.increment_pc(2); self.cycles += 7; (2, if is_emulation_mode {8} else {7})
if self.registers.emulation_mode {
self.cycles += 1;
}
} }
pub fn increment_cycles_stp(&mut self) { pub fn increment_cycles_stp() -> (u16, usize) {
self.registers.increment_pc(1); self.cycles += 3; (1, 3)
} }
pub fn increment_cycles_while_stopped(&mut self) { pub fn increment_cycles_while_stopped() -> (u16, usize) {
self.cycles += 1; (0, 1)
} }
pub fn increment_cycles_move(&mut self, count: usize) { pub fn increment_cycles_move(count: usize) -> (u16, usize) {
self.registers.increment_pc(3); self.cycles += 7 * count; (3, 7 * count)
} }
pub fn increment_cycles_test(&mut self, addressing_mode: AddressingMode) { pub fn increment_cycles_test(cpu_registers: &Registers, addressing_mode: AddressingMode) -> (u16, usize) {
let mut total_bytes = 0;
let mut total_cycles = 0;
let (bytes, cycles) = match addressing_mode { let (bytes, cycles) = match addressing_mode {
AddressingMode::Absolute => (3, 6), AddressingMode::Absolute => (3, 6),
AddressingMode::DirectPage => (2, 5), AddressingMode::DirectPage => (2, 5),
_ => unreachable!(), _ => unreachable!(),
}; };
self.registers.increment_pc(bytes); self.cycles += cycles; total_bytes += bytes; total_cycles += cycles;
let (_, cycles) = self.common_conditions(addressing_mode, &[ let (_, cycles) = common_conditions(cpu_registers, addressing_mode, &[
Condition::MemorySelectFlag, Condition::MemorySelectFlag,
Condition::DirectPageIsZero, Condition::DirectPageIsZero,
]); ]);
self.cycles += cycles; total_cycles += cycles;
}
(total_bytes, total_cycles)
} }
#[cfg(test)] #[cfg(test)]
@@ -440,73 +478,72 @@ mod cpu_instructions_tests {
#[test] #[test]
fn test_common_conditions() { fn test_common_conditions() {
let mut cpu = CPU::new(); let mut registers = Registers::new();
cpu.registers.emulation_mode = false; registers.emulation_mode = false;
// 16-bit Memory/accumulator flag condition // 16-bit Memory/accumulator flag condition
cpu.registers.pc = 0; registers.pc = 0;
cpu.registers.set_decimal_mode_flag(false); registers.set_decimal_mode_flag(false);
cpu.registers.set_16bit_mode(false); registers.set_16bit_mode(false);
let (bytes, cycles) = cpu.common_conditions(AddressingMode::Immediate, &ALL_CONDITIONS); let (bytes, cycles) = common_conditions(&registers, AddressingMode::Immediate, &ALL_CONDITIONS);
assert_eq!(bytes, 0); assert_eq!(bytes, 0);
assert_eq!(cycles, 0); assert_eq!(cycles, 0);
cpu.registers.pc = 0; registers.pc = 0;
cpu.registers.set_16bit_mode(true); registers.set_16bit_mode(true);
let (bytes, cycles) = cpu.common_conditions(AddressingMode::Immediate, &ALL_CONDITIONS); let (bytes, cycles) = common_conditions(&registers, AddressingMode::Immediate, &ALL_CONDITIONS);
assert_eq!(bytes, 1); assert_eq!(bytes, 1);
assert_eq!(cycles, 1); assert_eq!(cycles, 1);
// Decimal flag condition // Decimal flag condition
cpu.registers.pc = 0; registers.pc = 0;
cpu.registers.set_16bit_mode(true); registers.set_16bit_mode(true);
cpu.registers.set_decimal_mode_flag(true); registers.set_decimal_mode_flag(true);
let (bytes, cycles) = cpu.common_conditions(AddressingMode::Immediate, &ALL_CONDITIONS); let (bytes, cycles) = common_conditions(&registers, AddressingMode::Immediate, &ALL_CONDITIONS);
assert_eq!(bytes, 1); assert_eq!(bytes, 1);
assert_eq!(cycles, 2); assert_eq!(cycles, 2);
// Low byte of direct page register other than zero condition // Low byte of direct page register other than zero condition
cpu.registers.pc = 0; registers.pc = 0;
cpu.registers.set_16bit_mode(false); registers.set_16bit_mode(false);
cpu.registers.set_decimal_mode_flag(false); registers.set_decimal_mode_flag(false);
cpu.registers.d = 0x0000; registers.d = 0x0000;
let (bytes, cycles) = cpu.common_conditions(AddressingMode::DirectPage, &ALL_CONDITIONS); let (bytes, cycles) = common_conditions(&registers, AddressingMode::DirectPage, &ALL_CONDITIONS);
assert_eq!(bytes, 0); assert_eq!(bytes, 0);
assert_eq!(cycles, 0); assert_eq!(cycles, 0);
cpu.registers.pc = 0; registers.pc = 0;
cpu.registers.set_16bit_mode(false); registers.set_16bit_mode(false);
cpu.registers.set_decimal_mode_flag(false); registers.set_decimal_mode_flag(false);
cpu.registers.d = 0x0001; registers.d = 0x0001;
let (bytes, cycles) = cpu.common_conditions(AddressingMode::DirectPage, &ALL_CONDITIONS); let (bytes, cycles) = common_conditions(&registers, AddressingMode::DirectPage, &ALL_CONDITIONS);
assert_eq!(bytes, 0); assert_eq!(bytes, 0);
assert_eq!(cycles, 1); assert_eq!(cycles, 1);
// Adding index crosses a page boundary condition // Adding index crosses a page boundary condition
cpu.registers.pc = 0xFE; registers.pc = 0xFE;
cpu.registers.x = 0x0001; registers.x = 0x0001;
cpu.registers.set_16bit_mode(false); registers.set_16bit_mode(false);
cpu.registers.set_decimal_mode_flag(false); registers.set_decimal_mode_flag(false);
let (bytes, cycles) = cpu.common_conditions(AddressingMode::AbsoluteIndexed(IndexRegister::X), &ALL_CONDITIONS); let (bytes, cycles) = common_conditions(&registers, AddressingMode::AbsoluteIndexed(IndexRegister::X), &ALL_CONDITIONS);
assert_eq!(bytes, 0); assert_eq!(bytes, 0);
assert_eq!(cycles, 0); // Doesn't cross boundary assert_eq!(cycles, 0); // Doesn't cross boundary
cpu.registers.pc = 0xFE; registers.pc = 0xFE;
cpu.registers.x = 0x0010; registers.x = 0x0010;
cpu.registers.set_16bit_mode(false); registers.set_16bit_mode(false);
cpu.registers.set_decimal_mode_flag(false); registers.set_decimal_mode_flag(false);
let (bytes, cycles) = cpu.common_conditions(AddressingMode::AbsoluteIndexed(IndexRegister::X), &ALL_CONDITIONS); let (bytes, cycles) = common_conditions(&registers, AddressingMode::AbsoluteIndexed(IndexRegister::X), &ALL_CONDITIONS);
assert_eq!(bytes, 0); assert_eq!(bytes, 0);
assert_eq!(cycles, 1); // Crosses boundary assert_eq!(cycles, 1); // Crosses boundary
// Test common and aritmetic together // Test common and aritmetic together
cpu.registers.pc = 0xF5; registers.pc = 0xF5;
cpu.registers.x = 0x0010; registers.x = 0x0010;
cpu.cycles = 0; registers.set_16bit_mode(false);
cpu.registers.set_16bit_mode(false); registers.set_decimal_mode_flag(false);
cpu.registers.set_decimal_mode_flag(false); let (bytes, cycles) = increment_cycles_arithmetic(&registers, AddressingMode::AbsoluteIndexed(IndexRegister::X));
cpu.increment_cycles_arithmetic(AddressingMode::AbsoluteIndexed(IndexRegister::X)); assert_eq!(bytes, 3);
assert_eq!(cpu.registers.pc, 0xF5 + 3); assert_eq!(cycles, 5);
assert_eq!(cpu.cycles, 5);
} }
} }
+201 -100
View File
@@ -1,6 +1,7 @@
use super::cpu::CPU; use super::cpu::CPU;
use crate::cpu::bus::Bus; use crate::cpu::bus::Bus;
use crate::cpu::dma; use crate::cpu::dma;
use crate::cpu::cycles;
use crate::utils::addressing::{AddressingMode, IndexRegister}; use crate::utils::addressing::{AddressingMode, IndexRegister};
use crate::utils::alu; use crate::utils::alu;
use crate::utils::num_trait::SnesNum; use crate::utils::num_trait::SnesNum;
@@ -96,7 +97,8 @@ impl CPU {
self.registers.set_low_a(result as u8); self.registers.set_low_a(result as u8);
self.registers.set_flags(&affected_flags); self.registers.set_flags(&affected_flags);
} }
self.increment_cycles_arithmetic(addressing_mode); let (bytes, cycles) = cycles::increment_cycles_arithmetic(&self.registers, addressing_mode);
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn sbc(&mut self, bus: &mut Bus, addressing_mode: AddressingMode) { fn sbc(&mut self, bus: &mut Bus, addressing_mode: AddressingMode) {
@@ -121,7 +123,8 @@ impl CPU {
self.registers.set_low_a(result as u8); self.registers.set_low_a(result as u8);
self.registers.set_flags(&affected_flags); self.registers.set_flags(&affected_flags);
} }
self.increment_cycles_arithmetic(addressing_mode); let (bytes, cycles) = cycles::increment_cycles_arithmetic(&self.registers, addressing_mode);
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn do_dec<T: SnesNum>(&mut self, target: T) -> T { fn do_dec<T: SnesNum>(&mut self, target: T) -> T {
@@ -145,7 +148,8 @@ impl CPU {
let result = self.do_dec(value).to_u32() as u8; let result = self.do_dec(value).to_u32() as u8;
self.set_8bit_to_address(bus, addressing_mode, result); self.set_8bit_to_address(bus, addressing_mode, result);
} }
self.increment_cycles_inc_dec(addressing_mode); let (bytes, cycles) = cycles::increment_cycles_inc_dec(&self.registers, addressing_mode);
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn dex(&mut self) { fn dex(&mut self) {
@@ -155,7 +159,8 @@ impl CPU {
let result = self.do_dec(self.registers.x).to_u32() as u8; let result = self.do_dec(self.registers.x).to_u32() as u8;
self.registers.set_low_x(result); self.registers.set_low_x(result);
} }
self.increment_cycles_inc_dec_index(); let (bytes, cycles) = cycles::increment_cycles_inc_dec_index();
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn dey(&mut self) { fn dey(&mut self) {
@@ -165,7 +170,8 @@ impl CPU {
let result = self.do_dec(self.registers.y).to_u32() as u8; let result = self.do_dec(self.registers.y).to_u32() as u8;
self.registers.set_low_y(result); self.registers.set_low_y(result);
} }
self.increment_cycles_inc_dec_index(); let (bytes, cycles) = cycles::increment_cycles_inc_dec_index();
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn do_inc<T: SnesNum>(&mut self, target: T) -> T { fn do_inc<T: SnesNum>(&mut self, target: T) -> T {
@@ -189,7 +195,8 @@ impl CPU {
let result = self.do_inc(value).to_u32() as u8; let result = self.do_inc(value).to_u32() as u8;
self.set_8bit_to_address(bus, addressing_mode, result); self.set_8bit_to_address(bus, addressing_mode, result);
} }
self.increment_cycles_inc_dec(addressing_mode); let (bytes, cycles) = cycles::increment_cycles_inc_dec(&self.registers, addressing_mode);
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn inx(&mut self) { fn inx(&mut self) {
@@ -199,7 +206,8 @@ impl CPU {
let result = self.do_inc(self.registers.x).to_u32() as u8; let result = self.do_inc(self.registers.x).to_u32() as u8;
self.registers.set_low_x(result); self.registers.set_low_x(result);
} }
self.increment_cycles_inc_dec_index(); let (bytes, cycles) = cycles::increment_cycles_inc_dec_index();
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn iny(&mut self) { fn iny(&mut self) {
@@ -209,7 +217,8 @@ impl CPU {
let result = self.do_inc(self.registers.y).to_u32() as u8; let result = self.do_inc(self.registers.y).to_u32() as u8;
self.registers.set_low_y(result); self.registers.set_low_y(result);
} }
self.increment_cycles_inc_dec_index(); let (bytes, cycles) = cycles::increment_cycles_inc_dec_index();
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn do_comp<T: SnesNum>(&mut self, target: T, value: T) { fn do_comp<T: SnesNum>(&mut self, target: T, value: T) {
@@ -232,7 +241,8 @@ impl CPU {
let value = self.get_8bit_from_address(bus, addressing_mode); let value = self.get_8bit_from_address(bus, addressing_mode);
self.do_comp(target as u8, value); self.do_comp(target as u8, value);
} }
self.increment_cycles_arithmetic(addressing_mode); let (bytes, cycles) = cycles::increment_cycles_arithmetic(&self.registers, addressing_mode);
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn cpx(&mut self, bus: &mut Bus, addressing_mode: AddressingMode) { fn cpx(&mut self, bus: &mut Bus, addressing_mode: AddressingMode) {
@@ -245,7 +255,8 @@ impl CPU {
let value = self.get_8bit_from_address(bus, addressing_mode); let value = self.get_8bit_from_address(bus, addressing_mode);
self.do_comp(target as u8, value); self.do_comp(target as u8, value);
} }
self.increment_cycles_comp_index(addressing_mode); let (bytes, cycles) = cycles::increment_cycles_comp_index(&self.registers, addressing_mode);
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn cpy(&mut self, bus: &mut Bus, addressing_mode: AddressingMode) { fn cpy(&mut self, bus: &mut Bus, addressing_mode: AddressingMode) {
@@ -258,7 +269,8 @@ impl CPU {
let value = self.get_8bit_from_address(bus, addressing_mode); let value = self.get_8bit_from_address(bus, addressing_mode);
self.do_comp(target as u8, value); self.do_comp(target as u8, value);
} }
self.increment_cycles_comp_index(addressing_mode); let (bytes, cycles) = cycles::increment_cycles_comp_index(&self.registers, addressing_mode);
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn and(&mut self, bus: &mut Bus, addressing_mode: AddressingMode) { fn and(&mut self, bus: &mut Bus, addressing_mode: AddressingMode) {
@@ -274,7 +286,8 @@ impl CPU {
self.registers.set_low_a(result); self.registers.set_low_a(result);
self.registers.set_flags(&affected_flags); self.registers.set_flags(&affected_flags);
} }
self.increment_cycles_bitwise(addressing_mode); let (bytes, cycles) = cycles::increment_cycles_bitwise(&self.registers, addressing_mode);
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn ora(&mut self, bus: &mut Bus, addressing_mode: AddressingMode) { fn ora(&mut self, bus: &mut Bus, addressing_mode: AddressingMode) {
@@ -290,7 +303,8 @@ impl CPU {
self.registers.set_low_a(result); self.registers.set_low_a(result);
self.registers.set_flags(&affected_flags); self.registers.set_flags(&affected_flags);
} }
self.increment_cycles_bitwise(addressing_mode); let (bytes, cycles) = cycles::increment_cycles_bitwise(&self.registers, addressing_mode);
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn eor(&mut self, bus: &mut Bus, addressing_mode: AddressingMode) { fn eor(&mut self, bus: &mut Bus, addressing_mode: AddressingMode) {
@@ -306,7 +320,8 @@ impl CPU {
self.registers.set_low_a(result); self.registers.set_low_a(result);
self.registers.set_flags(&affected_flags); self.registers.set_flags(&affected_flags);
} }
self.increment_cycles_bitwise(addressing_mode); let (bytes, cycles) = cycles::increment_cycles_bitwise(&self.registers, addressing_mode);
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn asl(&mut self, bus: &mut Bus, addressing_mode: AddressingMode) { fn asl(&mut self, bus: &mut Bus, addressing_mode: AddressingMode) {
@@ -326,7 +341,8 @@ impl CPU {
self.set_8bit_to_address(bus, addressing_mode, result); self.set_8bit_to_address(bus, addressing_mode, result);
self.registers.set_flags(&affected_flags); self.registers.set_flags(&affected_flags);
} }
self.increment_cycles_shift(addressing_mode); let (bytes, cycles) = cycles::increment_cycles_shift(&self.registers, addressing_mode);
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn lsr(&mut self, bus: &mut Bus, addressing_mode: AddressingMode) { fn lsr(&mut self, bus: &mut Bus, addressing_mode: AddressingMode) {
@@ -346,7 +362,8 @@ impl CPU {
self.set_8bit_to_address(bus, addressing_mode, result); self.set_8bit_to_address(bus, addressing_mode, result);
self.registers.set_flags(&affected_flags); self.registers.set_flags(&affected_flags);
} }
self.increment_cycles_shift(addressing_mode); let (bytes, cycles) = cycles::increment_cycles_shift(&self.registers, addressing_mode);
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn do_bit<T: SnesNum>(&mut self, accumulator: T, value: T, addressing_mode: AddressingMode) { fn do_bit<T: SnesNum>(&mut self, accumulator: T, value: T, addressing_mode: AddressingMode) {
@@ -370,7 +387,8 @@ impl CPU {
let value = self.get_8bit_from_address(bus, addressing_mode); let value = self.get_8bit_from_address(bus, addressing_mode);
self.do_bit(self.registers.a as u8, value, addressing_mode); self.do_bit(self.registers.a as u8, value, addressing_mode);
} }
self.increment_cycles_bit(addressing_mode); let (bytes, cycles) = cycles::increment_cycles_bit(&self.registers, addressing_mode);
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn do_branch(&mut self, nearlabel: u8) -> bool { fn do_branch(&mut self, nearlabel: u8) -> bool {
@@ -389,63 +407,77 @@ impl CPU {
fn bcc(&mut self, bus: &mut Bus) { fn bcc(&mut self, bus: &mut Bus) {
let nearlabel = bus.read(self.registers.get_pc_address().wrapping_add(1)); let nearlabel = bus.read(self.registers.get_pc_address().wrapping_add(1));
self.increment_cycles_branch(); let (bytes, cycles) = cycles::increment_cycles_branch();
self.registers.increment_pc(bytes); self.cycles += cycles;
if !self.registers.get_carry_flag() { if !self.registers.get_carry_flag() {
let page_boundary_crossed = self.do_branch(nearlabel); let page_boundary_crossed = self.do_branch(nearlabel);
self.increment_cycles_branch_taken(page_boundary_crossed); let (bytes, cycles) = cycles::increment_cycles_branch_taken(page_boundary_crossed);
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
} }
fn bcs(&mut self, bus: &mut Bus) { fn bcs(&mut self, bus: &mut Bus) {
let nearlabel = bus.read(self.registers.get_pc_address().wrapping_add(1)); let nearlabel = bus.read(self.registers.get_pc_address().wrapping_add(1));
self.increment_cycles_branch(); let (bytes, cycles) = cycles::increment_cycles_branch();
self.registers.increment_pc(bytes); self.cycles += cycles;
if self.registers.get_carry_flag() { if self.registers.get_carry_flag() {
let page_boundary_crossed = self.do_branch(nearlabel); let page_boundary_crossed = self.do_branch(nearlabel);
self.increment_cycles_branch_taken(page_boundary_crossed); let (bytes, cycles) = cycles::increment_cycles_branch_taken(page_boundary_crossed);
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
} }
fn beq(&mut self, bus: &mut Bus) { fn beq(&mut self, bus: &mut Bus) {
let nearlabel = bus.read(self.registers.get_pc_address().wrapping_add(1)); let nearlabel = bus.read(self.registers.get_pc_address().wrapping_add(1));
self.increment_cycles_branch(); let (bytes, cycles) = cycles::increment_cycles_branch();
self.registers.increment_pc(bytes); self.cycles += cycles;
if self.registers.get_zero_flag() { if self.registers.get_zero_flag() {
let page_boundary_crossed = self.do_branch(nearlabel); let page_boundary_crossed = self.do_branch(nearlabel);
self.increment_cycles_branch_taken(page_boundary_crossed); let (bytes, cycles) = cycles::increment_cycles_branch_taken(page_boundary_crossed);
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
} }
fn bne(&mut self, bus: &mut Bus) { fn bne(&mut self, bus: &mut Bus) {
let nearlabel = bus.read(self.registers.get_pc_address().wrapping_add(1)); let nearlabel = bus.read(self.registers.get_pc_address().wrapping_add(1));
self.increment_cycles_branch(); let (bytes, cycles) = cycles::increment_cycles_branch();
self.registers.increment_pc(bytes); self.cycles += cycles;
if !self.registers.get_zero_flag() { if !self.registers.get_zero_flag() {
let page_boundary_crossed = self.do_branch(nearlabel); let page_boundary_crossed = self.do_branch(nearlabel);
self.increment_cycles_branch_taken(page_boundary_crossed); let (bytes, cycles) = cycles::increment_cycles_branch_taken(page_boundary_crossed);
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
} }
fn bmi(&mut self, bus: &mut Bus) { fn bmi(&mut self, bus: &mut Bus) {
let nearlabel = bus.read(self.registers.get_pc_address().wrapping_add(1)); let nearlabel = bus.read(self.registers.get_pc_address().wrapping_add(1));
self.increment_cycles_branch(); let (bytes, cycles) = cycles::increment_cycles_branch();
self.registers.increment_pc(bytes); self.cycles += cycles;
if self.registers.get_negative_flag() { if self.registers.get_negative_flag() {
let page_boundary_crossed = self.do_branch(nearlabel); let page_boundary_crossed = self.do_branch(nearlabel);
self.increment_cycles_branch_taken(page_boundary_crossed); let (bytes, cycles) = cycles::increment_cycles_branch_taken(page_boundary_crossed);
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
} }
fn bpl(&mut self, bus: &mut Bus) { fn bpl(&mut self, bus: &mut Bus) {
let nearlabel = bus.read(self.registers.get_pc_address().wrapping_add(1)); let nearlabel = bus.read(self.registers.get_pc_address().wrapping_add(1));
self.increment_cycles_branch(); let (bytes, cycles) = cycles::increment_cycles_branch();
self.registers.increment_pc(bytes); self.cycles += cycles;
if !self.registers.get_negative_flag() { if !self.registers.get_negative_flag() {
let page_boundary_crossed = self.do_branch(nearlabel); let page_boundary_crossed = self.do_branch(nearlabel);
self.increment_cycles_branch_taken(page_boundary_crossed); let (bytes, cycles) = cycles::increment_cycles_branch_taken(page_boundary_crossed);
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
} }
fn bra(&mut self, bus: &mut Bus) { fn bra(&mut self, bus: &mut Bus) {
let nearlabel = bus.read(self.registers.get_pc_address().wrapping_add(1)); let nearlabel = bus.read(self.registers.get_pc_address().wrapping_add(1));
self.increment_cycles_branch(); let (bytes, cycles) = cycles::increment_cycles_branch();
self.registers.increment_pc(bytes); self.cycles += cycles;
let page_boundary_crossed = self.do_branch(nearlabel); let page_boundary_crossed = self.do_branch(nearlabel);
self.increment_cycles_branch_taken(page_boundary_crossed); let (bytes, cycles) = cycles::increment_cycles_branch_taken(page_boundary_crossed);
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn brl(&mut self, bus: &mut Bus) { fn brl(&mut self, bus: &mut Bus) {
@@ -458,49 +490,59 @@ impl CPU {
} else { } else {
self.registers.increment_pc(label); self.registers.increment_pc(label);
} }
self.increment_cycles_branch_long(); let (bytes, cycles) = cycles::increment_cycles_branch_long();
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn bvc(&mut self, bus: &mut Bus) { fn bvc(&mut self, bus: &mut Bus) {
let nearlabel = bus.read(self.registers.get_pc_address().wrapping_add(1)); let nearlabel = bus.read(self.registers.get_pc_address().wrapping_add(1));
self.increment_cycles_branch(); let (bytes, cycles) = cycles::increment_cycles_branch();
self.registers.increment_pc(bytes); self.cycles += cycles;
if !self.registers.get_overflow_flag() { if !self.registers.get_overflow_flag() {
let page_boundary_crossed = self.do_branch(nearlabel); let page_boundary_crossed = self.do_branch(nearlabel);
self.increment_cycles_branch_taken(page_boundary_crossed); let (bytes, cycles) = cycles::increment_cycles_branch_taken(page_boundary_crossed);
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
} }
fn bvs(&mut self, bus: &mut Bus) { fn bvs(&mut self, bus: &mut Bus) {
let nearlabel = bus.read(self.registers.get_pc_address().wrapping_add(1)); let nearlabel = bus.read(self.registers.get_pc_address().wrapping_add(1));
self.increment_cycles_branch(); let (bytes, cycles) = cycles::increment_cycles_branch();
self.registers.increment_pc(bytes); self.cycles += cycles;
if self.registers.get_overflow_flag() { if self.registers.get_overflow_flag() {
let page_boundary_crossed = self.do_branch(nearlabel); let page_boundary_crossed = self.do_branch(nearlabel);
self.increment_cycles_branch_taken(page_boundary_crossed); let (bytes, cycles) = cycles::increment_cycles_branch_taken(page_boundary_crossed);
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
} }
fn clc(&mut self) { fn clc(&mut self) {
self.registers.set_carry_flag(false); self.registers.set_carry_flag(false);
self.increment_cycles_clear(); let (bytes, cycles) = cycles::increment_cycles_clear();
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn cld(&mut self) { fn cld(&mut self) {
self.registers.set_decimal_mode_flag(false); self.registers.set_decimal_mode_flag(false);
self.increment_cycles_clear(); let (bytes, cycles) = cycles::increment_cycles_clear();
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn cli(&mut self) { fn cli(&mut self) {
self.registers.set_irq_disable_flag(false); self.registers.set_irq_disable_flag(false);
self.increment_cycles_clear(); let (bytes, cycles) = cycles::increment_cycles_clear();
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn clv(&mut self) { fn clv(&mut self) {
self.registers.set_overflow_flag(false); self.registers.set_overflow_flag(false);
self.increment_cycles_clear(); let (bytes, cycles) = cycles::increment_cycles_clear();
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn nop(&mut self) { fn nop(&mut self) {
self.increment_cycles_nop(); let (bytes, cycles) = cycles::increment_cycles_nop();
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn jmp(&mut self, bus: &mut Bus, addressing_mode: AddressingMode) { fn jmp(&mut self, bus: &mut Bus, addressing_mode: AddressingMode) {
@@ -514,7 +556,8 @@ impl CPU {
if is_long { if is_long {
self.registers.pbr = (effective_address >> 16) as u8; self.registers.pbr = (effective_address >> 16) as u8;
} }
self.increment_cycles_jmp(addressing_mode); let (bytes, cycles) = cycles::increment_cycles_jmp(addressing_mode);
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
pub fn do_push(&mut self, bus: &mut Bus, bytes: &[u8]) { pub fn do_push(&mut self, bus: &mut Bus, bytes: &[u8]) {
@@ -531,7 +574,8 @@ impl CPU {
self.do_push(bus, &[self.registers.p]); self.do_push(bus, &[self.registers.p]);
self.registers.set_decimal_mode_flag(false); self.registers.set_decimal_mode_flag(false);
self.registers.set_irq_disable_flag(true); self.registers.set_irq_disable_flag(true);
self.increment_cycles_brk(); let (bytes, cycles) = cycles::increment_cycles_brk(self.registers.emulation_mode);
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn cop(&mut self, bus: &mut Bus) { fn cop(&mut self, bus: &mut Bus) {
@@ -540,25 +584,29 @@ impl CPU {
self.do_push(bus, &[self.registers.p]); self.do_push(bus, &[self.registers.p]);
self.registers.set_decimal_mode_flag(false); self.registers.set_decimal_mode_flag(false);
self.registers.set_irq_disable_flag(true); self.registers.set_irq_disable_flag(true);
self.increment_cycles_brk(); let (bytes, cycles) = cycles::increment_cycles_brk(self.registers.emulation_mode);
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn pea(&mut self, bus: &mut Bus) { fn pea(&mut self, bus: &mut Bus) {
let address = self.get_effective_address(bus, AddressingMode::Absolute); let address = self.get_effective_address(bus, AddressingMode::Absolute);
self.do_push(bus, &[(address >> 8) as u8, address as u8]); self.do_push(bus, &[(address >> 8) as u8, address as u8]);
self.increment_cycles_pea(); let (bytes, cycles) = cycles::increment_cycles_pea();
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn pei(&mut self, bus: &mut Bus) { fn pei(&mut self, bus: &mut Bus) {
let address = self.get_effective_address(bus, AddressingMode::DirectPageIndirect); let address = self.get_effective_address(bus, AddressingMode::DirectPageIndirect);
self.do_push(bus, &[(address >> 8) as u8, address as u8]); self.do_push(bus, &[(address >> 8) as u8, address as u8]);
self.increment_cycles_pei(); let (bytes, cycles) = cycles::increment_cycles_pei(&self.registers);
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn per(&mut self, bus: &mut Bus) { fn per(&mut self, bus: &mut Bus) {
let label = self.get_effective_address(bus, AddressingMode::Absolute) as u16; let label = self.get_effective_address(bus, AddressingMode::Absolute) as u16;
let is_negative = (label>> 15) == 1; let is_negative = (label>> 15) == 1;
self.increment_cycles_per(); let (bytes, cycles) = cycles::increment_cycles_per();
self.registers.increment_pc(bytes); self.cycles += cycles;
let address = match is_negative { let address = match is_negative {
true => self.registers.pc.wrapping_sub(!label + 1), true => self.registers.pc.wrapping_sub(!label + 1),
false=> self.registers.pc.wrapping_add(label), false=> self.registers.pc.wrapping_add(label),
@@ -573,28 +621,33 @@ impl CPU {
} else { } else {
self.do_push(bus, &[value as u8]); self.do_push(bus, &[value as u8]);
} }
self.increment_cycles_pha(); let (bytes, cycles) = cycles::increment_cycles_pha(self.registers.is_16bit_mode());
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn phb(&mut self, bus: &mut Bus) { fn phb(&mut self, bus: &mut Bus) {
self.do_push(bus, &[self.registers.dbr]); self.do_push(bus, &[self.registers.dbr]);
self.increment_cycles_phb(); let (bytes, cycles) = cycles::increment_cycles_phb();
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn phd(&mut self, bus: &mut Bus) { fn phd(&mut self, bus: &mut Bus) {
let value = self.registers.d; let value = self.registers.d;
self.do_push(bus, &[(value >> 8) as u8, value as u8]); self.do_push(bus, &[(value >> 8) as u8, value as u8]);
self.increment_cycles_phd(); let (bytes, cycles) = cycles::increment_cycles_phd();
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
pub fn phk(&mut self, bus: &mut Bus) { pub fn phk(&mut self, bus: &mut Bus) {
self.do_push(bus, &[self.registers.pbr]); self.do_push(bus, &[self.registers.pbr]);
self.increment_cycles_phk(); let (bytes, cycles) = cycles::increment_cycles_phk();
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
pub fn php(&mut self, bus: &mut Bus) { pub fn php(&mut self, bus: &mut Bus) {
self.do_push(bus, &[self.registers.p]); self.do_push(bus, &[self.registers.p]);
self.increment_cycles_php(); let (bytes, cycles) = cycles::increment_cycles_php();
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn phx(&mut self, bus: &mut Bus) { fn phx(&mut self, bus: &mut Bus) {
@@ -604,7 +657,8 @@ impl CPU {
} else { } else {
self.do_push(bus, &[value as u8]); self.do_push(bus, &[value as u8]);
} }
self.increment_cycles_push_index(); let (bytes, cycles) = cycles::increment_cycles_push_index(self.registers.is_16bit_index());
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn phy(&mut self, bus: &mut Bus) { fn phy(&mut self, bus: &mut Bus) {
@@ -614,7 +668,8 @@ impl CPU {
} else { } else {
self.do_push(bus, &[value as u8]); self.do_push(bus, &[value as u8]);
} }
self.increment_cycles_push_index(); let (bytes, cycles) = cycles::increment_cycles_push_index(self.registers.is_16bit_index());
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn jsr(&mut self, bus: &mut Bus, addressing_mode: AddressingMode) { fn jsr(&mut self, bus: &mut Bus, addressing_mode: AddressingMode) {
@@ -625,7 +680,8 @@ impl CPU {
_ => false, _ => false,
}; };
// We need to push the *next* instruction onto the stack // We need to push the *next* instruction onto the stack
self.increment_cycles_jsr(addressing_mode); let (bytes, cycles) = cycles::increment_cycles_jsr(addressing_mode);
self.registers.increment_pc(bytes); self.cycles += cycles;
let value = self.registers.get_pc_address(); let value = self.registers.get_pc_address();
if is_long { if is_long {
self.do_push(bus, &[ self.do_push(bus, &[
@@ -662,7 +718,8 @@ impl CPU {
self.registers.set_low_a(value); self.registers.set_low_a(value);
self.do_bit(self.registers.a as u8, value, addressing_mode); self.do_bit(self.registers.a as u8, value, addressing_mode);
} }
self.increment_cycles_lda(addressing_mode); let (bytes, cycles) = cycles::increment_cycles_lda(&self.registers, addressing_mode);
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn do_ld_index(&mut self, bus: &mut Bus, index: IndexRegister, addressing_mode: AddressingMode) { fn do_ld_index(&mut self, bus: &mut Bus, index: IndexRegister, addressing_mode: AddressingMode) {
@@ -687,7 +744,8 @@ impl CPU {
Flags::Zero(value == 0), Flags::Zero(value == 0),
]); ]);
} }
self.increment_cycles_ld_index(addressing_mode); let (bytes, cycles) = cycles::increment_cycles_ld_index(&self.registers, addressing_mode);
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn ldx(&mut self, bus: &mut Bus, addressing_mode: AddressingMode) { fn ldx(&mut self, bus: &mut Bus, addressing_mode: AddressingMode) {
@@ -726,24 +784,28 @@ impl CPU {
let bytes = self.do_pull(bus, 1); let bytes = self.do_pull(bus, 1);
self.registers.set_low_a(bytes[0]); self.registers.set_low_a(bytes[0]);
} }
self.increment_cycles_pla(); let (bytes, cycles) = cycles::increment_cycles_pla(self.registers.is_16bit_mode());
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn plb(&mut self, bus: &mut Bus) { fn plb(&mut self, bus: &mut Bus) {
self.registers.dbr = self.do_pull(bus, 1)[0]; self.registers.dbr = self.do_pull(bus, 1)[0];
self.increment_cycles_plb(); let (bytes, cycles) = cycles::increment_cycles_plb();
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn pld(&mut self, bus: &mut Bus) { fn pld(&mut self, bus: &mut Bus) {
let bytes = self.do_pull(bus, 2); let bytes = self.do_pull(bus, 2);
self.registers.d = (bytes[0] as u16) | ((bytes[1] as u16) << 8); self.registers.d = (bytes[0] as u16) | ((bytes[1] as u16) << 8);
self.increment_cycles_pld(); let (bytes, cycles) = cycles::increment_cycles_pld();
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn plp(&mut self, bus: &mut Bus) { fn plp(&mut self, bus: &mut Bus) {
let bytes = self.do_pull(bus, 1); let bytes = self.do_pull(bus, 1);
self.registers.p = bytes[0]; self.registers.p = bytes[0];
self.increment_cycles_plp(); let (bytes, cycles) = cycles::increment_cycles_plp();
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn plx(&mut self, bus: &mut Bus) { fn plx(&mut self, bus: &mut Bus) {
@@ -754,7 +816,8 @@ impl CPU {
let bytes = self.do_pull(bus, 1); let bytes = self.do_pull(bus, 1);
self.registers.set_low_x(bytes[0]); self.registers.set_low_x(bytes[0]);
} }
self.increment_cycles_pl_index(); let (bytes, cycles) = cycles::increment_cycles_pl_index(self.registers.is_16bit_index());
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn ply(&mut self, bus: &mut Bus) { fn ply(&mut self, bus: &mut Bus) {
@@ -765,13 +828,15 @@ impl CPU {
let bytes = self.do_pull(bus, 1); let bytes = self.do_pull(bus, 1);
self.registers.set_low_y(bytes[0]); self.registers.set_low_y(bytes[0]);
} }
self.increment_cycles_pl_index(); let (bytes, cycles) = cycles::increment_cycles_pl_index(self.registers.is_16bit_index());
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn rep(&mut self, bus: &mut Bus) { fn rep(&mut self, bus: &mut Bus) {
let byte = 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.registers.reset_rep_byte(byte);
self.increment_cycles_rep(); let (bytes, cycles) = cycles::increment_cycles_rep();
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn rol(&mut self, bus: &mut Bus, addressing_mode: AddressingMode) { fn rol(&mut self, bus: &mut Bus, addressing_mode: AddressingMode) {
@@ -791,7 +856,8 @@ impl CPU {
self.set_8bit_to_address(bus, addressing_mode, result); self.set_8bit_to_address(bus, addressing_mode, result);
self.registers.set_flags(&affected_flags); self.registers.set_flags(&affected_flags);
} }
self.increment_cycles_shift(addressing_mode); let (bytes, cycles) = cycles::increment_cycles_shift(&self.registers, addressing_mode);
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn ror(&mut self, bus: &mut Bus, addressing_mode: AddressingMode) { fn ror(&mut self, bus: &mut Bus, addressing_mode: AddressingMode) {
@@ -811,7 +877,8 @@ impl CPU {
self.set_8bit_to_address(bus, addressing_mode, result); self.set_8bit_to_address(bus, addressing_mode, result);
self.registers.set_flags(&affected_flags); self.registers.set_flags(&affected_flags);
} }
self.increment_cycles_shift(addressing_mode); let (bytes, cycles) = cycles::increment_cycles_shift(&self.registers, addressing_mode);
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn rtl(&mut self, bus: &mut Bus) { fn rtl(&mut self, bus: &mut Bus) {
@@ -819,35 +886,41 @@ impl CPU {
// Low byte of PC is pulled first, then high byte and then PBR // Low byte of PC is pulled first, then high byte and then PBR
self.registers.pc = (bytes[0] as u16) | ((bytes[1] as u16) << 8); self.registers.pc = (bytes[0] as u16) | ((bytes[1] as u16) << 8);
self.registers.pbr = bytes[2]; self.registers.pbr = bytes[2];
self.increment_cycles_return_subroutine(); let (bytes, cycles) = cycles::increment_cycles_return_subroutine();
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn rts(&mut self, bus: &mut Bus) { fn rts(&mut self, bus: &mut Bus) {
let bytes = self.do_pull(bus, 2); let bytes = self.do_pull(bus, 2);
// Low byte of PC is pulled first, then high byte // Low byte of PC is pulled first, then high byte
self.registers.pc = (bytes[0] as u16) | ((bytes[1] as u16) << 8); self.registers.pc = (bytes[0] as u16) | ((bytes[1] as u16) << 8);
self.increment_cycles_return_subroutine(); let (bytes, cycles) = cycles::increment_cycles_return_subroutine();
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn sec(&mut self) { fn sec(&mut self) {
self.registers.set_carry_flag(true); self.registers.set_carry_flag(true);
self.increment_cycles_set_flag(); let (bytes, cycles) = cycles::increment_cycles_set_flag();
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn sed(&mut self) { fn sed(&mut self) {
self.registers.set_decimal_mode_flag(true); self.registers.set_decimal_mode_flag(true);
self.increment_cycles_set_flag(); let (bytes, cycles) = cycles::increment_cycles_set_flag();
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn sei(&mut self) { fn sei(&mut self) {
self.registers.set_irq_disable_flag(true); self.registers.set_irq_disable_flag(true);
self.increment_cycles_set_flag(); let (bytes, cycles) = cycles::increment_cycles_set_flag();
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn sep(&mut self, bus: &mut Bus) { fn sep(&mut self, bus: &mut Bus) {
let byte = self.get_8bit_from_address(bus, AddressingMode::Immediate); let byte = self.get_8bit_from_address(bus, AddressingMode::Immediate);
self.registers.set_sep_byte(byte); self.registers.set_sep_byte(byte);
self.increment_cycles_sep(); let (bytes, cycles) = cycles::increment_cycles_sep();
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn sta(&mut self, bus: &mut Bus, addressing_mode: AddressingMode) { fn sta(&mut self, bus: &mut Bus, addressing_mode: AddressingMode) {
@@ -856,7 +929,8 @@ impl CPU {
} else { } else {
self.set_8bit_to_address(bus, addressing_mode, self.registers.a as u8); self.set_8bit_to_address(bus, addressing_mode, self.registers.a as u8);
} }
self.increment_cycles_sta(addressing_mode); let (bytes, cycles) = cycles::increment_cycles_sta(&self.registers, addressing_mode);
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn stx(&mut self, bus: &mut Bus, addressing_mode: AddressingMode) { fn stx(&mut self, bus: &mut Bus, addressing_mode: AddressingMode) {
@@ -865,7 +939,8 @@ impl CPU {
} else { } else {
self.set_8bit_to_address(bus, addressing_mode, self.registers.x as u8); self.set_8bit_to_address(bus, addressing_mode, self.registers.x as u8);
} }
self.increment_cycles_st_index(addressing_mode); let (bytes, cycles) = cycles::increment_cycles_st_index(&self.registers, addressing_mode);
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn sty(&mut self, bus: &mut Bus, addressing_mode: AddressingMode) { fn sty(&mut self, bus: &mut Bus, addressing_mode: AddressingMode) {
@@ -874,7 +949,8 @@ impl CPU {
} else { } else {
self.set_8bit_to_address(bus, addressing_mode, self.registers.y as u8); self.set_8bit_to_address(bus, addressing_mode, self.registers.y as u8);
} }
self.increment_cycles_st_index(addressing_mode); let (bytes, cycles) = cycles::increment_cycles_st_index(&self.registers, addressing_mode);
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn stz(&mut self, bus: &mut Bus, addressing_mode: AddressingMode) { fn stz(&mut self, bus: &mut Bus, addressing_mode: AddressingMode) {
@@ -883,12 +959,14 @@ impl CPU {
} else { } else {
self.set_8bit_to_address(bus, addressing_mode, 0); self.set_8bit_to_address(bus, addressing_mode, 0);
} }
self.increment_cycles_st_index(addressing_mode); let (bytes, cycles) = cycles::increment_cycles_st_index(&self.registers, addressing_mode);
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn stp(&mut self) { fn stp(&mut self) {
self.is_stopped = true; self.is_stopped = true;
self.increment_cycles_stp(); let (bytes, cycles) = cycles::increment_cycles_stp();
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn tax(&mut self) { fn tax(&mut self) {
@@ -902,7 +980,8 @@ impl CPU {
self.registers.set_negative_flag((result >> 7) == 1); self.registers.set_negative_flag((result >> 7) == 1);
self.registers.set_zero_flag(result == 0); self.registers.set_zero_flag(result == 0);
} }
self.increment_cycles_transfer(); let (bytes, cycles) = cycles::increment_cycles_transfer();
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn tay(&mut self) { fn tay(&mut self) {
@@ -916,7 +995,8 @@ impl CPU {
self.registers.set_negative_flag((result >> 7) == 1); self.registers.set_negative_flag((result >> 7) == 1);
self.registers.set_zero_flag(result == 0); self.registers.set_zero_flag(result == 0);
} }
self.increment_cycles_transfer(); let (bytes, cycles) = cycles::increment_cycles_transfer();
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn tcd(&mut self) { fn tcd(&mut self) {
@@ -924,7 +1004,8 @@ impl CPU {
self.registers.d = result; self.registers.d = result;
self.registers.set_negative_flag((result >> 7) == 1); self.registers.set_negative_flag((result >> 7) == 1);
self.registers.set_zero_flag(result == 0); self.registers.set_zero_flag(result == 0);
self.increment_cycles_transfer(); let (bytes, cycles) = cycles::increment_cycles_transfer();
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn tcs(&mut self) { fn tcs(&mut self) {
@@ -932,7 +1013,8 @@ impl CPU {
self.registers.sp = result; self.registers.sp = result;
self.registers.set_negative_flag((result >> 7) == 1); self.registers.set_negative_flag((result >> 7) == 1);
self.registers.set_zero_flag(result == 0); self.registers.set_zero_flag(result == 0);
self.increment_cycles_transfer(); let (bytes, cycles) = cycles::increment_cycles_transfer();
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn tdc(&mut self) { fn tdc(&mut self) {
@@ -940,7 +1022,8 @@ impl CPU {
self.registers.a = result; self.registers.a = result;
self.registers.set_negative_flag((result >> 7) == 1); self.registers.set_negative_flag((result >> 7) == 1);
self.registers.set_zero_flag(result == 0); self.registers.set_zero_flag(result == 0);
self.increment_cycles_transfer(); let (bytes, cycles) = cycles::increment_cycles_transfer();
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn tsc(&mut self) { fn tsc(&mut self) {
@@ -948,7 +1031,8 @@ impl CPU {
self.registers.a = result; self.registers.a = result;
self.registers.set_negative_flag((result >> 7) == 1); self.registers.set_negative_flag((result >> 7) == 1);
self.registers.set_zero_flag(result == 0); self.registers.set_zero_flag(result == 0);
self.increment_cycles_transfer(); let (bytes, cycles) = cycles::increment_cycles_transfer();
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn tsx(&mut self) { fn tsx(&mut self) {
@@ -963,7 +1047,8 @@ impl CPU {
self.registers.set_negative_flag((result >> 7) == 1); self.registers.set_negative_flag((result >> 7) == 1);
self.registers.set_zero_flag(result == 0); self.registers.set_zero_flag(result == 0);
} }
self.increment_cycles_transfer(); let (bytes, cycles) = cycles::increment_cycles_transfer();
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn txa(&mut self) { fn txa(&mut self) {
@@ -977,7 +1062,8 @@ impl CPU {
self.registers.set_negative_flag((result >> 7) == 1); self.registers.set_negative_flag((result >> 7) == 1);
self.registers.set_zero_flag(result == 0); self.registers.set_zero_flag(result == 0);
} }
self.increment_cycles_transfer(); let (bytes, cycles) = cycles::increment_cycles_transfer();
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn txs(&mut self) { fn txs(&mut self) {
@@ -991,7 +1077,8 @@ impl CPU {
self.registers.set_negative_flag((result >> 7) == 1); self.registers.set_negative_flag((result >> 7) == 1);
self.registers.set_zero_flag(result == 0); self.registers.set_zero_flag(result == 0);
} }
self.increment_cycles_transfer(); let (bytes, cycles) = cycles::increment_cycles_transfer();
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn txy(&mut self) { fn txy(&mut self) {
@@ -1005,7 +1092,8 @@ impl CPU {
self.registers.set_negative_flag((result >> 7) == 1); self.registers.set_negative_flag((result >> 7) == 1);
self.registers.set_zero_flag(result == 0); self.registers.set_zero_flag(result == 0);
} }
self.increment_cycles_transfer(); let (bytes, cycles) = cycles::increment_cycles_transfer();
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn tya(&mut self) { fn tya(&mut self) {
@@ -1019,7 +1107,8 @@ impl CPU {
self.registers.set_negative_flag((result >> 7) == 1); self.registers.set_negative_flag((result >> 7) == 1);
self.registers.set_zero_flag(result == 0); self.registers.set_zero_flag(result == 0);
} }
self.increment_cycles_transfer(); let (bytes, cycles) = cycles::increment_cycles_transfer();
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn tyx(&mut self) { fn tyx(&mut self) {
@@ -1033,14 +1122,16 @@ impl CPU {
self.registers.set_negative_flag((result >> 7) == 1); self.registers.set_negative_flag((result >> 7) == 1);
self.registers.set_zero_flag(result == 0); self.registers.set_zero_flag(result == 0);
} }
self.increment_cycles_transfer(); let (bytes, cycles) = cycles::increment_cycles_transfer();
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn xba(&mut self) { fn xba(&mut self) {
self.registers.a = (self.registers.a << 8) | (self.registers.a >> 8); self.registers.a = (self.registers.a << 8) | (self.registers.a >> 8);
self.registers.set_negative_flag(((self.registers.a as u8) >> 7) == 1); self.registers.set_negative_flag(((self.registers.a as u8) >> 7) == 1);
self.registers.set_zero_flag((self.registers.a as u8) == 0); self.registers.set_zero_flag((self.registers.a as u8) == 0);
self.increment_cycles_xba(); let (bytes, cycles) = cycles::increment_cycles_xba();
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn do_move(&mut self, bus: &mut Bus, is_next: bool) { fn do_move(&mut self, bus: &mut Bus, is_next: bool) {
@@ -1067,7 +1158,8 @@ impl CPU {
} }
count += 1; count += 1;
} }
self.increment_cycles_move(count); let (bytes, cycles) = cycles::increment_cycles_move(count);
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn mvn(&mut self, bus: &mut Bus) { fn mvn(&mut self, bus: &mut Bus) {
@@ -1085,7 +1177,8 @@ impl CPU {
if !self.registers.emulation_mode { if !self.registers.emulation_mode {
self.registers.pbr = self.do_pull(bus, 1)[0]; self.registers.pbr = self.do_pull(bus, 1)[0];
} }
self.increment_cycles_return_interrupt(); let (bytes, cycles) = cycles::increment_cycles_return_interrupt(self.registers.emulation_mode);
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn trb(&mut self, bus: &mut Bus, addressing_mode: AddressingMode) { fn trb(&mut self, bus: &mut Bus, addressing_mode: AddressingMode) {
@@ -1100,7 +1193,8 @@ impl CPU {
self.set_8bit_to_address(bus, addressing_mode, result); self.set_8bit_to_address(bus, addressing_mode, result);
self.registers.set_zero_flag(result == 0); self.registers.set_zero_flag(result == 0);
} }
self.increment_cycles_test(addressing_mode); let (bytes, cycles) = cycles::increment_cycles_test(&self.registers, addressing_mode);
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn tsb(&mut self, bus: &mut Bus, addressing_mode: AddressingMode) { fn tsb(&mut self, bus: &mut Bus, addressing_mode: AddressingMode) {
@@ -1115,23 +1209,27 @@ impl CPU {
self.set_8bit_to_address(bus, addressing_mode, result); self.set_8bit_to_address(bus, addressing_mode, result);
self.registers.set_zero_flag(result == 0); self.registers.set_zero_flag(result == 0);
} }
self.increment_cycles_test(addressing_mode); let (bytes, cycles) = cycles::increment_cycles_test(&self.registers, addressing_mode);
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn wai(&mut self) { fn wai(&mut self) {
self.is_waiting_interrupt = true; self.is_waiting_interrupt = true;
self.increment_cycles_stp(); let (bytes, cycles) = cycles::increment_cycles_stp();
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn wdm(&mut self) { fn wdm(&mut self) {
self.increment_cycles_wdm(); let (bytes, cycles) = cycles::increment_cycles_wdm();
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn xce(&mut self) { fn xce(&mut self) {
self.registers.exchange_carry_and_emulation(); self.registers.exchange_carry_and_emulation();
self.increment_cycles_exchange(); let (bytes, cycles) = cycles::increment_cycles_exchange();
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
fn check_running_state(&mut self, bus: &mut Bus) -> bool { fn check_running_state(&mut self, bus: &mut Bus) -> bool {
@@ -1143,7 +1241,8 @@ impl CPU {
for (src, dst) in pending_bus_writes { for (src, dst) in pending_bus_writes {
let byte = bus.read(src); let byte = bus.read(src);
bus.write(dst, byte); bus.write(dst, byte);
self.increment_cycles_while_stopped(); let (bytes, cycles) = cycles::increment_cycles_while_stopped();
self.registers.increment_pc(bytes); self.cycles += cycles;
} }
if !bus.dma.is_active() { if !bus.dma.is_active() {
bus.write(dma::MDMAEN as u32, 0x00) bus.write(dma::MDMAEN as u32, 0x00)
@@ -1151,12 +1250,14 @@ impl CPU {
return false; return false;
} }
if self.is_stopped { if self.is_stopped {
self.increment_cycles_while_stopped(); let (bytes, cycles) = cycles::increment_cycles_while_stopped();
self.registers.increment_pc(bytes); self.cycles += cycles;
return false; return false;
} }
if self.is_waiting_interrupt { if self.is_waiting_interrupt {
// TODO: check for interrupts here // TODO: check for interrupts here
self.increment_cycles_while_stopped(); let (bytes, cycles) = cycles::increment_cycles_while_stopped();
self.registers.increment_pc(bytes); self.cycles += cycles;
return false; return false;
} }
return true; return true;