diff --git a/Cargo.toml b/Cargo.toml index 10a86ac..0f0cad5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,17 +26,17 @@ # POSSIBILITY OF SUCH DAMAGE. [package] -name = "emu6502" +name = "mos6502" version = "0.0.1" authors = ["The 6502-rs Developers"] [lib] # This will look in src/lib.rs -name = "emu6502" +name = "mos6502" [[bin]] -# This will look in src/bin/emu6502.rs -name = "emu6502" +# This will look in src/bin/mos6502.rs +name = "mos6502" [dependencies] bitflags = "0.9.1" diff --git a/src/bin/main.rs b/src/bin/main.rs index a9b7322..22e0586 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -25,17 +25,17 @@ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. -extern crate emu6502; +extern crate mos6502; #[cfg(not(test))] -use emu6502::machine; +use mos6502::cpu; #[cfg(not(test))] -use emu6502::address::Address; +use mos6502::address::Address; #[cfg(not(test))] fn main() { - let mut machine = machine::Machine::new(); + let mut cpu = cpu::CPU::new(); // "Load" a program @@ -67,51 +67,36 @@ fn main() { // Code start 0xA9, // LDA Immediate 0x01, // Immediate operand - 0x69, // ADC Immediate 0x07, // Immediate operand - 0x65, // ADC ZeroPage 0x01, // ZeroPage operand - 0xA2, // LDX Immediate 0x01, // Immediate operand - 0x75, // ADC ZeroPageX 0x02, // ZeroPageX operand - 0x6D, // ADC Absolute 0x01, // Absolute operand 0x80, // Absolute operand - 0xA2, // LDX immediate 0x08, // Immediate operand - 0x7D, // ADC AbsoluteX 0x00, // AbsoluteX operand 0x80, // AbsoluteX operand - 0xA0, // LDY immediate 0x04, // Immediate operand - 0x79, // ADC AbsoluteY 0x00, // AbsoluteY operand 0x80, // AbsoluteY operand - 0xA2, // LDX immediate 0x05, // Immediate operand - 0x61, // ADC IndexedIndirectX 0x03, // IndexedIndirectX operand - 0xA0, // LDY immediate 0x10, // Immediate operand - 0x71, // ADC IndirectIndexedY 0x0F, // IndirectIndexedY operand - 0xEA, // NOP :) - 0xFF, // Something invalid -- the end! ]; @@ -143,14 +128,13 @@ fn main() { 0x06, // ADC IndirectIndexedY target ]; - machine.memory.set_bytes(Address(0x0000), &zero_page_data); - machine.memory.set_bytes(Address(0x4000), &program); - machine.memory.set_bytes(Address(0x8000), &data); + cpu.memory.set_bytes(Address(0x0000), &zero_page_data); + cpu.memory.set_bytes(Address(0x4000), &program); + cpu.memory.set_bytes(Address(0x8000), &data); - machine.registers.program_counter = Address(0x4000); + cpu.registers.program_counter = Address(0x4000); - machine.run(); + cpu.run(); - println!("{:?}", machine); + println!("{:?}", cpu); } - diff --git a/src/machine.rs b/src/cpu.rs similarity index 57% rename from src/machine.rs rename to src/cpu.rs index 7c9e1c8..2bdca43 100644 --- a/src/machine.rs +++ b/src/cpu.rs @@ -32,25 +32,25 @@ use instruction; use instruction::{DecodedInstr, Instruction, OpInput}; use memory::Memory; use registers::{Registers, StackPointer, Status, StatusArgs}; -use registers::{PS_NEGATIVE, PS_DECIMAL_MODE, PS_OVERFLOW, PS_ZERO, PS_CARRY, - PS_DISABLE_INTERRUPTS}; +use registers::{PS_CARRY, PS_DECIMAL_MODE, PS_DISABLE_INTERRUPTS, PS_NEGATIVE, PS_OVERFLOW, + PS_ZERO}; #[derive(Clone)] -pub struct Machine { +pub struct CPU { pub registers: Registers, pub memory: Memory, } -impl Machine { - pub fn new() -> Machine { - Machine { +impl CPU { + pub fn new() -> CPU { + CPU { registers: Registers::new(), memory: Memory::new(), } } pub fn reset(&mut self) { - *self = Machine::new(); + *self = CPU::new(); } pub fn fetch_next_and_decode(&mut self) -> Option { @@ -98,12 +98,11 @@ impl Machine { (Instruction::ASL, OpInput::UseImplied) => { // Accumulator mode let mut val = self.registers.accumulator as u8; - Machine::shift_left_with_flags(&mut val, &mut self.registers.status); + CPU::shift_left_with_flags(&mut val, &mut self.registers.status); self.registers.accumulator = val as i8; - } (Instruction::ASL, OpInput::UseAddress(addr)) => { - Machine::shift_left_with_flags( + CPU::shift_left_with_flags( self.memory.get_byte_mut_ref(addr), &mut self.registers.status, ); @@ -226,7 +225,7 @@ impl Machine { let m = m + 1; self.memory.set_byte(addr, m); let i = m as i8; - Machine::set_flags_from_i8(&mut self.registers.status, i); + CPU::set_flags_from_i8(&mut self.registers.status, i); } (Instruction::INX, OpInput::UseImplied) => { let x = self.registers.index_x + 1; @@ -272,11 +271,11 @@ impl Machine { (Instruction::LSR, OpInput::UseImplied) => { // Accumulator mode let mut val = self.registers.accumulator as u8; - Machine::shift_right_with_flags(&mut val, &mut self.registers.status); + CPU::shift_right_with_flags(&mut val, &mut self.registers.status); self.registers.accumulator = val as i8; } (Instruction::LSR, OpInput::UseAddress(addr)) => { - Machine::shift_right_with_flags( + CPU::shift_right_with_flags( self.memory.get_byte_mut_ref(addr), &mut self.registers.status, ); @@ -317,11 +316,11 @@ impl Machine { (Instruction::ROL, OpInput::UseImplied) => { // Accumulator mode let mut val = self.registers.accumulator as u8; - Machine::rotate_left_with_flags(&mut val, &mut self.registers.status); + CPU::rotate_left_with_flags(&mut val, &mut self.registers.status); self.registers.accumulator = val as i8; } (Instruction::ROL, OpInput::UseAddress(addr)) => { - Machine::rotate_left_with_flags( + CPU::rotate_left_with_flags( self.memory.get_byte_mut_ref(addr), &mut self.registers.status, ); @@ -329,11 +328,11 @@ impl Machine { (Instruction::ROR, OpInput::UseImplied) => { // Accumulator mode let mut val = self.registers.accumulator as u8; - Machine::rotate_right_with_flags(&mut val, &mut self.registers.status); + CPU::rotate_right_with_flags(&mut val, &mut self.registers.status); self.registers.accumulator = val as i8; } (Instruction::ROR, OpInput::UseAddress(addr)) => { - Machine::rotate_right_with_flags( + CPU::rotate_right_with_flags( self.memory.get_byte_mut_ref(addr), &mut self.registers.status, ); @@ -404,7 +403,7 @@ impl Machine { (_, _) => { debug!( "attempting to execute unimplemented or invalid \ - instruction" + instruction" ); } }; @@ -446,7 +445,7 @@ impl Machine { ..StatusArgs::none() }), ); - Machine::set_flags_from_i8(status, *p_val as i8); + CPU::set_flags_from_i8(status, *p_val as i8); } fn shift_right_with_flags(p_val: &mut u8, status: &mut Status) { @@ -460,7 +459,7 @@ impl Machine { ..StatusArgs::none() }), ); - Machine::set_flags_from_i8(status, *p_val as i8); + CPU::set_flags_from_i8(status, *p_val as i8); } fn rotate_left_with_flags(p_val: &mut u8, status: &mut Status) { @@ -476,7 +475,7 @@ impl Machine { ..StatusArgs::none() }), ); - Machine::set_flags_from_i8(status, *p_val as i8); + CPU::set_flags_from_i8(status, *p_val as i8); } fn rotate_right_with_flags(p_val: &mut u8, status: &mut Status) { @@ -492,16 +491,16 @@ impl Machine { ..StatusArgs::none() }), ); - Machine::set_flags_from_i8(status, *p_val as i8); + CPU::set_flags_from_i8(status, *p_val as i8); } fn set_i8_with_flags(mem: &mut i8, status: &mut Status, value: i8) { *mem = value; - Machine::set_flags_from_i8(status, value); + CPU::set_flags_from_i8(status, value); } fn load_x_register(&mut self, value: i8) { - Machine::set_i8_with_flags( + CPU::set_i8_with_flags( &mut self.registers.index_x, &mut self.registers.status, value, @@ -509,7 +508,7 @@ impl Machine { } fn load_y_register(&mut self, value: i8) { - Machine::set_i8_with_flags( + CPU::set_i8_with_flags( &mut self.registers.index_y, &mut self.registers.status, value, @@ -517,7 +516,7 @@ impl Machine { } fn load_accumulator(&mut self, value: i8) { - Machine::set_i8_with_flags( + CPU::set_i8_with_flags( &mut self.registers.accumulator, &mut self.registers.status, value, @@ -544,8 +543,8 @@ impl Machine { let did_carry = (a_after as u8) < (a_before as u8); - let did_overflow = (a_before < 0 && value < 0 && a_after >= 0) || - (a_before > 0 && value > 0 && a_after <= 0); + let did_overflow = (a_before < 0 && value < 0 && a_after >= 0) + || (a_before > 0 && value > 0 && a_after <= 0); let mask = PS_CARRY | PS_OVERFLOW; @@ -574,7 +573,7 @@ impl Machine { if self.registers.status.contains(PS_DECIMAL_MODE) { debug!( "binary-coded decimal not implemented for \ - subtract_with_carry" + subtract_with_carry" ); } else { // A - M - (1 - C) @@ -599,8 +598,8 @@ impl Machine { // range of - M - (1 - C) is -128 to 128 // -(127 + 1) to -(-128 + 0) // - let over = ((nc == 0 && value < 0) || (nc == 1 && value < -1)) && a_before >= 0 && - a_after < 0; + let over = + ((nc == 0 && value < 0) || (nc == 1 && value < -1)) && a_before >= 0 && a_after < 0; let under = (a_before < 0) && (-value - nc < 0) && a_after >= 0; @@ -759,11 +758,11 @@ impl Machine { } } -impl std::fmt::Debug for Machine { +impl std::fmt::Debug for CPU { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!( f, - "Machine Dump:\n\nAccumulator: {}", + "CPU Dump:\n\nAccumulator: {}", self.registers.accumulator ) } @@ -777,446 +776,448 @@ mod tests { #[test] fn add_with_carry_test() { - let mut machine = Machine::new(); + let mut CPU = CPU::new(); - machine.add_with_carry(1); - assert_eq!(machine.registers.accumulator, 1); - assert_eq!(machine.registers.status.contains(PS_CARRY), false); - assert_eq!(machine.registers.status.contains(PS_ZERO), false); - assert_eq!(machine.registers.status.contains(PS_NEGATIVE), false); - assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false); + CPU.add_with_carry(1); + assert_eq!(CPU.registers.accumulator, 1); + assert_eq!(CPU.registers.status.contains(PS_CARRY), false); + assert_eq!(CPU.registers.status.contains(PS_ZERO), false); + assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), false); + assert_eq!(CPU.registers.status.contains(PS_OVERFLOW), false); - machine.add_with_carry(-1); - assert_eq!(machine.registers.accumulator, 0); - assert_eq!(machine.registers.status.contains(PS_CARRY), true); - assert_eq!(machine.registers.status.contains(PS_ZERO), true); - assert_eq!(machine.registers.status.contains(PS_NEGATIVE), false); - assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false); + CPU.add_with_carry(-1); + assert_eq!(CPU.registers.accumulator, 0); + assert_eq!(CPU.registers.status.contains(PS_CARRY), true); + assert_eq!(CPU.registers.status.contains(PS_ZERO), true); + assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), false); + assert_eq!(CPU.registers.status.contains(PS_OVERFLOW), false); - machine.add_with_carry(1); - assert_eq!(machine.registers.accumulator, 2); - assert_eq!(machine.registers.status.contains(PS_CARRY), false); - assert_eq!(machine.registers.status.contains(PS_ZERO), false); - assert_eq!(machine.registers.status.contains(PS_NEGATIVE), false); - assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false); + CPU.add_with_carry(1); + assert_eq!(CPU.registers.accumulator, 2); + assert_eq!(CPU.registers.status.contains(PS_CARRY), false); + assert_eq!(CPU.registers.status.contains(PS_ZERO), false); + assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), false); + assert_eq!(CPU.registers.status.contains(PS_OVERFLOW), false); - let mut machine = Machine::new(); + let mut CPU = CPU::new(); - machine.add_with_carry(127); - assert_eq!(machine.registers.accumulator, 127); - assert_eq!(machine.registers.status.contains(PS_CARRY), false); - assert_eq!(machine.registers.status.contains(PS_ZERO), false); - assert_eq!(machine.registers.status.contains(PS_NEGATIVE), false); - assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false); + CPU.add_with_carry(127); + assert_eq!(CPU.registers.accumulator, 127); + assert_eq!(CPU.registers.status.contains(PS_CARRY), false); + assert_eq!(CPU.registers.status.contains(PS_ZERO), false); + assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), false); + assert_eq!(CPU.registers.status.contains(PS_OVERFLOW), false); - machine.add_with_carry(-127); - assert_eq!(machine.registers.accumulator, 0); - assert_eq!(machine.registers.status.contains(PS_CARRY), true); - assert_eq!(machine.registers.status.contains(PS_ZERO), true); - assert_eq!(machine.registers.status.contains(PS_NEGATIVE), false); - assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false); + CPU.add_with_carry(-127); + assert_eq!(CPU.registers.accumulator, 0); + assert_eq!(CPU.registers.status.contains(PS_CARRY), true); + assert_eq!(CPU.registers.status.contains(PS_ZERO), true); + assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), false); + assert_eq!(CPU.registers.status.contains(PS_OVERFLOW), false); - machine.registers.status.remove(PS_CARRY); - machine.add_with_carry(-128); - assert_eq!(machine.registers.accumulator, -128); - assert_eq!(machine.registers.status.contains(PS_CARRY), false); - assert_eq!(machine.registers.status.contains(PS_ZERO), false); - assert_eq!(machine.registers.status.contains(PS_NEGATIVE), true); - assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false); + CPU.registers.status.remove(PS_CARRY); + CPU.add_with_carry(-128); + assert_eq!(CPU.registers.accumulator, -128); + assert_eq!(CPU.registers.status.contains(PS_CARRY), false); + assert_eq!(CPU.registers.status.contains(PS_ZERO), false); + assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), true); + assert_eq!(CPU.registers.status.contains(PS_OVERFLOW), false); - machine.add_with_carry(127); - assert_eq!(machine.registers.accumulator, -1); - assert_eq!(machine.registers.status.contains(PS_CARRY), false); - assert_eq!(machine.registers.status.contains(PS_ZERO), false); - assert_eq!(machine.registers.status.contains(PS_NEGATIVE), true); - assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false); + CPU.add_with_carry(127); + assert_eq!(CPU.registers.accumulator, -1); + assert_eq!(CPU.registers.status.contains(PS_CARRY), false); + assert_eq!(CPU.registers.status.contains(PS_ZERO), false); + assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), true); + assert_eq!(CPU.registers.status.contains(PS_OVERFLOW), false); - let mut machine = Machine::new(); + let mut CPU = CPU::new(); - machine.add_with_carry(127); - assert_eq!(machine.registers.accumulator, 127); - assert_eq!(machine.registers.status.contains(PS_CARRY), false); - assert_eq!(machine.registers.status.contains(PS_ZERO), false); - assert_eq!(machine.registers.status.contains(PS_NEGATIVE), false); - assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false); + CPU.add_with_carry(127); + assert_eq!(CPU.registers.accumulator, 127); + assert_eq!(CPU.registers.status.contains(PS_CARRY), false); + assert_eq!(CPU.registers.status.contains(PS_ZERO), false); + assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), false); + assert_eq!(CPU.registers.status.contains(PS_OVERFLOW), false); - machine.add_with_carry(1); - assert_eq!(machine.registers.accumulator, -128); - assert_eq!(machine.registers.status.contains(PS_CARRY), false); - assert_eq!(machine.registers.status.contains(PS_ZERO), false); - assert_eq!(machine.registers.status.contains(PS_NEGATIVE), true); - assert_eq!(machine.registers.status.contains(PS_OVERFLOW), true); + CPU.add_with_carry(1); + assert_eq!(CPU.registers.accumulator, -128); + assert_eq!(CPU.registers.status.contains(PS_CARRY), false); + assert_eq!(CPU.registers.status.contains(PS_ZERO), false); + assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), true); + assert_eq!(CPU.registers.status.contains(PS_OVERFLOW), true); } #[test] fn and_test() { - let mut machine = Machine::new(); + let mut CPU = CPU::new(); - machine.registers.accumulator = 0; - machine.and(-1); - assert_eq!(machine.registers.accumulator, 0); - assert_eq!(machine.registers.status.contains(PS_ZERO), true); - assert_eq!(machine.registers.status.contains(PS_NEGATIVE), false); + CPU.registers.accumulator = 0; + CPU.and(-1); + assert_eq!(CPU.registers.accumulator, 0); + assert_eq!(CPU.registers.status.contains(PS_ZERO), true); + assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), false); - machine.registers.accumulator = -1; - machine.and(0); - assert_eq!(machine.registers.accumulator, 0); - assert_eq!(machine.registers.status.contains(PS_ZERO), true); - assert_eq!(machine.registers.status.contains(PS_NEGATIVE), false); + CPU.registers.accumulator = -1; + CPU.and(0); + assert_eq!(CPU.registers.accumulator, 0); + assert_eq!(CPU.registers.status.contains(PS_ZERO), true); + assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), false); - machine.registers.accumulator = -1; - machine.and(0x0f); - assert_eq!(machine.registers.accumulator, 0x0f); - assert_eq!(machine.registers.status.contains(PS_ZERO), false); - assert_eq!(machine.registers.status.contains(PS_NEGATIVE), false); + CPU.registers.accumulator = -1; + CPU.and(0x0f); + assert_eq!(CPU.registers.accumulator, 0x0f); + assert_eq!(CPU.registers.status.contains(PS_ZERO), false); + assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), false); - machine.registers.accumulator = -1; - machine.and(-128); - assert_eq!(machine.registers.accumulator, -128); - assert_eq!(machine.registers.status.contains(PS_ZERO), false); - assert_eq!(machine.registers.status.contains(PS_NEGATIVE), true); + CPU.registers.accumulator = -1; + CPU.and(-128); + assert_eq!(CPU.registers.accumulator, -128); + assert_eq!(CPU.registers.status.contains(PS_ZERO), false); + assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), true); } #[test] fn subtract_with_carry_test() { - let mut machine = Machine::new(); + let mut CPU = CPU::new(); - machine.execute_instruction((Instruction::SEC, OpInput::UseImplied)); - machine.registers.accumulator = 0; + CPU.execute_instruction((Instruction::SEC, OpInput::UseImplied)); + CPU.registers.accumulator = 0; - machine.subtract_with_carry(1); - assert_eq!(machine.registers.accumulator, -1); - assert_eq!(machine.registers.status.contains(PS_CARRY), true); - assert_eq!(machine.registers.status.contains(PS_ZERO), false); - assert_eq!(machine.registers.status.contains(PS_NEGATIVE), true); - assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false); + CPU.subtract_with_carry(1); + assert_eq!(CPU.registers.accumulator, -1); + assert_eq!(CPU.registers.status.contains(PS_CARRY), true); + assert_eq!(CPU.registers.status.contains(PS_ZERO), false); + assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), true); + assert_eq!(CPU.registers.status.contains(PS_OVERFLOW), false); - machine.execute_instruction((Instruction::SEC, OpInput::UseImplied)); - machine.registers.accumulator = -128; - machine.subtract_with_carry(1); - assert_eq!(machine.registers.accumulator, 127); - assert_eq!(machine.registers.status.contains(PS_CARRY), false); - assert_eq!(machine.registers.status.contains(PS_ZERO), false); - assert_eq!(machine.registers.status.contains(PS_NEGATIVE), false); - assert_eq!(machine.registers.status.contains(PS_OVERFLOW), true); + CPU.execute_instruction((Instruction::SEC, OpInput::UseImplied)); + CPU.registers.accumulator = -128; + CPU.subtract_with_carry(1); + assert_eq!(CPU.registers.accumulator, 127); + assert_eq!(CPU.registers.status.contains(PS_CARRY), false); + assert_eq!(CPU.registers.status.contains(PS_ZERO), false); + assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), false); + assert_eq!(CPU.registers.status.contains(PS_OVERFLOW), true); - machine.execute_instruction((Instruction::SEC, OpInput::UseImplied)); - machine.registers.accumulator = 127; - machine.subtract_with_carry(-1); - assert_eq!(machine.registers.accumulator, -128); - assert_eq!(machine.registers.status.contains(PS_CARRY), true); - assert_eq!(machine.registers.status.contains(PS_ZERO), false); - assert_eq!(machine.registers.status.contains(PS_NEGATIVE), true); - assert_eq!(machine.registers.status.contains(PS_OVERFLOW), true); + CPU.execute_instruction((Instruction::SEC, OpInput::UseImplied)); + CPU.registers.accumulator = 127; + CPU.subtract_with_carry(-1); + assert_eq!(CPU.registers.accumulator, -128); + assert_eq!(CPU.registers.status.contains(PS_CARRY), true); + assert_eq!(CPU.registers.status.contains(PS_ZERO), false); + assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), true); + assert_eq!(CPU.registers.status.contains(PS_OVERFLOW), true); - machine.execute_instruction((Instruction::CLC, OpInput::UseImplied)); - machine.registers.accumulator = -64; - machine.subtract_with_carry(64); - assert_eq!(machine.registers.accumulator, 127); - assert_eq!(machine.registers.status.contains(PS_CARRY), false); - assert_eq!(machine.registers.status.contains(PS_ZERO), false); - assert_eq!(machine.registers.status.contains(PS_NEGATIVE), false); - assert_eq!(machine.registers.status.contains(PS_OVERFLOW), true); + CPU.execute_instruction((Instruction::CLC, OpInput::UseImplied)); + CPU.registers.accumulator = -64; + CPU.subtract_with_carry(64); + assert_eq!(CPU.registers.accumulator, 127); + assert_eq!(CPU.registers.status.contains(PS_CARRY), false); + assert_eq!(CPU.registers.status.contains(PS_ZERO), false); + assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), false); + assert_eq!(CPU.registers.status.contains(PS_OVERFLOW), true); - machine.execute_instruction((Instruction::SEC, OpInput::UseImplied)); - machine.registers.accumulator = 0; - machine.subtract_with_carry(-128); - assert_eq!(machine.registers.accumulator, -128); - assert_eq!(machine.registers.status.contains(PS_CARRY), true); - assert_eq!(machine.registers.status.contains(PS_ZERO), false); - assert_eq!(machine.registers.status.contains(PS_NEGATIVE), true); - assert_eq!(machine.registers.status.contains(PS_OVERFLOW), true); + CPU.execute_instruction((Instruction::SEC, OpInput::UseImplied)); + CPU.registers.accumulator = 0; + CPU.subtract_with_carry(-128); + assert_eq!(CPU.registers.accumulator, -128); + assert_eq!(CPU.registers.status.contains(PS_CARRY), true); + assert_eq!(CPU.registers.status.contains(PS_ZERO), false); + assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), true); + assert_eq!(CPU.registers.status.contains(PS_OVERFLOW), true); - machine.execute_instruction((Instruction::CLC, OpInput::UseImplied)); - machine.registers.accumulator = 0; - machine.subtract_with_carry(127); - assert_eq!(machine.registers.accumulator, -128); - assert_eq!(machine.registers.status.contains(PS_CARRY), true); - assert_eq!(machine.registers.status.contains(PS_ZERO), false); - assert_eq!(machine.registers.status.contains(PS_NEGATIVE), true); - assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false); + CPU.execute_instruction((Instruction::CLC, OpInput::UseImplied)); + CPU.registers.accumulator = 0; + CPU.subtract_with_carry(127); + assert_eq!(CPU.registers.accumulator, -128); + assert_eq!(CPU.registers.status.contains(PS_CARRY), true); + assert_eq!(CPU.registers.status.contains(PS_ZERO), false); + assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), true); + assert_eq!(CPU.registers.status.contains(PS_OVERFLOW), false); } #[test] fn decrement_memory_test() { - let mut machine = Machine::new(); + let mut CPU = CPU::new(); let addr = Address(0xA1B2); - machine.memory.set_byte(addr, 5); + CPU.memory.set_byte(addr, 5); - machine.decrement_memory(addr); - assert_eq!(machine.memory.get_byte(addr), 4); - assert_eq!(machine.registers.status.contains(PS_ZERO), false); - assert_eq!(machine.registers.status.contains(PS_NEGATIVE), false); + CPU.decrement_memory(addr); + assert_eq!(CPU.memory.get_byte(addr), 4); + assert_eq!(CPU.registers.status.contains(PS_ZERO), false); + assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), false); - machine.decrement_memory(addr); - assert_eq!(machine.memory.get_byte(addr), 3); - assert_eq!(machine.registers.status.contains(PS_ZERO), false); - assert_eq!(machine.registers.status.contains(PS_NEGATIVE), false); + CPU.decrement_memory(addr); + assert_eq!(CPU.memory.get_byte(addr), 3); + assert_eq!(CPU.registers.status.contains(PS_ZERO), false); + assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), false); - machine.decrement_memory(addr); - machine.decrement_memory(addr); - machine.decrement_memory(addr); - assert_eq!(machine.memory.get_byte(addr), 0); - assert_eq!(machine.registers.status.contains(PS_ZERO), true); - assert_eq!(machine.registers.status.contains(PS_NEGATIVE), false); + CPU.decrement_memory(addr); + CPU.decrement_memory(addr); + CPU.decrement_memory(addr); + assert_eq!(CPU.memory.get_byte(addr), 0); + assert_eq!(CPU.registers.status.contains(PS_ZERO), true); + assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), false); - machine.decrement_memory(addr); - assert_eq!(machine.memory.get_byte(addr) as i8, -1); - assert_eq!(machine.registers.status.contains(PS_ZERO), false); - assert_eq!(machine.registers.status.contains(PS_NEGATIVE), true); + CPU.decrement_memory(addr); + assert_eq!(CPU.memory.get_byte(addr) as i8, -1); + assert_eq!(CPU.registers.status.contains(PS_ZERO), false); + assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), true); } #[test] fn logical_shift_right_test() { // Testing UseImplied version (which targets the accumulator) only, for now - let mut machine = Machine::new(); - machine.execute_instruction((Instruction::LDA, OpInput::UseImmediate(0))); - machine.execute_instruction((Instruction::LSR, OpInput::UseImplied)); - assert_eq!(machine.registers.accumulator, 0); - assert_eq!(machine.registers.status.contains(PS_CARRY), false); - assert_eq!(machine.registers.status.contains(PS_ZERO), true); - assert_eq!(machine.registers.status.contains(PS_NEGATIVE), false); - assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false); + let mut CPU = CPU::new(); + CPU.execute_instruction((Instruction::LDA, OpInput::UseImmediate(0))); + CPU.execute_instruction((Instruction::LSR, OpInput::UseImplied)); + assert_eq!(CPU.registers.accumulator, 0); + assert_eq!(CPU.registers.status.contains(PS_CARRY), false); + assert_eq!(CPU.registers.status.contains(PS_ZERO), true); + assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), false); + assert_eq!(CPU.registers.status.contains(PS_OVERFLOW), false); - machine.execute_instruction((Instruction::LDA, OpInput::UseImmediate(1))); - machine.execute_instruction((Instruction::LSR, OpInput::UseImplied)); - assert_eq!(machine.registers.accumulator, 0); - assert_eq!(machine.registers.status.contains(PS_CARRY), true); - assert_eq!(machine.registers.status.contains(PS_ZERO), true); - assert_eq!(machine.registers.status.contains(PS_NEGATIVE), false); - assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false); + CPU.execute_instruction((Instruction::LDA, OpInput::UseImmediate(1))); + CPU.execute_instruction((Instruction::LSR, OpInput::UseImplied)); + assert_eq!(CPU.registers.accumulator, 0); + assert_eq!(CPU.registers.status.contains(PS_CARRY), true); + assert_eq!(CPU.registers.status.contains(PS_ZERO), true); + assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), false); + assert_eq!(CPU.registers.status.contains(PS_OVERFLOW), false); - machine.execute_instruction((Instruction::LDA, OpInput::UseImmediate(255))); - machine.execute_instruction((Instruction::LSR, OpInput::UseImplied)); - assert_eq!(machine.registers.accumulator, 0x7F); - assert_eq!(machine.registers.status.contains(PS_CARRY), true); - assert_eq!(machine.registers.status.contains(PS_ZERO), false); - assert_eq!(machine.registers.status.contains(PS_NEGATIVE), false); - assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false); + CPU.execute_instruction((Instruction::LDA, OpInput::UseImmediate(255))); + CPU.execute_instruction((Instruction::LSR, OpInput::UseImplied)); + assert_eq!(CPU.registers.accumulator, 0x7F); + assert_eq!(CPU.registers.status.contains(PS_CARRY), true); + assert_eq!(CPU.registers.status.contains(PS_ZERO), false); + assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), false); + assert_eq!(CPU.registers.status.contains(PS_OVERFLOW), false); - machine.execute_instruction((Instruction::LDA, OpInput::UseImmediate(254))); - machine.execute_instruction((Instruction::LSR, OpInput::UseImplied)); - assert_eq!(machine.registers.accumulator, 0x7F); - assert_eq!(machine.registers.status.contains(PS_CARRY), false); - assert_eq!(machine.registers.status.contains(PS_ZERO), false); - assert_eq!(machine.registers.status.contains(PS_NEGATIVE), false); - assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false); + CPU.execute_instruction((Instruction::LDA, OpInput::UseImmediate(254))); + CPU.execute_instruction((Instruction::LSR, OpInput::UseImplied)); + assert_eq!(CPU.registers.accumulator, 0x7F); + assert_eq!(CPU.registers.status.contains(PS_CARRY), false); + assert_eq!(CPU.registers.status.contains(PS_ZERO), false); + assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), false); + assert_eq!(CPU.registers.status.contains(PS_OVERFLOW), false); } #[test] fn dec_x_test() { - let mut machine = Machine::new(); + let mut CPU = CPU::new(); - machine.dec_x(); - assert_eq!(machine.registers.index_x, -1); - assert_eq!(machine.registers.status.contains(PS_CARRY), false); - assert_eq!(machine.registers.status.contains(PS_ZERO), false); - assert_eq!(machine.registers.status.contains(PS_NEGATIVE), true); - assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false); + CPU.dec_x(); + assert_eq!(CPU.registers.index_x, -1); + assert_eq!(CPU.registers.status.contains(PS_CARRY), false); + assert_eq!(CPU.registers.status.contains(PS_ZERO), false); + assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), true); + assert_eq!(CPU.registers.status.contains(PS_OVERFLOW), false); - machine.dec_x(); - assert_eq!(machine.registers.index_x, -2); - assert_eq!(machine.registers.status.contains(PS_CARRY), false); - assert_eq!(machine.registers.status.contains(PS_ZERO), false); - assert_eq!(machine.registers.status.contains(PS_NEGATIVE), true); - assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false); + CPU.dec_x(); + assert_eq!(CPU.registers.index_x, -2); + assert_eq!(CPU.registers.status.contains(PS_CARRY), false); + assert_eq!(CPU.registers.status.contains(PS_ZERO), false); + assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), true); + assert_eq!(CPU.registers.status.contains(PS_OVERFLOW), false); - machine.load_x_register(5); - machine.dec_x(); - assert_eq!(machine.registers.index_x, 4); - assert_eq!(machine.registers.status.contains(PS_CARRY), false); - assert_eq!(machine.registers.status.contains(PS_ZERO), false); - assert_eq!(machine.registers.status.contains(PS_NEGATIVE), false); - assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false); + CPU.load_x_register(5); + CPU.dec_x(); + assert_eq!(CPU.registers.index_x, 4); + assert_eq!(CPU.registers.status.contains(PS_CARRY), false); + assert_eq!(CPU.registers.status.contains(PS_ZERO), false); + assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), false); + assert_eq!(CPU.registers.status.contains(PS_OVERFLOW), false); - machine.dec_x(); - machine.dec_x(); - machine.dec_x(); - machine.dec_x(); + CPU.dec_x(); + CPU.dec_x(); + CPU.dec_x(); + CPU.dec_x(); - assert_eq!(machine.registers.index_x, 0); - assert_eq!(machine.registers.status.contains(PS_CARRY), false); - assert_eq!(machine.registers.status.contains(PS_ZERO), true); - assert_eq!(machine.registers.status.contains(PS_NEGATIVE), false); - assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false); + assert_eq!(CPU.registers.index_x, 0); + assert_eq!(CPU.registers.status.contains(PS_CARRY), false); + assert_eq!(CPU.registers.status.contains(PS_ZERO), true); + assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), false); + assert_eq!(CPU.registers.status.contains(PS_OVERFLOW), false); - machine.dec_x(); - assert_eq!(machine.registers.index_x, -1); - assert_eq!(machine.registers.status.contains(PS_CARRY), false); - assert_eq!(machine.registers.status.contains(PS_ZERO), false); - assert_eq!(machine.registers.status.contains(PS_NEGATIVE), true); - assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false); + CPU.dec_x(); + assert_eq!(CPU.registers.index_x, -1); + assert_eq!(CPU.registers.status.contains(PS_CARRY), false); + assert_eq!(CPU.registers.status.contains(PS_ZERO), false); + assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), true); + assert_eq!(CPU.registers.status.contains(PS_OVERFLOW), false); } #[test] fn jump_test() { - let mut machine = Machine::new(); + let mut CPU = CPU::new(); let addr = Address(0xA1B1); - machine.jump(addr); - assert_eq!(machine.registers.program_counter, addr); + CPU.jump(addr); + assert_eq!(CPU.registers.program_counter, addr); } #[test] fn branch_if_carry_clear_test() { - let mut machine = Machine::new(); + let mut CPU = CPU::new(); - machine.execute_instruction((Instruction::SEC, OpInput::UseImplied)); - machine.branch_if_carry_clear(Address(0xABCD)); - assert_eq!(machine.registers.program_counter, Address(0)); + CPU.execute_instruction((Instruction::SEC, OpInput::UseImplied)); + CPU.branch_if_carry_clear(Address(0xABCD)); + assert_eq!(CPU.registers.program_counter, Address(0)); - machine.execute_instruction((Instruction::CLC, OpInput::UseImplied)); - machine.branch_if_carry_clear(Address(0xABCD)); - assert_eq!(machine.registers.program_counter, Address(0xABCD)); + CPU.execute_instruction((Instruction::CLC, OpInput::UseImplied)); + CPU.branch_if_carry_clear(Address(0xABCD)); + assert_eq!(CPU.registers.program_counter, Address(0xABCD)); } #[test] fn branch_if_carry_set_test() { - let mut machine = Machine::new(); + let mut CPU = CPU::new(); - machine.execute_instruction((Instruction::CLC, OpInput::UseImplied)); - machine.branch_if_carry_set(Address(0xABCD)); - assert_eq!(machine.registers.program_counter, Address(0)); + CPU.execute_instruction((Instruction::CLC, OpInput::UseImplied)); + CPU.branch_if_carry_set(Address(0xABCD)); + assert_eq!(CPU.registers.program_counter, Address(0)); - machine.execute_instruction((Instruction::SEC, OpInput::UseImplied)); - machine.branch_if_carry_set(Address(0xABCD)); - assert_eq!(machine.registers.program_counter, Address(0xABCD)); + CPU.execute_instruction((Instruction::SEC, OpInput::UseImplied)); + CPU.branch_if_carry_set(Address(0xABCD)); + assert_eq!(CPU.registers.program_counter, Address(0xABCD)); } #[test] fn branch_if_equal_test() { - let mut machine = Machine::new(); + let mut CPU = CPU::new(); - machine.branch_if_equal(Address(0xABCD)); - assert_eq!(machine.registers.program_counter, Address(0)); + CPU.branch_if_equal(Address(0xABCD)); + assert_eq!(CPU.registers.program_counter, Address(0)); - machine.registers.status.or(PS_ZERO); - machine.branch_if_equal(Address(0xABCD)); - assert_eq!(machine.registers.program_counter, Address(0xABCD)); + CPU.registers.status.or(PS_ZERO); + CPU.branch_if_equal(Address(0xABCD)); + assert_eq!(CPU.registers.program_counter, Address(0xABCD)); } #[test] fn branch_if_minus_test() { { - let mut machine = Machine::new(); - let registers_before = machine.registers; + let mut CPU = CPU::new(); + let registers_before = CPU.registers; - machine.branch_if_minus(Address(0xABCD)); - assert_eq!(machine.registers, registers_before); - assert_eq!(machine.registers.program_counter, Address(0)); + CPU.branch_if_minus(Address(0xABCD)); + assert_eq!(CPU.registers, registers_before); + assert_eq!(CPU.registers.program_counter, Address(0)); } { - let mut machine = Machine::new(); + let mut CPU = CPU::new(); - machine.registers.status.or(PS_NEGATIVE); - let registers_before = machine.registers; + CPU.registers.status.or(PS_NEGATIVE); + let registers_before = CPU.registers; - machine.branch_if_minus(Address(0xABCD)); - assert_eq!(machine.registers.status, registers_before.status); - assert_eq!(machine.registers.program_counter, Address(0xABCD)); + CPU.branch_if_minus(Address(0xABCD)); + assert_eq!(CPU.registers.status, registers_before.status); + assert_eq!(CPU.registers.program_counter, Address(0xABCD)); } } #[test] fn branch_if_positive_test() { - let mut machine = Machine::new(); + let mut CPU = CPU::new(); - machine.registers.status.insert(PS_NEGATIVE); - machine.branch_if_positive(Address(0xABCD)); - assert_eq!(machine.registers.program_counter, Address(0)); + CPU.registers.status.insert(PS_NEGATIVE); + CPU.branch_if_positive(Address(0xABCD)); + assert_eq!(CPU.registers.program_counter, Address(0)); - machine.registers.status.remove(PS_NEGATIVE); - machine.branch_if_positive(Address(0xABCD)); - assert_eq!(machine.registers.program_counter, Address(0xABCD)); + CPU.registers.status.remove(PS_NEGATIVE); + CPU.branch_if_positive(Address(0xABCD)); + assert_eq!(CPU.registers.program_counter, Address(0xABCD)); } #[test] fn branch_if_overflow_clear_test() { - let mut machine = Machine::new(); + let mut CPU = CPU::new(); - machine.registers.status.insert(PS_OVERFLOW); - machine.branch_if_overflow_clear(Address(0xABCD)); - assert_eq!(machine.registers.program_counter, Address(0)); + CPU.registers.status.insert(PS_OVERFLOW); + CPU.branch_if_overflow_clear(Address(0xABCD)); + assert_eq!(CPU.registers.program_counter, Address(0)); - machine.registers.status.remove(PS_OVERFLOW); - machine.branch_if_overflow_clear(Address(0xABCD)); - assert_eq!(machine.registers.program_counter, Address(0xABCD)); + CPU.registers.status.remove(PS_OVERFLOW); + CPU.branch_if_overflow_clear(Address(0xABCD)); + assert_eq!(CPU.registers.program_counter, Address(0xABCD)); } #[test] fn branch_if_overflow_set_test() { - let mut machine = Machine::new(); + let mut CPU = CPU::new(); - machine.branch_if_overflow_set(Address(0xABCD)); - assert_eq!(machine.registers.program_counter, Address(0)); + CPU.branch_if_overflow_set(Address(0xABCD)); + assert_eq!(CPU.registers.program_counter, Address(0)); - machine.registers.status.insert(PS_OVERFLOW); - machine.branch_if_overflow_set(Address(0xABCD)); - assert_eq!(machine.registers.program_counter, Address(0xABCD)); + CPU.registers.status.insert(PS_OVERFLOW); + CPU.branch_if_overflow_set(Address(0xABCD)); + assert_eq!(CPU.registers.program_counter, Address(0xABCD)); } #[cfg(test)] fn compare_test_helper(compare: &mut F, load_instruction: Instruction) where - F: FnMut(&mut Machine, u8), + F: FnMut(&mut CPU, u8), { - let mut machine = Machine::new(); + let mut CPU = CPU::new(); - machine.execute_instruction((load_instruction, OpInput::UseImmediate(127))); + CPU.execute_instruction((load_instruction, OpInput::UseImmediate(127))); - compare(&mut machine, 127); - assert!(machine.registers.status.contains(PS_ZERO)); - assert!(machine.registers.status.contains(PS_CARRY)); - assert!(!machine.registers.status.contains(PS_NEGATIVE)); + compare(&mut CPU, 127); + assert!(CPU.registers.status.contains(PS_ZERO)); + assert!(CPU.registers.status.contains(PS_CARRY)); + assert!(!CPU.registers.status.contains(PS_NEGATIVE)); - machine.execute_instruction((load_instruction, OpInput::UseImmediate(127))); + CPU.execute_instruction((load_instruction, OpInput::UseImmediate(127))); - compare(&mut machine, 1); - assert!(!machine.registers.status.contains(PS_ZERO)); - assert!(machine.registers.status.contains(PS_CARRY)); - assert!(!machine.registers.status.contains(PS_NEGATIVE)); + compare(&mut CPU, 1); + assert!(!CPU.registers.status.contains(PS_ZERO)); + assert!(CPU.registers.status.contains(PS_CARRY)); + assert!(!CPU.registers.status.contains(PS_NEGATIVE)); - machine.execute_instruction((load_instruction, OpInput::UseImmediate(1))); + CPU.execute_instruction((load_instruction, OpInput::UseImmediate(1))); - compare(&mut machine, 2); - assert!(!machine.registers.status.contains(PS_ZERO)); - assert!(!machine.registers.status.contains(PS_CARRY)); - assert!(machine.registers.status.contains(PS_NEGATIVE)); + compare(&mut CPU, 2); + assert!(!CPU.registers.status.contains(PS_ZERO)); + assert!(!CPU.registers.status.contains(PS_CARRY)); + assert!(CPU.registers.status.contains(PS_NEGATIVE)); - machine.execute_instruction((load_instruction, OpInput::UseImmediate(20))); + CPU.execute_instruction((load_instruction, OpInput::UseImmediate(20))); - compare(&mut machine, -50i8 as u8); - assert!(!machine.registers.status.contains(PS_ZERO)); - assert!(!machine.registers.status.contains(PS_CARRY)); - assert!(!machine.registers.status.contains(PS_NEGATIVE)); + compare(&mut CPU, -50i8 as u8); + assert!(!CPU.registers.status.contains(PS_ZERO)); + assert!(!CPU.registers.status.contains(PS_CARRY)); + assert!(!CPU.registers.status.contains(PS_NEGATIVE)); - machine.execute_instruction((load_instruction, OpInput::UseImmediate(1))); + CPU.execute_instruction((load_instruction, OpInput::UseImmediate(1))); - compare(&mut machine, -1i8 as u8); - assert!(!machine.registers.status.contains(PS_ZERO)); - assert!(!machine.registers.status.contains(PS_CARRY)); - assert!(!machine.registers.status.contains(PS_NEGATIVE)); + compare(&mut CPU, -1i8 as u8); + assert!(!CPU.registers.status.contains(PS_ZERO)); + assert!(!CPU.registers.status.contains(PS_CARRY)); + assert!(!CPU.registers.status.contains(PS_NEGATIVE)); - machine.execute_instruction((load_instruction, OpInput::UseImmediate(127))); + CPU.execute_instruction((load_instruction, OpInput::UseImmediate(127))); - compare(&mut machine, -128i8 as u8); - assert!(!machine.registers.status.contains(PS_ZERO)); - assert!(!machine.registers.status.contains(PS_CARRY)); - assert!(machine.registers.status.contains(PS_NEGATIVE)); + compare(&mut CPU, -128i8 as u8); + assert!(!CPU.registers.status.contains(PS_ZERO)); + assert!(!CPU.registers.status.contains(PS_CARRY)); + assert!(CPU.registers.status.contains(PS_NEGATIVE)); } #[test] fn compare_with_a_register_test() { compare_test_helper( - &mut |machine: &mut Machine, val: u8| { machine.compare_with_a_register(val); }, + &mut |CPU: &mut CPU, val: u8| { + CPU.compare_with_a_register(val); + }, Instruction::LDA, ); } @@ -1224,7 +1225,9 @@ mod tests { #[test] fn compare_with_x_register_test() { compare_test_helper( - &mut |machine: &mut Machine, val: u8| { machine.compare_with_x_register(val); }, + &mut |CPU: &mut CPU, val: u8| { + CPU.compare_with_x_register(val); + }, Instruction::LDX, ); } @@ -1232,34 +1235,36 @@ mod tests { #[test] fn compare_with_y_register_test() { compare_test_helper( - &mut |machine: &mut Machine, val: u8| { machine.compare_with_y_register(val); }, + &mut |CPU: &mut CPU, val: u8| { + CPU.compare_with_y_register(val); + }, Instruction::LDY, ); } #[test] fn exclusive_or_test() { - let mut machine = Machine::new(); + let mut CPU = CPU::new(); for a_before in range_inclusive(0u8, 255u8) { for val in range_inclusive(0u8, 255u8) { - machine.execute_instruction((Instruction::LDA, OpInput::UseImmediate(a_before))); + CPU.execute_instruction((Instruction::LDA, OpInput::UseImmediate(a_before))); - machine.exclusive_or(val); + CPU.exclusive_or(val); let a_after = a_before ^ val; - assert_eq!(machine.registers.accumulator, a_after as i8); + assert_eq!(CPU.registers.accumulator, a_after as i8); if a_after == 0 { - assert!(machine.registers.status.contains(PS_ZERO)); + assert!(CPU.registers.status.contains(PS_ZERO)); } else { - assert!(!machine.registers.status.contains(PS_ZERO)); + assert!(!CPU.registers.status.contains(PS_ZERO)); } if (a_after as i8) < 0 { - assert!(machine.registers.status.contains(PS_NEGATIVE)); + assert!(CPU.registers.status.contains(PS_NEGATIVE)); } else { - assert!(!machine.registers.status.contains(PS_NEGATIVE)); + assert!(!CPU.registers.status.contains(PS_NEGATIVE)); } } } @@ -1267,27 +1272,27 @@ mod tests { #[test] fn inclusive_or_test() { - let mut machine = Machine::new(); + let mut CPU = CPU::new(); for a_before in range_inclusive(0u8, 255u8) { for val in range_inclusive(0u8, 255u8) { - machine.execute_instruction((Instruction::LDA, OpInput::UseImmediate(a_before))); + CPU.execute_instruction((Instruction::LDA, OpInput::UseImmediate(a_before))); - machine.inclusive_or(val); + CPU.inclusive_or(val); let a_after = a_before | val; - assert_eq!(machine.registers.accumulator, a_after as i8); + assert_eq!(CPU.registers.accumulator, a_after as i8); if a_after == 0 { - assert!(machine.registers.status.contains(PS_ZERO)); + assert!(CPU.registers.status.contains(PS_ZERO)); } else { - assert!(!machine.registers.status.contains(PS_ZERO)); + assert!(!CPU.registers.status.contains(PS_ZERO)); } if (a_after as i8) < 0 { - assert!(machine.registers.status.contains(PS_NEGATIVE)); + assert!(CPU.registers.status.contains(PS_NEGATIVE)); } else { - assert!(!machine.registers.status.contains(PS_NEGATIVE)); + assert!(!CPU.registers.status.contains(PS_NEGATIVE)); } } } diff --git a/src/instruction.rs b/src/instruction.rs index a3c52cd..cf77feb 100644 --- a/src/instruction.rs +++ b/src/instruction.rs @@ -27,7 +27,7 @@ use address::Address; use address::AddressDiff; -use machine::Machine; +use cpu::CPU; // Abbreviations // @@ -119,17 +119,17 @@ pub enum OpInput { #[derive(Copy, Clone)] pub enum AddressingMode { - Accumulator, // 1 LSR A work directly on accumulator - Implied, // 1 BRK - Immediate, // 2 LDA #10 8-bit constant in instruction - ZeroPage, // 2 LDA $00 zero-page address - ZeroPageX, // 2 LDA $80,X address is X register + 8-bit constant - ZeroPageY, // 2 LDX $10,Y address is Y register + 8-bit constant - Relative, // 2 BNE LABEL branch target as signed relative offset - Absolute, // 3 JMP $1000 full 16-bit address - AbsoluteX, // 3 STA $1000,X full 16-bit address plus X register - AbsoluteY, // 3 STA $1000,Y full 16-bit address plus Y register - Indirect, // 3 JMP ($1000) jump to address stored at address + Accumulator, // 1 LSR A work directly on accumulator + Implied, // 1 BRK + Immediate, // 2 LDA #10 8-bit constant in instruction + ZeroPage, // 2 LDA $00 zero-page address + ZeroPageX, // 2 LDA $80,X address is X register + 8-bit constant + ZeroPageY, // 2 LDX $10,Y address is Y register + 8-bit constant + Relative, // 2 BNE LABEL branch target as signed relative offset + Absolute, // 3 JMP $1000 full 16-bit address + AbsoluteX, // 3 STA $1000,X full 16-bit address plus X register + AbsoluteY, // 3 STA $1000,Y full 16-bit address plus Y register + Indirect, // 3 JMP ($1000) jump to address stored at address IndexedIndirectX, // 2 LDA ($10,X) load from address stored at (constant // zero page address plus X register) IndirectIndexedY, // 2 LDA ($10),Y load from (address stored at constant @@ -163,21 +163,19 @@ impl AddressingMode { AddressDiff(x) } - pub fn process(self, machine: &Machine, arr: &[u8]) -> OpInput { - + pub fn process(self, cpu: &CPU, arr: &[u8]) -> OpInput { debug_assert!({ let AddressDiff(x) = self.extra_bytes(); arr.len() == x as usize }); - let x = machine.registers.index_x as u8; - let y = machine.registers.index_y as u8; + let x = cpu.registers.index_x as u8; + let y = cpu.registers.index_y as u8; - let memory = &machine.memory; + let memory = &cpu.memory; match self { - AddressingMode::Accumulator | - AddressingMode::Implied => { + AddressingMode::Accumulator | AddressingMode::Implied => { // Always the same -- no input OpInput::UseImplied } @@ -254,518 +252,517 @@ impl AddressingMode { pub type DecodedInstr = (Instruction, OpInput); -pub static OPCODES: [Option<(Instruction, AddressingMode)>; 256] = - [ - /*0x00*/ - Some((Instruction::BRK, AddressingMode::Implied)), - /*0x01*/ - Some((Instruction::ORA, AddressingMode::IndexedIndirectX)), - /*0x02*/ - None, - /*0x03*/ - None, - /*0x04*/ - None, - /*0x05*/ - Some((Instruction::ORA, AddressingMode::ZeroPage)), - /*0x06*/ - Some((Instruction::ASL, AddressingMode::ZeroPage)), - /*0x07*/ - None, - /*0x08*/ - Some((Instruction::PHP, AddressingMode::Implied)), - /*0x09*/ - Some((Instruction::ORA, AddressingMode::Immediate)), - /*0x0A*/ - Some((Instruction::ASL, AddressingMode::Accumulator)), - /*0x0B*/ - None, - /*0x0C*/ - None, - /*0x0D*/ - Some((Instruction::ORA, AddressingMode::Absolute)), - /*0x0E*/ - Some((Instruction::ASL, AddressingMode::Absolute)), - /*0x0F*/ - None, - /*0x10*/ - Some((Instruction::BPL, AddressingMode::Relative)), - /*0x11*/ - Some((Instruction::ORA, AddressingMode::IndirectIndexedY)), - /*0x12*/ - None, - /*0x13*/ - None, - /*0x14*/ - None, - /*0x15*/ - Some((Instruction::ORA, AddressingMode::ZeroPageX)), - /*0x16*/ - Some((Instruction::ASL, AddressingMode::ZeroPageX)), - /*0x17*/ - None, - /*0x18*/ - Some((Instruction::CLC, AddressingMode::Implied)), - /*0x19*/ - Some((Instruction::ORA, AddressingMode::AbsoluteY)), - /*0x1A*/ - None, - /*0x1B*/ - None, - /*0x1C*/ - None, - /*0x1D*/ - Some((Instruction::ORA, AddressingMode::AbsoluteX)), - /*0x1E*/ - Some((Instruction::ASL, AddressingMode::AbsoluteX)), - /*0x1F*/ - None, - /*0x20*/ - Some((Instruction::JSR, AddressingMode::Absolute)), - /*0x21*/ - Some((Instruction::AND, AddressingMode::IndexedIndirectX)), - /*0x22*/ - None, - /*0x23*/ - None, - /*0x24*/ - Some((Instruction::BIT, AddressingMode::ZeroPage)), - /*0x25*/ - Some((Instruction::AND, AddressingMode::ZeroPage)), - /*0x26*/ - Some((Instruction::ROL, AddressingMode::ZeroPage)), - /*0x27*/ - None, - /*0x28*/ - Some((Instruction::PLP, AddressingMode::Implied)), - /*0x29*/ - Some((Instruction::AND, AddressingMode::Immediate)), - /*0x2A*/ - Some((Instruction::ROL, AddressingMode::Accumulator)), - /*0x2B*/ - None, - /*0x2C*/ - Some((Instruction::BIT, AddressingMode::Absolute)), - /*0x2D*/ - Some((Instruction::AND, AddressingMode::Absolute)), - /*0x2E*/ - Some((Instruction::ROL, AddressingMode::Absolute)), - /*0x2F*/ - None, - /*0x30*/ - Some((Instruction::BMI, AddressingMode::Relative)), - /*0x31*/ - Some((Instruction::AND, AddressingMode::IndirectIndexedY)), - /*0x32*/ - None, - /*0x33*/ - None, - /*0x34*/ - None, - /*0x35*/ - Some((Instruction::AND, AddressingMode::ZeroPageX)), - /*0x36*/ - Some((Instruction::ROL, AddressingMode::ZeroPageX)), - /*0x37*/ - None, - /*0x38*/ - Some((Instruction::SEC, AddressingMode::Implied)), - /*0x39*/ - Some((Instruction::AND, AddressingMode::AbsoluteY)), - /*0x3A*/ - None, - /*0x3B*/ - None, - /*0x3C*/ - None, - /*0x3D*/ - Some((Instruction::AND, AddressingMode::AbsoluteX)), - /*0x3E*/ - Some((Instruction::ROL, AddressingMode::AbsoluteX)), - /*0x3F*/ - None, - /*0x40*/ - Some((Instruction::RTI, AddressingMode::Implied)), - /*0x41*/ - Some((Instruction::EOR, AddressingMode::IndexedIndirectX)), - /*0x42*/ - None, - /*0x43*/ - None, - /*0x44*/ - None, - /*0x45*/ - Some((Instruction::EOR, AddressingMode::ZeroPage)), - /*0x46*/ - Some((Instruction::LSR, AddressingMode::ZeroPage)), - /*0x47*/ - None, - /*0x48*/ - Some((Instruction::PHA, AddressingMode::Implied)), - /*0x49*/ - Some((Instruction::EOR, AddressingMode::Immediate)), - /*0x4A*/ - Some((Instruction::LSR, AddressingMode::Accumulator)), - /*0x4B*/ - None, - /*0x4C*/ - Some((Instruction::JMP, AddressingMode::Absolute)), - /*0x4D*/ - Some((Instruction::EOR, AddressingMode::Absolute)), - /*0x4E*/ - Some((Instruction::LSR, AddressingMode::Absolute)), - /*0x4F*/ - None, - /*0x50*/ - Some((Instruction::BVC, AddressingMode::Relative)), - /*0x51*/ - Some((Instruction::EOR, AddressingMode::IndirectIndexedY)), - /*0x52*/ - None, - /*0x53*/ - None, - /*0x54*/ - None, - /*0x55*/ - Some((Instruction::EOR, AddressingMode::ZeroPageX)), - /*0x56*/ - Some((Instruction::LSR, AddressingMode::ZeroPageX)), - /*0x57*/ - None, - /*0x58*/ - None, - /*0x59*/ - Some((Instruction::EOR, AddressingMode::AbsoluteY)), - /*0x5A*/ - None, - /*0x5B*/ - None, - /*0x5C*/ - None, - /*0x5D*/ - Some((Instruction::EOR, AddressingMode::AbsoluteX)), - /*0x5E*/ - Some((Instruction::LSR, AddressingMode::AbsoluteX)), - /*0x5F*/ - None, - /*0x60*/ - Some((Instruction::RTS, AddressingMode::Implied)), - /*0x61*/ - Some((Instruction::ADC, AddressingMode::IndexedIndirectX)), - /*0x62*/ - None, - /*0x63*/ - None, - /*0x64*/ - None, - /*0x65*/ - Some((Instruction::ADC, AddressingMode::ZeroPage)), - /*0x66*/ - Some((Instruction::ROR, AddressingMode::ZeroPage)), - /*0x67*/ - None, - /*0x68*/ - Some((Instruction::PLA, AddressingMode::Implied)), - /*0x69*/ - Some((Instruction::ADC, AddressingMode::Immediate)), - /*0x6A*/ - Some((Instruction::ROR, AddressingMode::Accumulator)), - /*0x6B*/ - None, - /*0x6C*/ - Some((Instruction::JMP, AddressingMode::Indirect)), - /*0x6D*/ - Some((Instruction::ADC, AddressingMode::Absolute)), - /*0x6E*/ - Some((Instruction::ROR, AddressingMode::Absolute)), - /*0x6F*/ - None, - /*0x70*/ - Some((Instruction::BVS, AddressingMode::Relative)), - /*0x71*/ - Some((Instruction::ADC, AddressingMode::IndirectIndexedY)), - /*0x72*/ - None, - /*0x73*/ - None, - /*0x74*/ - None, - /*0x75*/ - Some((Instruction::ADC, AddressingMode::ZeroPageX)), - /*0x76*/ - Some((Instruction::ROR, AddressingMode::ZeroPageX)), - /*0x77*/ - None, - /*0x78*/ - Some((Instruction::SEI, AddressingMode::Implied)), - /*0x79*/ - Some((Instruction::ADC, AddressingMode::AbsoluteY)), - /*0x7A*/ - None, - /*0x7B*/ - None, - /*0x7C*/ - None, - /*0x7D*/ - Some((Instruction::ADC, AddressingMode::AbsoluteX)), - /*0x7E*/ - Some((Instruction::ROR, AddressingMode::AbsoluteX)), - /*0x7F*/ - None, - /*0x80*/ - None, - /*0x81*/ - Some((Instruction::STA, AddressingMode::IndexedIndirectX)), - /*0x82*/ - None, - /*0x83*/ - None, - /*0x84*/ - Some((Instruction::STY, AddressingMode::ZeroPage)), - /*0x85*/ - Some((Instruction::STA, AddressingMode::ZeroPage)), - /*0x86*/ - Some((Instruction::STX, AddressingMode::ZeroPage)), - /*0x87*/ - None, - /*0x88*/ - Some((Instruction::DEY, AddressingMode::Implied)), - /*0x89*/ - None, - /*0x8A*/ - Some((Instruction::TXA, AddressingMode::Implied)), - /*0x8B*/ - None, - /*0x8C*/ - Some((Instruction::STY, AddressingMode::Absolute)), - /*0x8D*/ - Some((Instruction::STA, AddressingMode::Absolute)), - /*0x8E*/ - Some((Instruction::STX, AddressingMode::Absolute)), - /*0x8F*/ - None, - /*0x90*/ - Some((Instruction::BCC, AddressingMode::Relative)), - /*0x91*/ - Some((Instruction::STA, AddressingMode::IndirectIndexedY)), - /*0x92*/ - None, - /*0x93*/ - None, - /*0x94*/ - Some((Instruction::STY, AddressingMode::ZeroPageX)), - /*0x95*/ - Some((Instruction::STA, AddressingMode::ZeroPageX)), - /*0x96*/ - Some((Instruction::STX, AddressingMode::ZeroPageY)), - /*0x97*/ - None, - /*0x98*/ - Some((Instruction::TYA, AddressingMode::Implied)), - /*0x99*/ - Some((Instruction::STA, AddressingMode::AbsoluteY)), - /*0x9A*/ - Some((Instruction::TXS, AddressingMode::Implied)), - /*0x9B*/ - None, - /*0x9C*/ - None, - /*0x9D*/ - Some((Instruction::STA, AddressingMode::AbsoluteX)), - /*0x9E*/ - None, - /*0x9F*/ - None, - /*0xA0*/ - Some((Instruction::LDY, AddressingMode::Immediate)), - /*0xA1*/ - Some((Instruction::LDA, AddressingMode::IndexedIndirectX)), - /*0xA2*/ - Some((Instruction::LDX, AddressingMode::Immediate)), - /*0xA3*/ - None, - /*0xA4*/ - Some((Instruction::LDY, AddressingMode::ZeroPage)), - /*0xA5*/ - Some((Instruction::LDA, AddressingMode::ZeroPage)), - /*0xA6*/ - Some((Instruction::LDX, AddressingMode::ZeroPage)), - /*0xA7*/ - None, - /*0xA8*/ - Some((Instruction::TAY, AddressingMode::Implied)), - /*0xA9*/ - Some((Instruction::LDA, AddressingMode::Immediate)), - /*0xAA*/ - Some((Instruction::TAX, AddressingMode::Implied)), - /*0xAB*/ - None, - /*0xAC*/ - Some((Instruction::LDY, AddressingMode::Absolute)), - /*0xAD*/ - Some((Instruction::LDA, AddressingMode::Absolute)), - /*0xAE*/ - Some((Instruction::LDX, AddressingMode::Absolute)), - /*0xAF*/ - None, - /*0xB0*/ - Some((Instruction::BCS, AddressingMode::Relative)), - /*0xB1*/ - Some((Instruction::LDA, AddressingMode::IndirectIndexedY)), - /*0xB2*/ - None, - /*0xB3*/ - None, - /*0xB4*/ - Some((Instruction::LDY, AddressingMode::ZeroPageX)), - /*0xB5*/ - Some((Instruction::LDA, AddressingMode::ZeroPageX)), - /*0xB6*/ - Some((Instruction::LDX, AddressingMode::ZeroPageY)), - /*0xB7*/ - None, - /*0xB8*/ - Some((Instruction::CLV, AddressingMode::Implied)), - /*0xB9*/ - Some((Instruction::LDA, AddressingMode::AbsoluteY)), - /*0xBA*/ - Some((Instruction::TSX, AddressingMode::Implied)), - /*0xBB*/ - None, - /*0xBC*/ - Some((Instruction::LDY, AddressingMode::AbsoluteX)), - /*0xBD*/ - Some((Instruction::LDA, AddressingMode::AbsoluteX)), - /*0xBE*/ - Some((Instruction::LDX, AddressingMode::AbsoluteY)), - /*0xBF*/ - None, - /*0xC0*/ - Some((Instruction::CPY, AddressingMode::Immediate)), - /*0xC1*/ - Some((Instruction::CMP, AddressingMode::IndexedIndirectX)), - /*0xC2*/ - None, - /*0xC3*/ - None, - /*0xC4*/ - Some((Instruction::CPY, AddressingMode::ZeroPage)), - /*0xC5*/ - Some((Instruction::CMP, AddressingMode::ZeroPage)), - /*0xC6*/ - Some((Instruction::DEC, AddressingMode::ZeroPage)), - /*0xC7*/ - None, - /*0xC8*/ - Some((Instruction::INY, AddressingMode::Implied)), - /*0xC9*/ - Some((Instruction::CMP, AddressingMode::Immediate)), - /*0xCA*/ - Some((Instruction::DEX, AddressingMode::Implied)), - /*0xCB*/ - None, - /*0xCC*/ - Some((Instruction::CPY, AddressingMode::Absolute)), - /*0xCD*/ - Some((Instruction::CMP, AddressingMode::Absolute)), - /*0xCE*/ - Some((Instruction::DEC, AddressingMode::Absolute)), - /*0xCF*/ - None, - /*0xD0*/ - Some((Instruction::BNE, AddressingMode::Relative)), - /*0xD1*/ - Some((Instruction::CMP, AddressingMode::IndirectIndexedY)), - /*0xD2*/ - None, - /*0xD3*/ - None, - /*0xD4*/ - None, - /*0xD5*/ - Some((Instruction::CMP, AddressingMode::ZeroPageX)), - /*0xD6*/ - Some((Instruction::DEC, AddressingMode::ZeroPageX)), - /*0xD7*/ - None, - /*0xD8*/ - Some((Instruction::CLD, AddressingMode::Implied)), - /*0xD9*/ - Some((Instruction::CMP, AddressingMode::AbsoluteY)), - /*0xDA*/ - None, - /*0xDB*/ - None, - /*0xDC*/ - None, - /*0xDD*/ - Some((Instruction::CMP, AddressingMode::AbsoluteX)), - /*0xDE*/ - Some((Instruction::DEC, AddressingMode::AbsoluteX)), - /*0xDF*/ - None, - /*0xE0*/ - Some((Instruction::CPX, AddressingMode::Immediate)), - /*0xE1*/ - Some((Instruction::SBC, AddressingMode::IndexedIndirectX)), - /*0xE2*/ - None, - /*0xE3*/ - None, - /*0xE4*/ - Some((Instruction::CPX, AddressingMode::ZeroPage)), - /*0xE5*/ - Some((Instruction::SBC, AddressingMode::ZeroPage)), - /*0xE6*/ - Some((Instruction::INC, AddressingMode::ZeroPage)), - /*0xE7*/ - None, - /*0xE8*/ - Some((Instruction::INX, AddressingMode::Implied)), - /*0xE9*/ - Some((Instruction::SBC, AddressingMode::Immediate)), - /*0xEA*/ - Some((Instruction::NOP, AddressingMode::Implied)), - /*0xEB*/ - None, - /*0xEC*/ - Some((Instruction::CPX, AddressingMode::Absolute)), - /*0xED*/ - Some((Instruction::SBC, AddressingMode::Absolute)), - /*0xEE*/ - Some((Instruction::INC, AddressingMode::Absolute)), - /*0xEF*/ - None, - /*0xF0*/ - Some((Instruction::BEQ, AddressingMode::Relative)), - /*0xF1*/ - Some((Instruction::SBC, AddressingMode::IndirectIndexedY)), - /*0xF2*/ - None, - /*0xF3*/ - None, - /*0xF4*/ - None, - /*0xF5*/ - Some((Instruction::SBC, AddressingMode::ZeroPageX)), - /*0xF6*/ - Some((Instruction::INC, AddressingMode::ZeroPageX)), - /*0xF7*/ - None, - /*0xF8*/ - Some((Instruction::SED, AddressingMode::Implied)), - /*0xF9*/ - Some((Instruction::SBC, AddressingMode::AbsoluteY)), - /*0xFA*/ - None, - /*0xFB*/ - None, - /*0xFC*/ - None, - /*0xFD*/ - Some((Instruction::SBC, AddressingMode::AbsoluteX)), - /*0xFE*/ - Some((Instruction::INC, AddressingMode::AbsoluteX)), - /*0xFF*/ - None, - ]; +pub static OPCODES: [Option<(Instruction, AddressingMode)>; 256] = [ + /*0x00*/ + Some((Instruction::BRK, AddressingMode::Implied)), + /*0x01*/ + Some((Instruction::ORA, AddressingMode::IndexedIndirectX)), + /*0x02*/ + None, + /*0x03*/ + None, + /*0x04*/ + None, + /*0x05*/ + Some((Instruction::ORA, AddressingMode::ZeroPage)), + /*0x06*/ + Some((Instruction::ASL, AddressingMode::ZeroPage)), + /*0x07*/ + None, + /*0x08*/ + Some((Instruction::PHP, AddressingMode::Implied)), + /*0x09*/ + Some((Instruction::ORA, AddressingMode::Immediate)), + /*0x0A*/ + Some((Instruction::ASL, AddressingMode::Accumulator)), + /*0x0B*/ + None, + /*0x0C*/ + None, + /*0x0D*/ + Some((Instruction::ORA, AddressingMode::Absolute)), + /*0x0E*/ + Some((Instruction::ASL, AddressingMode::Absolute)), + /*0x0F*/ + None, + /*0x10*/ + Some((Instruction::BPL, AddressingMode::Relative)), + /*0x11*/ + Some((Instruction::ORA, AddressingMode::IndirectIndexedY)), + /*0x12*/ + None, + /*0x13*/ + None, + /*0x14*/ + None, + /*0x15*/ + Some((Instruction::ORA, AddressingMode::ZeroPageX)), + /*0x16*/ + Some((Instruction::ASL, AddressingMode::ZeroPageX)), + /*0x17*/ + None, + /*0x18*/ + Some((Instruction::CLC, AddressingMode::Implied)), + /*0x19*/ + Some((Instruction::ORA, AddressingMode::AbsoluteY)), + /*0x1A*/ + None, + /*0x1B*/ + None, + /*0x1C*/ + None, + /*0x1D*/ + Some((Instruction::ORA, AddressingMode::AbsoluteX)), + /*0x1E*/ + Some((Instruction::ASL, AddressingMode::AbsoluteX)), + /*0x1F*/ + None, + /*0x20*/ + Some((Instruction::JSR, AddressingMode::Absolute)), + /*0x21*/ + Some((Instruction::AND, AddressingMode::IndexedIndirectX)), + /*0x22*/ + None, + /*0x23*/ + None, + /*0x24*/ + Some((Instruction::BIT, AddressingMode::ZeroPage)), + /*0x25*/ + Some((Instruction::AND, AddressingMode::ZeroPage)), + /*0x26*/ + Some((Instruction::ROL, AddressingMode::ZeroPage)), + /*0x27*/ + None, + /*0x28*/ + Some((Instruction::PLP, AddressingMode::Implied)), + /*0x29*/ + Some((Instruction::AND, AddressingMode::Immediate)), + /*0x2A*/ + Some((Instruction::ROL, AddressingMode::Accumulator)), + /*0x2B*/ + None, + /*0x2C*/ + Some((Instruction::BIT, AddressingMode::Absolute)), + /*0x2D*/ + Some((Instruction::AND, AddressingMode::Absolute)), + /*0x2E*/ + Some((Instruction::ROL, AddressingMode::Absolute)), + /*0x2F*/ + None, + /*0x30*/ + Some((Instruction::BMI, AddressingMode::Relative)), + /*0x31*/ + Some((Instruction::AND, AddressingMode::IndirectIndexedY)), + /*0x32*/ + None, + /*0x33*/ + None, + /*0x34*/ + None, + /*0x35*/ + Some((Instruction::AND, AddressingMode::ZeroPageX)), + /*0x36*/ + Some((Instruction::ROL, AddressingMode::ZeroPageX)), + /*0x37*/ + None, + /*0x38*/ + Some((Instruction::SEC, AddressingMode::Implied)), + /*0x39*/ + Some((Instruction::AND, AddressingMode::AbsoluteY)), + /*0x3A*/ + None, + /*0x3B*/ + None, + /*0x3C*/ + None, + /*0x3D*/ + Some((Instruction::AND, AddressingMode::AbsoluteX)), + /*0x3E*/ + Some((Instruction::ROL, AddressingMode::AbsoluteX)), + /*0x3F*/ + None, + /*0x40*/ + Some((Instruction::RTI, AddressingMode::Implied)), + /*0x41*/ + Some((Instruction::EOR, AddressingMode::IndexedIndirectX)), + /*0x42*/ + None, + /*0x43*/ + None, + /*0x44*/ + None, + /*0x45*/ + Some((Instruction::EOR, AddressingMode::ZeroPage)), + /*0x46*/ + Some((Instruction::LSR, AddressingMode::ZeroPage)), + /*0x47*/ + None, + /*0x48*/ + Some((Instruction::PHA, AddressingMode::Implied)), + /*0x49*/ + Some((Instruction::EOR, AddressingMode::Immediate)), + /*0x4A*/ + Some((Instruction::LSR, AddressingMode::Accumulator)), + /*0x4B*/ + None, + /*0x4C*/ + Some((Instruction::JMP, AddressingMode::Absolute)), + /*0x4D*/ + Some((Instruction::EOR, AddressingMode::Absolute)), + /*0x4E*/ + Some((Instruction::LSR, AddressingMode::Absolute)), + /*0x4F*/ + None, + /*0x50*/ + Some((Instruction::BVC, AddressingMode::Relative)), + /*0x51*/ + Some((Instruction::EOR, AddressingMode::IndirectIndexedY)), + /*0x52*/ + None, + /*0x53*/ + None, + /*0x54*/ + None, + /*0x55*/ + Some((Instruction::EOR, AddressingMode::ZeroPageX)), + /*0x56*/ + Some((Instruction::LSR, AddressingMode::ZeroPageX)), + /*0x57*/ + None, + /*0x58*/ + None, + /*0x59*/ + Some((Instruction::EOR, AddressingMode::AbsoluteY)), + /*0x5A*/ + None, + /*0x5B*/ + None, + /*0x5C*/ + None, + /*0x5D*/ + Some((Instruction::EOR, AddressingMode::AbsoluteX)), + /*0x5E*/ + Some((Instruction::LSR, AddressingMode::AbsoluteX)), + /*0x5F*/ + None, + /*0x60*/ + Some((Instruction::RTS, AddressingMode::Implied)), + /*0x61*/ + Some((Instruction::ADC, AddressingMode::IndexedIndirectX)), + /*0x62*/ + None, + /*0x63*/ + None, + /*0x64*/ + None, + /*0x65*/ + Some((Instruction::ADC, AddressingMode::ZeroPage)), + /*0x66*/ + Some((Instruction::ROR, AddressingMode::ZeroPage)), + /*0x67*/ + None, + /*0x68*/ + Some((Instruction::PLA, AddressingMode::Implied)), + /*0x69*/ + Some((Instruction::ADC, AddressingMode::Immediate)), + /*0x6A*/ + Some((Instruction::ROR, AddressingMode::Accumulator)), + /*0x6B*/ + None, + /*0x6C*/ + Some((Instruction::JMP, AddressingMode::Indirect)), + /*0x6D*/ + Some((Instruction::ADC, AddressingMode::Absolute)), + /*0x6E*/ + Some((Instruction::ROR, AddressingMode::Absolute)), + /*0x6F*/ + None, + /*0x70*/ + Some((Instruction::BVS, AddressingMode::Relative)), + /*0x71*/ + Some((Instruction::ADC, AddressingMode::IndirectIndexedY)), + /*0x72*/ + None, + /*0x73*/ + None, + /*0x74*/ + None, + /*0x75*/ + Some((Instruction::ADC, AddressingMode::ZeroPageX)), + /*0x76*/ + Some((Instruction::ROR, AddressingMode::ZeroPageX)), + /*0x77*/ + None, + /*0x78*/ + Some((Instruction::SEI, AddressingMode::Implied)), + /*0x79*/ + Some((Instruction::ADC, AddressingMode::AbsoluteY)), + /*0x7A*/ + None, + /*0x7B*/ + None, + /*0x7C*/ + None, + /*0x7D*/ + Some((Instruction::ADC, AddressingMode::AbsoluteX)), + /*0x7E*/ + Some((Instruction::ROR, AddressingMode::AbsoluteX)), + /*0x7F*/ + None, + /*0x80*/ + None, + /*0x81*/ + Some((Instruction::STA, AddressingMode::IndexedIndirectX)), + /*0x82*/ + None, + /*0x83*/ + None, + /*0x84*/ + Some((Instruction::STY, AddressingMode::ZeroPage)), + /*0x85*/ + Some((Instruction::STA, AddressingMode::ZeroPage)), + /*0x86*/ + Some((Instruction::STX, AddressingMode::ZeroPage)), + /*0x87*/ + None, + /*0x88*/ + Some((Instruction::DEY, AddressingMode::Implied)), + /*0x89*/ + None, + /*0x8A*/ + Some((Instruction::TXA, AddressingMode::Implied)), + /*0x8B*/ + None, + /*0x8C*/ + Some((Instruction::STY, AddressingMode::Absolute)), + /*0x8D*/ + Some((Instruction::STA, AddressingMode::Absolute)), + /*0x8E*/ + Some((Instruction::STX, AddressingMode::Absolute)), + /*0x8F*/ + None, + /*0x90*/ + Some((Instruction::BCC, AddressingMode::Relative)), + /*0x91*/ + Some((Instruction::STA, AddressingMode::IndirectIndexedY)), + /*0x92*/ + None, + /*0x93*/ + None, + /*0x94*/ + Some((Instruction::STY, AddressingMode::ZeroPageX)), + /*0x95*/ + Some((Instruction::STA, AddressingMode::ZeroPageX)), + /*0x96*/ + Some((Instruction::STX, AddressingMode::ZeroPageY)), + /*0x97*/ + None, + /*0x98*/ + Some((Instruction::TYA, AddressingMode::Implied)), + /*0x99*/ + Some((Instruction::STA, AddressingMode::AbsoluteY)), + /*0x9A*/ + Some((Instruction::TXS, AddressingMode::Implied)), + /*0x9B*/ + None, + /*0x9C*/ + None, + /*0x9D*/ + Some((Instruction::STA, AddressingMode::AbsoluteX)), + /*0x9E*/ + None, + /*0x9F*/ + None, + /*0xA0*/ + Some((Instruction::LDY, AddressingMode::Immediate)), + /*0xA1*/ + Some((Instruction::LDA, AddressingMode::IndexedIndirectX)), + /*0xA2*/ + Some((Instruction::LDX, AddressingMode::Immediate)), + /*0xA3*/ + None, + /*0xA4*/ + Some((Instruction::LDY, AddressingMode::ZeroPage)), + /*0xA5*/ + Some((Instruction::LDA, AddressingMode::ZeroPage)), + /*0xA6*/ + Some((Instruction::LDX, AddressingMode::ZeroPage)), + /*0xA7*/ + None, + /*0xA8*/ + Some((Instruction::TAY, AddressingMode::Implied)), + /*0xA9*/ + Some((Instruction::LDA, AddressingMode::Immediate)), + /*0xAA*/ + Some((Instruction::TAX, AddressingMode::Implied)), + /*0xAB*/ + None, + /*0xAC*/ + Some((Instruction::LDY, AddressingMode::Absolute)), + /*0xAD*/ + Some((Instruction::LDA, AddressingMode::Absolute)), + /*0xAE*/ + Some((Instruction::LDX, AddressingMode::Absolute)), + /*0xAF*/ + None, + /*0xB0*/ + Some((Instruction::BCS, AddressingMode::Relative)), + /*0xB1*/ + Some((Instruction::LDA, AddressingMode::IndirectIndexedY)), + /*0xB2*/ + None, + /*0xB3*/ + None, + /*0xB4*/ + Some((Instruction::LDY, AddressingMode::ZeroPageX)), + /*0xB5*/ + Some((Instruction::LDA, AddressingMode::ZeroPageX)), + /*0xB6*/ + Some((Instruction::LDX, AddressingMode::ZeroPageY)), + /*0xB7*/ + None, + /*0xB8*/ + Some((Instruction::CLV, AddressingMode::Implied)), + /*0xB9*/ + Some((Instruction::LDA, AddressingMode::AbsoluteY)), + /*0xBA*/ + Some((Instruction::TSX, AddressingMode::Implied)), + /*0xBB*/ + None, + /*0xBC*/ + Some((Instruction::LDY, AddressingMode::AbsoluteX)), + /*0xBD*/ + Some((Instruction::LDA, AddressingMode::AbsoluteX)), + /*0xBE*/ + Some((Instruction::LDX, AddressingMode::AbsoluteY)), + /*0xBF*/ + None, + /*0xC0*/ + Some((Instruction::CPY, AddressingMode::Immediate)), + /*0xC1*/ + Some((Instruction::CMP, AddressingMode::IndexedIndirectX)), + /*0xC2*/ + None, + /*0xC3*/ + None, + /*0xC4*/ + Some((Instruction::CPY, AddressingMode::ZeroPage)), + /*0xC5*/ + Some((Instruction::CMP, AddressingMode::ZeroPage)), + /*0xC6*/ + Some((Instruction::DEC, AddressingMode::ZeroPage)), + /*0xC7*/ + None, + /*0xC8*/ + Some((Instruction::INY, AddressingMode::Implied)), + /*0xC9*/ + Some((Instruction::CMP, AddressingMode::Immediate)), + /*0xCA*/ + Some((Instruction::DEX, AddressingMode::Implied)), + /*0xCB*/ + None, + /*0xCC*/ + Some((Instruction::CPY, AddressingMode::Absolute)), + /*0xCD*/ + Some((Instruction::CMP, AddressingMode::Absolute)), + /*0xCE*/ + Some((Instruction::DEC, AddressingMode::Absolute)), + /*0xCF*/ + None, + /*0xD0*/ + Some((Instruction::BNE, AddressingMode::Relative)), + /*0xD1*/ + Some((Instruction::CMP, AddressingMode::IndirectIndexedY)), + /*0xD2*/ + None, + /*0xD3*/ + None, + /*0xD4*/ + None, + /*0xD5*/ + Some((Instruction::CMP, AddressingMode::ZeroPageX)), + /*0xD6*/ + Some((Instruction::DEC, AddressingMode::ZeroPageX)), + /*0xD7*/ + None, + /*0xD8*/ + Some((Instruction::CLD, AddressingMode::Implied)), + /*0xD9*/ + Some((Instruction::CMP, AddressingMode::AbsoluteY)), + /*0xDA*/ + None, + /*0xDB*/ + None, + /*0xDC*/ + None, + /*0xDD*/ + Some((Instruction::CMP, AddressingMode::AbsoluteX)), + /*0xDE*/ + Some((Instruction::DEC, AddressingMode::AbsoluteX)), + /*0xDF*/ + None, + /*0xE0*/ + Some((Instruction::CPX, AddressingMode::Immediate)), + /*0xE1*/ + Some((Instruction::SBC, AddressingMode::IndexedIndirectX)), + /*0xE2*/ + None, + /*0xE3*/ + None, + /*0xE4*/ + Some((Instruction::CPX, AddressingMode::ZeroPage)), + /*0xE5*/ + Some((Instruction::SBC, AddressingMode::ZeroPage)), + /*0xE6*/ + Some((Instruction::INC, AddressingMode::ZeroPage)), + /*0xE7*/ + None, + /*0xE8*/ + Some((Instruction::INX, AddressingMode::Implied)), + /*0xE9*/ + Some((Instruction::SBC, AddressingMode::Immediate)), + /*0xEA*/ + Some((Instruction::NOP, AddressingMode::Implied)), + /*0xEB*/ + None, + /*0xEC*/ + Some((Instruction::CPX, AddressingMode::Absolute)), + /*0xED*/ + Some((Instruction::SBC, AddressingMode::Absolute)), + /*0xEE*/ + Some((Instruction::INC, AddressingMode::Absolute)), + /*0xEF*/ + None, + /*0xF0*/ + Some((Instruction::BEQ, AddressingMode::Relative)), + /*0xF1*/ + Some((Instruction::SBC, AddressingMode::IndirectIndexedY)), + /*0xF2*/ + None, + /*0xF3*/ + None, + /*0xF4*/ + None, + /*0xF5*/ + Some((Instruction::SBC, AddressingMode::ZeroPageX)), + /*0xF6*/ + Some((Instruction::INC, AddressingMode::ZeroPageX)), + /*0xF7*/ + None, + /*0xF8*/ + Some((Instruction::SED, AddressingMode::Implied)), + /*0xF9*/ + Some((Instruction::SBC, AddressingMode::AbsoluteY)), + /*0xFA*/ + None, + /*0xFB*/ + None, + /*0xFC*/ + None, + /*0xFD*/ + Some((Instruction::SBC, AddressingMode::AbsoluteX)), + /*0xFE*/ + Some((Instruction::INC, AddressingMode::AbsoluteX)), + /*0xFF*/ + None, +]; diff --git a/src/lib.rs b/src/lib.rs index f79a6e3..fd23caf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -36,6 +36,6 @@ extern crate bitflags; pub mod address; pub mod instruction; -pub mod machine; +pub mod cpu; pub mod memory; pub mod registers;