diff --git a/beneater/src/bin/beneater.rs b/beneater/src/bin/beneater.rs index fca8a86..3e44973 100644 --- a/beneater/src/bin/beneater.rs +++ b/beneater/src/bin/beneater.rs @@ -1,9 +1,9 @@ // This is the GUI for the BenEater PC +use beneater::parts::backplane::Backplane; +use beneater::parts::ben_eater_pc::BenEaterPC; use beneater::parts::cpu_display::CpuDisplay; use macroquad::prelude::*; use macroquad::telemetry::frame; -use beneater::parts::ben_eater_pc::BenEaterPC; -use beneater::parts::backplane::Backplane; #[macroquad::main("Ben Eaters PC")] async fn main() { println!("Taxation is Theft"); @@ -21,7 +21,7 @@ async fn main() { draw_text("Ben Eater", 20.0, 20.0, 30.0, BLACK); dm.render(20.0, 40.0); - // CpuDisplay::render(&computer.cpu, 20.0, 120.0); + // CpuDisplay::render(&computer.cpu, 20.0, 120.0); frame_number += 1; diff --git a/beneater/src/bin/make_rom.rs b/beneater/src/bin/make_rom.rs index 5c2dba6..ba71992 100644 --- a/beneater/src/bin/make_rom.rs +++ b/beneater/src/bin/make_rom.rs @@ -1,5 +1,5 @@ -use std::fs; use core::constants::constants_system::SIZE_32KB; +use std::fs; fn main() { // make the rom data in memory. diff --git a/beneater/src/bin/urn.rs b/beneater/src/bin/urn.rs index d2ed7c8..d0793dc 100644 --- a/beneater/src/bin/urn.rs +++ b/beneater/src/bin/urn.rs @@ -1,20 +1,24 @@ +use beneater::parts::backplane::Backplane; +use core::constants::constants_isa_op::*; +use core::constants::constants_system::*; use std::fs; use std::ops::Index; -use beneater::parts::backplane::Backplane; -use core::constants::constants_system::*; -use core::constants::constants_isa_op::*; fn main() { println!("Taxation is Theft"); let mut backplane = Backplane::new(); + backplane.load_rom(); println!("Backplane is live."); let mut new_program = [0x00u8; SIZE_32KB]; new_program[(OFFSET_RESET_VECTOR - SIZE_32KB as u16) as usize] = 0x00; new_program[(OFFSET_RESET_VECTOR + 1 - SIZE_32KB as u16) as usize] = 0x60; println!("Set offset in rom..."); - println!("VALUE AT OFFSET_RESET_VECTOR = 0x{:02x} ", new_program[(OFFSET_RESET_VECTOR - SIZE_32KB as u16) as usize]); + println!( + "VALUE AT OFFSET_RESET_VECTOR = 0x{:02x} ", + new_program[(OFFSET_RESET_VECTOR - SIZE_32KB as u16) as usize] + ); // println!("{:?}", new_program); backplane.rom.program(&new_program); @@ -22,5 +26,4 @@ fn main() { backplane.memory[0x6000] = ISA_OP_LDA_I; backplane.memory[0x6001] = 0xab; backplane.tick(); - } diff --git a/beneater/src/parts/address_bus.rs b/beneater/src/parts/address_bus.rs index d20bc44..9658d50 100644 --- a/beneater/src/parts/address_bus.rs +++ b/beneater/src/parts/address_bus.rs @@ -1,9 +1,9 @@ pub struct AddressBus { - pub address: u16 + pub address: u16, } impl AddressBus { pub fn new() -> Self { AddressBus { address: 0x0000 } } -} \ No newline at end of file +} diff --git a/beneater/src/parts/backplane.rs b/beneater/src/parts/backplane.rs index 6dc0d82..b4e00a2 100644 --- a/beneater/src/parts/backplane.rs +++ b/beneater/src/parts/backplane.rs @@ -1,15 +1,27 @@ -use core::mos6502cpu::Mos6502Cpu; use crate::parts::mos6522_peripheral::Mos6522Peripheral; use crate::parts::via6522::VIA6522; use core::constants::constants_system::*; +use core::mos6502cpu::Mos6502Cpu; use core::periph::at28c256::At28C256; use core::periph::rom_chip::RomChip; + +/// Backplane +/// +/// A Backplane hold and coordinates the cpu with the +/// rest of the peripherals. +/// +/// This system has +/// -> VIA6522 for peripherals +/// -> 322KB RAM +/// -> 32KB ROM pub struct Backplane { // pub for dev pub cpu: Mos6502Cpu, pub via: VIA6522, - pub memory: Box<[u8; SIZE_64KB]>, - pub rom: At28C256 + pub memory: Box<[u8; SIZE_32KB]>, + pub rom: At28C256, + data_bus: u8, + address_bus: u16 } impl Backplane { @@ -17,8 +29,10 @@ impl Backplane { Backplane { cpu: Mos6502Cpu::default(), via: VIA6522::default(), - memory: Box::new([0x00; SIZE_64KB]), - rom: At28C256::default() + memory: Box::new([0x00; SIZE_32KB]), + rom: At28C256::default(), + data_bus: 0x00, + address_bus: 0x0000 } } @@ -26,48 +40,91 @@ impl Backplane { self.rom.program(to_load); } + + + + pub fn tick(&mut self) { // is the CPU in read or write state - let address = self.cpu.address_bus(); - let data = self.cpu.data_bus(); + self.address_bus = self.cpu.address_bus(); + self.data_bus = self.cpu.data_bus(); let rw = self.cpu.read_signal; println!("- TICK START:"); - println!("| CPU: Address: 0b{address:016b} Data: 0b{data:08b} CPU RW: {rw}"); + println!("| CPU: Address: 0b{:016b} Data: 0b{:08b} CPU RW: {rw}", self.address_bus, self.data_bus); // via state - println!("| VIA 0b{:08b}/0b{:08b}/0b{:08b}/0b{:08b}/", + println!( + "| VIA 0b{:08b}/0b{:08b}/0b{:08b}/0b{:08b}/", self.via.read(VIA6522_ORA), self.via.read(VIA6522_ORA), self.via.read(VIA6522_DDRB), self.via.read(VIA6522_DDRA), ); println!("| LCD"); - match address { - /// VIA - 0x6000..0x6010 => { - if self.cpu.read_signal { - self.cpu.set_data_bus(self.via.read((address - 0x6000) as u8)); - } else { - self.via.write((address - 0x6000) as u8, self.cpu.data_bus()); + + + // if we are reading + if rw { + println!("CPU HAS SET READ FLAG FOR ADDRESS {address:04x} with data 0x{data:02x}"); + match self.address_bus { + 0x0000..=0x3fff => { + // read from ram + + }, + 0x4000..=0x7fff => { + // read from ROM + } - self.via.tick(); - } - /// RAM - 0x0000..=0x3fff => { - if self.cpu.read_signal { - self.cpu.set_data_bus(self.memory[address as usize]); - } else { - self.memory[address as usize] = data; + _ => { + println!("READ OUTSIDE DATA RANGE"); } } - /// ROM - 0x4000..=0x7fff => { - self.rom.read(&(address - 0x4000)); - } - /// The ether. Scarrrrrrrryyyy...... - _ => { - println!("Lost READ:?{} to {:04x}", self.cpu.read_signal, address); + } else { + println!("CPU HAS SET WRITE FLAG FOR ADDRESS 0x{address:04x} with data 0x{data:02x}"); + match self.address_bus { + 0x6000..=0x600f => { + self.via.write((self.address_bus - 0x6000) as u8, self.data_bus); + }, + 0x0000..=0x3fff => { + self.memory[self.address_bus] = self.data_bus; + } + _ => { + println!("ATTEMPT TO WRITE OUTSIDE OF MEMORY"); + } } } + + // + // + // match address { + // /// VIA + // 0x6000..=0x600f => { + // if self.cpu.read_signal { + // self.cpu + // .set_data_bus(self.via.read((address - 0x6000) as u8)); + // } else { + // self.via + // .write((address - 0x6000) as u8, self.cpu.data_bus()); + // } + // self.via.tick(); + // } + // /// RAM + // 0x0000..=0x3fff => { + // if self.cpu.read_signal { + // self.cpu.set_data_bus(self.memory[address as usize]); + // } else { + // self.memory[address as usize] = data; + // } + // } + // /// ROM + // 0x4000..=0x7fff => { + // println!("ROM READ AT {address:04x} / ROM OFFSET {:04x}", address - 0x4000); + // self.rom.read(&(address - 0x4000)); + // } + // /// The ether. Scarrrrrrrryyyy...... + // _ => { + // println!("XXXXLost READ:?{} to {:04x}", self.cpu.read_signal, address); + // } + // } println!("- TICK DONE"); } -} \ No newline at end of file +} diff --git a/beneater/src/parts/ben_eater_pc.rs b/beneater/src/parts/ben_eater_pc.rs index eb27df6..b92dc72 100644 --- a/beneater/src/parts/ben_eater_pc.rs +++ b/beneater/src/parts/ben_eater_pc.rs @@ -1,10 +1,10 @@ +use crate::parts::clock::Clock; +use core::constants::constants_system::*; +use core::mos6502cpu::Mos6502Cpu; use std::fs; use std::fs::File; use std::io::{BufReader, Read}; use std::path::Path; -use crate::parts::clock::Clock; -use core::mos6502cpu::Mos6502Cpu; -use core::constants::constants_system::*; pub struct BenEaterPC { clock: Clock, @@ -19,11 +19,11 @@ impl BenEaterPC { println!("New BENEATERPC"); BenEaterPC { clock: Clock::new(), - cpu: Mos6502Cpu::default() + cpu: Mos6502Cpu::default(), } } - pub fn tick_system(&mut self) { + pub fn tick_system(&mut self) { self.cpu.tick(); if self.cpu.microcode_step == 0 { // tick the clock. diff --git a/beneater/src/parts/clock.rs b/beneater/src/parts/clock.rs index 0c0caef..e76561e 100644 --- a/beneater/src/parts/clock.rs +++ b/beneater/src/parts/clock.rs @@ -1,13 +1,10 @@ pub struct Clock { - ticks: u32 + ticks: u32, } impl Clock { pub fn new() -> Self { - - Clock { - ticks: 0 - } + Clock { ticks: 0 } } pub fn tick(&mut self) { diff --git a/beneater/src/parts/cpu_display.rs b/beneater/src/parts/cpu_display.rs index d02e37b..0e249b8 100644 --- a/beneater/src/parts/cpu_display.rs +++ b/beneater/src/parts/cpu_display.rs @@ -1,7 +1,7 @@ +use core::mos6502cpu::Mos6502Cpu; use macroquad::color::{BLACK, Color}; use macroquad::prelude::*; use macroquad::text::draw_text; -use core::mos6502cpu::Mos6502Cpu; pub struct CpuDisplay {} impl CpuDisplay { @@ -12,11 +12,41 @@ impl CpuDisplay { // ...build the interface Self::draw_square(x_offset, y_offset, x_offset + 300.0, y_offset + 85.0, BLACK); - draw_text(format!("PC: 0x{:04x} / {}", pc, pc).as_str(), x_offset + 5.0, y_offset + 18.0, 15.0, BLACK); - draw_text(format!("A: 0x{:02x} X: 0x{:02x} Y: 0x{:02x}", a, x, y).as_str(), x_offset + 5.0, y_offset + 35.0, 15.0, BLACK); - draw_text(format!("Address: {:016b} | {:04x}", address_bus, address_bus).as_str(), x_offset + 5.0, y_offset + 55.0, 15.0, BLACK); - draw_text(format!("Data: {:08b} | {:02x}", data_bus, data_bus).as_str(), x_offset + 5.0, y_offset + 75.0, 15.0, BLACK); - draw_text(format!("MS: {:02x}", microsteps_remaining).as_str(), x_offset + 5.0, y_offset + 95.0, 15.0, BLACK); + draw_text( + format!("PC: 0x{:04x} / {}", pc, pc).as_str(), + x_offset + 5.0, + y_offset + 18.0, + 15.0, + BLACK, + ); + draw_text( + format!("A: 0x{:02x} X: 0x{:02x} Y: 0x{:02x}", a, x, y).as_str(), + x_offset + 5.0, + y_offset + 35.0, + 15.0, + BLACK, + ); + draw_text( + format!("Address: {:016b} | {:04x}", address_bus, address_bus).as_str(), + x_offset + 5.0, + y_offset + 55.0, + 15.0, + BLACK, + ); + draw_text( + format!("Data: {:08b} | {:02x}", data_bus, data_bus).as_str(), + x_offset + 5.0, + y_offset + 75.0, + 15.0, + BLACK, + ); + draw_text( + format!("MS: {:02x}", microsteps_remaining).as_str(), + x_offset + 5.0, + y_offset + 95.0, + 15.0, + BLACK, + ); } fn draw_square(x1: f32, y1: f32, x2: f32, y2: f32, color: Color) { @@ -26,4 +56,4 @@ impl CpuDisplay { draw_line(x1, y2, x2, y2, 1.0, color); draw_line(x2, y1, x2, y2, 1.0, color); } -} \ No newline at end of file +} diff --git a/beneater/src/parts/data_bus.rs b/beneater/src/parts/data_bus.rs index 2ed9056..0fb32ea 100644 --- a/beneater/src/parts/data_bus.rs +++ b/beneater/src/parts/data_bus.rs @@ -1,9 +1,9 @@ pub struct DataBus { - pub data: u8 + pub data: u8, } impl DataBus { pub fn new() -> Self { DataBus { data: 0x00 } } -} \ No newline at end of file +} diff --git a/beneater/src/parts/display_matrix.rs b/beneater/src/parts/display_matrix.rs index 67e1f69..1b10990 100644 --- a/beneater/src/parts/display_matrix.rs +++ b/beneater/src/parts/display_matrix.rs @@ -1,5 +1,5 @@ -use std::time::{Duration, Instant}; use crate::parts::mos6522_peripheral::Mos6522Peripheral; +use std::time::{Duration, Instant}; #[derive(Debug)] pub struct HD44780 { @@ -46,7 +46,7 @@ impl Mos6522Peripheral for HD44780 { self.write_control_lines( control & 1 << 2 == 0, control & 1 << 1 == 0, - control & 1 == 0 + control & 1 == 0, ); } diff --git a/beneater/src/parts/mod.rs b/beneater/src/parts/mod.rs index d789a31..f7cfbf7 100644 --- a/beneater/src/parts/mod.rs +++ b/beneater/src/parts/mod.rs @@ -1,10 +1,10 @@ -pub mod clock; -pub mod ben_eater_pc; -pub mod via6522; -pub mod display_matrix; pub mod address_bus; -pub mod data_bus; -pub mod cpu_display; -pub mod ram_display; -pub mod mos6522_peripheral; pub mod backplane; +pub mod ben_eater_pc; +pub mod clock; +pub mod cpu_display; +pub mod data_bus; +pub mod display_matrix; +pub mod mos6522_peripheral; +pub mod ram_display; +pub mod via6522; diff --git a/beneater/src/parts/ram_display.rs b/beneater/src/parts/ram_display.rs index 104389e..5220360 100644 --- a/beneater/src/parts/ram_display.rs +++ b/beneater/src/parts/ram_display.rs @@ -4,10 +4,15 @@ pub struct RamDisplay {} impl RamDisplay { pub fn render(ram: &Box<[u8]>, x_offset: f32, y_offset: f32) { - Self::draw_square(x_offset, y_offset, x_offset + 200.0, y_offset + 300.0, BLACK); + Self::draw_square( + x_offset, + y_offset, + x_offset + 200.0, + y_offset + 300.0, + BLACK, + ); draw_text("RAM", x_offset + 5.0, y_offset + 5.0, 15.0, BLACK); - } fn draw_square(x1: f32, y1: f32, x2: f32, y2: f32, color: Color) { @@ -17,4 +22,4 @@ impl RamDisplay { draw_line(x1, y2, x2, y2, 1.0, color); draw_line(x2, y1, x2, y2, 1.0, color); } -} \ No newline at end of file +} diff --git a/beneater/src/parts/via6522.rs b/beneater/src/parts/via6522.rs index 0ae0263..50edf60 100644 --- a/beneater/src/parts/via6522.rs +++ b/beneater/src/parts/via6522.rs @@ -57,7 +57,6 @@ impl VIA6522 { } } - pub fn read(&self, addr: u8) -> u8 { match (addr & 0x0F) { VIA6522_ORB => self.orb, diff --git a/cli/src/bin/decode.rs b/cli/src/bin/decode.rs index fb6e2b6..26f542b 100644 --- a/cli/src/bin/decode.rs +++ b/cli/src/bin/decode.rs @@ -1,5 +1,5 @@ -use core::instruction::Instruction; use core::address_mode::AddressMode; +use core::instruction::Instruction; use core::operand::Operand; use core::operation::Operation; @@ -11,12 +11,13 @@ fn main() { op: Operation::NOP, mode: AddressMode::Implied, operand: Operand::None, - }, &[0xea] - )]; + }, + &[0xea], + )]; for (op, bytes) in instructions { assert_eq!(Instruction::decode(bytes), Some(op)); } - // let instruction = Instruction::decode(&[0xea]); - // println!("NOP Decoded -> {:?}", instruction); + // let instruction = Instruction::decode(&[0xea]); + // println!("NOP Decoded -> {:?}", instruction); } diff --git a/cli/src/bin/ticker.rs b/cli/src/bin/ticker.rs index c3fa74b..7a326f0 100644 --- a/cli/src/bin/ticker.rs +++ b/cli/src/bin/ticker.rs @@ -1,7 +1,5 @@ use core::mos6502cpu::Mos6502Cpu; fn main() { - let x = Mos6502Cpu::default(); - -} \ No newline at end of file +} diff --git a/core/src/address_mode.rs b/core/src/address_mode.rs index f2d8c55..4236823 100644 --- a/core/src/address_mode.rs +++ b/core/src/address_mode.rs @@ -1,4 +1,3 @@ - /// Represents the various addressing modes of the 6502 CPU. #[derive(PartialEq, Debug, Copy, Clone)] pub enum AddressMode { diff --git a/core/src/computers/beneater/beneater.rs b/core/src/computers/beneater/beneater.rs index aaadee8..cc4ea5b 100644 --- a/core/src/computers/beneater/beneater.rs +++ b/core/src/computers/beneater/beneater.rs @@ -1,9 +1,5 @@ - /// BenEater computer represents the 'Ben Eater' 6502 breadboard computer. /// This was built along watching the video series where Ben builds a /// 6502 on a breadboard and explains each step. /// -pub struct BenEater { - -} - +pub struct BenEater {} diff --git a/core/src/computers/mod.rs b/core/src/computers/mod.rs index ff5f773..0188360 100644 --- a/core/src/computers/mod.rs +++ b/core/src/computers/mod.rs @@ -1,2 +1 @@ pub mod beneater; - diff --git a/core/src/constants/constants_isa_op.rs b/core/src/constants/constants_isa_op.rs index 1324ca5..2b35a0b 100644 --- a/core/src/constants/constants_isa_op.rs +++ b/core/src/constants/constants_isa_op.rs @@ -107,7 +107,6 @@ pub const ISA_OP_LDY_ZP: u8 = 0xa4; pub const ISA_OP_LDY_ZPX: u8 = 0xb4; pub const ISA_OP_LDY_ABS: u8 = 0xac; pub const ISA_OP_LDY_ABSX: u8 = 0xbc; - pub const ISA_OP_LSR_A: u8 = 0x4a; pub const ISA_OP_LSR_ZP: u8 = 0x46; pub const ISA_OP_LSR_ZPX: u8 = 0x56; @@ -167,4 +166,4 @@ pub const ISA_OP_TAY: u8 = 0xa8; pub const ISA_OP_TSX: u8 = 0xba; pub const ISA_OP_TXA: u8 = 0x8a; pub const ISA_OP_TXS: u8 = 0x9a; -pub const ISA_OP_TYA: u8 = 0x98; \ No newline at end of file +pub const ISA_OP_TYA: u8 = 0x98; diff --git a/core/src/constants/constants_isa_stub.rs b/core/src/constants/constants_isa_stub.rs index d5fede4..17a7f59 100644 --- a/core/src/constants/constants_isa_stub.rs +++ b/core/src/constants/constants_isa_stub.rs @@ -54,4 +54,4 @@ pub const ISA_STUB_TAY: &str = "TAY"; pub const ISA_STUB_TSX: &str = "TSX"; pub const ISA_STUB_TXA: &str = "TXA"; pub const ISA_STUB_TXS: &str = "TXS"; -pub const ISA_STUB_TYA: &str = "TYA"; \ No newline at end of file +pub const ISA_STUB_TYA: &str = "TYA"; diff --git a/core/src/constants/constants_system.rs b/core/src/constants/constants_system.rs index c1406b9..62c24f8 100644 --- a/core/src/constants/constants_system.rs +++ b/core/src/constants/constants_system.rs @@ -5,7 +5,6 @@ pub const SIZE_64KB: usize = SIZE_1KB * 64; pub const OFFSET_RESET_VECTOR: u16 = 0xfffc; pub const OFFSET_INT_VECTOR: u16 = 0xfffe; - pub const VIA6522_ORB: u8 = 0; pub const VIA6522_ORA: u8 = 1; pub const VIA6522_DDRB: u8 = 2; diff --git a/core/src/constants/mod.rs b/core/src/constants/mod.rs index dd5953c..9443730 100644 --- a/core/src/constants/mod.rs +++ b/core/src/constants/mod.rs @@ -1,3 +1,3 @@ -pub mod constants_isa_stub; pub mod constants_isa_op; +pub mod constants_isa_stub; pub mod constants_system; diff --git a/core/src/instruction.rs b/core/src/instruction.rs index 978d1be..6ec93f2 100644 --- a/core/src/instruction.rs +++ b/core/src/instruction.rs @@ -1,4 +1,3 @@ -use log::trace; use crate::address_mode::AddressMode; use crate::address_mode::AddressMode::*; use crate::address_mode::AddressMode::*; @@ -7,6 +6,7 @@ use crate::op_info::OpInfo; use crate::operand::Operand; use crate::operation::Operation; use crate::operation::Operation::*; +use log::trace; #[derive(Debug, PartialEq)] pub struct Instruction { @@ -23,216 +23,1273 @@ impl Instruction { } pub fn decode(bytes: &[u8]) -> Option { - let info = Instruction::opinfo(bytes)?; + let info = Instruction::opinfo(bytes)?; let operand = match info.length { - 2 => Operand::Byte(*bytes.get(1)?), - 3 => Operand::Word(u16::from_le_bytes([*bytes.get(1)?, *bytes.get(2)?])), - _ => Operand::None, - }; + 2 => Operand::Byte(*bytes.get(1)?), + 3 => Operand::Word(u16::from_le_bytes([*bytes.get(1)?, *bytes.get(2)?])), + _ => Operand::None, + }; - let instruction = Instruction { - op: info.operation, - mode: info.mode, - operand, - }; + let instruction = Instruction { + op: info.operation, + mode: info.mode, + operand, + }; - trace!("RETURNING: {:?}", instruction); - Some(instruction) + trace!("RETURNING: {:?}", instruction); + Some(instruction) } } #[cfg(test)] mod test { + use super::*; use crate::address_mode::AddressMode::*; use crate::instruction::Instruction; use crate::operation::Operation::*; - use super::*; #[test] fn decode_instruction() { let params = vec![ // ADC - (vec![0x69, 0xab], Instruction { op: ADC, mode: Immediate, operand: Operand::Byte(0xab) }), - (vec![0x65, 0xab], Instruction { op: ADC, mode: ZeroPage, operand: Operand::Byte(0xab) }), - (vec![0x75, 0xab], Instruction { op: ADC, mode: ZeroPageX, operand: Operand::Byte(0xab) }), - (vec![0x6d, 0xcd, 0xab], Instruction { op: ADC, mode: Absolute, operand: Operand::Word(0xabcd) }), - (vec![0x7d, 0xcd, 0xab], Instruction { op: ADC, mode: AbsoluteX, operand: Operand::Word(0xabcd) }), - (vec![0x79, 0xcd, 0xab], Instruction { op: ADC, mode: AbsoluteY, operand: Operand::Word(0xabcd) }), - (vec![0x61, 0xab], Instruction { op: ADC, mode: IndirectX, operand: Operand::Byte(0xab) }), - (vec![0x71, 0xab], Instruction { op: ADC, mode: IndirectY, operand: Operand::Byte(0xab) }), + ( + vec![0x69, 0xab], + Instruction { + op: ADC, + mode: Immediate, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0x65, 0xab], + Instruction { + op: ADC, + mode: ZeroPage, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0x75, 0xab], + Instruction { + op: ADC, + mode: ZeroPageX, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0x6d, 0xcd, 0xab], + Instruction { + op: ADC, + mode: Absolute, + operand: Operand::Word(0xabcd), + }, + ), + ( + vec![0x7d, 0xcd, 0xab], + Instruction { + op: ADC, + mode: AbsoluteX, + operand: Operand::Word(0xabcd), + }, + ), + ( + vec![0x79, 0xcd, 0xab], + Instruction { + op: ADC, + mode: AbsoluteY, + operand: Operand::Word(0xabcd), + }, + ), + ( + vec![0x61, 0xab], + Instruction { + op: ADC, + mode: IndirectX, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0x71, 0xab], + Instruction { + op: ADC, + mode: IndirectY, + operand: Operand::Byte(0xab), + }, + ), // AND - (vec![0x29, 0xab], Instruction { op: AND, mode: Immediate, operand: Operand::Byte(0xab) }), - (vec![0x25, 0xab], Instruction { op: AND, mode: ZeroPage, operand: Operand::Byte(0xab) }), - (vec![0x35, 0xab], Instruction { op: AND, mode: ZeroPageX, operand: Operand::Byte(0xab) }), - (vec![0x2d, 0xcd, 0xab], Instruction { op: AND, mode: Absolute, operand: Operand::Word(0xabcd) }), - (vec![0x3d, 0xcd, 0xab], Instruction { op: AND, mode: AbsoluteX, operand: Operand::Word(0xabcd) }), - (vec![0x39, 0xcd, 0xab], Instruction { op: AND, mode: AbsoluteY, operand: Operand::Word(0xabcd) }), - (vec![0x21, 0xab], Instruction { op: AND, mode: IndirectX, operand: Operand::Byte(0xab) }), - (vec![0x31, 0xab], Instruction { op: AND, mode: IndirectY, operand: Operand::Byte(0xab) }), + ( + vec![0x29, 0xab], + Instruction { + op: AND, + mode: Immediate, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0x25, 0xab], + Instruction { + op: AND, + mode: ZeroPage, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0x35, 0xab], + Instruction { + op: AND, + mode: ZeroPageX, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0x2d, 0xcd, 0xab], + Instruction { + op: AND, + mode: Absolute, + operand: Operand::Word(0xabcd), + }, + ), + ( + vec![0x3d, 0xcd, 0xab], + Instruction { + op: AND, + mode: AbsoluteX, + operand: Operand::Word(0xabcd), + }, + ), + ( + vec![0x39, 0xcd, 0xab], + Instruction { + op: AND, + mode: AbsoluteY, + operand: Operand::Word(0xabcd), + }, + ), + ( + vec![0x21, 0xab], + Instruction { + op: AND, + mode: IndirectX, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0x31, 0xab], + Instruction { + op: AND, + mode: IndirectY, + operand: Operand::Byte(0xab), + }, + ), // ASL - (vec![0x0a], Instruction { op: ASL, mode: Accumulator, operand: Operand::None }), - (vec![0x06, 0xab], Instruction { op: ASL, mode: ZeroPage, operand: Operand::Byte(0xab) }), - (vec![0x16, 0xab], Instruction { op: ASL, mode: ZeroPageX, operand: Operand::Byte(0xab) }), - (vec![0x0e, 0xcd, 0xab], Instruction { op: ASL, mode: Absolute, operand: Operand::Word(0xabcd) }), - (vec![0x1e, 0xcd, 0xab], Instruction { op: ASL, mode: AbsoluteX, operand: Operand::Word(0xabcd) }), + ( + vec![0x0a], + Instruction { + op: ASL, + mode: Accumulator, + operand: Operand::None, + }, + ), + ( + vec![0x06, 0xab], + Instruction { + op: ASL, + mode: ZeroPage, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0x16, 0xab], + Instruction { + op: ASL, + mode: ZeroPageX, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0x0e, 0xcd, 0xab], + Instruction { + op: ASL, + mode: Absolute, + operand: Operand::Word(0xabcd), + }, + ), + ( + vec![0x1e, 0xcd, 0xab], + Instruction { + op: ASL, + mode: AbsoluteX, + operand: Operand::Word(0xabcd), + }, + ), // BIT - (vec![0x24, 0xab], Instruction { op: BIT, mode: ZeroPage, operand: Operand::Byte(0xab) }), - (vec![0x2c, 0xcd, 0xab], Instruction { op: BIT, mode: Absolute, operand: Operand::Word(0xabcd) }), + ( + vec![0x24, 0xab], + Instruction { + op: BIT, + mode: ZeroPage, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0x2c, 0xcd, 0xab], + Instruction { + op: BIT, + mode: Absolute, + operand: Operand::Word(0xabcd), + }, + ), // BCC, BCS, BEQ, BMI, BNE, BPL, BVC, BVS - (vec![0x10, 0xab], Instruction { op: BPL, mode: Implied, operand: Operand::Byte(0xab) }), - (vec![0x30, 0xab], Instruction { op: BMI, mode: Implied, operand: Operand::Byte(0xab) }), - (vec![0x50, 0xab], Instruction { op: BVC, mode: Implied, operand: Operand::Byte(0xab) }), - (vec![0x70, 0xab], Instruction { op: BVS, mode: Implied, operand: Operand::Byte(0xab) }), - (vec![0x90, 0xab], Instruction { op: BCC, mode: Implied, operand: Operand::Byte(0xab) }), - (vec![0xb0, 0xab], Instruction { op: BCS, mode: Implied, operand: Operand::Byte(0xab) }), - (vec![0xd0, 0xab], Instruction { op: BNE, mode: Implied, operand: Operand::Byte(0xab) }), - (vec![0xf0, 0xab], Instruction { op: BEQ, mode: Implied, operand: Operand::Byte(0xab) }), + ( + vec![0x10, 0xab], + Instruction { + op: BPL, + mode: Implied, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0x30, 0xab], + Instruction { + op: BMI, + mode: Implied, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0x50, 0xab], + Instruction { + op: BVC, + mode: Implied, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0x70, 0xab], + Instruction { + op: BVS, + mode: Implied, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0x90, 0xab], + Instruction { + op: BCC, + mode: Implied, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0xb0, 0xab], + Instruction { + op: BCS, + mode: Implied, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0xd0, 0xab], + Instruction { + op: BNE, + mode: Implied, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0xf0, 0xab], + Instruction { + op: BEQ, + mode: Implied, + operand: Operand::Byte(0xab), + }, + ), // BRK - (vec![0x00], Instruction { op: BRK, mode: Implied, operand: Operand::None }), + ( + vec![0x00], + Instruction { + op: BRK, + mode: Implied, + operand: Operand::None, + }, + ), // CLC, CLD, CLI, CLV - (vec![0x18], Instruction { op: CLC, mode: Implied, operand: Operand::None }), - (vec![0xd8], Instruction { op: CLD, mode: Implied, operand: Operand::None }), - (vec![0x58], Instruction { op: CLI, mode: Implied, operand: Operand::None }), - (vec![0xb8], Instruction { op: CLV, mode: Implied, operand: Operand::None }), + ( + vec![0x18], + Instruction { + op: CLC, + mode: Implied, + operand: Operand::None, + }, + ), + ( + vec![0xd8], + Instruction { + op: CLD, + mode: Implied, + operand: Operand::None, + }, + ), + ( + vec![0x58], + Instruction { + op: CLI, + mode: Implied, + operand: Operand::None, + }, + ), + ( + vec![0xb8], + Instruction { + op: CLV, + mode: Implied, + operand: Operand::None, + }, + ), // CMP - (vec![0xc9, 0xab], Instruction { op: CMP, mode: Immediate, operand: Operand::Byte(0xab) }), - (vec![0xc5, 0xab], Instruction { op: CMP, mode: ZeroPage, operand: Operand::Byte(0xab) }), - (vec![0xd5, 0xab], Instruction { op: CMP, mode: ZeroPageX, operand: Operand::Byte(0xab) }), - (vec![0xcd, 0xcd, 0xab], Instruction { op: CMP, mode: Absolute, operand: Operand::Word(0xabcd) }), - (vec![0xdd, 0xcd, 0xab], Instruction { op: CMP, mode: AbsoluteX, operand: Operand::Word(0xabcd) }), - (vec![0xd9, 0xcd, 0xab], Instruction { op: CMP, mode: AbsoluteY, operand: Operand::Word(0xabcd) }), - (vec![0xc1, 0xab], Instruction { op: CMP, mode: IndirectX, operand: Operand::Byte(0xab) }), - (vec![0xd1, 0xab], Instruction { op: CMP, mode: IndirectY, operand: Operand::Byte(0xab) }), + ( + vec![0xc9, 0xab], + Instruction { + op: CMP, + mode: Immediate, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0xc5, 0xab], + Instruction { + op: CMP, + mode: ZeroPage, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0xd5, 0xab], + Instruction { + op: CMP, + mode: ZeroPageX, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0xcd, 0xcd, 0xab], + Instruction { + op: CMP, + mode: Absolute, + operand: Operand::Word(0xabcd), + }, + ), + ( + vec![0xdd, 0xcd, 0xab], + Instruction { + op: CMP, + mode: AbsoluteX, + operand: Operand::Word(0xabcd), + }, + ), + ( + vec![0xd9, 0xcd, 0xab], + Instruction { + op: CMP, + mode: AbsoluteY, + operand: Operand::Word(0xabcd), + }, + ), + ( + vec![0xc1, 0xab], + Instruction { + op: CMP, + mode: IndirectX, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0xd1, 0xab], + Instruction { + op: CMP, + mode: IndirectY, + operand: Operand::Byte(0xab), + }, + ), // CPX - (vec![0xe0, 0xab], Instruction { op: CPX, mode: Immediate, operand: Operand::Byte(0xab) }), - (vec![0xe4, 0xab], Instruction { op: CPX, mode: ZeroPage, operand: Operand::Byte(0xab) }), - (vec![0xec, 0xcd, 0xab], Instruction { op: CPX, mode: Absolute, operand: Operand::Word(0xabcd) }), + ( + vec![0xe0, 0xab], + Instruction { + op: CPX, + mode: Immediate, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0xe4, 0xab], + Instruction { + op: CPX, + mode: ZeroPage, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0xec, 0xcd, 0xab], + Instruction { + op: CPX, + mode: Absolute, + operand: Operand::Word(0xabcd), + }, + ), // CPY - (vec![0xc0, 0xab], Instruction { op: CPY, mode: Immediate, operand: Operand::Byte(0xab) }), - (vec![0xc4, 0xab], Instruction { op: CPY, mode: ZeroPage, operand: Operand::Byte(0xab) }), - (vec![0xcc, 0xcd, 0xab], Instruction { op: CPY, mode: Absolute, operand: Operand::Word(0xabcd) }), + ( + vec![0xc0, 0xab], + Instruction { + op: CPY, + mode: Immediate, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0xc4, 0xab], + Instruction { + op: CPY, + mode: ZeroPage, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0xcc, 0xcd, 0xab], + Instruction { + op: CPY, + mode: Absolute, + operand: Operand::Word(0xabcd), + }, + ), // DEC, DEX, DEY - (vec![0xc6, 0xab], Instruction { op: DEC, mode: ZeroPage, operand: Operand::Byte(0xab) }), - (vec![0xd6, 0xab], Instruction { op: DEC, mode: ZeroPageX, operand: Operand::Byte(0xab) }), - (vec![0xce, 0xcd, 0xab], Instruction { op: DEC, mode: Absolute, operand: Operand::Word(0xabcd) }), - (vec![0xde, 0xcd, 0xab], Instruction { op: DEC, mode: AbsoluteX, operand: Operand::Word(0xabcd) }), - (vec![0xca], Instruction { op: DEX, mode: Implied, operand: Operand::None }), - (vec![0x88], Instruction { op: DEY, mode: Implied, operand: Operand::None }), + ( + vec![0xc6, 0xab], + Instruction { + op: DEC, + mode: ZeroPage, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0xd6, 0xab], + Instruction { + op: DEC, + mode: ZeroPageX, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0xce, 0xcd, 0xab], + Instruction { + op: DEC, + mode: Absolute, + operand: Operand::Word(0xabcd), + }, + ), + ( + vec![0xde, 0xcd, 0xab], + Instruction { + op: DEC, + mode: AbsoluteX, + operand: Operand::Word(0xabcd), + }, + ), + ( + vec![0xca], + Instruction { + op: DEX, + mode: Implied, + operand: Operand::None, + }, + ), + ( + vec![0x88], + Instruction { + op: DEY, + mode: Implied, + operand: Operand::None, + }, + ), // EOR - (vec![0x49, 0xab], Instruction { op: EOR, mode: Immediate, operand: Operand::Byte(0xab) }), - (vec![0x45, 0xab], Instruction { op: EOR, mode: ZeroPage, operand: Operand::Byte(0xab) }), - (vec![0x55, 0xab], Instruction { op: EOR, mode: ZeroPageX, operand: Operand::Byte(0xab) }), - (vec![0x4d, 0xcd, 0xab], Instruction { op: EOR, mode: Absolute, operand: Operand::Word(0xabcd) }), - (vec![0x5d, 0xcd, 0xab], Instruction { op: EOR, mode: AbsoluteX, operand: Operand::Word(0xabcd) }), - (vec![0x59, 0xcd, 0xab], Instruction { op: EOR, mode: AbsoluteY, operand: Operand::Word(0xabcd) }), - (vec![0x41, 0xab], Instruction { op: EOR, mode: IndirectX, operand: Operand::Byte(0xab) }), - (vec![0x51, 0xab], Instruction { op: EOR, mode: IndirectY, operand: Operand::Byte(0xab) }), + ( + vec![0x49, 0xab], + Instruction { + op: EOR, + mode: Immediate, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0x45, 0xab], + Instruction { + op: EOR, + mode: ZeroPage, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0x55, 0xab], + Instruction { + op: EOR, + mode: ZeroPageX, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0x4d, 0xcd, 0xab], + Instruction { + op: EOR, + mode: Absolute, + operand: Operand::Word(0xabcd), + }, + ), + ( + vec![0x5d, 0xcd, 0xab], + Instruction { + op: EOR, + mode: AbsoluteX, + operand: Operand::Word(0xabcd), + }, + ), + ( + vec![0x59, 0xcd, 0xab], + Instruction { + op: EOR, + mode: AbsoluteY, + operand: Operand::Word(0xabcd), + }, + ), + ( + vec![0x41, 0xab], + Instruction { + op: EOR, + mode: IndirectX, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0x51, 0xab], + Instruction { + op: EOR, + mode: IndirectY, + operand: Operand::Byte(0xab), + }, + ), // INC, INX, INY - (vec![0xe6, 0xab], Instruction { op: INC, mode: ZeroPage, operand: Operand::Byte(0xab) }), - (vec![0xf6, 0xab], Instruction { op: INC, mode: ZeroPageX, operand: Operand::Byte(0xab) }), - (vec![0xee, 0xcd, 0xab], Instruction { op: INC, mode: Absolute, operand: Operand::Word(0xabcd) }), - (vec![0xfe, 0xcd, 0xab], Instruction { op: INC, mode: AbsoluteX, operand: Operand::Word(0xabcd) }), - (vec![0xe8], Instruction { op: INX, mode: Implied, operand: Operand::None }), - (vec![0xc8], Instruction { op: INY, mode: Implied, operand: Operand::None }), + ( + vec![0xe6, 0xab], + Instruction { + op: INC, + mode: ZeroPage, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0xf6, 0xab], + Instruction { + op: INC, + mode: ZeroPageX, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0xee, 0xcd, 0xab], + Instruction { + op: INC, + mode: Absolute, + operand: Operand::Word(0xabcd), + }, + ), + ( + vec![0xfe, 0xcd, 0xab], + Instruction { + op: INC, + mode: AbsoluteX, + operand: Operand::Word(0xabcd), + }, + ), + ( + vec![0xe8], + Instruction { + op: INX, + mode: Implied, + operand: Operand::None, + }, + ), + ( + vec![0xc8], + Instruction { + op: INY, + mode: Implied, + operand: Operand::None, + }, + ), // JMP, JSR - (vec![0x4c, 0xcd, 0xab], Instruction { op: JMP, mode: Absolute, operand: Operand::Word(0xabcd) }), - (vec![0x6c, 0xcd, 0xab], Instruction { op: JMP, mode: Indirect, operand: Operand::Word(0xabcd) }), - (vec![0x20], Instruction { op: JSR, mode: Implied, operand: Operand::None }), + ( + vec![0x4c, 0xcd, 0xab], + Instruction { + op: JMP, + mode: Absolute, + operand: Operand::Word(0xabcd), + }, + ), + ( + vec![0x6c, 0xcd, 0xab], + Instruction { + op: JMP, + mode: Indirect, + operand: Operand::Word(0xabcd), + }, + ), + ( + vec![0x20], + Instruction { + op: JSR, + mode: Implied, + operand: Operand::None, + }, + ), // LDA - (vec![0xa9, 0xab], Instruction { op: LDA, mode: Immediate, operand: Operand::Byte(0xab) }), - (vec![0xa5, 0xab], Instruction { op: LDA, mode: ZeroPage, operand: Operand::Byte(0xab) }), - (vec![0xb5, 0xab], Instruction { op: LDA, mode: ZeroPageX, operand: Operand::Byte(0xab) }), - (vec![0xad, 0xcd, 0xab], Instruction { op: LDA, mode: Absolute, operand: Operand::Word(0xabcd) }), - (vec![0xbd, 0xcd, 0xab], Instruction { op: LDA, mode: AbsoluteX, operand: Operand::Word(0xabcd) }), - (vec![0xb9, 0xcd, 0xab], Instruction { op: LDA, mode: AbsoluteY, operand: Operand::Word(0xabcd) }), - (vec![0xa1, 0xab], Instruction { op: LDA, mode: IndirectX, operand: Operand::Byte(0xab) }), - (vec![0xb1, 0xab], Instruction { op: LDA, mode: IndirectY, operand: Operand::Byte(0xab) }), + ( + vec![0xa9, 0xab], + Instruction { + op: LDA, + mode: Immediate, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0xa5, 0xab], + Instruction { + op: LDA, + mode: ZeroPage, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0xb5, 0xab], + Instruction { + op: LDA, + mode: ZeroPageX, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0xad, 0xcd, 0xab], + Instruction { + op: LDA, + mode: Absolute, + operand: Operand::Word(0xabcd), + }, + ), + ( + vec![0xbd, 0xcd, 0xab], + Instruction { + op: LDA, + mode: AbsoluteX, + operand: Operand::Word(0xabcd), + }, + ), + ( + vec![0xb9, 0xcd, 0xab], + Instruction { + op: LDA, + mode: AbsoluteY, + operand: Operand::Word(0xabcd), + }, + ), + ( + vec![0xa1, 0xab], + Instruction { + op: LDA, + mode: IndirectX, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0xb1, 0xab], + Instruction { + op: LDA, + mode: IndirectY, + operand: Operand::Byte(0xab), + }, + ), // LDX - (vec![0xa2, 0xab], Instruction { op: LDX, mode: Immediate, operand: Operand::Byte(0xab) }), - (vec![0xa6, 0xab], Instruction { op: LDX, mode: ZeroPage, operand: Operand::Byte(0xab) }), - (vec![0xb6, 0xab], Instruction { op: LDX, mode: ZeroPageY, operand: Operand::Byte(0xab) }), - (vec![0xae, 0xcd, 0xab], Instruction { op: LDX, mode: Absolute, operand: Operand::Word(0xabcd) }), - (vec![0xbe, 0xcd, 0xab], Instruction { op: LDX, mode: AbsoluteY, operand: Operand::Word(0xabcd) }), + ( + vec![0xa2, 0xab], + Instruction { + op: LDX, + mode: Immediate, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0xa6, 0xab], + Instruction { + op: LDX, + mode: ZeroPage, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0xb6, 0xab], + Instruction { + op: LDX, + mode: ZeroPageY, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0xae, 0xcd, 0xab], + Instruction { + op: LDX, + mode: Absolute, + operand: Operand::Word(0xabcd), + }, + ), + ( + vec![0xbe, 0xcd, 0xab], + Instruction { + op: LDX, + mode: AbsoluteY, + operand: Operand::Word(0xabcd), + }, + ), // LDY - (vec![0xa0, 0xab], Instruction { op: LDY, mode: Immediate, operand: Operand::Byte(0xab) }), - (vec![0xa4, 0xab], Instruction { op: LDY, mode: ZeroPage, operand: Operand::Byte(0xab) }), - (vec![0xb4, 0xab], Instruction { op: LDY, mode: ZeroPageX, operand: Operand::Byte(0xab) }), - (vec![0xac, 0xcd, 0xab], Instruction { op: LDY, mode: Absolute, operand: Operand::Word(0xabcd) }), - (vec![0xbc, 0xcd, 0xab], Instruction { op: LDY, mode: AbsoluteX, operand: Operand::Word(0xabcd) }), + ( + vec![0xa0, 0xab], + Instruction { + op: LDY, + mode: Immediate, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0xa4, 0xab], + Instruction { + op: LDY, + mode: ZeroPage, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0xb4, 0xab], + Instruction { + op: LDY, + mode: ZeroPageX, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0xac, 0xcd, 0xab], + Instruction { + op: LDY, + mode: Absolute, + operand: Operand::Word(0xabcd), + }, + ), + ( + vec![0xbc, 0xcd, 0xab], + Instruction { + op: LDY, + mode: AbsoluteX, + operand: Operand::Word(0xabcd), + }, + ), // LSR - (vec![0x4a], Instruction { op: LSR, mode: Accumulator, operand: Operand::None }), - (vec![0x46, 0xab], Instruction { op: LSR, mode: ZeroPage, operand: Operand::Byte(0xab) }), - (vec![0x56, 0xab], Instruction { op: LSR, mode: ZeroPageX, operand: Operand::Byte(0xab) }), - (vec![0x4e, 0xcd, 0xab], Instruction { op: LSR, mode: Absolute, operand: Operand::Word(0xabcd) }), - (vec![0x5e, 0xcd, 0xab], Instruction { op: LSR, mode: AbsoluteX, operand: Operand::Word(0xabcd) }), + ( + vec![0x4a], + Instruction { + op: LSR, + mode: Accumulator, + operand: Operand::None, + }, + ), + ( + vec![0x46, 0xab], + Instruction { + op: LSR, + mode: ZeroPage, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0x56, 0xab], + Instruction { + op: LSR, + mode: ZeroPageX, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0x4e, 0xcd, 0xab], + Instruction { + op: LSR, + mode: Absolute, + operand: Operand::Word(0xabcd), + }, + ), + ( + vec![0x5e, 0xcd, 0xab], + Instruction { + op: LSR, + mode: AbsoluteX, + operand: Operand::Word(0xabcd), + }, + ), // NOP - (vec![0xea], Instruction { op: NOP, mode: Implied, operand: Operand::None }), + ( + vec![0xea], + Instruction { + op: NOP, + mode: Implied, + operand: Operand::None, + }, + ), // ORA - (vec![0x09, 0xab], Instruction { op: ORA, mode: Immediate, operand: Operand::Byte(0xab) }), - (vec![0x05, 0xab], Instruction { op: ORA, mode: ZeroPage, operand: Operand::Byte(0xab) }), - (vec![0x15, 0xab], Instruction { op: ORA, mode: ZeroPageX, operand: Operand::Byte(0xab) }), - (vec![0x0d, 0xcd, 0xab], Instruction { op: ORA, mode: Absolute, operand: Operand::Word(0xabcd) }), - (vec![0x1d, 0xcd, 0xab], Instruction { op: ORA, mode: AbsoluteX, operand: Operand::Word(0xabcd) }), - (vec![0x19, 0xcd, 0xab], Instruction { op: ORA, mode: AbsoluteY, operand: Operand::Word(0xabcd) }), - (vec![0x01, 0xab], Instruction { op: ORA, mode: IndirectX, operand: Operand::Byte(0xab) }), - (vec![0x11, 0xab], Instruction { op: ORA, mode: IndirectY, operand: Operand::Byte(0xab) }), + ( + vec![0x09, 0xab], + Instruction { + op: ORA, + mode: Immediate, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0x05, 0xab], + Instruction { + op: ORA, + mode: ZeroPage, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0x15, 0xab], + Instruction { + op: ORA, + mode: ZeroPageX, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0x0d, 0xcd, 0xab], + Instruction { + op: ORA, + mode: Absolute, + operand: Operand::Word(0xabcd), + }, + ), + ( + vec![0x1d, 0xcd, 0xab], + Instruction { + op: ORA, + mode: AbsoluteX, + operand: Operand::Word(0xabcd), + }, + ), + ( + vec![0x19, 0xcd, 0xab], + Instruction { + op: ORA, + mode: AbsoluteY, + operand: Operand::Word(0xabcd), + }, + ), + ( + vec![0x01, 0xab], + Instruction { + op: ORA, + mode: IndirectX, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0x11, 0xab], + Instruction { + op: ORA, + mode: IndirectY, + operand: Operand::Byte(0xab), + }, + ), // PHA, PHP, PLA, PLP - (vec![0x48], Instruction { op: PHA, mode: Implied, operand: Operand::None }), - (vec![0x08], Instruction { op: PHP, mode: Implied, operand: Operand::None }), - (vec![0x68], Instruction { op: PLA, mode: Implied, operand: Operand::None }), - (vec![0x28], Instruction { op: PLP, mode: Implied, operand: Operand::None }), + ( + vec![0x48], + Instruction { + op: PHA, + mode: Implied, + operand: Operand::None, + }, + ), + ( + vec![0x08], + Instruction { + op: PHP, + mode: Implied, + operand: Operand::None, + }, + ), + ( + vec![0x68], + Instruction { + op: PLA, + mode: Implied, + operand: Operand::None, + }, + ), + ( + vec![0x28], + Instruction { + op: PLP, + mode: Implied, + operand: Operand::None, + }, + ), // ROL - (vec![0x2a], Instruction { op: ROL, mode: Accumulator, operand: Operand::None }), - (vec![0x26, 0xab], Instruction { op: ROL, mode: ZeroPage, operand: Operand::Byte(0xab) }), - (vec![0x36, 0xab], Instruction { op: ROL, mode: ZeroPageX, operand: Operand::Byte(0xab) }), - (vec![0x2e, 0xcd, 0xab], Instruction { op: ROL, mode: Absolute, operand: Operand::Word(0xabcd) }), - (vec![0x3e, 0xcd, 0xab], Instruction { op: ROL, mode: AbsoluteX, operand: Operand::Word(0xabcd) }), + ( + vec![0x2a], + Instruction { + op: ROL, + mode: Accumulator, + operand: Operand::None, + }, + ), + ( + vec![0x26, 0xab], + Instruction { + op: ROL, + mode: ZeroPage, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0x36, 0xab], + Instruction { + op: ROL, + mode: ZeroPageX, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0x2e, 0xcd, 0xab], + Instruction { + op: ROL, + mode: Absolute, + operand: Operand::Word(0xabcd), + }, + ), + ( + vec![0x3e, 0xcd, 0xab], + Instruction { + op: ROL, + mode: AbsoluteX, + operand: Operand::Word(0xabcd), + }, + ), // ROR - (vec![0x6a], Instruction { op: ROR, mode: Accumulator, operand: Operand::None }), - (vec![0x66, 0xab], Instruction { op: ROR, mode: ZeroPage, operand: Operand::Byte(0xab) }), - (vec![0x76, 0xab], Instruction { op: ROR, mode: ZeroPageX, operand: Operand::Byte(0xab) }), - (vec![0x6e, 0xcd, 0xab], Instruction { op: ROR, mode: Absolute, operand: Operand::Word(0xabcd) }), - (vec![0x7e, 0xcd, 0xab], Instruction { op: ROR, mode: AbsoluteX, operand: Operand::Word(0xabcd) }), + ( + vec![0x6a], + Instruction { + op: ROR, + mode: Accumulator, + operand: Operand::None, + }, + ), + ( + vec![0x66, 0xab], + Instruction { + op: ROR, + mode: ZeroPage, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0x76, 0xab], + Instruction { + op: ROR, + mode: ZeroPageX, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0x6e, 0xcd, 0xab], + Instruction { + op: ROR, + mode: Absolute, + operand: Operand::Word(0xabcd), + }, + ), + ( + vec![0x7e, 0xcd, 0xab], + Instruction { + op: ROR, + mode: AbsoluteX, + operand: Operand::Word(0xabcd), + }, + ), // RTI, RTS - (vec![0x40], Instruction { op: RTI, mode: Implied, operand: Operand::None }), - (vec![0x60], Instruction { op: RTS, mode: Implied, operand: Operand::None }), + ( + vec![0x40], + Instruction { + op: RTI, + mode: Implied, + operand: Operand::None, + }, + ), + ( + vec![0x60], + Instruction { + op: RTS, + mode: Implied, + operand: Operand::None, + }, + ), // SBC - (vec![0xe9, 0xab], Instruction { op: SBC, mode: Immediate, operand: Operand::Byte(0xab) }), - (vec![0xe5, 0xab], Instruction { op: SBC, mode: ZeroPage, operand: Operand::Byte(0xab) }), - (vec![0xf5, 0xab], Instruction { op: SBC, mode: ZeroPageX, operand: Operand::Byte(0xab) }), - (vec![0xed, 0xcd, 0xab], Instruction { op: SBC, mode: Absolute, operand: Operand::Word(0xabcd) }), - (vec![0xfd, 0xcd, 0xab], Instruction { op: SBC, mode: AbsoluteX, operand: Operand::Word(0xabcd) }), - (vec![0xf9, 0xcd, 0xab], Instruction { op: SBC, mode: AbsoluteY, operand: Operand::Word(0xabcd) }), - (vec![0xe1, 0xab], Instruction { op: SBC, mode: IndirectX, operand: Operand::Byte(0xab) }), - (vec![0xf1, 0xab], Instruction { op: SBC, mode: IndirectY, operand: Operand::Byte(0xab) }), + ( + vec![0xe9, 0xab], + Instruction { + op: SBC, + mode: Immediate, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0xe5, 0xab], + Instruction { + op: SBC, + mode: ZeroPage, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0xf5, 0xab], + Instruction { + op: SBC, + mode: ZeroPageX, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0xed, 0xcd, 0xab], + Instruction { + op: SBC, + mode: Absolute, + operand: Operand::Word(0xabcd), + }, + ), + ( + vec![0xfd, 0xcd, 0xab], + Instruction { + op: SBC, + mode: AbsoluteX, + operand: Operand::Word(0xabcd), + }, + ), + ( + vec![0xf9, 0xcd, 0xab], + Instruction { + op: SBC, + mode: AbsoluteY, + operand: Operand::Word(0xabcd), + }, + ), + ( + vec![0xe1, 0xab], + Instruction { + op: SBC, + mode: IndirectX, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0xf1, 0xab], + Instruction { + op: SBC, + mode: IndirectY, + operand: Operand::Byte(0xab), + }, + ), // SEC, SED, SEI - (vec![0x38], Instruction { op: SEC, mode: Implied, operand: Operand::None }), - (vec![0xf8], Instruction { op: SED, mode: Implied, operand: Operand::None }), - (vec![0x78], Instruction { op: SEI, mode: Implied, operand: Operand::None }), + ( + vec![0x38], + Instruction { + op: SEC, + mode: Implied, + operand: Operand::None, + }, + ), + ( + vec![0xf8], + Instruction { + op: SED, + mode: Implied, + operand: Operand::None, + }, + ), + ( + vec![0x78], + Instruction { + op: SEI, + mode: Implied, + operand: Operand::None, + }, + ), // STA - (vec![0x85, 0xab], Instruction { op: STA, mode: ZeroPage, operand: Operand::Byte(0xab) }), - (vec![0x95, 0xab], Instruction { op: STA, mode: ZeroPageX, operand: Operand::Byte(0xab) }), - (vec![0x8d, 0xcd, 0xab], Instruction { op: STA, mode: Absolute, operand: Operand::Word(0xabcd) }), - (vec![0x9d, 0xcd, 0xab], Instruction { op: STA, mode: AbsoluteX, operand: Operand::Word(0xabcd) }), - (vec![0x99, 0xcd, 0xab], Instruction { op: STA, mode: AbsoluteY, operand: Operand::Word(0xabcd) }), - (vec![0x81, 0xab], Instruction { op: STA, mode: IndirectX, operand: Operand::Byte(0xab) }), - (vec![0x91, 0xab], Instruction { op: STA, mode: IndirectY, operand: Operand::Byte(0xab) }), + ( + vec![0x85, 0xab], + Instruction { + op: STA, + mode: ZeroPage, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0x95, 0xab], + Instruction { + op: STA, + mode: ZeroPageX, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0x8d, 0xcd, 0xab], + Instruction { + op: STA, + mode: Absolute, + operand: Operand::Word(0xabcd), + }, + ), + ( + vec![0x9d, 0xcd, 0xab], + Instruction { + op: STA, + mode: AbsoluteX, + operand: Operand::Word(0xabcd), + }, + ), + ( + vec![0x99, 0xcd, 0xab], + Instruction { + op: STA, + mode: AbsoluteY, + operand: Operand::Word(0xabcd), + }, + ), + ( + vec![0x81, 0xab], + Instruction { + op: STA, + mode: IndirectX, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0x91, 0xab], + Instruction { + op: STA, + mode: IndirectY, + operand: Operand::Byte(0xab), + }, + ), // STX - (vec![0x86, 0xab], Instruction { op: STX, mode: ZeroPage, operand: Operand::Byte(0xab) }), - (vec![0x96, 0xab], Instruction { op: STX, mode: ZeroPageY, operand: Operand::Byte(0xab) }), - (vec![0x8e, 0xcd, 0xab], Instruction { op: STX, mode: Absolute, operand: Operand::Word(0xabcd) }), + ( + vec![0x86, 0xab], + Instruction { + op: STX, + mode: ZeroPage, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0x96, 0xab], + Instruction { + op: STX, + mode: ZeroPageY, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0x8e, 0xcd, 0xab], + Instruction { + op: STX, + mode: Absolute, + operand: Operand::Word(0xabcd), + }, + ), // STY - (vec![0x84, 0xab], Instruction { op: STY, mode: ZeroPage, operand: Operand::Byte(0xab) }), - (vec![0x94, 0xab], Instruction { op: STY, mode: ZeroPageX, operand: Operand::Byte(0xab) }), - (vec![0x8c, 0xcd, 0xab], Instruction { op: STY, mode: Absolute, operand: Operand::Word(0xabcd) }), + ( + vec![0x84, 0xab], + Instruction { + op: STY, + mode: ZeroPage, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0x94, 0xab], + Instruction { + op: STY, + mode: ZeroPageX, + operand: Operand::Byte(0xab), + }, + ), + ( + vec![0x8c, 0xcd, 0xab], + Instruction { + op: STY, + mode: Absolute, + operand: Operand::Word(0xabcd), + }, + ), // TAX, TAY, TSX, TXA, TXS, TYA - (vec![0xaa], Instruction { op: TAX, mode: Implied, operand: Operand::None }), - (vec![0xa8], Instruction { op: TAY, mode: Implied, operand: Operand::None }), - (vec![0xba], Instruction { op: TSX, mode: Implied, operand: Operand::None }), - (vec![0x8a], Instruction { op: TXA, mode: Implied, operand: Operand::None }), - (vec![0x9a], Instruction { op: TXS, mode: Implied, operand: Operand::None }), - (vec![0x98], Instruction { op: TYA, mode: Implied, operand: Operand::None }) + ( + vec![0xaa], + Instruction { + op: TAX, + mode: Implied, + operand: Operand::None, + }, + ), + ( + vec![0xa8], + Instruction { + op: TAY, + mode: Implied, + operand: Operand::None, + }, + ), + ( + vec![0xba], + Instruction { + op: TSX, + mode: Implied, + operand: Operand::None, + }, + ), + ( + vec![0x8a], + Instruction { + op: TXA, + mode: Implied, + operand: Operand::None, + }, + ), + ( + vec![0x9a], + Instruction { + op: TXS, + mode: Implied, + operand: Operand::None, + }, + ), + ( + vec![0x98], + Instruction { + op: TYA, + mode: Implied, + operand: Operand::None, + }, + ), ]; for (bytes, instruction) in params { let result1 = Instruction::decode(&bytes); diff --git a/core/src/instruction2/from_bytes.rs b/core/src/instruction2/from_bytes.rs deleted file mode 100644 index 3706319..0000000 --- a/core/src/instruction2/from_bytes.rs +++ /dev/null @@ -1,23 +0,0 @@ -use log::debug; -use crate::address_mode::AddressMode::*; -use crate::constants::constants_isa_op::*; - -fn join_word(low: u8, high: u8) -> u16 { - ((high as u16) << 8) | low as u16 -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn test_join_word() { - let low: u8 = 0xcd; - let high: u8 = 0xab; - - assert_eq!( - join_word(low, high), - 0xabcd - ); - } -} diff --git a/core/src/instruction2/mod.rs b/core/src/instruction2/mod.rs deleted file mode 100644 index 9de61ef..0000000 --- a/core/src/instruction2/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -use crate::address_mode::AddressMode; -use crate::address_mode::AddressMode::*; -use crate::mos6502flags::Mos6502Flag::*; - -mod from_bytes; -mod to_bytes; -mod to_string; diff --git a/core/src/instruction2/to_bytes.rs b/core/src/instruction2/to_bytes.rs deleted file mode 100644 index 451e74e..0000000 --- a/core/src/instruction2/to_bytes.rs +++ /dev/null @@ -1,38 +0,0 @@ -use crate::address_mode::AddressMode; -use crate::address_mode::AddressMode::{Absolute, AbsoluteX, AbsoluteY, Immediate, IndirectX, IndirectY, ZeroPage, ZeroPageX, ZeroPageY}; -use crate::constants::constants_isa_op::*; - -fn split_word_hl(to_split: u16) -> (u8, u8) { - let low = (to_split & 0xff) as u8; - let high = ((to_split & 0xff00) >> 8) as u8; - (high, low) -} - -fn split_word_lh(to_split: u16) -> (u8, u8) { - let low = (to_split & 0xff) as u8; - let high = ((to_split & 0xff00) >> 8) as u8; - (low, high) -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn split_le() { - let value = 0xabcd; - let (high, low) = split_word_hl(value); - - assert_eq!(low, 0xcd); - assert_eq!(high, 0xab); - } - - #[test] - fn split_be() { - let value = 0xabcd; - let (low, high) = split_word_lh(value); - - assert_eq!(low, 0xcd); - assert_eq!(high, 0xab); - } -} diff --git a/core/src/instruction2/to_string.rs b/core/src/instruction2/to_string.rs deleted file mode 100644 index ff6606a..0000000 --- a/core/src/instruction2/to_string.rs +++ /dev/null @@ -1,18 +0,0 @@ - -fn format(mode: &AddressMode, prefix: &str) -> String { - // let suffix = match mode { - // AddressMode::Implied => "", - // AddressMode::Accumulator => " A", - // AddressMode::Immediate(value) => &*format!(" #${value:02x}"), - // AddressMode::ZeroPage(value) => &*format!(" ${value:02x}"), - // AddressMode::ZeroPageX(value) => &*format!(" ${value:02x},X"), - // AddressMode::Absolute(offset) => &*format!(" ${offset:04x}"), - // AddressMode::AbsoluteX(offset) => &*format!(" ${offset:04x},X"), - // AddressMode::AbsoluteY(offset) => &*format!(" ${offset:04x},Y"), - // AddressMode::IndirectX(value) => &*format!(" (${value:02x},X)"), - // AddressMode::IndirectY(value) => &*format!(" (${value:02x}),Y"), - // AddressMode::ZeroPageY(value) => &*format!(" ${value:02x},Y") - // }; - // format!("{}{}", prefix, suffix) - prefix.to_string() -} \ No newline at end of file diff --git a/core/src/instruction_table.rs b/core/src/instruction_table.rs index 808b5e8..bf57a2f 100644 --- a/core/src/instruction_table.rs +++ b/core/src/instruction_table.rs @@ -1,10 +1,36 @@ use crate::address_mode::AddressMode; -use crate::constants::constants_isa_op::{ISA_OP_ADC_ABS, ISA_OP_ADC_ABSX, ISA_OP_ADC_ABSY, ISA_OP_ADC_I, ISA_OP_ADC_INDX, ISA_OP_ADC_INDY, ISA_OP_ADC_Z, ISA_OP_ADC_ZX, ISA_OP_AND_ABS, ISA_OP_AND_ABSX, ISA_OP_AND_ABSY, ISA_OP_AND_I, ISA_OP_AND_INDX, ISA_OP_AND_INDY, ISA_OP_AND_Z, ISA_OP_AND_ZX, ISA_OP_ASL_A, ISA_OP_ASL_ABS, ISA_OP_ASL_ABSX, ISA_OP_ASL_Z, ISA_OP_ASL_ZX, ISA_OP_BCC, ISA_OP_BCS, ISA_OP_BEQ, ISA_OP_BIT_ABS, ISA_OP_BIT_ZP, ISA_OP_BMI, ISA_OP_BNE, ISA_OP_BPL, ISA_OP_BRK, ISA_OP_BVC, ISA_OP_BVS, ISA_OP_CLC, ISA_OP_CLD, ISA_OP_CLI, ISA_OP_CLV, ISA_OP_CMP_ABS, ISA_OP_CMP_ABSX, ISA_OP_CMP_ABSY, ISA_OP_CMP_I, ISA_OP_CMP_INDX, ISA_OP_CMP_INDY, ISA_OP_CMP_ZP, ISA_OP_CMP_ZPX, ISA_OP_CPX_ABS, ISA_OP_CPX_I, ISA_OP_CPX_ZP, ISA_OP_CPY_ABS, ISA_OP_CPY_I, ISA_OP_CPY_ZP, ISA_OP_DEC_ABS, ISA_OP_DEC_ABSX, ISA_OP_DEC_ZP, ISA_OP_DEC_ZPX, ISA_OP_DEX, ISA_OP_DEY, ISA_OP_EOR_ABS, ISA_OP_EOR_ABSX, ISA_OP_EOR_ABSY, ISA_OP_EOR_I, ISA_OP_EOR_INDX, ISA_OP_EOR_INDY, ISA_OP_EOR_ZP, ISA_OP_EOR_ZPX, ISA_OP_INC_ABS, ISA_OP_INC_ABSX, ISA_OP_INC_ZP, ISA_OP_INC_ZPX, ISA_OP_INX, ISA_OP_INY, ISA_OP_JMP_ABS, ISA_OP_JMP_IND, ISA_OP_JSR, ISA_OP_LDA_ABS, ISA_OP_LDA_ABSX, ISA_OP_LDA_ABSY, ISA_OP_LDA_I, ISA_OP_LDA_INDX, ISA_OP_LDA_INDY, ISA_OP_LDA_Z, ISA_OP_LDA_ZX, ISA_OP_LDX_ABS, ISA_OP_LDX_ABSY, ISA_OP_LDX_I, ISA_OP_LDX_ZP, ISA_OP_LDX_ZPY, ISA_OP_LDY_ABS, ISA_OP_LDY_ABSX, ISA_OP_LDY_I, ISA_OP_LDY_ZP, ISA_OP_LDY_ZPX, ISA_OP_LSR_A, ISA_OP_LSR_ABS, ISA_OP_LSR_ABSX, ISA_OP_LSR_ZP, ISA_OP_LSR_ZPX, ISA_OP_NOP, ISA_OP_ORA_ABS, ISA_OP_ORA_ABSX, ISA_OP_ORA_ABSY, ISA_OP_ORA_I, ISA_OP_ORA_INDX, ISA_OP_ORA_INDY, ISA_OP_ORA_ZP, ISA_OP_ORA_ZPX, ISA_OP_PHA, ISA_OP_PHP, ISA_OP_PLA, ISA_OP_PLP, ISA_OP_ROL_A, ISA_OP_ROL_ABS, ISA_OP_ROL_ABSX, ISA_OP_ROL_ZP, ISA_OP_ROL_ZPX, ISA_OP_ROR_A, ISA_OP_ROR_ABS, ISA_OP_ROR_ABSX, ISA_OP_ROR_ZP, ISA_OP_ROR_ZPX, ISA_OP_RTI, ISA_OP_RTS, ISA_OP_SBC_ABS, ISA_OP_SBC_ABSX, ISA_OP_SBC_ABSY, ISA_OP_SBC_I, ISA_OP_SBC_INDX, ISA_OP_SBC_INDY, ISA_OP_SBC_ZP, ISA_OP_SBC_ZPX, ISA_OP_SEC, ISA_OP_SED, ISA_OP_SEI, ISA_OP_STA_ABS, ISA_OP_STA_ABSX, ISA_OP_STA_ABSY, ISA_OP_STA_INDX, ISA_OP_STA_INDY, ISA_OP_STA_ZP, ISA_OP_STA_ZPX, ISA_OP_STX_ABS, ISA_OP_STX_ZP, ISA_OP_STX_ZPY, ISA_OP_STY_ABS, ISA_OP_STY_ZP, ISA_OP_STY_ZPX, ISA_OP_TAX, ISA_OP_TAY, ISA_OP_TSX, ISA_OP_TXA, ISA_OP_TXS, ISA_OP_TYA}; +use crate::constants::constants_isa_op::{ + ISA_OP_ADC_ABS, ISA_OP_ADC_ABSX, ISA_OP_ADC_ABSY, ISA_OP_ADC_I, ISA_OP_ADC_INDX, + ISA_OP_ADC_INDY, ISA_OP_ADC_Z, ISA_OP_ADC_ZX, ISA_OP_AND_ABS, ISA_OP_AND_ABSX, ISA_OP_AND_ABSY, + ISA_OP_AND_I, ISA_OP_AND_INDX, ISA_OP_AND_INDY, ISA_OP_AND_Z, ISA_OP_AND_ZX, ISA_OP_ASL_A, + ISA_OP_ASL_ABS, ISA_OP_ASL_ABSX, ISA_OP_ASL_Z, ISA_OP_ASL_ZX, ISA_OP_BCC, ISA_OP_BCS, + ISA_OP_BEQ, ISA_OP_BIT_ABS, ISA_OP_BIT_ZP, ISA_OP_BMI, ISA_OP_BNE, ISA_OP_BPL, ISA_OP_BRK, + ISA_OP_BVC, ISA_OP_BVS, ISA_OP_CLC, ISA_OP_CLD, ISA_OP_CLI, ISA_OP_CLV, ISA_OP_CMP_ABS, + ISA_OP_CMP_ABSX, ISA_OP_CMP_ABSY, ISA_OP_CMP_I, ISA_OP_CMP_INDX, ISA_OP_CMP_INDY, + ISA_OP_CMP_ZP, ISA_OP_CMP_ZPX, ISA_OP_CPX_ABS, ISA_OP_CPX_I, ISA_OP_CPX_ZP, ISA_OP_CPY_ABS, + ISA_OP_CPY_I, ISA_OP_CPY_ZP, ISA_OP_DEC_ABS, ISA_OP_DEC_ABSX, ISA_OP_DEC_ZP, ISA_OP_DEC_ZPX, + ISA_OP_DEX, ISA_OP_DEY, ISA_OP_EOR_ABS, ISA_OP_EOR_ABSX, ISA_OP_EOR_ABSY, ISA_OP_EOR_I, + ISA_OP_EOR_INDX, ISA_OP_EOR_INDY, ISA_OP_EOR_ZP, ISA_OP_EOR_ZPX, ISA_OP_INC_ABS, + ISA_OP_INC_ABSX, ISA_OP_INC_ZP, ISA_OP_INC_ZPX, ISA_OP_INX, ISA_OP_INY, ISA_OP_JMP_ABS, + ISA_OP_JMP_IND, ISA_OP_JSR, ISA_OP_LDA_ABS, ISA_OP_LDA_ABSX, ISA_OP_LDA_ABSY, ISA_OP_LDA_I, + ISA_OP_LDA_INDX, ISA_OP_LDA_INDY, ISA_OP_LDA_Z, ISA_OP_LDA_ZX, ISA_OP_LDX_ABS, ISA_OP_LDX_ABSY, + ISA_OP_LDX_I, ISA_OP_LDX_ZP, ISA_OP_LDX_ZPY, ISA_OP_LDY_ABS, ISA_OP_LDY_ABSX, ISA_OP_LDY_I, + ISA_OP_LDY_ZP, ISA_OP_LDY_ZPX, ISA_OP_LSR_A, ISA_OP_LSR_ABS, ISA_OP_LSR_ABSX, ISA_OP_LSR_ZP, + ISA_OP_LSR_ZPX, ISA_OP_NOP, ISA_OP_ORA_ABS, ISA_OP_ORA_ABSX, ISA_OP_ORA_ABSY, ISA_OP_ORA_I, + ISA_OP_ORA_INDX, ISA_OP_ORA_INDY, ISA_OP_ORA_ZP, ISA_OP_ORA_ZPX, ISA_OP_PHA, ISA_OP_PHP, + ISA_OP_PLA, ISA_OP_PLP, ISA_OP_ROL_A, ISA_OP_ROL_ABS, ISA_OP_ROL_ABSX, ISA_OP_ROL_ZP, + ISA_OP_ROL_ZPX, ISA_OP_ROR_A, ISA_OP_ROR_ABS, ISA_OP_ROR_ABSX, ISA_OP_ROR_ZP, ISA_OP_ROR_ZPX, + ISA_OP_RTI, ISA_OP_RTS, ISA_OP_SBC_ABS, ISA_OP_SBC_ABSX, ISA_OP_SBC_ABSY, ISA_OP_SBC_I, + ISA_OP_SBC_INDX, ISA_OP_SBC_INDY, ISA_OP_SBC_ZP, ISA_OP_SBC_ZPX, ISA_OP_SEC, ISA_OP_SED, + ISA_OP_SEI, ISA_OP_STA_ABS, ISA_OP_STA_ABSX, ISA_OP_STA_ABSY, ISA_OP_STA_INDX, ISA_OP_STA_INDY, + ISA_OP_STA_ZP, ISA_OP_STA_ZPX, ISA_OP_STX_ABS, ISA_OP_STX_ZP, ISA_OP_STX_ZPY, ISA_OP_STY_ABS, + ISA_OP_STY_ZP, ISA_OP_STY_ZPX, ISA_OP_TAX, ISA_OP_TAY, ISA_OP_TSX, ISA_OP_TXA, ISA_OP_TXS, + ISA_OP_TYA, +}; use crate::op_info::OpInfo; use crate::operation::Operation; use crate::operation::Operation::*; - pub fn INSTRUCTION_CYCLES(instruction: u8) -> u8 { INSTRUCTION_TABLE[instruction as usize].unwrap().cycles } @@ -723,7 +749,7 @@ pub const INSTRUCTION_TABLE: [Option; 256] = { operation: Operation::ROR, mode: AddressMode::Accumulator, length: 1, - cycles: 2 + cycles: 2, }); table[ISA_OP_ROR_ZP as usize] = Some(OpInfo { operation: Operation::ROR, @@ -996,4 +1022,4 @@ mod test { defined_count ); } -} \ No newline at end of file +} diff --git a/core/src/lib.rs b/core/src/lib.rs index 94ef2f8..a5362e8 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -1,11 +1,11 @@ -pub mod periph; pub mod address_mode; -pub mod mos6502cpu; -pub mod instruction; -pub mod mos6502flags; +pub mod computers; pub mod constants; -pub mod operation; +pub mod instruction; +pub mod instruction_table; +pub mod mos6502cpu; +pub mod mos6502flags; pub mod op_info; pub mod operand; -pub mod instruction_table; -pub mod computers; +pub mod operation; +pub mod periph; diff --git a/core/src/mos6502cpu.rs b/core/src/mos6502cpu.rs index 508318b..266735c 100644 --- a/core/src/mos6502cpu.rs +++ b/core/src/mos6502cpu.rs @@ -1,14 +1,14 @@ -use log::trace; use crate::address_mode::AddressMode; use crate::constants::constants_isa_op::ISA_OP_NOP; +use crate::constants::constants_system::*; use crate::instruction::Instruction; -use crate::mos6502flags::{Mos6502Flag, Mos6502Flags}; +use crate::instruction_table::INSTRUCTION_TABLE; use crate::mos6502flags::Mos6502Flag::*; +use crate::mos6502flags::{Mos6502Flag, Mos6502Flags}; use crate::op_info::OpInfo; use crate::operand::Operand; use crate::operation::Operation; -use crate::constants::constants_system::*; -use crate::instruction_table::INSTRUCTION_TABLE; +use log::trace; pub struct Mos6502Cpu { memory: [u8; SIZE_64KB], @@ -30,15 +30,14 @@ pub struct Mos6502Cpu { ir: Instruction, // Instruction Register oi: OpInfo, has_reset: bool, - iv: u16, // Interrupt Vector + iv: u16, // Interrupt Vector cycle_carry: u16, // Value to hold between microsteps ir_bytes: [u8; 4], /// CPU Read signal - pub read_signal: bool + pub read_signal: bool, } impl Mos6502Cpu { - /// set_data_bus /// /// Sets data on the data bus. @@ -71,7 +70,7 @@ impl Default for Mos6502Cpu { iv: 0xfffe, cycle_carry: 0x0000, ir_bytes: [0x00; 4], - read_signal: true + read_signal: true, }; working.reset_cpu(); working @@ -108,7 +107,10 @@ impl Mos6502Cpu { self.iv = self.read_word(&OFFSET_INT_VECTOR); self.address_bus = self.pc; self.read_signal = true; - println!("PC and IV are now set from ROM addresses / AB = {:016b}", self.address_bus); + println!( + "PC and IV are now set from ROM addresses / AB = {:016b}", + self.address_bus + ); } fn read_word(&self, offset: &u16) -> u16 { @@ -126,7 +128,11 @@ impl Mos6502Cpu { self.flags.flag(flag_to_read) } pub fn poke_flag(&mut self, flag_to_set: Mos6502Flag, new_value: bool) { - if new_value { self.flags.set_flag(flag_to_set) } else { self.flags.clear_flag(flag_to_set) } + if new_value { + self.flags.set_flag(flag_to_set) + } else { + self.flags.clear_flag(flag_to_set) + } } pub fn peek(&self, offset: u16) -> u8 { @@ -142,10 +148,9 @@ impl Mos6502Cpu { self.a } pub fn poke_a(&mut self, new_a: u8) { + println!("Updating register A from [{}] to [{}]", self.a, new_a); - println!("Updating register A from [{}] to [{}]", self.a, new_a); - - self.a = new_a; + self.a = new_a; } pub fn peek_x(&self) -> u8 { @@ -175,7 +180,6 @@ impl Mos6502Cpu { /// Ticks the CPU pub fn tick(&mut self) { - println!("PREPARiNG TO TICK CPU AT PC 0x{:04x}", self.pc); if self.microcode_step == 0 { println!("OUT OF MICROSTEPS. Decoding the next instruction"); @@ -190,28 +194,27 @@ impl Mos6502Cpu { // set the counter to the number of steps left } else { // run 1 microcode step - println!("Microstep {}/{} for {:?}", self.microcode_step, self.oi.cycles, self.ir.op); + println!( + "Microstep {}/{} for {:?}", + self.microcode_step, self.oi.cycles, self.ir.op + ); match self.ir.op { - Operation::ADC => { - match self.microcode_step { - 1 => { - match self.ir.mode { - AddressMode::Immediate => {} - AddressMode::ZeroPage => {} - AddressMode::ZeroPageX => {} - AddressMode::Absolute => {} - AddressMode::AbsoluteX => {} - AddressMode::AbsoluteY => {} - AddressMode::Indirect => {} - AddressMode::IndirectX => {} - AddressMode::IndirectY => {} - _ => {} - } - }, - 2 => {}, + Operation::ADC => match self.microcode_step { + 1 => match self.ir.mode { + AddressMode::Immediate => {} + AddressMode::ZeroPage => {} + AddressMode::ZeroPageX => {} + AddressMode::Absolute => {} + AddressMode::AbsoluteX => {} + AddressMode::AbsoluteY => {} + AddressMode::Indirect => {} + AddressMode::IndirectX => {} + AddressMode::IndirectY => {} _ => {} - } - } + }, + 2 => {} + _ => {} + }, Operation::AND => {} Operation::ASL => {} Operation::BCC => {} @@ -247,10 +250,8 @@ impl Mos6502Cpu { AddressMode::ZeroPage => { // read from let offset = match self.ir.operand { - Operand::Byte(z) => { - z - } - _ => { 0x00 } + Operand::Byte(z) => z, + _ => 0x00, }; trace!("READING FROM MEMORY AT 0x{offset:04x}"); self.memory[offset as usize] @@ -258,37 +259,29 @@ impl Mos6502Cpu { } AddressMode::ZeroPageX => { let offset = match self.ir.operand { - Operand::Byte(z) => { - z - } - _ => { 0x00 } + Operand::Byte(z) => z, + _ => 0x00, }; // self.memory.peek(offset + self.x); self.memory[offset as usize] } AddressMode::Absolute => { let offset = match self.ir.operand { - Operand::Word(offset) => { - offset - } - _ => { 0x00 } + Operand::Word(offset) => offset, + _ => 0x00, }; // self.memory.peek(offset) self.memory[offset as usize] } AddressMode::AbsoluteX => { let offset = match self.ir.operand { - Operand::Word(offset) => { - offset - } - _ => { 0x00 } + Operand::Word(offset) => offset, + _ => 0x00, }; // self.memory.peek(offset + self.x); self.memory[offset as usize] } - _ => { - 0x00 - } + _ => 0x00, }; } // DEC write memory @@ -310,8 +303,8 @@ impl Mos6502Cpu { (self.y, _) = self.y.overflowing_sub(1); } } - Operation::EOR => { } - Operation::INC => { } + Operation::EOR => {} + Operation::INC => {} Operation::INX => { if self.microcode_step == 1 { let (new_x, new_carry) = self.x.overflowing_add(1); @@ -328,75 +321,67 @@ impl Mos6502Cpu { self.poke_flag(Carry, new_carry); self.address_bus = self.pc; self.data_bus = 0x00; - } } - Operation::JMP => { - match self.ir.operand { - Operand::Word(offset) => { - self.pc = offset; - self.address_bus = self.pc; - self.data_bus = 0x00; - } - _ => {} } } + Operation::JMP => match self.ir.operand { + Operand::Word(offset) => { + self.pc = offset; + self.address_bus = self.pc; + self.data_bus = 0x00; + } + _ => {} + }, Operation::JSR => { // push pc to stack. // jump to the subroutine. } - Operation::LDA => { - match self.oi.mode { - AddressMode::Immediate => { - match self.ir.operand { - Operand::Byte(value) => { - println!("Loading 0x{value:02x} ({value}) into A"); - self.a = value; - } - _ => {} - } + Operation::LDA => match self.oi.mode { + AddressMode::Immediate => match self.ir.operand { + Operand::Byte(value) => { + println!("Loading 0x{value:02x} ({value}) into A"); + self.a = value; } - AddressMode::ZeroPage => { - match self.ir.operand { - Operand::Byte(value) => { - println!("Loading from zero page at 0x{value:02x} ({value})"); - self.a = self.memory[value as usize]; - } - _ => {} - } + _ => {} + }, + AddressMode::ZeroPage => match self.ir.operand { + Operand::Byte(value) => { + println!("Loading from zero page at 0x{value:02x} ({value})"); + self.a = self.memory[value as usize]; } - AddressMode::ZeroPageX => { - match self.ir.operand { - Operand::Byte(value) => { - let x_offset = self.x; - self.a = self.memory[(value + x_offset) as usize]; - } - _ => {} - } + _ => {} + }, + AddressMode::ZeroPageX => match self.ir.operand { + Operand::Byte(value) => { + let x_offset = self.x; + self.a = self.memory[(value + x_offset) as usize]; } - AddressMode::Absolute => { - if let Operand::Word(offset) = self.ir.operand { - println!("Loading from absolute address 0x{offset:04x}"); - self.a = self.memory[offset as usize]; - } - - } - AddressMode::AbsoluteX => { - if let Operand::Word(offset) = self.ir.operand { - self.a = self.memory[(offset + self.x as u16) as usize]; - } - } - AddressMode::AbsoluteY => { - if let Operand::Word(offset) = self.ir.operand { - self.a = self.memory[(offset + self.y as u16) as usize]; - } - } - AddressMode::Indirect => {} - AddressMode::IndirectX => {} - AddressMode::IndirectY => {} - _ => { - println!("INVALID ADDRESS MODE FOR LDA"); + _ => {} + }, + AddressMode::Absolute => { + if let Operand::Word(offset) = self.ir.operand { + println!("Loading from absolute address 0x{offset:04x}"); + self.a = self.memory[offset as usize]; } } - } + AddressMode::AbsoluteX => { + if let Operand::Word(offset) = self.ir.operand { + self.a = self.memory[(offset + self.x as u16) as usize]; + } + } + AddressMode::AbsoluteY => { + if let Operand::Word(offset) = self.ir.operand { + let real_offset = offset + self.y as u16; + println!("offset: {offset:04x} + {:02x}", self.y); + self.a = self.memory[(offset + self.y as u16) as usize]; + } + } + AddressMode::Indirect => {} + AddressMode::IndirectX => {} + AddressMode::IndirectY => {} + _ => { + println!("INVALID ADDRESS MODE FOR LDA"); + } + }, Operation::LDX => {} Operation::LDY => {} Operation::LSR => {} @@ -501,13 +486,11 @@ impl Mos6502Cpu { Operation::TAY => { self.y = self.a; } - Operation::TSX => { - } + Operation::TSX => {} Operation::TXA => { self.a = self.x; } - Operation::TXS => { - } + Operation::TXS => {} Operation::TYA => { self.y = self.a; } @@ -517,25 +500,41 @@ impl Mos6502Cpu { } pub fn dump(&self) { - println!("CPU State: PC: {:04x} / A: {:02x} / X: {:02x} / Y: {:02x} / ADDRESS: {:04x} / DATA: {:02x} / MICROSTEPS: {:02x} / S: {}", - self.pc, self.a, self.x, self.y, self.address_bus, self.data_bus, self.microcode_step, self.flags.dump()); + println!( + "CPU State: PC: {:04x} / A: {:02x} / X: {:02x} / Y: {:02x} / ADDRESS: {:04x} / DATA: {:02x} / MICROSTEPS: {:02x} / S: {}", + self.pc, + self.a, + self.x, + self.y, + self.address_bus, + self.data_bus, + self.microcode_step, + self.flags.dump() + ); } /// dump_data /// /// returns /// PC, A, X, Y, Address_Bus, Data_Bus, Microcode_Step - pub fn dump_data(&self) -> ( u16, u8, u8, u8, u16, u8, u8) { - (self.pc, self.a, self.x, self.y, self.address_bus, self.data_bus, self.microcode_step) + pub fn dump_data(&self) -> (u16, u8, u8, u8, u16, u8, u8) { + ( + self.pc, + self.a, + self.x, + self.y, + self.address_bus, + self.data_bus, + self.microcode_step, + ) } - } #[cfg(test)] mod test { + use super::*; use crate::constants::constants_isa_op::*; use crate::instruction_table::{INSTRUCTION_CYCLES, INSTRUCTION_TABLE}; - use super::*; #[test] fn clc() { @@ -548,7 +547,9 @@ mod test { cpu.pc = 0x6000; // Tick the CPU through the instruction - for _ in 0..INSTRUCTION_TABLE[ISA_OP_CLC as usize].unwrap().cycles { cpu.tick(); } + for _ in 0..INSTRUCTION_CYCLES(ISA_OP_CLC) { + cpu.tick(); + } assert!(!cpu.peek_flag(Carry)); } @@ -560,7 +561,9 @@ mod test { cpu.memory[0x6000] = ISA_OP_CLD; cpu.pc = 0x6000; - for _ in 0..INSTRUCTION_TABLE[ISA_OP_CLD as usize].unwrap().cycles { cpu.tick(); } + for _ in 0..INSTRUCTION_CYCLES(ISA_OP_CLD) { + cpu.tick(); + } assert!(!cpu.peek_flag(Decimal)); } @@ -572,10 +575,11 @@ mod test { cpu.memory[0x6000] = ISA_OP_CLI; cpu.pc = 0x6000; - for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_CLI) { cpu.tick(); } + for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_CLI) { + cpu.tick(); + } assert!(!cpu.peek_flag(Interrupt)); - } #[test] @@ -585,7 +589,9 @@ mod test { cpu.memory[0x6000] = ISA_OP_CLV; cpu.pc = 0x6000; - for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_CLV) { cpu.tick(); } + for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_CLV) { + cpu.tick(); + } assert!(!cpu.peek_flag(Overflow)); } @@ -597,7 +603,9 @@ mod test { cpu.memory[0x6001] = 0xab; cpu.pc = 0x6000; - for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_LDA_I) { cpu.tick(); } + for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_LDA_I) { + cpu.tick(); + } assert_eq!(cpu.a, 0xab); } @@ -611,7 +619,9 @@ mod test { cpu.memory[0x00ac] = 0xbe; cpu.pc = 0x6000; - for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_LDA_ZX) { cpu.tick(); }; + for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_LDA_ZX) { + cpu.tick(); + } // println!("MEMORY AT 0x00aa, ab, ac, ad, ae -> {:02x} {:02x} {:02x} {:02x} {:02x}", cpu.memory[0x00aa], cpu.memory[0x00ab], cpu.memory[0x00ac], cpu.memory[0x00ad], cpu.memory[0x00ae]); // cpu.dump(); @@ -630,7 +640,9 @@ mod test { cpu.memory[0x00ab] = 0xbe; cpu.pc = 0x6000; - for _ in 0..INSTRUCTION_CYCLES(ISA_OP_LDA_Z) { cpu.tick(); } + for _ in 0..INSTRUCTION_CYCLES(ISA_OP_LDA_Z) { + cpu.tick(); + } assert_eq!(cpu.a, 0xbe); } @@ -644,7 +656,9 @@ mod test { cpu.memory[0x0eef] = 0xab; cpu.pc = 0x6000; - for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_LDA_ABS) { cpu.tick(); } + for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_LDA_ABS) { + cpu.tick(); + } assert_eq!(cpu.a, 0xab); } @@ -659,7 +673,9 @@ mod test { cpu.memory[0x0ef0] = 0xab; cpu.pc = 0x6000; - for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_LDA_ABSX) { cpu.tick(); } + for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_LDA_ABSX) { + cpu.tick(); + } assert_eq!(cpu.a, 0xab); } @@ -669,12 +685,14 @@ mod test { let mut cpu = Mos6502Cpu::default(); cpu.memory[0x6000] = ISA_OP_LDA_ABSY; cpu.memory[0x6001] = 0xef; - cpu.memory[0x6002] = 0xbe; + cpu.memory[0x6002] = 0x0e; cpu.poke_y(0x01); cpu.memory[0x0ef0] = 0xab; cpu.pc = 0x6000; - for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_LDA_ABSY) { cpu.tick(); } + for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_LDA_ABSY) { + cpu.tick(); + } assert_eq!(cpu.a, 0xab); } @@ -687,9 +705,13 @@ mod test { cpu.memory[0x6001] = ISA_OP_INX; cpu.pc = 0x6000; - for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_DEX) { cpu.tick(); } + for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_DEX) { + cpu.tick(); + } assert_eq!(0xaa, cpu.x); - for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_INX) { cpu.tick(); } + for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_INX) { + cpu.tick(); + } assert_eq!(0xab, cpu.x); } @@ -701,9 +723,13 @@ mod test { cpu.memory[0x6001] = ISA_OP_INY; cpu.pc = 0x6000; - for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_DEY) { cpu.tick(); } + for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_DEY) { + cpu.tick(); + } assert_eq!(0xaa, cpu.peek_y()); - for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_INY) { cpu.tick(); } + for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_INY) { + cpu.tick(); + } assert_eq!(0xab, cpu.peek_y()); } @@ -715,9 +741,28 @@ mod test { cpu.memory[0x6001] = ISA_OP_ROR_A; cpu.pc = 0x6000; - for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_ROL_A) { cpu.tick(); } + for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_ROL_A) { + cpu.tick(); + } assert_eq!(cpu.peek_a(), 0b0101_0101); - for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_ROR_A) { cpu.tick(); } + for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_ROR_A) { + cpu.tick(); + } assert_eq!(cpu.peek_a(), 0b1010_1010); } + + #[test] + fn rol_zp_ror_zp() { + let mut cpu = Mos6502Cpu::default(); + cpu.memory[0x00ab] = 0b0101_0101; + cpu.memory[0x6000] = ISA_OP_ROL_ZP; + cpu.memory[0x6001] = 0xab; + cpu.pc = 0x6000; + + for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_ROL_ZP) { + cpu.tick(); + } + + assert_eq!(cpu.memory[0xab], 0b1010_1010);; + } } diff --git a/core/src/mos6502flags.rs b/core/src/mos6502flags.rs index 9795a29..a52286d 100644 --- a/core/src/mos6502flags.rs +++ b/core/src/mos6502flags.rs @@ -1,4 +1,6 @@ -use crate::mos6502flags::Mos6502Flag::{Break, Carry, Decimal, Interrupt, Negative, Overflow, Zero}; +use crate::mos6502flags::Mos6502Flag::{ + Break, Carry, Decimal, Interrupt, Negative, Overflow, Zero, +}; pub const BIT_NEGATIVE: u8 = 7; pub const BIT_OVERFLOW: u8 = 6; @@ -59,7 +61,7 @@ impl Mos6502Flag { Decimal => BIT_DECIMAL, Break => BIT_BREAK, Overflow => BIT_OVERFLOW, - Negative => BIT_NEGATIVE + Negative => BIT_NEGATIVE, } } } @@ -77,14 +79,15 @@ pub struct Mos6502Flags { impl Mos6502Flags { pub fn dump(&self) -> String { - format!("{}{}{}{}{}{}{}", - if self.carry { 'C' } else { 'c' }, - if self.zero { 'Z' } else { 'z' }, - if self.interrupt { 'I' } else { 'i' }, - if self.decimal { 'D' } else { 'd' }, - if self.break_flag { 'B' } else { 'b' }, - if self.overflow { 'O' } else { 'o' }, - if self.negative { 'N' } else { 'n' } + format!( + "{}{}{}{}{}{}{}", + if self.carry { 'C' } else { 'c' }, + if self.zero { 'Z' } else { 'z' }, + if self.interrupt { 'I' } else { 'i' }, + if self.decimal { 'D' } else { 'd' }, + if self.break_flag { 'B' } else { 'b' }, + if self.overflow { 'O' } else { 'o' }, + if self.negative { 'N' } else { 'n' } ) } } @@ -113,7 +116,8 @@ impl Mos6502Flags { Break => self.break_flag = false, Overflow => self.overflow = false, Negative => self.negative = false, - } } + } + } fn change_flag(&mut self, flag_to_change: Mos6502Flag, new_value: bool) { if new_value { @@ -139,25 +143,37 @@ impl Mos6502Flags { pub fn as_byte(&self) -> u8 { let mut working = 0x00; - if self.flag(Negative) { working += 1 << Negative.index(); } - if self.flag(Overflow) { working += 1 << Overflow.index(); } - working += 1 << 5; // Always Set - if self.flag(Break) { working += 1 << Break.index(); } - if self.flag(Decimal) { working += 1 << Decimal.index(); } - if self.flag(Interrupt) { working += 1 << Interrupt.index(); } - if self.flag(Zero) { working += 1 << Zero.index(); } - if self.flag(Carry) { working += 1 << Carry.index(); } + if self.flag(Negative) { + working += 1 << Negative.index(); + } + if self.flag(Overflow) { + working += 1 << Overflow.index(); + } + working += 1 << 5; // Always Set + if self.flag(Break) { + working += 1 << Break.index(); + } + if self.flag(Decimal) { + working += 1 << Decimal.index(); + } + if self.flag(Interrupt) { + working += 1 << Interrupt.index(); + } + if self.flag(Zero) { + working += 1 << Zero.index(); + } + if self.flag(Carry) { + working += 1 << Carry.index(); + } working } - - pub fn from_byte(src: u8) -> Self { let mut working = Self::default(); working.change_flag(Negative, Self::bit(src, Negative.index())); - working.change_flag(Overflow, Self::bit(src, Overflow.index())); + working.change_flag(Overflow, Self::bit(src, Overflow.index())); working.change_flag(Break, Self::bit(src, Break.index())); working.change_flag(Decimal, Self::bit(src, Decimal.index())); working.change_flag(Interrupt, Self::bit(src, Interrupt.index())); @@ -182,14 +198,15 @@ impl Mos6502Flags { } } - #[cfg(test)] mod test { use super::*; #[test] - fn smoke() { assert!(true); } + fn smoke() { + assert!(true); + } #[test] fn sanity() { diff --git a/core/src/operation.rs b/core/src/operation.rs index 5702bd5..0fd8473 100644 --- a/core/src/operation.rs +++ b/core/src/operation.rs @@ -356,5 +356,4 @@ pub enum Operation { /// /// Addressing Modes: Implied TYA, - -} \ No newline at end of file +} diff --git a/core/src/periph/at28c256/default.rs b/core/src/periph/at28c256/default.rs index 29548d6..47dd1d9 100644 --- a/core/src/periph/at28c256/default.rs +++ b/core/src/periph/at28c256/default.rs @@ -6,10 +6,10 @@ impl Default for At28C256 { fn default() -> Self { let vec = vec![0xea; SIZE_32KB]; let boxed_slice: Box<[u8]> = vec.into_boxed_slice(); - let boxed_array: Box<[u8; SIZE_32KB]> = boxed_slice.try_into().expect("Failed to convert Vec to boxed array"); - At28C256 { - data: boxed_array, - } + let boxed_array: Box<[u8; SIZE_32KB]> = boxed_slice + .try_into() + .expect("Failed to convert Vec to boxed array"); + At28C256 { data: boxed_array } } } @@ -18,5 +18,7 @@ mod test { use super::*; #[test] - fn smoke() { assert!(true); } + fn smoke() { + assert!(true); + } } diff --git a/core/src/periph/at28c256/mod.rs b/core/src/periph/at28c256/mod.rs index 4ef17dd..bc2f44e 100644 --- a/core/src/periph/at28c256/mod.rs +++ b/core/src/periph/at28c256/mod.rs @@ -1,9 +1,9 @@ mod default; mod rom_chip; -use std::io::Read; use crate::constants::constants_system::SIZE_32KB; use crate::periph::rom_chip::RomChip; +use std::io::Read; /// At28C256 /// @@ -25,8 +25,8 @@ impl At28C256 { #[cfg(test)] mod test { - use crate::constants::constants_system::SIZE_1KB; use super::*; + use crate::constants::constants_system::SIZE_1KB; #[test] fn smoke() { @@ -40,9 +40,8 @@ mod test { data.data[i] = 0xea; } for offset in 0..SIZE_32KB { - if offset.is_multiple_of(SIZE_1KB) { - }; - assert_eq!(0xea, data.read(&(offset as u16))); + if offset.is_multiple_of(SIZE_1KB) {}; + assert_eq!(0xea, data.read(&(offset as u16))); } } } diff --git a/core/src/periph/at28c256/rom_chip.rs b/core/src/periph/at28c256/rom_chip.rs index 29849b2..47d657f 100644 --- a/core/src/periph/at28c256/rom_chip.rs +++ b/core/src/periph/at28c256/rom_chip.rs @@ -3,7 +3,6 @@ use crate::periph::at28c256::At28C256; use crate::periph::rom_chip::RomChip; impl RomChip for At28C256 { - fn read(&self, offset: &u16) -> u8 { self.data[*offset as usize] } @@ -21,7 +20,7 @@ mod test { use super::*; #[test] - fn smoke() { assert!(true); } - - -} \ No newline at end of file + fn smoke() { + assert!(true); + } +} diff --git a/core/src/periph/hm62256.rs b/core/src/periph/hm62256.rs index ee951d2..de273c9 100644 --- a/core/src/periph/hm62256.rs +++ b/core/src/periph/hm62256.rs @@ -1,23 +1,24 @@ // HM62256 Static Ram -use log::debug; use crate::constants::constants_system::SIZE_32KB; use crate::periph::ram_chip::RamChip; use crate::periph::rom_chip::RomChip; +use log::debug; pub struct Hm62256 { pub(crate) base_offset: u16, - pub(crate) data: Box<[u8]> + pub(crate) data: Box<[u8]>, } impl Default for Hm62256 { fn default() -> Self { let vec = vec![0x00; SIZE_32KB]; let boxed_slice: Box<[u8]> = vec.into_boxed_slice(); - let boxed_array: Box<[u8; SIZE_32KB]> = boxed_slice.try_into().expect("Unable to box the ram"); + let boxed_array: Box<[u8; SIZE_32KB]> = + boxed_slice.try_into().expect("Unable to box the ram"); Hm62256 { base_offset: 0x0000, - data: boxed_array + data: boxed_array, } } } @@ -25,7 +26,7 @@ impl Default for Hm62256 { impl RomChip for Hm62256 { fn read(&self, offset: &u16) -> u8 { // loops memory around past 32k - let effective = *offset as i32 % SIZE_32KB as i32; + let effective = *offset as i32 % SIZE_32KB as i32; self.data[effective as usize] } @@ -37,7 +38,7 @@ impl RomChip for Hm62256 { impl RamChip for Hm62256 { fn write(&mut self, offset: &u16, value: &u8) { - let effective = *offset as i32 % SIZE_32KB as i32; + let effective = *offset as i32 % SIZE_32KB as i32; println!("Writing at E[{effective:04x}] / O[{offset:04x}]"); self.data[effective as usize] = *value; } @@ -45,11 +46,13 @@ impl RamChip for Hm62256 { #[cfg(test)] mod test { - use rand::random; use super::*; + use rand::random; #[test] - fn smoke() { assert!(true) } + fn smoke() { + assert!(true) + } #[test] fn written_data_comes_back() { @@ -59,7 +62,7 @@ mod test { for _ in 0..100_000 { let mut offset: u16 = random(); println!("SIze = {SIZE_32KB}"); - let value: u8 =random(); + let value: u8 = random(); println!("Wrote [{value:02x}] to [{offset:04x}]"); ram.write(&offset, &value); diff --git a/core/src/periph/mod.rs b/core/src/periph/mod.rs index a507e5a..0f30a79 100644 --- a/core/src/periph/mod.rs +++ b/core/src/periph/mod.rs @@ -1,6 +1,5 @@ pub mod rom_chip; pub mod at28c256; -pub mod ram_chip; pub mod hm62256; - +pub mod ram_chip; diff --git a/core/tests/execution_tests.rs b/core/tests/execution_tests.rs index e69de29..8b13789 100644 --- a/core/tests/execution_tests.rs +++ b/core/tests/execution_tests.rs @@ -0,0 +1 @@ + diff --git a/core/tests/instruction_encode_decode.rs b/core/tests/instruction_encode_decode.rs index e69de29..8b13789 100644 --- a/core/tests/instruction_encode_decode.rs +++ b/core/tests/instruction_encode_decode.rs @@ -0,0 +1 @@ +