start of rom_only PC

This commit is contained in:
2025-07-07 07:36:41 -04:00
parent b9242b1943
commit 9c672741ed
23 changed files with 349 additions and 114 deletions
+717
View File
@@ -0,0 +1,717 @@
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::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 log::trace;
pub struct Mos6502Cpu {
pub(crate) memory: [u8; SIZE_64KB],
/// accumulator
pub(crate) a: u8,
/// x register
pub(crate) x: u8,
/// y register
pub(crate) y: u8,
/// cpu flags
pub(crate) flags: Mos6502Flags,
/// program counter
pub pc: u16,
/// stack offset
pub(crate) s: u8,
pub microcode_step: u8,
pub(crate) address_bus: u16,
pub(crate) data_bus: u8,
pub(crate) ir: Instruction, // Instruction Register
pub(crate) oi: OpInfo,
pub(crate) has_reset: bool,
pub(crate) iv: u16, // Interrupt Vector
pub(crate) cycle_carry: u16, // Value to hold between microsteps
pub(crate) ir_bytes: [u8; 4],
/// CPU Read signal
pub read_signal: bool,
pub(crate) reset_vector: u16,
pub(crate) int_vector: u16
}
impl Mos6502Cpu {
/// set_data_bus
///
/// Sets data on the data bus.
/// Used when CPU is in "R" mode
pub fn set_data_bus(&mut self, to_set: u8) {
self.data_bus = to_set;
}
}
impl Default for Mos6502Cpu {
fn default() -> Self {
let mut working = Mos6502Cpu {
memory: [0x00; SIZE_64KB],
a: 0x00,
x: 0x00,
y: 0x00,
flags: Default::default(),
pc: 0xfffd,
s: 0x00,
microcode_step: 0x00,
address_bus: 0x00,
data_bus: 0x00,
ir: Instruction {
op: Operation::NOP,
mode: AddressMode::Implied,
operand: Operand::None,
},
oi: INSTRUCTION_TABLE[ISA_OP_NOP as usize].unwrap(),
has_reset: false,
iv: 0xfffe,
cycle_carry: 0x0000,
ir_bytes: [0x00; 4],
read_signal: true,
reset_vector: 0x0000,
int_vector: 0x0000
};
working.reset_cpu();
working
}
}
impl Mos6502Cpu {
pub fn address_bus(&self) -> u16 {
self.address_bus
}
pub fn data_bus(&self) -> u8 {
self.data_bus
}
//
// fn read_word(&self, offset: &u16) -> u16 {
// println!("READING OFFSET 0x{offset:04x} and 0x{:04x}", offset + 1);
// let low = self.memory[*offset as usize];
// let high = self.memory[*offset as usize + 1];
// println!("LOW = 0x{low:02x} HIGH = 0x{high:02x}");
// let result = (high as u16) << 8 | low as u16;
// // println!("MEMORY: {:?}", self.memory);
// println!("READ {result:04x}");
// result
// }
pub fn peek_flag(&self, flag_to_read: Mos6502Flag) -> bool {
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)
}
}
pub fn peek(&self, offset: u16) -> u8 {
self.memory[offset as usize]
}
pub fn poke(&mut self, offset: u16, value: u8) {
println!("Setting memory at {offset:04x} to {value:02x}");
self.memory[offset as usize] = value
}
pub fn peek_a(&self) -> u8 {
println!("Readding register A => 0x{:02x}", self.a);
self.a
}
pub fn poke_a(&mut self, new_a: u8) {
println!("Updating register A from [{}] to [{}]", self.a, new_a);
self.a = new_a;
}
pub fn peek_x(&self) -> u8 {
println!("Readding register X => 0x{}", self.x);
self.x
}
pub fn poke_x(&mut self, new_x: u8) {
println!("Updating register X from [{}] to [{}]", self.x, new_x);
self.x = new_x
}
pub fn peek_y(&self) -> u8 {
self.y
}
pub fn poke_y(&mut self, new_y: u8) {
self.y = new_y
}
fn advance_pc(&mut self, how_far: u16) {
self.pc += how_far;
}
fn set_pc_to(&mut self, new_pc: u16) {
self.pc = new_pc;
}
/// 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");
let offset = self.pc as usize;
// TODO: this calls opinfo 2x
self.oi = Instruction::opinfo(&self.memory[offset..offset + 4]).unwrap();
self.ir = Instruction::decode(&self.memory[offset..offset + 4]).unwrap();
self.microcode_step = self.oi.cycles;
println!("Decoded [[{:?}]]", self.ir);
self.advance_pc(self.oi.length as u16);
// load the microstep buffer with what steps to run
// 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
);
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::AND => {}
Operation::ASL => {}
Operation::BCC => {}
Operation::BCS => {}
Operation::BEQ => {}
Operation::BIT => {}
Operation::BMI => {}
Operation::BNE => {}
Operation::BPL => {}
Operation::BRK => {}
Operation::BVC => {}
Operation::BVS => {}
Operation::CLC => {
self.flags.clear_flag(Carry);
}
Operation::CLD => {
self.flags.clear_flag(Decimal);
}
Operation::CLI => {
self.flags.clear_flag(Interrupt);
}
Operation::CLV => {
self.flags.clear_flag(Overflow);
}
Operation::CMP => {}
Operation::CPX => {}
Operation::CPY => {}
Operation::DEC => {
match self.microcode_step {
// DEC Step 1
1 => {
let working_value = match self.oi.mode {
AddressMode::ZeroPage => {
// read from
let offset = match self.ir.operand {
Operand::Byte(z) => z,
_ => 0x00,
};
trace!("READING FROM MEMORY AT 0x{offset:04x}");
self.memory[offset as usize]
// self.peek(offset);
}
AddressMode::ZeroPageX => {
let offset = match self.ir.operand {
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,
};
// self.memory.peek(offset)
self.memory[offset as usize]
}
AddressMode::AbsoluteX => {
let offset = match self.ir.operand {
Operand::Word(offset) => offset,
_ => 0x00,
};
// self.memory.peek(offset + self.x);
self.memory[offset as usize]
}
_ => 0x00,
};
}
// DEC write memory
2 => {
self.a = self.cycle_carry as u8;
}
_ => {}
}
}
Operation::DEX => {
if self.microcode_step == 1 {
let (new_x, new_carry) = self.x.overflowing_sub(1);
self.poke_x(new_x);
self.poke_flag(Carry, new_carry);
}
}
Operation::DEY => {
if self.microcode_step == 1 {
(self.y, _) = self.y.overflowing_sub(1);
}
}
Operation::EOR => {}
Operation::INC => {}
Operation::INX => {
if self.microcode_step == 1 {
let (new_x, new_carry) = self.x.overflowing_add(1);
self.poke_x(new_x);
self.poke_flag(Carry, new_carry);
self.address_bus = self.pc;
self.data_bus = 0x00;
}
}
Operation::INY => {
if self.microcode_step == 1 {
let (new_y, new_carry) = self.y.overflowing_add(1);
self.poke_y(new_y);
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::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;
}
_ => {}
},
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::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 => {}
Operation::NOP => {
// do nothing.
}
Operation::ORA => {}
Operation::PHA => {}
Operation::PHP => {}
Operation::PLA => {}
Operation::PLP => {}
Operation::ROL => {
if self.microcode_step == 1 {
self.a = self.a.rotate_left(1);
}
}
Operation::ROR => {
// rotate A
if self.microcode_step == 1 {
self.a = self.a.rotate_right(1);
}
}
Operation::RTI => {}
Operation::RTS => {}
Operation::SBC => {}
Operation::SEC => {
self.flags.set_flag(Carry);
}
Operation::SED => {
self.flags.set_flag(Decimal);
}
Operation::SEI => {
self.flags.set_flag(Interrupt);
}
Operation::STA => {
match self.oi.mode {
AddressMode::ZeroPage => {
// write to the zero page.
match self.ir.operand {
Operand::Byte(target) => {
self.memory[target as usize] = self.a;
}
_ => {
// Invalid parameter
}
}
}
AddressMode::ZeroPageX => {
match self.ir.operand {
Operand::Byte(target) => {
let x = self.x;
self.memory[(x + target) as usize] = self.a;
}
_ => {
// Invalid Parameter
}
}
}
AddressMode::Absolute => {
// write from A to the specified memory location
match self.ir.operand {
Operand::Word(offset) => {
self.memory[offset as usize] = self.a;
}
_ => {
// Invalid Parameter
}
}
}
AddressMode::AbsoluteX => {
match self.ir.operand {
Operand::Word(offset) => {
self.memory[(offset + self.x as u16) as usize] = self.a;
}
_ => {
// Invalid Parameter
}
}
}
AddressMode::AbsoluteY => {
match self.ir.operand {
Operand::Word(offset) => {
self.memory[(offset + self.y as u16) as usize] = self.a;
}
_ => {
// Invalid Parameter
}
}
}
AddressMode::IndirectX => {}
AddressMode::IndirectY => {}
_ => {
// invalid memory mode
}
}
}
Operation::STX => {}
Operation::STY => {}
Operation::TAX => {
self.x = self.a;
}
Operation::TAY => {
self.y = self.a;
}
Operation::TSX => {}
Operation::TXA => {
self.a = self.x;
}
Operation::TXS => {}
Operation::TYA => {
self.y = self.a;
}
}
self.microcode_step -= 1;
}
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::constants::constants_isa_op::*;
use crate::instruction_table::{INSTRUCTION_CYCLES, INSTRUCTION_TABLE};
#[test]
fn clc() {
// setup the CPU for our test
let mut cpu = Mos6502Cpu::default();
cpu.flags.set_flag(Carry);
// Load our 'test program'
cpu.memory[0x6000] = ISA_OP_CLC;
// Start the PC at our program
cpu.pc = 0x6000;
// Tick the CPU through the instruction
for _ in 0..INSTRUCTION_CYCLES(ISA_OP_CLC) {
cpu.tick();
}
assert!(!cpu.peek_flag(Carry));
}
#[test]
fn cld() {
let mut cpu = Mos6502Cpu::default();
cpu.flags.set_flag(Decimal);
cpu.memory[0x6000] = ISA_OP_CLD;
cpu.pc = 0x6000;
for _ in 0..INSTRUCTION_CYCLES(ISA_OP_CLD) {
cpu.tick();
}
assert!(!cpu.peek_flag(Decimal));
}
#[test]
fn cli() {
let mut cpu = Mos6502Cpu::default();
cpu.flags.set_flag(Interrupt);
cpu.memory[0x6000] = ISA_OP_CLI;
cpu.pc = 0x6000;
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_CLI) {
cpu.tick();
}
assert!(!cpu.peek_flag(Interrupt));
}
#[test]
fn clv() {
let mut cpu = Mos6502Cpu::default();
cpu.flags.set_flag(Overflow);
cpu.memory[0x6000] = ISA_OP_CLV;
cpu.pc = 0x6000;
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_CLV) {
cpu.tick();
}
assert!(!cpu.peek_flag(Overflow));
}
#[test]
fn lda_immediate() {
let mut cpu = Mos6502Cpu::default();
cpu.memory[0x6000] = ISA_OP_LDA_I;
cpu.memory[0x6001] = 0xab;
cpu.pc = 0x6000;
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_LDA_I) {
cpu.tick();
}
assert_eq!(cpu.a, 0xab);
}
#[test]
fn lda_zx() {
let mut cpu = Mos6502Cpu::default();
cpu.poke_x(1);
cpu.memory[0x6000] = ISA_OP_LDA_ZX;
cpu.memory[0x6001] = 0xab;
cpu.memory[0x00ac] = 0xbe;
cpu.pc = 0x6000;
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();
assert_eq!(cpu.peek_a(), 0xbe);
assert!(!cpu.peek_flag(Zero));
assert!(!cpu.peek_flag(Carry));
assert!(!cpu.peek_flag(Negative));
}
#[test]
fn lda_zeropage() {
let mut cpu = Mos6502Cpu::default();
cpu.memory[0x6000] = ISA_OP_LDA_Z;
cpu.memory[0x6001] = 0xab;
// Load ZeroPage
cpu.memory[0x00ab] = 0xbe;
cpu.pc = 0x6000;
for _ in 0..INSTRUCTION_CYCLES(ISA_OP_LDA_Z) {
cpu.tick();
}
assert_eq!(cpu.a, 0xbe);
}
#[test]
fn lda_absolute() {
let mut cpu = Mos6502Cpu::default();
cpu.memory[0x6000] = ISA_OP_LDA_ABS;
cpu.memory[0x6001] = 0xef;
cpu.memory[0x6002] = 0x0e;
cpu.memory[0x0eef] = 0xab;
cpu.pc = 0x6000;
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_LDA_ABS) {
cpu.tick();
}
assert_eq!(cpu.a, 0xab);
}
#[test]
fn lda_absolutex() {
let mut cpu = Mos6502Cpu::default();
cpu.memory[0x6000] = ISA_OP_LDA_ABSX;
cpu.memory[0x6001] = 0xef;
cpu.memory[0x6002] = 0x0e;
cpu.poke_x(0x01);
cpu.memory[0x0ef0] = 0xab;
cpu.pc = 0x6000;
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_LDA_ABSX) {
cpu.tick();
}
assert_eq!(cpu.a, 0xab);
}
#[test]
fn lda_absolutey() {
let mut cpu = Mos6502Cpu::default();
cpu.memory[0x6000] = ISA_OP_LDA_ABSY;
cpu.memory[0x6001] = 0xef;
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();
}
assert_eq!(cpu.a, 0xab);
}
#[test]
fn dex_inx() {
let mut cpu = Mos6502Cpu::default();
cpu.x = 0xab;
cpu.memory[0x6000] = ISA_OP_DEX;
cpu.memory[0x6001] = ISA_OP_INX;
cpu.pc = 0x6000;
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();
}
assert_eq!(0xab, cpu.x);
}
#[test]
fn dey_iny() {
let mut cpu = Mos6502Cpu::default();
cpu.poke_y(0xab);
cpu.memory[0x6000] = ISA_OP_DEY;
cpu.memory[0x6001] = ISA_OP_INY;
cpu.pc = 0x6000;
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();
}
assert_eq!(0xab, cpu.peek_y());
}
#[test]
fn rol_a_ror_a() {
let mut cpu = Mos6502Cpu::default();
cpu.poke_a(0b1010_1010); // 0xaa
cpu.memory[0x6000] = ISA_OP_ROL_A;
cpu.memory[0x6001] = ISA_OP_ROR_A;
cpu.pc = 0x6000;
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();
}
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);;
}
}
+35
View File
@@ -0,0 +1,35 @@
use crate::mos6502cpu::cpu::Mos6502Cpu;
impl Mos6502Cpu {
/// 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, u16, u16) {
(
self.pc,
self.a,
self.x,
self.y,
self.address_bus,
self.data_bus,
self.microcode_step,
self.reset_vector,
self.int_vector
)
}
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()
);
}
}
+6
View File
@@ -0,0 +1,6 @@
pub mod cpu;
pub mod new;
pub mod tick2;
mod dbg;
mod tick_stages;
+26
View File
@@ -0,0 +1,26 @@
use crate::constants::constants_system::{OFFSET_RESET_VECTOR, SIZE_64KB};
use crate::mos6502cpu::cpu::Mos6502Cpu;
impl Mos6502Cpu {
pub fn new() -> Mos6502Cpu {
let array = [0x00u8; SIZE_64KB];
let mut working = Mos6502Cpu {
memory: array,
ir_bytes: [0x00; 4],
..Default::default()
};
working.reset_cpu();
working
}
pub(crate) fn reset_cpu(&mut self) {
self.microcode_step = 7 + 4;
// self = &mut Mos6502Cpu::default();
println!("Should tick 7 times, then 4 cycles to read the reset and int vectors.");
// read the value at 0xfffc 0xfffd for our reset vector.
// read the value at 0xfffe 0xffff for our int vector
}
}
+64
View File
@@ -0,0 +1,64 @@
use crate::constants::constants_system::{OFFSET_INT_VECTOR, OFFSET_RESET_VECTOR};
use crate::mos6502cpu::cpu::Mos6502Cpu;
impl Mos6502Cpu {
/// AccurateTick
///
/// In: address_bus > Address of data operationm
/// data_bus > Data read or written
/// State:
/// read_bus > Flag for if cpu is reading or writing the data bus
/// cycle_step > Index for what step of the Decode->Load->Execute cycle we are in
/// Out: address_bus > address for operation
/// data_bus > data for the operation
/// read_bus > lets rest of the computer know if the CPU is reading from the address
/// provided or if we are writing to the address
pub fn tick2(&mut self, address_bus: u16, data_bus: u8) -> (u16, u8, bool) {
if self.has_reset {
// we have completed the reset cycle
if self.read_signal {
// we should see new data in the data_bus for us
let read_data = data_bus;
} else {
// we are writing to the bus.
}
} else {
println!("Reset microstep {}", self.microcode_step);
// we need to do the reset steps
// reduce the number of remaining microsteps
self.read_signal = true;
match self.microcode_step {
4 => {
// read first byte of reset vector
self.address_bus = OFFSET_RESET_VECTOR;
}
3 => {
// at this point data holds the upper byte of our reset vector
self.reset_vector = (data_bus as u16) << 8;
// read secondd byte of reset vector
self.address_bus = OFFSET_RESET_VECTOR + 1;
}
2 => {
self.reset_vector |= data_bus as u16;
println!("Loaded reset vector of 0x{:04x}", self.reset_vector);
// read first byte of interrupt vector
self.address_bus = OFFSET_INT_VECTOR;
}
1 => {
// read second byte of interrupt vector
self.address_bus = OFFSET_INT_VECTOR + 1;
}
0 => {
self.int_vector |= data_bus as u16;
println!("Loaded interrupt vector of 0x{:04x}", self.int_vector);
self.pc = self.reset_vector;
println!("Set PC to Reset Vector. Giddy-up!");
}
_ => {
}
}
self.microcode_step -= 1;
}
(self.address_bus, self.data_bus, self.read_signal)
}
}
+19
View File
@@ -0,0 +1,19 @@
/// Mos6502TickStates
///
/// The set of what a tick can be doing
///
enum Mos6502TickStates {
/// Loading the first byte into the IR
LoadingInstruction,
/// Loading an 8 bit parameter
Loading8BitParameter,
/// Loading the MSB 8 bits
Loading16BitParameter1,
/// Loading the LSB 8 bits
Loading16BitParameter2,
/// Stalling for accurate emulation
Stall(u8),
/// Completed the instruction
Complete
}