diff --git a/gameboy-lib/src/cpu/command/alu_commands.rs b/gameboy-lib/src/cpu/command/alu_commands.rs new file mode 100644 index 0000000..62c5ca2 --- /dev/null +++ b/gameboy-lib/src/cpu/command/alu_commands.rs @@ -0,0 +1,274 @@ +use crate::cpu::{instructions::ArithmeticInstruction, registers::Register, Cpu, FlagUpdate}; + +use super::Command; + +pub struct ArithmeticCommand<'a> { + instruction: &'a ArithmeticInstruction, + cpu: &'a mut Cpu, +} + +impl<'a> ArithmeticCommand<'a> { + pub fn new(instruction: &'a ArithmeticInstruction, cpu: &'a mut Cpu) -> ArithmeticCommand<'a> { + ArithmeticCommand { instruction, cpu } + } + + fn alu_operation16(&mut self, instruction: &ArithmeticInstruction, op: F) -> u16 + where + F: Fn(u16, u16) -> (u16, Vec), + { + let (value, pc) = match instruction { + ArithmeticInstruction::Add16(from) => { + let value = self.cpu.registers.get_16(&from); + (value, self.cpu.pc.wrapping_add(1)) + } + ArithmeticInstruction::Add16SP => { + let n = self.cpu.memory.read(self.cpu.pc + 1) as u16; + let sp = self.cpu.registers.get_16(&Register::SP); + let result = sp.wrapping_add(n); + (result as u16, self.cpu.pc.wrapping_add(2)) + } + _ => panic!("[CPU] Invalid instruction {:?}", instruction), + }; + + let hl = self.cpu.registers.get_16(&Register::HL); + let (result, flag_update) = op(hl, value); + + if let ArithmeticInstruction::Add16SP = instruction { + self.cpu.registers.set_16(&Register::SP, value) + } else { + self.cpu.registers.set_16(&Register::HL, result); + } + + for flag in flag_update { + self.cpu.update_flag(flag); + } + + return pc; + } + + fn alu_operation(&mut self, instruction: &ArithmeticInstruction, op: F) -> u16 + where + F: Fn(u8, u8) -> (u8, Vec), + { + let (value, pc) = match instruction { + ArithmeticInstruction::Cp(from) + | ArithmeticInstruction::Xor(from) + | ArithmeticInstruction::And(from) + | ArithmeticInstruction::Or(from) + | ArithmeticInstruction::Add(from) + | ArithmeticInstruction::Sub(from) => self.cpu.extract_operand(&from), + ArithmeticInstruction::Adc(from) | ArithmeticInstruction::Sbc(from) => { + let (mut value, pc) = self.cpu.extract_operand(&from); + if self.cpu.registers.f.carry { + value = value.wrapping_add(1); + } + (value, pc) + } + _ => panic!("[CPU] Invalid instruction {:?}", instruction), + }; + + let a = self.cpu.registers.get(&Register::A); + let (result, flag_update) = op(a, value); + self.cpu.registers.set(&Register::A, result); + + for flag in flag_update { + self.cpu.update_flag(flag); + } + + return pc; + } + + fn and(&mut self, instruction: &ArithmeticInstruction) -> u16 { + self.alu_operation(instruction, |a, b| { + let result = a & b; + ( + result, + vec![ + FlagUpdate::Zero(result == 0), + FlagUpdate::Subtract(false), + FlagUpdate::HalfCarry(true), + FlagUpdate::Carry(false), + ], + ) + }) + } + + fn or(&mut self, instruction: &ArithmeticInstruction) -> u16 { + self.alu_operation(instruction, |a, b| { + let result = a | b; + ( + result, + vec![ + FlagUpdate::Zero(result == 0), + FlagUpdate::Subtract(false), + FlagUpdate::HalfCarry(false), + FlagUpdate::Carry(false), + ], + ) + }) + } + + fn xor(&mut self, instruction: &ArithmeticInstruction) -> u16 { + self.alu_operation(instruction, |a, b| { + let result = a ^ b; + ( + result, + vec![ + FlagUpdate::Zero(result == 0), + FlagUpdate::Subtract(false), + FlagUpdate::HalfCarry(false), + FlagUpdate::Carry(false), + ], + ) + }) + } + + fn compare(&mut self, instruction: &ArithmeticInstruction) -> u16 { + self.alu_operation(instruction, |a, b| { + let result = a.wrapping_sub(b); + ( + a, + vec![ + FlagUpdate::Zero(result == 0), + FlagUpdate::Subtract(true), + FlagUpdate::HalfCarry((a & 0xF) < (b & 0xF)), + FlagUpdate::Carry(a < b), + ], + ) + }) + } + + fn inc(&mut self, register: &Register) -> u16 { + let value = match ®ister { + Register::HL => self + .cpu + .memory + .read(self.cpu.registers.get_16(&Register::HL)), + _ => self.cpu.registers.get(®ister), + }; + + let result = value.wrapping_add(1); + + self.cpu.registers.f.zero = result == 0; + self.cpu.registers.f.subtract = false; + self.cpu.registers.f.half_carry = (value & 0xF) == 0xF; + + if let Register::HL = register { + self.cpu + .memory + .write(self.cpu.registers.get_16(&Register::HL), result); + } else { + self.cpu.registers.set(®ister, result); + } + + self.cpu.pc.wrapping_add(1) + } + + fn inc16(&mut self, register: &Register) -> u16 { + let value = self.cpu.registers.get_16(®ister); + let result = value.wrapping_add(1); + self.cpu.registers.set_16(®ister, result); + + self.cpu.pc.wrapping_add(1) + } + + fn dec(&mut self, register: &Register) -> u16 { + let value = match ®ister { + Register::HL => self + .cpu + .memory + .read(self.cpu.registers.get_16(&Register::HL)), + _ => self.cpu.registers.get(®ister), + }; + + let result = value.wrapping_sub(1); + + self.cpu.registers.f.zero = result == 0; + self.cpu.registers.f.subtract = true; + self.cpu.registers.f.half_carry = (value & 0xF) == 0x0; + + if let Register::HL = register { + self.cpu + .memory + .write(self.cpu.registers.get_16(&Register::HL), result); + } else { + self.cpu.registers.set(®ister, result); + } + + self.cpu.pc.wrapping_add(1) + } + + fn dec16(&mut self, register: &Register) -> u16 { + let value = self.cpu.registers.get_16(®ister); + let result = value.wrapping_sub(1); + self.cpu.registers.set_16(®ister, result); + + self.cpu.pc.wrapping_add(1) + } + + fn add(&mut self, instruction: &ArithmeticInstruction) -> u16 { + self.alu_operation(instruction, |a, b| { + let (result, did_overflow) = a.overflowing_add(b); + ( + result, + vec![ + FlagUpdate::Zero(result == 0), + FlagUpdate::Subtract(false), + FlagUpdate::HalfCarry(((a & 0x0F) + (b & 0x0F)) & 0x10 == 0x10), + FlagUpdate::Carry(did_overflow), + ], + ) + }) + } + + fn add16(&mut self, instruction: &ArithmeticInstruction) -> u16 { + self.alu_operation16(&instruction, |a, b| { + let (result, did_overflow) = a.overflowing_add(b); + ( + result, + vec![ + FlagUpdate::Zero(false), + FlagUpdate::Subtract(false), + FlagUpdate::HalfCarry(((a & 0x0FFF) + (b & 0x0FFF)) & 0x1000 == 0x1000), + FlagUpdate::Carry(did_overflow), + ], + ) + }) + } + + fn sub(&mut self, instruction: &ArithmeticInstruction) -> u16 { + self.alu_operation(instruction, |a, b| { + let (result, did_overflow) = a.overflowing_sub(b); + ( + result, + vec![ + FlagUpdate::Zero(result == 0), + FlagUpdate::Subtract(true), + FlagUpdate::HalfCarry((a & 0xF) < (b & 0xF)), + FlagUpdate::Carry(did_overflow), + ], + ) + }) + } +} + +impl Command for ArithmeticCommand<'_> { + fn execute(&mut self) -> u16 { + let instruction = &self.instruction; + match instruction { + ArithmeticInstruction::Add(_) | ArithmeticInstruction::Adc(_) => self.add(instruction), + ArithmeticInstruction::Add16(_) | ArithmeticInstruction::Add16SP => { + self.add16(instruction) + } + ArithmeticInstruction::Sub(_) | ArithmeticInstruction::Sbc(_) => self.sub(instruction), + ArithmeticInstruction::And(_) => self.and(instruction), + ArithmeticInstruction::Or(_) => self.or(instruction), + ArithmeticInstruction::Xor(_) => self.xor(instruction), + ArithmeticInstruction::Cp(_) => self.compare(instruction), + ArithmeticInstruction::Inc(register) => self.inc(®ister), + ArithmeticInstruction::Inc16(register) => self.inc16(®ister), + ArithmeticInstruction::Dec(register) => self.dec(®ister), + ArithmeticInstruction::Dec16(register) => self.dec16(®ister), + } + } +} diff --git a/gameboy-lib/src/cpu/command/load_commands.rs b/gameboy-lib/src/cpu/command/load_commands.rs new file mode 100644 index 0000000..f9a7fa3 --- /dev/null +++ b/gameboy-lib/src/cpu/command/load_commands.rs @@ -0,0 +1,208 @@ +use crate::cpu::instructions::LoadInstruction; +use crate::cpu::registers::Register; +use crate::cpu::Cpu; + +use super::Command; + +pub struct LoadCommand<'a> { + instruction: &'a LoadInstruction, + cpu: &'a mut Cpu, +} + +impl<'a> LoadCommand<'a> { + pub fn new(instruction: &'a LoadInstruction, cpu: &'a mut Cpu) -> LoadCommand<'a> { + LoadCommand { instruction, cpu } + } + + fn push(&mut self, register: &Register) -> u16 { + let value = self.cpu.registers.get_16(®ister); + let next_sp = self.cpu.registers.sp.get().wrapping_sub(2); + self.cpu.registers.sp.set(next_sp); + self.cpu.memory.write_16(self.cpu.registers.sp.get(), value); + + self.cpu.pc.wrapping_add(1) + } + + fn pop(&mut self, register: &Register) -> u16 { + let value = self.cpu.memory.read_16(self.cpu.registers.sp.get()); + self.cpu.registers.set_16(®ister, value); + self.cpu + .registers + .sp + .set(self.cpu.registers.sp.get().wrapping_add(2)); + + self.cpu.pc.wrapping_add(1) + } + + fn load_8(&mut self, instruction: &LoadInstruction) -> u16 { + match instruction { + LoadInstruction::Ld8(to, from) => match (&to, &from) { + (Register::BC | Register::DE | Register::HL | Register::AF, Register::D8) => { + let value = self.cpu.memory.read(self.cpu.pc + 1); + let address = self.cpu.registers.get_16(&to); + self.cpu.memory.write(address, value); + + self.cpu.pc.wrapping_add(2) + } + (Register::BC | Register::DE | Register::HL | Register::AF, from) => { + let value = self.cpu.registers.get(from); + let address = self.cpu.registers.get_16(&to); + self.cpu.memory.write(address, value); + + self.cpu.pc.wrapping_add(1) + } + (Register::D16, from) => { + let value = self.cpu.registers.get(from); + let address = self.cpu.memory.read_16(self.cpu.pc + 1); + self.cpu.memory.write(address, value); + + self.cpu.pc.wrapping_add(3) + } + (to, Register::HL | Register::BC | Register::DE | Register::AF) => { + let address = self.cpu.registers.get_16(&from); + let value = self.cpu.memory.read(address); + self.cpu.registers.set(to, value); + + self.cpu.pc.wrapping_add(1) + } + (to, Register::D8) => { + let value = self.cpu.memory.read(self.cpu.pc + 1); + self.cpu.registers.set(to, value); + + self.cpu.pc.wrapping_add(2) + } + (to, Register::D16) => { + let address = self.cpu.memory.read_16(self.cpu.pc + 1); + let value = self.cpu.memory.read(address); + self.cpu.registers.set(to, value); + + self.cpu.pc.wrapping_add(3) + } + (to, from) => { + let value = self.cpu.registers.get(from); + self.cpu.registers.set(to, value); + + self.cpu.pc.wrapping_add(1) + } + }, + _ => panic!("[CPU] Invalid instruction {:?}", instruction), + } + } + + fn load_16(&mut self, instruction: &LoadInstruction) -> u16 { + match instruction { + LoadInstruction::Ld16(to, from) => match (&to, &from) { + (Register::SP, Register::HL) => { + let value = self.cpu.registers.get_16(&Register::HL); + self.cpu.registers.sp.set(value); + + self.cpu.pc.wrapping_add(1) + } + (Register::SP, Register::D8) => { + let n = self.cpu.memory.read(self.cpu.pc + 1) as u16; + let (address, did_overflow) = self.cpu.registers.sp.get().overflowing_add(n); + println!( + "[CPU] SP: 0x{:x} + 0x{:x} = 0x{:x}", + self.cpu.registers.sp.get(), + n, + address + ); + self.cpu.registers.set_16(&Register::HL, address); + + self.cpu.registers.f.zero = false; + self.cpu.registers.f.subtract = false; + self.cpu.registers.f.half_carry = + (((self.cpu.registers.sp.get() & 0xFFF) + (n & 0xFFF)) & 0x1000) == 0x1000; + self.cpu.registers.f.carry = did_overflow; + + self.cpu.pc.wrapping_add(3) + } + (Register::D16, Register::SP) => { + let address = self.cpu.memory.read_16(self.cpu.pc + 1); + self.cpu.registers.sp.set(address); + + self.cpu.pc.wrapping_add(3) + } + (Register::BC | Register::DE | Register::HL | Register::SP, Register::D16) => { + let value = self.cpu.memory.read_16(self.cpu.pc + 1); + self.cpu.registers.set_16(&to, value); + + self.cpu.pc.wrapping_add(3) + } + (to, from) => { + let value = self.cpu.registers.get_16(from); + self.cpu.registers.set_16(to, value); + + self.cpu.pc.wrapping_add(1) + } + }, + _ => panic!("[CPU] Invalid instruction {:?}", instruction), + } + } + + fn load_special(&mut self, instruction: &LoadInstruction) -> u16 { + match instruction { + LoadInstruction::LdCa => { + let address = 0xFF00 + self.cpu.registers.get(&Register::C) as u16; + let value = self.cpu.registers.get(&Register::A); + self.cpu.memory.write(address, value); + + self.cpu.pc.wrapping_add(1) + } + LoadInstruction::LdAc => { + let address = 0xFF00 + self.cpu.registers.get(&Register::C) as u16; + let value = self.cpu.memory.read(address); + self.cpu.registers.set(&Register::A, value); + + self.cpu.pc.wrapping_add(1) + } + LoadInstruction::LdNa => { + let address = 0xFF00 + self.cpu.memory.read(self.cpu.pc + 1) as u16; + let value = self.cpu.registers.get(&Register::A); + self.cpu.memory.write(address, value); + + self.cpu.pc.wrapping_add(2) + } + LoadInstruction::LdAn => { + let address = 0xFF00 + self.cpu.memory.read(self.cpu.pc + 1) as u16; + let value = self.cpu.memory.read(address); + self.cpu.registers.set(&Register::A, value); + + self.cpu.pc.wrapping_add(2) + } + LoadInstruction::LdHi => { + let address = self.cpu.registers.get_16(&Register::HL) + 1; + let value = self.cpu.registers.get(&Register::A); + self.cpu.memory.write(address, value); + + self.cpu.pc.wrapping_add(1) + } + LoadInstruction::LdHd => { + let address = self.cpu.registers.get_16(&Register::HL) - 1; + let value = self.cpu.registers.get(&Register::A); + self.cpu.memory.write(address, value); + + self.cpu.pc.wrapping_add(1) + } + _ => panic!("[CPU] Invalid instruction {:?}", instruction), + } + } +} + +impl Command for LoadCommand<'_> { + fn execute(&mut self) -> u16 { + let instruction = &self.instruction; + match instruction { + LoadInstruction::Push(register) => self.push(register), + LoadInstruction::Pop(ref register) => self.pop(register), + LoadInstruction::Ld8(_, _) => self.load_8(&self.instruction), + LoadInstruction::Ld16(_, _) => self.load_16(&self.instruction), + LoadInstruction::LdCa + | LoadInstruction::LdAc + | LoadInstruction::LdNa + | LoadInstruction::LdAn + | LoadInstruction::LdHi + | LoadInstruction::LdHd => self.load_special(&self.instruction), + } + } +} diff --git a/gameboy-lib/src/cpu/command/misc_commands.rs b/gameboy-lib/src/cpu/command/misc_commands.rs new file mode 100644 index 0000000..405818e --- /dev/null +++ b/gameboy-lib/src/cpu/command/misc_commands.rs @@ -0,0 +1,50 @@ +use crate::cpu::{instructions::MiscInstruction, registers::Register, Cpu}; + +use super::Command; + + +pub struct MiscCommand<'a> { + instruction: &'a MiscInstruction, + cpu: &'a mut Cpu, +} + +impl<'a> MiscCommand<'a> { + pub fn new(instruction: &'a MiscInstruction, cpu: &'a mut Cpu) -> MiscCommand<'a> { + MiscCommand { instruction, cpu } + } + + fn nop(&mut self) -> u16 { + self.cpu.pc.wrapping_add(1) + } + + fn swap(&mut self, from: &Register) -> u16 { + let (value, pc) = self.cpu.extract_operand(from); + let upper = value >> 4; + let lower = value << 4; + let result = upper | lower; + + if let Register::HL = from { + self.cpu.memory + .write(self.cpu.registers.get_16(&Register::HL), result); + } else { + self.cpu.registers.set(from, result); + } + + self.cpu.registers.f.zero = result == 0; + self.cpu.registers.f.subtract = false; + self.cpu.registers.f.half_carry = false; + self.cpu.registers.f.carry = false; + + return pc; + } +} + +impl Command for MiscCommand<'_> { + fn execute(&mut self) -> u16 { + match &self.instruction { + MiscInstruction::Nop => self.nop(), + MiscInstruction::Swap(from) => self.swap(from), + _ => unimplemented!(), + } + } +} diff --git a/gameboy-lib/src/cpu/command/mod.rs b/gameboy-lib/src/cpu/command/mod.rs new file mode 100644 index 0000000..1495cd1 --- /dev/null +++ b/gameboy-lib/src/cpu/command/mod.rs @@ -0,0 +1,45 @@ +use self::{alu_commands::ArithmeticCommand, load_commands::LoadCommand}; + +use super::{instructions::Instruction, Cpu}; + +pub mod alu_commands; +pub mod load_commands; +pub mod misc_commands; + +pub trait Command { + fn execute(&mut self) -> u16; +} + +pub struct CommandFactory<'a> { + cpu: &'a mut Cpu, +} + +impl<'a> CommandFactory<'a> { + pub fn new(cpu: &'a mut Cpu) -> CommandFactory<'a> { + CommandFactory { cpu } + } + + pub fn create_command(&'a mut self, instruction: &'a Instruction, prefixed: bool) -> Box { + if prefixed { + self.prefix_command(instruction) + } else { + self.command(instruction) + } + } + + fn command(&'a mut self, instruction: &'a Instruction) -> Box { + match instruction { + Instruction::Load(load_command) => Box::new(LoadCommand::new(load_command, self.cpu)), + Instruction::Arithmetic(alu_command) => Box::new(ArithmeticCommand::new(alu_command, self.cpu)), + Instruction::Misc(misc_command) => Box::new(misc_commands::MiscCommand::new(&misc_command, self.cpu)), + _ => unimplemented!(), + } + } + + fn prefix_command(&'a mut self, instruction: &'a Instruction) -> Box { + match instruction { + Instruction::Misc(misc_command) => Box::new(misc_commands::MiscCommand::new(&misc_command, self.cpu)), + _ => unimplemented!(), + } + } +} diff --git a/gameboy-lib/src/cpu/instructions.rs b/gameboy-lib/src/cpu/instructions.rs index 9d1067c..d3deec9 100644 --- a/gameboy-lib/src/cpu/instructions.rs +++ b/gameboy-lib/src/cpu/instructions.rs @@ -9,8 +9,7 @@ pub enum FlagCondition { } #[derive(Debug)] -pub enum Instruction { - Nop, // No operation +pub enum LoadInstruction { Ld8(Register, Register), // Load 8-bit value into register Ld16(Register, Register), // Load 16-bit value into register LdCa, // Load $FF00 + C into A @@ -21,21 +20,29 @@ pub enum Instruction { LdHd, // Load A into HL - 1 Push(Register), // Push register onto stack Pop(Register), // Pop register from stack - Add(Register), // Add register to A - Add16(Register), // Add register to HL - Add16SP, // Add SP to HL - Adc(Register), // Add register to A with carry - Sub(Register), // Subtract register from A - Sbc(Register), // Subtract register from A with carry - And(Register), // Logical AND register with A - Or(Register), // Logical OR register with A - Xor(Register), // Logical XOR register with A - Cp(Register), // Compare register with A - Inc(Register), // Increment register - Inc16(Register), // Increment register - Dec(Register), // Decrement register - Dec16(Register), // Decrement register +} +#[derive(Debug)] +pub enum ArithmeticInstruction { + Add(Register), // Add register to A + Add16(Register), // Add register to HL + Add16SP, // Add SP to HL + Adc(Register), // Add register to A with carry + Sub(Register), // Subtract register from A + Sbc(Register), // Subtract register from A with carry + And(Register), // Logical AND register with A + Or(Register), // Logical OR register with A + Xor(Register), // Logical XOR register with A + Cp(Register), // Compare register with A + Inc(Register), // Increment register + Inc16(Register), // Increment register + Dec(Register), // Decrement register + Dec16(Register), // Decrement register +} + +#[derive(Debug)] +pub enum MiscInstruction { + Nop, // No operation Swap(Register), // Swap upper and lower nibbles of register DAA, // Decimal adjust register A CPL, // Complement A @@ -45,7 +52,10 @@ pub enum Instruction { STOP, // Stop CPU DI, // Disable interrupts EI, // Enable interrupts +} +#[derive(Debug)] +pub enum RotateInstruction { RLCA, // Rotate A left RLA, // Rotate A left through carry RRCA, // Rotate A right @@ -57,26 +67,50 @@ pub enum Instruction { SLA(Register), // Shift register left SRA(Register), // Shift register right SRL(Register), // Shift register right +} + +#[derive(Debug)] +pub enum JumpInstruction { + Jp, // Jump to address + JpCond(FlagCondition), // Conditional jump to address + JpHL, // Jump to HL + Jr, // Jump relative + JrCond(FlagCondition), // Conditional jump relative +} +#[derive(Debug)] +pub enum BitInstruction { Bit(u8, Register), // Test bit in register Set(u8, Register), // Set bit in register Res(u8, Register), // Reset bit in register +} - Jp, // Jump to address - JpCond(FlagCondition), // Conditional jump to address - JpHL, // Jump to HL - Jr, // Jump relative - JrCond(FlagCondition), // Conditional jump relative - +#[derive(Debug)] +pub enum CallInstruction { Call, // Call address CallCond(FlagCondition), // Conditional call address +} +#[derive(Debug)] +pub enum ReturnInstruction { Rst(u8), // Restart to address Ret, // Return from subroutine RetCond(FlagCondition), // Conditional return from subroutine Reti, // Return from interrupt } +#[derive(Debug)] +pub enum Instruction { + Load(LoadInstruction), + Arithmetic(ArithmeticInstruction), + Misc(MiscInstruction), + Rotate(RotateInstruction), + Jump(JumpInstruction), + Bit(BitInstruction), + Call(CallInstruction), + Return(ReturnInstruction), +} + impl Instruction { pub fn from_byte(byte: u8, prefix: bool) -> Option { return if prefix { @@ -88,292 +122,292 @@ impl Instruction { fn from_byte_with_prefix(byte: u8) -> Option { match byte { - 0x37 => Some(Instruction::Swap(Register::A)), - 0x30 => Some(Instruction::Swap(Register::B)), - 0x31 => Some(Instruction::Swap(Register::C)), - 0x32 => Some(Instruction::Swap(Register::D)), - 0x33 => Some(Instruction::Swap(Register::E)), - 0x34 => Some(Instruction::Swap(Register::H)), - 0x35 => Some(Instruction::Swap(Register::L)), - 0x36 => Some(Instruction::Swap(Register::HL)), - - 0x07 => Some(Instruction::RLC(Register::A)), - 0x00 => Some(Instruction::RLC(Register::B)), - 0x01 => Some(Instruction::RLC(Register::C)), - 0x02 => Some(Instruction::RLC(Register::D)), - 0x03 => Some(Instruction::RLC(Register::E)), - 0x04 => Some(Instruction::RLC(Register::H)), - 0x05 => Some(Instruction::RLC(Register::L)), - 0x06 => Some(Instruction::RLC(Register::HL)), - - 0x17 => Some(Instruction::RL(Register::A)), - 0x10 => Some(Instruction::RL(Register::B)), - 0x11 => Some(Instruction::RL(Register::C)), - 0x12 => Some(Instruction::RL(Register::D)), - 0x13 => Some(Instruction::RL(Register::E)), - 0x14 => Some(Instruction::RL(Register::H)), - 0x15 => Some(Instruction::RL(Register::L)), - 0x16 => Some(Instruction::RL(Register::HL)), - - 0x0F => Some(Instruction::RRC(Register::A)), - 0x08 => Some(Instruction::RRC(Register::B)), - 0x09 => Some(Instruction::RRC(Register::C)), - 0x0A => Some(Instruction::RRC(Register::D)), - 0x0B => Some(Instruction::RRC(Register::E)), - 0x0C => Some(Instruction::RRC(Register::H)), - 0x0D => Some(Instruction::RRC(Register::L)), - 0x0E => Some(Instruction::RRC(Register::HL)), - - 0x1F => Some(Instruction::RR(Register::A)), - 0x18 => Some(Instruction::RR(Register::B)), - 0x19 => Some(Instruction::RR(Register::C)), - 0x1A => Some(Instruction::RR(Register::D)), - 0x1B => Some(Instruction::RR(Register::E)), - 0x1C => Some(Instruction::RR(Register::H)), - 0x1D => Some(Instruction::RR(Register::L)), - 0x1E => Some(Instruction::RR(Register::HL)), - - 0x27 => Some(Instruction::SLA(Register::A)), - 0x20 => Some(Instruction::SLA(Register::B)), - 0x21 => Some(Instruction::SLA(Register::C)), - 0x22 => Some(Instruction::SLA(Register::D)), - 0x23 => Some(Instruction::SLA(Register::E)), - 0x24 => Some(Instruction::SLA(Register::H)), - 0x25 => Some(Instruction::SLA(Register::L)), - 0x26 => Some(Instruction::SLA(Register::HL)), - - 0x2F => Some(Instruction::SRA(Register::A)), - 0x28 => Some(Instruction::SRA(Register::B)), - 0x29 => Some(Instruction::SRA(Register::C)), - 0x2A => Some(Instruction::SRA(Register::D)), - 0x2B => Some(Instruction::SRA(Register::E)), - 0x2C => Some(Instruction::SRA(Register::H)), - 0x2D => Some(Instruction::SRA(Register::L)), - 0x2E => Some(Instruction::SRA(Register::HL)), - - 0x3F => Some(Instruction::SRL(Register::A)), - 0x38 => Some(Instruction::SRL(Register::B)), - 0x39 => Some(Instruction::SRL(Register::C)), - 0x3A => Some(Instruction::SRL(Register::D)), - 0x3B => Some(Instruction::SRL(Register::E)), - 0x3C => Some(Instruction::SRL(Register::H)), - 0x3D => Some(Instruction::SRL(Register::L)), - 0x3E => Some(Instruction::SRL(Register::HL)), - - 0x40 => Some(Instruction::Bit(0, Register::B)), - 0x41 => Some(Instruction::Bit(0, Register::C)), - 0x42 => Some(Instruction::Bit(0, Register::D)), - 0x43 => Some(Instruction::Bit(0, Register::E)), - 0x44 => Some(Instruction::Bit(0, Register::H)), - 0x45 => Some(Instruction::Bit(0, Register::L)), - 0x46 => Some(Instruction::Bit(0, Register::HL)), - - 0x47 => Some(Instruction::Bit(1, Register::B)), - 0x48 => Some(Instruction::Bit(1, Register::C)), - 0x49 => Some(Instruction::Bit(1, Register::D)), - 0x4A => Some(Instruction::Bit(1, Register::E)), - 0x4B => Some(Instruction::Bit(1, Register::H)), - 0x4C => Some(Instruction::Bit(1, Register::L)), - 0x4D => Some(Instruction::Bit(1, Register::HL)), - 0x4E => Some(Instruction::Bit(1, Register::A)), - - 0x50 => Some(Instruction::Bit(2, Register::B)), - 0x51 => Some(Instruction::Bit(2, Register::C)), - 0x52 => Some(Instruction::Bit(2, Register::D)), - 0x53 => Some(Instruction::Bit(2, Register::E)), - 0x54 => Some(Instruction::Bit(2, Register::H)), - 0x55 => Some(Instruction::Bit(2, Register::L)), - 0x56 => Some(Instruction::Bit(2, Register::HL)), - 0x57 => Some(Instruction::Bit(2, Register::A)), - - 0x58 => Some(Instruction::Bit(3, Register::B)), - 0x59 => Some(Instruction::Bit(3, Register::C)), - 0x5A => Some(Instruction::Bit(3, Register::D)), - 0x5B => Some(Instruction::Bit(3, Register::E)), - 0x5C => Some(Instruction::Bit(3, Register::H)), - 0x5D => Some(Instruction::Bit(3, Register::L)), - 0x5E => Some(Instruction::Bit(3, Register::HL)), - 0x5F => Some(Instruction::Bit(3, Register::A)), - - 0x60 => Some(Instruction::Bit(4, Register::B)), - 0x61 => Some(Instruction::Bit(4, Register::C)), - 0x62 => Some(Instruction::Bit(4, Register::D)), - 0x63 => Some(Instruction::Bit(4, Register::E)), - 0x64 => Some(Instruction::Bit(4, Register::H)), - 0x65 => Some(Instruction::Bit(4, Register::L)), - 0x66 => Some(Instruction::Bit(4, Register::HL)), - 0x67 => Some(Instruction::Bit(4, Register::A)), - - 0x68 => Some(Instruction::Bit(5, Register::B)), - 0x69 => Some(Instruction::Bit(5, Register::C)), - 0x6A => Some(Instruction::Bit(5, Register::D)), - 0x6B => Some(Instruction::Bit(5, Register::E)), - 0x6C => Some(Instruction::Bit(5, Register::H)), - 0x6D => Some(Instruction::Bit(5, Register::L)), - 0x6E => Some(Instruction::Bit(5, Register::HL)), - 0x6F => Some(Instruction::Bit(5, Register::A)), - - 0x70 => Some(Instruction::Bit(6, Register::B)), - 0x71 => Some(Instruction::Bit(6, Register::C)), - 0x72 => Some(Instruction::Bit(6, Register::D)), - 0x73 => Some(Instruction::Bit(6, Register::E)), - 0x74 => Some(Instruction::Bit(6, Register::H)), - 0x75 => Some(Instruction::Bit(6, Register::L)), - 0x76 => Some(Instruction::Bit(6, Register::HL)), - 0x77 => Some(Instruction::Bit(6, Register::A)), - - 0x78 => Some(Instruction::Bit(7, Register::B)), - 0x79 => Some(Instruction::Bit(7, Register::C)), - 0x7A => Some(Instruction::Bit(7, Register::D)), - 0x7B => Some(Instruction::Bit(7, Register::E)), - 0x7C => Some(Instruction::Bit(7, Register::H)), - 0x7D => Some(Instruction::Bit(7, Register::L)), - 0x7E => Some(Instruction::Bit(7, Register::HL)), - 0x7F => Some(Instruction::Bit(7, Register::A)), - - 0xC0 => Some(Instruction::Set(0, Register::B)), - 0xC1 => Some(Instruction::Set(0, Register::C)), - 0xC2 => Some(Instruction::Set(0, Register::D)), - 0xC3 => Some(Instruction::Set(0, Register::E)), - 0xC4 => Some(Instruction::Set(0, Register::H)), - 0xC5 => Some(Instruction::Set(0, Register::L)), - 0xC6 => Some(Instruction::Set(0, Register::HL)), - 0xC7 => Some(Instruction::Set(0, Register::A)), - - 0xC8 => Some(Instruction::Set(1, Register::B)), - 0xC9 => Some(Instruction::Set(1, Register::C)), - 0xCA => Some(Instruction::Set(1, Register::D)), - 0xCB => Some(Instruction::Set(1, Register::E)), - 0xCC => Some(Instruction::Set(1, Register::H)), - 0xCD => Some(Instruction::Set(1, Register::L)), - 0xCE => Some(Instruction::Set(1, Register::HL)), - 0xCF => Some(Instruction::Set(1, Register::A)), - - 0xD0 => Some(Instruction::Set(2, Register::B)), - 0xD1 => Some(Instruction::Set(2, Register::C)), - 0xD2 => Some(Instruction::Set(2, Register::D)), - 0xD3 => Some(Instruction::Set(2, Register::E)), - 0xD4 => Some(Instruction::Set(2, Register::H)), - 0xD5 => Some(Instruction::Set(2, Register::L)), - 0xD6 => Some(Instruction::Set(2, Register::HL)), - 0xD7 => Some(Instruction::Set(2, Register::A)), - - 0xD8 => Some(Instruction::Set(3, Register::B)), - 0xD9 => Some(Instruction::Set(3, Register::C)), - 0xDA => Some(Instruction::Set(3, Register::D)), - 0xDB => Some(Instruction::Set(3, Register::E)), - 0xDC => Some(Instruction::Set(3, Register::H)), - 0xDD => Some(Instruction::Set(3, Register::L)), - 0xDE => Some(Instruction::Set(3, Register::HL)), - 0xDF => Some(Instruction::Set(3, Register::A)), - - 0xE0 => Some(Instruction::Set(4, Register::B)), - 0xE1 => Some(Instruction::Set(4, Register::C)), - 0xE2 => Some(Instruction::Set(4, Register::D)), - 0xE3 => Some(Instruction::Set(4, Register::E)), - 0xE4 => Some(Instruction::Set(4, Register::H)), - 0xE5 => Some(Instruction::Set(4, Register::L)), - 0xE6 => Some(Instruction::Set(4, Register::HL)), - 0xE7 => Some(Instruction::Set(4, Register::A)), - - 0xE8 => Some(Instruction::Set(5, Register::B)), - 0xE9 => Some(Instruction::Set(5, Register::C)), - 0xEA => Some(Instruction::Set(5, Register::D)), - 0xEB => Some(Instruction::Set(5, Register::E)), - 0xEC => Some(Instruction::Set(5, Register::H)), - 0xED => Some(Instruction::Set(5, Register::L)), - 0xEE => Some(Instruction::Set(5, Register::HL)), - 0xEF => Some(Instruction::Set(5, Register::A)), - - 0xF0 => Some(Instruction::Set(6, Register::B)), - 0xF1 => Some(Instruction::Set(6, Register::C)), - 0xF2 => Some(Instruction::Set(6, Register::D)), - 0xF3 => Some(Instruction::Set(6, Register::E)), - 0xF4 => Some(Instruction::Set(6, Register::H)), - 0xF5 => Some(Instruction::Set(6, Register::L)), - 0xF6 => Some(Instruction::Set(6, Register::HL)), - 0xF7 => Some(Instruction::Set(6, Register::A)), - - 0xF8 => Some(Instruction::Set(7, Register::B)), - 0xF9 => Some(Instruction::Set(7, Register::C)), - 0xFA => Some(Instruction::Set(7, Register::D)), - 0xFB => Some(Instruction::Set(7, Register::E)), - 0xFC => Some(Instruction::Set(7, Register::H)), - 0xFD => Some(Instruction::Set(7, Register::L)), - 0xFE => Some(Instruction::Set(7, Register::HL)), - 0xFF => Some(Instruction::Set(7, Register::A)), - - 0x80 => Some(Instruction::Res(0, Register::B)), - 0x81 => Some(Instruction::Res(0, Register::C)), - 0x82 => Some(Instruction::Res(0, Register::D)), - 0x83 => Some(Instruction::Res(0, Register::E)), - 0x84 => Some(Instruction::Res(0, Register::H)), - 0x85 => Some(Instruction::Res(0, Register::L)), - 0x86 => Some(Instruction::Res(0, Register::HL)), - 0x87 => Some(Instruction::Res(0, Register::A)), - - 0x88 => Some(Instruction::Res(1, Register::B)), - 0x89 => Some(Instruction::Res(1, Register::C)), - 0x8A => Some(Instruction::Res(1, Register::D)), - 0x8B => Some(Instruction::Res(1, Register::E)), - 0x8C => Some(Instruction::Res(1, Register::H)), - 0x8D => Some(Instruction::Res(1, Register::L)), - 0x8E => Some(Instruction::Res(1, Register::HL)), - 0x8F => Some(Instruction::Res(1, Register::A)), - - 0x90 => Some(Instruction::Res(2, Register::B)), - 0x91 => Some(Instruction::Res(2, Register::C)), - 0x92 => Some(Instruction::Res(2, Register::D)), - 0x93 => Some(Instruction::Res(2, Register::E)), - 0x94 => Some(Instruction::Res(2, Register::H)), - 0x95 => Some(Instruction::Res(2, Register::L)), - 0x96 => Some(Instruction::Res(2, Register::HL)), - 0x97 => Some(Instruction::Res(2, Register::A)), - - 0x98 => Some(Instruction::Res(3, Register::B)), - 0x99 => Some(Instruction::Res(3, Register::C)), - 0x9A => Some(Instruction::Res(3, Register::D)), - 0x9B => Some(Instruction::Res(3, Register::E)), - 0x9C => Some(Instruction::Res(3, Register::H)), - 0x9D => Some(Instruction::Res(3, Register::L)), - 0x9E => Some(Instruction::Res(3, Register::HL)), - 0x9F => Some(Instruction::Res(3, Register::A)), - - 0xA0 => Some(Instruction::Res(4, Register::B)), - 0xA1 => Some(Instruction::Res(4, Register::C)), - 0xA2 => Some(Instruction::Res(4, Register::D)), - 0xA3 => Some(Instruction::Res(4, Register::E)), - 0xA4 => Some(Instruction::Res(4, Register::H)), - 0xA5 => Some(Instruction::Res(4, Register::L)), - 0xA6 => Some(Instruction::Res(4, Register::HL)), - 0xA7 => Some(Instruction::Res(4, Register::A)), - - 0xA8 => Some(Instruction::Res(5, Register::B)), - 0xA9 => Some(Instruction::Res(5, Register::C)), - 0xAA => Some(Instruction::Res(5, Register::D)), - 0xAB => Some(Instruction::Res(5, Register::E)), - 0xAC => Some(Instruction::Res(5, Register::H)), - 0xAD => Some(Instruction::Res(5, Register::L)), - 0xAE => Some(Instruction::Res(5, Register::HL)), - 0xAF => Some(Instruction::Res(5, Register::A)), - - 0xB0 => Some(Instruction::Res(6, Register::B)), - 0xB1 => Some(Instruction::Res(6, Register::C)), - 0xB2 => Some(Instruction::Res(6, Register::D)), - 0xB3 => Some(Instruction::Res(6, Register::E)), - 0xB4 => Some(Instruction::Res(6, Register::H)), - 0xB5 => Some(Instruction::Res(6, Register::L)), - 0xB6 => Some(Instruction::Res(6, Register::HL)), - 0xB7 => Some(Instruction::Res(6, Register::A)), - - 0xB8 => Some(Instruction::Res(7, Register::B)), - 0xB9 => Some(Instruction::Res(7, Register::C)), - 0xBA => Some(Instruction::Res(7, Register::D)), - 0xBB => Some(Instruction::Res(7, Register::E)), - 0xBC => Some(Instruction::Res(7, Register::H)), - 0xBD => Some(Instruction::Res(7, Register::L)), - 0xBE => Some(Instruction::Res(7, Register::HL)), - 0xBF => Some(Instruction::Res(7, Register::A)), + 0x37 => Some(Instruction::Misc(MiscInstruction::Swap(Register::A))), + 0x30 => Some(Instruction::Misc(MiscInstruction::Swap(Register::B))), + 0x31 => Some(Instruction::Misc(MiscInstruction::Swap(Register::C))), + 0x32 => Some(Instruction::Misc(MiscInstruction::Swap(Register::D))), + 0x33 => Some(Instruction::Misc(MiscInstruction::Swap(Register::E))), + 0x34 => Some(Instruction::Misc(MiscInstruction::Swap(Register::H))), + 0x35 => Some(Instruction::Misc(MiscInstruction::Swap(Register::L))), + 0x36 => Some(Instruction::Misc(MiscInstruction::Swap(Register::HL))), + + 0x07 => Some(Instruction::Rotate(RotateInstruction::RLC(Register::A))), + 0x00 => Some(Instruction::Rotate(RotateInstruction::RLC(Register::B))), + 0x01 => Some(Instruction::Rotate(RotateInstruction::RLC(Register::C))), + 0x02 => Some(Instruction::Rotate(RotateInstruction::RLC(Register::D))), + 0x03 => Some(Instruction::Rotate(RotateInstruction::RLC(Register::E))), + 0x04 => Some(Instruction::Rotate(RotateInstruction::RLC(Register::H))), + 0x05 => Some(Instruction::Rotate(RotateInstruction::RLC(Register::L))), + 0x06 => Some(Instruction::Rotate(RotateInstruction::RLC(Register::HL))), + + 0x17 => Some(Instruction::Rotate(RotateInstruction::RL(Register::A))), + 0x10 => Some(Instruction::Rotate(RotateInstruction::RL(Register::B))), + 0x11 => Some(Instruction::Rotate(RotateInstruction::RL(Register::C))), + 0x12 => Some(Instruction::Rotate(RotateInstruction::RL(Register::D))), + 0x13 => Some(Instruction::Rotate(RotateInstruction::RL(Register::E))), + 0x14 => Some(Instruction::Rotate(RotateInstruction::RL(Register::H))), + 0x15 => Some(Instruction::Rotate(RotateInstruction::RL(Register::L))), + 0x16 => Some(Instruction::Rotate(RotateInstruction::RL(Register::HL))), + + 0x0F => Some(Instruction::Rotate(RotateInstruction::RRC(Register::A))), + 0x08 => Some(Instruction::Rotate(RotateInstruction::RRC(Register::B))), + 0x09 => Some(Instruction::Rotate(RotateInstruction::RRC(Register::C))), + 0x0A => Some(Instruction::Rotate(RotateInstruction::RRC(Register::D))), + 0x0B => Some(Instruction::Rotate(RotateInstruction::RRC(Register::E))), + 0x0C => Some(Instruction::Rotate(RotateInstruction::RRC(Register::H))), + 0x0D => Some(Instruction::Rotate(RotateInstruction::RRC(Register::L))), + 0x0E => Some(Instruction::Rotate(RotateInstruction::RRC(Register::HL))), + + 0x1F => Some(Instruction::Rotate(RotateInstruction::RR(Register::A))), + 0x18 => Some(Instruction::Rotate(RotateInstruction::RR(Register::B))), + 0x19 => Some(Instruction::Rotate(RotateInstruction::RR(Register::C))), + 0x1A => Some(Instruction::Rotate(RotateInstruction::RR(Register::D))), + 0x1B => Some(Instruction::Rotate(RotateInstruction::RR(Register::E))), + 0x1C => Some(Instruction::Rotate(RotateInstruction::RR(Register::H))), + 0x1D => Some(Instruction::Rotate(RotateInstruction::RR(Register::L))), + 0x1E => Some(Instruction::Rotate(RotateInstruction::RR(Register::HL))), + + 0x27 => Some(Instruction::Rotate(RotateInstruction::SLA(Register::A))), + 0x20 => Some(Instruction::Rotate(RotateInstruction::SLA(Register::B))), + 0x21 => Some(Instruction::Rotate(RotateInstruction::SLA(Register::C))), + 0x22 => Some(Instruction::Rotate(RotateInstruction::SLA(Register::D))), + 0x23 => Some(Instruction::Rotate(RotateInstruction::SLA(Register::E))), + 0x24 => Some(Instruction::Rotate(RotateInstruction::SLA(Register::H))), + 0x25 => Some(Instruction::Rotate(RotateInstruction::SLA(Register::L))), + 0x26 => Some(Instruction::Rotate(RotateInstruction::SLA(Register::HL))), + + 0x2F => Some(Instruction::Rotate(RotateInstruction::SRA(Register::A))), + 0x28 => Some(Instruction::Rotate(RotateInstruction::SRA(Register::B))), + 0x29 => Some(Instruction::Rotate(RotateInstruction::SRA(Register::C))), + 0x2A => Some(Instruction::Rotate(RotateInstruction::SRA(Register::D))), + 0x2B => Some(Instruction::Rotate(RotateInstruction::SRA(Register::E))), + 0x2C => Some(Instruction::Rotate(RotateInstruction::SRA(Register::H))), + 0x2D => Some(Instruction::Rotate(RotateInstruction::SRA(Register::L))), + 0x2E => Some(Instruction::Rotate(RotateInstruction::SRA(Register::HL))), + + 0x3F => Some(Instruction::Rotate(RotateInstruction::SRL(Register::A))), + 0x38 => Some(Instruction::Rotate(RotateInstruction::SRL(Register::B))), + 0x39 => Some(Instruction::Rotate(RotateInstruction::SRL(Register::C))), + 0x3A => Some(Instruction::Rotate(RotateInstruction::SRL(Register::D))), + 0x3B => Some(Instruction::Rotate(RotateInstruction::SRL(Register::E))), + 0x3C => Some(Instruction::Rotate(RotateInstruction::SRL(Register::H))), + 0x3D => Some(Instruction::Rotate(RotateInstruction::SRL(Register::L))), + 0x3E => Some(Instruction::Rotate(RotateInstruction::SRL(Register::HL))), + + 0x40 => Some(Instruction::Bit(BitInstruction::Bit(0, Register::B))), + 0x41 => Some(Instruction::Bit(BitInstruction::Bit(0, Register::C))), + 0x42 => Some(Instruction::Bit(BitInstruction::Bit(0, Register::D))), + 0x43 => Some(Instruction::Bit(BitInstruction::Bit(0, Register::E))), + 0x44 => Some(Instruction::Bit(BitInstruction::Bit(0, Register::H))), + 0x45 => Some(Instruction::Bit(BitInstruction::Bit(0, Register::L))), + 0x46 => Some(Instruction::Bit(BitInstruction::Bit(0, Register::HL))), + + 0x47 => Some(Instruction::Bit(BitInstruction::Bit(1, Register::B))), + 0x48 => Some(Instruction::Bit(BitInstruction::Bit(1, Register::C))), + 0x49 => Some(Instruction::Bit(BitInstruction::Bit(1, Register::D))), + 0x4A => Some(Instruction::Bit(BitInstruction::Bit(1, Register::E))), + 0x4B => Some(Instruction::Bit(BitInstruction::Bit(1, Register::H))), + 0x4C => Some(Instruction::Bit(BitInstruction::Bit(1, Register::L))), + 0x4D => Some(Instruction::Bit(BitInstruction::Bit(1, Register::HL))), + 0x4E => Some(Instruction::Bit(BitInstruction::Bit(1, Register::A))), + + 0x50 => Some(Instruction::Bit(BitInstruction::Bit(2, Register::B))), + 0x51 => Some(Instruction::Bit(BitInstruction::Bit(2, Register::C))), + 0x52 => Some(Instruction::Bit(BitInstruction::Bit(2, Register::D))), + 0x53 => Some(Instruction::Bit(BitInstruction::Bit(2, Register::E))), + 0x54 => Some(Instruction::Bit(BitInstruction::Bit(2, Register::H))), + 0x55 => Some(Instruction::Bit(BitInstruction::Bit(2, Register::L))), + 0x56 => Some(Instruction::Bit(BitInstruction::Bit(2, Register::HL))), + 0x57 => Some(Instruction::Bit(BitInstruction::Bit(2, Register::A))), + + 0x58 => Some(Instruction::Bit(BitInstruction::Bit(3, Register::B))), + 0x59 => Some(Instruction::Bit(BitInstruction::Bit(3, Register::C))), + 0x5A => Some(Instruction::Bit(BitInstruction::Bit(3, Register::D))), + 0x5B => Some(Instruction::Bit(BitInstruction::Bit(3, Register::E))), + 0x5C => Some(Instruction::Bit(BitInstruction::Bit(3, Register::H))), + 0x5D => Some(Instruction::Bit(BitInstruction::Bit(3, Register::L))), + 0x5E => Some(Instruction::Bit(BitInstruction::Bit(3, Register::HL))), + 0x5F => Some(Instruction::Bit(BitInstruction::Bit(3, Register::A))), + + 0x60 => Some(Instruction::Bit(BitInstruction::Bit(4, Register::B))), + 0x61 => Some(Instruction::Bit(BitInstruction::Bit(4, Register::C))), + 0x62 => Some(Instruction::Bit(BitInstruction::Bit(4, Register::D))), + 0x63 => Some(Instruction::Bit(BitInstruction::Bit(4, Register::E))), + 0x64 => Some(Instruction::Bit(BitInstruction::Bit(4, Register::H))), + 0x65 => Some(Instruction::Bit(BitInstruction::Bit(4, Register::L))), + 0x66 => Some(Instruction::Bit(BitInstruction::Bit(4, Register::HL))), + 0x67 => Some(Instruction::Bit(BitInstruction::Bit(4, Register::A))), + + 0x68 => Some(Instruction::Bit(BitInstruction::Bit(5, Register::B))), + 0x69 => Some(Instruction::Bit(BitInstruction::Bit(5, Register::C))), + 0x6A => Some(Instruction::Bit(BitInstruction::Bit(5, Register::D))), + 0x6B => Some(Instruction::Bit(BitInstruction::Bit(5, Register::E))), + 0x6C => Some(Instruction::Bit(BitInstruction::Bit(5, Register::H))), + 0x6D => Some(Instruction::Bit(BitInstruction::Bit(5, Register::L))), + 0x6E => Some(Instruction::Bit(BitInstruction::Bit(5, Register::HL))), + 0x6F => Some(Instruction::Bit(BitInstruction::Bit(5, Register::A))), + + 0x70 => Some(Instruction::Bit(BitInstruction::Bit(6, Register::B))), + 0x71 => Some(Instruction::Bit(BitInstruction::Bit(6, Register::C))), + 0x72 => Some(Instruction::Bit(BitInstruction::Bit(6, Register::D))), + 0x73 => Some(Instruction::Bit(BitInstruction::Bit(6, Register::E))), + 0x74 => Some(Instruction::Bit(BitInstruction::Bit(6, Register::H))), + 0x75 => Some(Instruction::Bit(BitInstruction::Bit(6, Register::L))), + 0x76 => Some(Instruction::Bit(BitInstruction::Bit(6, Register::HL))), + 0x77 => Some(Instruction::Bit(BitInstruction::Bit(6, Register::A))), + + 0x78 => Some(Instruction::Bit(BitInstruction::Bit(7, Register::B))), + 0x79 => Some(Instruction::Bit(BitInstruction::Bit(7, Register::C))), + 0x7A => Some(Instruction::Bit(BitInstruction::Bit(7, Register::D))), + 0x7B => Some(Instruction::Bit(BitInstruction::Bit(7, Register::E))), + 0x7C => Some(Instruction::Bit(BitInstruction::Bit(7, Register::H))), + 0x7D => Some(Instruction::Bit(BitInstruction::Bit(7, Register::L))), + 0x7E => Some(Instruction::Bit(BitInstruction::Bit(7, Register::HL))), + 0x7F => Some(Instruction::Bit(BitInstruction::Bit(7, Register::A))), + + 0xC0 => Some(Instruction::Bit(BitInstruction::Set(0, Register::B))), + 0xC1 => Some(Instruction::Bit(BitInstruction::Set(0, Register::C))), + 0xC2 => Some(Instruction::Bit(BitInstruction::Set(0, Register::D))), + 0xC3 => Some(Instruction::Bit(BitInstruction::Set(0, Register::E))), + 0xC4 => Some(Instruction::Bit(BitInstruction::Set(0, Register::H))), + 0xC5 => Some(Instruction::Bit(BitInstruction::Set(0, Register::L))), + 0xC6 => Some(Instruction::Bit(BitInstruction::Set(0, Register::HL))), + 0xC7 => Some(Instruction::Bit(BitInstruction::Set(0, Register::A))), + + 0xC8 => Some(Instruction::Bit(BitInstruction::Set(1, Register::B))), + 0xC9 => Some(Instruction::Bit(BitInstruction::Set(1, Register::C))), + 0xCA => Some(Instruction::Bit(BitInstruction::Set(1, Register::D))), + 0xCB => Some(Instruction::Bit(BitInstruction::Set(1, Register::E))), + 0xCC => Some(Instruction::Bit(BitInstruction::Set(1, Register::H))), + 0xCD => Some(Instruction::Bit(BitInstruction::Set(1, Register::L))), + 0xCE => Some(Instruction::Bit(BitInstruction::Set(1, Register::HL))), + 0xCF => Some(Instruction::Bit(BitInstruction::Set(1, Register::A))), + + 0xD0 => Some(Instruction::Bit(BitInstruction::Set(2, Register::B))), + 0xD1 => Some(Instruction::Bit(BitInstruction::Set(2, Register::C))), + 0xD2 => Some(Instruction::Bit(BitInstruction::Set(2, Register::D))), + 0xD3 => Some(Instruction::Bit(BitInstruction::Set(2, Register::E))), + 0xD4 => Some(Instruction::Bit(BitInstruction::Set(2, Register::H))), + 0xD5 => Some(Instruction::Bit(BitInstruction::Set(2, Register::L))), + 0xD6 => Some(Instruction::Bit(BitInstruction::Set(2, Register::HL))), + 0xD7 => Some(Instruction::Bit(BitInstruction::Set(2, Register::A))), + + 0xD8 => Some(Instruction::Bit(BitInstruction::Set(3, Register::B))), + 0xD9 => Some(Instruction::Bit(BitInstruction::Set(3, Register::C))), + 0xDA => Some(Instruction::Bit(BitInstruction::Set(3, Register::D))), + 0xDB => Some(Instruction::Bit(BitInstruction::Set(3, Register::E))), + 0xDC => Some(Instruction::Bit(BitInstruction::Set(3, Register::H))), + 0xDD => Some(Instruction::Bit(BitInstruction::Set(3, Register::L))), + 0xDE => Some(Instruction::Bit(BitInstruction::Set(3, Register::HL))), + 0xDF => Some(Instruction::Bit(BitInstruction::Set(3, Register::A))), + + 0xE0 => Some(Instruction::Bit(BitInstruction::Set(4, Register::B))), + 0xE1 => Some(Instruction::Bit(BitInstruction::Set(4, Register::C))), + 0xE2 => Some(Instruction::Bit(BitInstruction::Set(4, Register::D))), + 0xE3 => Some(Instruction::Bit(BitInstruction::Set(4, Register::E))), + 0xE4 => Some(Instruction::Bit(BitInstruction::Set(4, Register::H))), + 0xE5 => Some(Instruction::Bit(BitInstruction::Set(4, Register::L))), + 0xE6 => Some(Instruction::Bit(BitInstruction::Set(4, Register::HL))), + 0xE7 => Some(Instruction::Bit(BitInstruction::Set(4, Register::A))), + + 0xE8 => Some(Instruction::Bit(BitInstruction::Set(5, Register::B))), + 0xE9 => Some(Instruction::Bit(BitInstruction::Set(5, Register::C))), + 0xEA => Some(Instruction::Bit(BitInstruction::Set(5, Register::D))), + 0xEB => Some(Instruction::Bit(BitInstruction::Set(5, Register::E))), + 0xEC => Some(Instruction::Bit(BitInstruction::Set(5, Register::H))), + 0xED => Some(Instruction::Bit(BitInstruction::Set(5, Register::L))), + 0xEE => Some(Instruction::Bit(BitInstruction::Set(5, Register::HL))), + 0xEF => Some(Instruction::Bit(BitInstruction::Set(5, Register::A))), + + 0xF0 => Some(Instruction::Bit(BitInstruction::Set(6, Register::B))), + 0xF1 => Some(Instruction::Bit(BitInstruction::Set(6, Register::C))), + 0xF2 => Some(Instruction::Bit(BitInstruction::Set(6, Register::D))), + 0xF3 => Some(Instruction::Bit(BitInstruction::Set(6, Register::E))), + 0xF4 => Some(Instruction::Bit(BitInstruction::Set(6, Register::H))), + 0xF5 => Some(Instruction::Bit(BitInstruction::Set(6, Register::L))), + 0xF6 => Some(Instruction::Bit(BitInstruction::Set(6, Register::HL))), + 0xF7 => Some(Instruction::Bit(BitInstruction::Set(6, Register::A))), + + 0xF8 => Some(Instruction::Bit(BitInstruction::Set(7, Register::B))), + 0xF9 => Some(Instruction::Bit(BitInstruction::Set(7, Register::C))), + 0xFA => Some(Instruction::Bit(BitInstruction::Set(7, Register::D))), + 0xFB => Some(Instruction::Bit(BitInstruction::Set(7, Register::E))), + 0xFC => Some(Instruction::Bit(BitInstruction::Set(7, Register::H))), + 0xFD => Some(Instruction::Bit(BitInstruction::Set(7, Register::L))), + 0xFE => Some(Instruction::Bit(BitInstruction::Set(7, Register::HL))), + 0xFF => Some(Instruction::Bit(BitInstruction::Set(7, Register::A))), + + 0x80 => Some(Instruction::Bit(BitInstruction::Res(0, Register::B))), + 0x81 => Some(Instruction::Bit(BitInstruction::Res(0, Register::C))), + 0x82 => Some(Instruction::Bit(BitInstruction::Res(0, Register::D))), + 0x83 => Some(Instruction::Bit(BitInstruction::Res(0, Register::E))), + 0x84 => Some(Instruction::Bit(BitInstruction::Res(0, Register::H))), + 0x85 => Some(Instruction::Bit(BitInstruction::Res(0, Register::L))), + 0x86 => Some(Instruction::Bit(BitInstruction::Res(0, Register::HL))), + 0x87 => Some(Instruction::Bit(BitInstruction::Res(0, Register::A))), + + 0x88 => Some(Instruction::Bit(BitInstruction::Res(1, Register::B))), + 0x89 => Some(Instruction::Bit(BitInstruction::Res(1, Register::C))), + 0x8A => Some(Instruction::Bit(BitInstruction::Res(1, Register::D))), + 0x8B => Some(Instruction::Bit(BitInstruction::Res(1, Register::E))), + 0x8C => Some(Instruction::Bit(BitInstruction::Res(1, Register::H))), + 0x8D => Some(Instruction::Bit(BitInstruction::Res(1, Register::L))), + 0x8E => Some(Instruction::Bit(BitInstruction::Res(1, Register::HL))), + 0x8F => Some(Instruction::Bit(BitInstruction::Res(1, Register::A))), + + 0x90 => Some(Instruction::Bit(BitInstruction::Res(2, Register::B))), + 0x91 => Some(Instruction::Bit(BitInstruction::Res(2, Register::C))), + 0x92 => Some(Instruction::Bit(BitInstruction::Res(2, Register::D))), + 0x93 => Some(Instruction::Bit(BitInstruction::Res(2, Register::E))), + 0x94 => Some(Instruction::Bit(BitInstruction::Res(2, Register::H))), + 0x95 => Some(Instruction::Bit(BitInstruction::Res(2, Register::L))), + 0x96 => Some(Instruction::Bit(BitInstruction::Res(2, Register::HL))), + 0x97 => Some(Instruction::Bit(BitInstruction::Res(2, Register::A))), + + 0x98 => Some(Instruction::Bit(BitInstruction::Res(3, Register::B))), + 0x99 => Some(Instruction::Bit(BitInstruction::Res(3, Register::C))), + 0x9A => Some(Instruction::Bit(BitInstruction::Res(3, Register::D))), + 0x9B => Some(Instruction::Bit(BitInstruction::Res(3, Register::E))), + 0x9C => Some(Instruction::Bit(BitInstruction::Res(3, Register::H))), + 0x9D => Some(Instruction::Bit(BitInstruction::Res(3, Register::L))), + 0x9E => Some(Instruction::Bit(BitInstruction::Res(3, Register::HL))), + 0x9F => Some(Instruction::Bit(BitInstruction::Res(3, Register::A))), + + 0xA0 => Some(Instruction::Bit(BitInstruction::Res(4, Register::B))), + 0xA1 => Some(Instruction::Bit(BitInstruction::Res(4, Register::C))), + 0xA2 => Some(Instruction::Bit(BitInstruction::Res(4, Register::D))), + 0xA3 => Some(Instruction::Bit(BitInstruction::Res(4, Register::E))), + 0xA4 => Some(Instruction::Bit(BitInstruction::Res(4, Register::H))), + 0xA5 => Some(Instruction::Bit(BitInstruction::Res(4, Register::L))), + 0xA6 => Some(Instruction::Bit(BitInstruction::Res(4, Register::HL))), + 0xA7 => Some(Instruction::Bit(BitInstruction::Res(4, Register::A))), + + 0xA8 => Some(Instruction::Bit(BitInstruction::Res(5, Register::B))), + 0xA9 => Some(Instruction::Bit(BitInstruction::Res(5, Register::C))), + 0xAA => Some(Instruction::Bit(BitInstruction::Res(5, Register::D))), + 0xAB => Some(Instruction::Bit(BitInstruction::Res(5, Register::E))), + 0xAC => Some(Instruction::Bit(BitInstruction::Res(5, Register::H))), + 0xAD => Some(Instruction::Bit(BitInstruction::Res(5, Register::L))), + 0xAE => Some(Instruction::Bit(BitInstruction::Res(5, Register::HL))), + 0xAF => Some(Instruction::Bit(BitInstruction::Res(5, Register::A))), + + 0xB0 => Some(Instruction::Bit(BitInstruction::Res(6, Register::B))), + 0xB1 => Some(Instruction::Bit(BitInstruction::Res(6, Register::C))), + 0xB2 => Some(Instruction::Bit(BitInstruction::Res(6, Register::D))), + 0xB3 => Some(Instruction::Bit(BitInstruction::Res(6, Register::E))), + 0xB4 => Some(Instruction::Bit(BitInstruction::Res(6, Register::H))), + 0xB5 => Some(Instruction::Bit(BitInstruction::Res(6, Register::L))), + 0xB6 => Some(Instruction::Bit(BitInstruction::Res(6, Register::HL))), + 0xB7 => Some(Instruction::Bit(BitInstruction::Res(6, Register::A))), + + 0xB8 => Some(Instruction::Bit(BitInstruction::Res(7, Register::B))), + 0xB9 => Some(Instruction::Bit(BitInstruction::Res(7, Register::C))), + 0xBA => Some(Instruction::Bit(BitInstruction::Res(7, Register::D))), + 0xBB => Some(Instruction::Bit(BitInstruction::Res(7, Register::E))), + 0xBC => Some(Instruction::Bit(BitInstruction::Res(7, Register::H))), + 0xBD => Some(Instruction::Bit(BitInstruction::Res(7, Register::L))), + 0xBE => Some(Instruction::Bit(BitInstruction::Res(7, Register::HL))), + 0xBF => Some(Instruction::Bit(BitInstruction::Res(7, Register::A))), _ => None, } @@ -381,292 +415,292 @@ impl Instruction { fn from_byte_without_prefix(byte: u8) -> Option { match byte { - 0x00 => Some(Instruction::Nop), - 0x06 => Some(Instruction::Ld8(Register::B, Register::D8)), - 0x0E => Some(Instruction::Ld8(Register::C, Register::D8)), - 0x16 => Some(Instruction::Ld8(Register::D, Register::D8)), - 0x1E => Some(Instruction::Ld8(Register::E, Register::D8)), - 0x26 => Some(Instruction::Ld8(Register::H, Register::D8)), - 0x2E => Some(Instruction::Ld8(Register::L, Register::D8)), - - 0x7F => Some(Instruction::Ld8(Register::A, Register::A)), - 0x78 => Some(Instruction::Ld8(Register::A, Register::B)), - 0x79 => Some(Instruction::Ld8(Register::A, Register::C)), - 0x7A => Some(Instruction::Ld8(Register::A, Register::D)), - 0x7B => Some(Instruction::Ld8(Register::A, Register::E)), - 0x7C => Some(Instruction::Ld8(Register::A, Register::H)), - 0x7D => Some(Instruction::Ld8(Register::A, Register::L)), - 0x0A => Some(Instruction::Ld8(Register::A, Register::BC)), - 0x1A => Some(Instruction::Ld8(Register::A, Register::DE)), - 0x7E => Some(Instruction::Ld8(Register::A, Register::HL)), - 0xFA => Some(Instruction::Ld8(Register::A, Register::D16)), - 0x3E => Some(Instruction::Ld8(Register::A, Register::D8)), - - 0x40 => Some(Instruction::Ld8(Register::B, Register::B)), - 0x41 => Some(Instruction::Ld8(Register::B, Register::C)), - 0x42 => Some(Instruction::Ld8(Register::B, Register::D)), - 0x43 => Some(Instruction::Ld8(Register::B, Register::E)), - 0x44 => Some(Instruction::Ld8(Register::B, Register::H)), - 0x45 => Some(Instruction::Ld8(Register::B, Register::L)), - 0x46 => Some(Instruction::Ld8(Register::B, Register::HL)), - - 0x48 => Some(Instruction::Ld8(Register::C, Register::B)), - 0x49 => Some(Instruction::Ld8(Register::C, Register::C)), - 0x4A => Some(Instruction::Ld8(Register::C, Register::D)), - 0x4B => Some(Instruction::Ld8(Register::C, Register::E)), - 0x4C => Some(Instruction::Ld8(Register::C, Register::H)), - 0x4D => Some(Instruction::Ld8(Register::C, Register::L)), - 0x4E => Some(Instruction::Ld8(Register::C, Register::HL)), - - 0x50 => Some(Instruction::Ld8(Register::D, Register::B)), - 0x51 => Some(Instruction::Ld8(Register::D, Register::C)), - 0x52 => Some(Instruction::Ld8(Register::D, Register::D)), - 0x53 => Some(Instruction::Ld8(Register::D, Register::E)), - 0x54 => Some(Instruction::Ld8(Register::D, Register::H)), - 0x55 => Some(Instruction::Ld8(Register::D, Register::L)), - 0x56 => Some(Instruction::Ld8(Register::D, Register::HL)), - - 0x58 => Some(Instruction::Ld8(Register::E, Register::B)), - 0x59 => Some(Instruction::Ld8(Register::E, Register::C)), - 0x5A => Some(Instruction::Ld8(Register::E, Register::D)), - 0x5B => Some(Instruction::Ld8(Register::E, Register::E)), - 0x5C => Some(Instruction::Ld8(Register::E, Register::H)), - 0x5D => Some(Instruction::Ld8(Register::E, Register::L)), - 0x5E => Some(Instruction::Ld8(Register::E, Register::HL)), - - 0x60 => Some(Instruction::Ld8(Register::H, Register::B)), - 0x61 => Some(Instruction::Ld8(Register::H, Register::C)), - 0x62 => Some(Instruction::Ld8(Register::H, Register::D)), - 0x63 => Some(Instruction::Ld8(Register::H, Register::E)), - 0x64 => Some(Instruction::Ld8(Register::H, Register::H)), - 0x65 => Some(Instruction::Ld8(Register::H, Register::L)), - 0x66 => Some(Instruction::Ld8(Register::H, Register::HL)), - - 0x68 => Some(Instruction::Ld8(Register::L, Register::B)), - 0x69 => Some(Instruction::Ld8(Register::L, Register::C)), - 0x6A => Some(Instruction::Ld8(Register::L, Register::D)), - 0x6B => Some(Instruction::Ld8(Register::L, Register::E)), - 0x6C => Some(Instruction::Ld8(Register::L, Register::H)), - 0x6D => Some(Instruction::Ld8(Register::L, Register::L)), - 0x6E => Some(Instruction::Ld8(Register::L, Register::HL)), - - 0x70 => Some(Instruction::Ld8(Register::HL, Register::B)), - 0x71 => Some(Instruction::Ld8(Register::HL, Register::C)), - 0x72 => Some(Instruction::Ld8(Register::HL, Register::D)), - 0x73 => Some(Instruction::Ld8(Register::HL, Register::E)), - 0x74 => Some(Instruction::Ld8(Register::HL, Register::H)), - 0x75 => Some(Instruction::Ld8(Register::HL, Register::L)), - 0x36 => Some(Instruction::Ld8(Register::HL, Register::D8)), - - 0x47 => Some(Instruction::Ld8(Register::B, Register::A)), - 0x4F => Some(Instruction::Ld8(Register::C, Register::A)), - 0x57 => Some(Instruction::Ld8(Register::D, Register::A)), - 0x5F => Some(Instruction::Ld8(Register::E, Register::A)), - 0x67 => Some(Instruction::Ld8(Register::H, Register::A)), - 0x6F => Some(Instruction::Ld8(Register::L, Register::A)), - 0x02 => Some(Instruction::Ld8(Register::BC, Register::A)), - 0x12 => Some(Instruction::Ld8(Register::DE, Register::A)), - 0x77 => Some(Instruction::Ld8(Register::HL, Register::A)), - 0xEA => Some(Instruction::Ld8(Register::D16, Register::A)), - - 0xF2 => Some(Instruction::LdAc), - 0xE2 => Some(Instruction::LdCa), - - 0x3A => Some(Instruction::LdHd), - 0x32 => Some(Instruction::LdHd), - - 0x2A => Some(Instruction::LdHi), - 0x22 => Some(Instruction::LdHi), - - 0xE0 => Some(Instruction::LdNa), - 0xF0 => Some(Instruction::LdAn), - - 0x01 => Some(Instruction::Ld16(Register::BC, Register::D16)), - 0x11 => Some(Instruction::Ld16(Register::DE, Register::D16)), - 0x21 => Some(Instruction::Ld16(Register::HL, Register::D16)), - 0x31 => Some(Instruction::Ld16(Register::SP, Register::D16)), - - 0xF9 => Some(Instruction::Ld16(Register::SP, Register::HL)), - 0xF8 => Some(Instruction::Ld16(Register::SP, Register::D8)), - 0x08 => Some(Instruction::Ld16(Register::D16, Register::SP)), - - 0xF5 => Some(Instruction::Push(Register::AF)), - 0xC5 => Some(Instruction::Push(Register::BC)), - 0xD5 => Some(Instruction::Push(Register::DE)), - 0xE5 => Some(Instruction::Push(Register::HL)), - - 0xF1 => Some(Instruction::Pop(Register::AF)), - 0xC1 => Some(Instruction::Pop(Register::BC)), - 0xD1 => Some(Instruction::Pop(Register::DE)), - 0xE1 => Some(Instruction::Pop(Register::HL)), - - 0x87 => Some(Instruction::Add(Register::A)), - 0x80 => Some(Instruction::Add(Register::B)), - 0x81 => Some(Instruction::Add(Register::C)), - 0x82 => Some(Instruction::Add(Register::D)), - 0x83 => Some(Instruction::Add(Register::E)), - 0x84 => Some(Instruction::Add(Register::H)), - 0x85 => Some(Instruction::Add(Register::L)), - 0x86 => Some(Instruction::Add(Register::HL)), - 0xC6 => Some(Instruction::Add(Register::D8)), - - 0x8F => Some(Instruction::Adc(Register::A)), - 0x88 => Some(Instruction::Adc(Register::B)), - 0x89 => Some(Instruction::Adc(Register::C)), - 0x8A => Some(Instruction::Adc(Register::D)), - 0x8B => Some(Instruction::Adc(Register::E)), - 0x8C => Some(Instruction::Adc(Register::H)), - 0x8D => Some(Instruction::Adc(Register::L)), - 0x8E => Some(Instruction::Adc(Register::HL)), - 0xCE => Some(Instruction::Adc(Register::D8)), - - 0x97 => Some(Instruction::Sub(Register::A)), - 0x90 => Some(Instruction::Sub(Register::B)), - 0x91 => Some(Instruction::Sub(Register::C)), - 0x92 => Some(Instruction::Sub(Register::D)), - 0x93 => Some(Instruction::Sub(Register::E)), - 0x94 => Some(Instruction::Sub(Register::H)), - 0x95 => Some(Instruction::Sub(Register::L)), - 0x96 => Some(Instruction::Sub(Register::HL)), - 0xD6 => Some(Instruction::Sub(Register::D8)), - - 0x9F => Some(Instruction::Sbc(Register::A)), - 0x98 => Some(Instruction::Sbc(Register::B)), - 0x99 => Some(Instruction::Sbc(Register::C)), - 0x9A => Some(Instruction::Sbc(Register::D)), - 0x9B => Some(Instruction::Sbc(Register::E)), - 0x9C => Some(Instruction::Sbc(Register::H)), - 0x9D => Some(Instruction::Sbc(Register::L)), - 0x9E => Some(Instruction::Sbc(Register::HL)), - 0xDE => Some(Instruction::Sbc(Register::D8)), - - 0xA7 => Some(Instruction::And(Register::A)), - 0xA0 => Some(Instruction::And(Register::B)), - 0xA1 => Some(Instruction::And(Register::C)), - 0xA2 => Some(Instruction::And(Register::D)), - 0xA3 => Some(Instruction::And(Register::E)), - 0xA4 => Some(Instruction::And(Register::H)), - 0xA5 => Some(Instruction::And(Register::L)), - 0xA6 => Some(Instruction::And(Register::HL)), - 0xE6 => Some(Instruction::And(Register::D8)), - - 0xB7 => Some(Instruction::Or(Register::A)), - 0xB0 => Some(Instruction::Or(Register::B)), - 0xB1 => Some(Instruction::Or(Register::C)), - 0xB2 => Some(Instruction::Or(Register::D)), - 0xB3 => Some(Instruction::Or(Register::E)), - 0xB4 => Some(Instruction::Or(Register::H)), - 0xB5 => Some(Instruction::Or(Register::L)), - 0xB6 => Some(Instruction::Or(Register::HL)), - 0xF6 => Some(Instruction::Or(Register::D8)), - - 0xAF => Some(Instruction::Xor(Register::A)), - 0xA8 => Some(Instruction::Xor(Register::B)), - 0xA9 => Some(Instruction::Xor(Register::C)), - 0xAA => Some(Instruction::Xor(Register::D)), - 0xAB => Some(Instruction::Xor(Register::E)), - 0xAC => Some(Instruction::Xor(Register::H)), - 0xAD => Some(Instruction::Xor(Register::L)), - 0xAE => Some(Instruction::Xor(Register::HL)), - 0xEE => Some(Instruction::Xor(Register::D8)), - - 0xBF => Some(Instruction::Cp(Register::A)), - 0xB8 => Some(Instruction::Cp(Register::B)), - 0xB9 => Some(Instruction::Cp(Register::C)), - 0xBA => Some(Instruction::Cp(Register::D)), - 0xBB => Some(Instruction::Cp(Register::E)), - 0xBC => Some(Instruction::Cp(Register::H)), - 0xBD => Some(Instruction::Cp(Register::L)), - 0xBE => Some(Instruction::Cp(Register::HL)), - 0xFE => Some(Instruction::Cp(Register::D8)), - - 0x3C => Some(Instruction::Inc(Register::A)), - 0x04 => Some(Instruction::Inc(Register::B)), - 0x0C => Some(Instruction::Inc(Register::C)), - 0x14 => Some(Instruction::Inc(Register::D)), - 0x1C => Some(Instruction::Inc(Register::E)), - 0x24 => Some(Instruction::Inc(Register::H)), - 0x2C => Some(Instruction::Inc(Register::L)), - 0x34 => Some(Instruction::Inc(Register::HL)), - - 0x3D => Some(Instruction::Dec(Register::A)), - 0x05 => Some(Instruction::Dec(Register::B)), - 0x0D => Some(Instruction::Dec(Register::C)), - 0x15 => Some(Instruction::Dec(Register::D)), - 0x1D => Some(Instruction::Dec(Register::E)), - 0x25 => Some(Instruction::Dec(Register::H)), - 0x2D => Some(Instruction::Dec(Register::L)), - 0x35 => Some(Instruction::Dec(Register::HL)), - - 0x09 => Some(Instruction::Add16(Register::BC)), - 0x19 => Some(Instruction::Add16(Register::DE)), - 0x29 => Some(Instruction::Add16(Register::HL)), - 0x39 => Some(Instruction::Add16(Register::SP)), - - 0xE8 => Some(Instruction::Add16SP), - - 0x03 => Some(Instruction::Inc16(Register::BC)), - 0x13 => Some(Instruction::Inc16(Register::DE)), - 0x23 => Some(Instruction::Inc16(Register::HL)), - 0x33 => Some(Instruction::Inc16(Register::SP)), - - 0x0B => Some(Instruction::Dec16(Register::BC)), - 0x1B => Some(Instruction::Dec16(Register::DE)), - 0x2B => Some(Instruction::Dec16(Register::HL)), - 0x3B => Some(Instruction::Dec16(Register::SP)), - - 0x27 => Some(Instruction::DAA), - 0x2F => Some(Instruction::CPL), - 0x3F => Some(Instruction::CCF), - 0x37 => Some(Instruction::SCF), - - 0x76 => Some(Instruction::HALT), - 0x10 => Some(Instruction::STOP), - 0xF3 => Some(Instruction::DI), - 0xFB => Some(Instruction::EI), - - 0x07 => Some(Instruction::RLCA), - 0x17 => Some(Instruction::RLA), - 0x0F => Some(Instruction::RRCA), - 0x1F => Some(Instruction::RRA), - - 0xC3 => Some(Instruction::Jp), - 0xC2 => Some(Instruction::JpCond(FlagCondition::NZ)), - 0xCA => Some(Instruction::JpCond(FlagCondition::Z)), - 0xD2 => Some(Instruction::JpCond(FlagCondition::NC)), - 0xDA => Some(Instruction::JpCond(FlagCondition::C)), - - 0xE9 => Some(Instruction::JpHL), - - 0x18 => Some(Instruction::Jr), - 0x20 => Some(Instruction::JrCond(FlagCondition::NZ)), - 0x28 => Some(Instruction::JrCond(FlagCondition::Z)), - 0x30 => Some(Instruction::JrCond(FlagCondition::NC)), - 0x38 => Some(Instruction::JrCond(FlagCondition::C)), - - 0xCD => Some(Instruction::Call), - 0xC4 => Some(Instruction::CallCond(FlagCondition::NZ)), - 0xCC => Some(Instruction::CallCond(FlagCondition::Z)), - 0xD4 => Some(Instruction::CallCond(FlagCondition::NC)), - 0xDC => Some(Instruction::CallCond(FlagCondition::C)), - - 0xC7 => Some(Instruction::Rst(0x00)), - 0xCF => Some(Instruction::Rst(0x08)), - 0xD7 => Some(Instruction::Rst(0x10)), - 0xDF => Some(Instruction::Rst(0x18)), - 0xE7 => Some(Instruction::Rst(0x20)), - 0xEF => Some(Instruction::Rst(0x28)), - 0xF7 => Some(Instruction::Rst(0x30)), - 0xFF => Some(Instruction::Rst(0x38)), - - 0xC9 => Some(Instruction::Ret), - - 0xC0 => Some(Instruction::RetCond(FlagCondition::NZ)), - 0xC8 => Some(Instruction::RetCond(FlagCondition::Z)), - 0xD0 => Some(Instruction::RetCond(FlagCondition::NC)), - 0xD8 => Some(Instruction::RetCond(FlagCondition::C)), - - 0xD9 => Some(Instruction::Reti), + 0x00 => Some(Instruction::Misc(MiscInstruction::Nop)), + 0x06 => Some(Instruction::Load(LoadInstruction::Ld8(Register::B, Register::D8))), + 0x0E => Some(Instruction::Load(LoadInstruction::Ld8(Register::C, Register::D8))), + 0x16 => Some(Instruction::Load(LoadInstruction::Ld8(Register::D, Register::D8))), + 0x1E => Some(Instruction::Load(LoadInstruction::Ld8(Register::E, Register::D8))), + 0x26 => Some(Instruction::Load(LoadInstruction::Ld8(Register::H, Register::D8))), + 0x2E => Some(Instruction::Load(LoadInstruction::Ld8(Register::L, Register::D8))), + + 0x7F => Some(Instruction::Load(LoadInstruction::Ld8(Register::A, Register::A))), + 0x78 => Some(Instruction::Load(LoadInstruction::Ld8(Register::A, Register::B))), + 0x79 => Some(Instruction::Load(LoadInstruction::Ld8(Register::A, Register::C))), + 0x7A => Some(Instruction::Load(LoadInstruction::Ld8(Register::A, Register::D))), + 0x7B => Some(Instruction::Load(LoadInstruction::Ld8(Register::A, Register::E))), + 0x7C => Some(Instruction::Load(LoadInstruction::Ld8(Register::A, Register::H))), + 0x7D => Some(Instruction::Load(LoadInstruction::Ld8(Register::A, Register::L))), + 0x0A => Some(Instruction::Load(LoadInstruction::Ld8(Register::A, Register::BC))), + 0x1A => Some(Instruction::Load(LoadInstruction::Ld8(Register::A, Register::DE))), + 0x7E => Some(Instruction::Load(LoadInstruction::Ld8(Register::A, Register::HL))), + 0xFA => Some(Instruction::Load(LoadInstruction::Ld8(Register::A, Register::D16))), + 0x3E => Some(Instruction::Load(LoadInstruction::Ld8(Register::A, Register::D8))), + + 0x40 => Some(Instruction::Load(LoadInstruction::Ld8(Register::B, Register::B))), + 0x41 => Some(Instruction::Load(LoadInstruction::Ld8(Register::B, Register::C))), + 0x42 => Some(Instruction::Load(LoadInstruction::Ld8(Register::B, Register::D))), + 0x43 => Some(Instruction::Load(LoadInstruction::Ld8(Register::B, Register::E))), + 0x44 => Some(Instruction::Load(LoadInstruction::Ld8(Register::B, Register::H))), + 0x45 => Some(Instruction::Load(LoadInstruction::Ld8(Register::B, Register::L))), + 0x46 => Some(Instruction::Load(LoadInstruction::Ld8(Register::B, Register::HL))), + + 0x48 => Some(Instruction::Load(LoadInstruction::Ld8(Register::C, Register::B))), + 0x49 => Some(Instruction::Load(LoadInstruction::Ld8(Register::C, Register::C))), + 0x4A => Some(Instruction::Load(LoadInstruction::Ld8(Register::C, Register::D))), + 0x4B => Some(Instruction::Load(LoadInstruction::Ld8(Register::C, Register::E))), + 0x4C => Some(Instruction::Load(LoadInstruction::Ld8(Register::C, Register::H))), + 0x4D => Some(Instruction::Load(LoadInstruction::Ld8(Register::C, Register::L))), + 0x4E => Some(Instruction::Load(LoadInstruction::Ld8(Register::C, Register::HL))), + + 0x50 => Some(Instruction::Load(LoadInstruction::Ld8(Register::D, Register::B))), + 0x51 => Some(Instruction::Load(LoadInstruction::Ld8(Register::D, Register::C))), + 0x52 => Some(Instruction::Load(LoadInstruction::Ld8(Register::D, Register::D))), + 0x53 => Some(Instruction::Load(LoadInstruction::Ld8(Register::D, Register::E))), + 0x54 => Some(Instruction::Load(LoadInstruction::Ld8(Register::D, Register::H))), + 0x55 => Some(Instruction::Load(LoadInstruction::Ld8(Register::D, Register::L))), + 0x56 => Some(Instruction::Load(LoadInstruction::Ld8(Register::D, Register::HL))), + + 0x58 => Some(Instruction::Load(LoadInstruction::Ld8(Register::E, Register::B))), + 0x59 => Some(Instruction::Load(LoadInstruction::Ld8(Register::E, Register::C))), + 0x5A => Some(Instruction::Load(LoadInstruction::Ld8(Register::E, Register::D))), + 0x5B => Some(Instruction::Load(LoadInstruction::Ld8(Register::E, Register::E))), + 0x5C => Some(Instruction::Load(LoadInstruction::Ld8(Register::E, Register::H))), + 0x5D => Some(Instruction::Load(LoadInstruction::Ld8(Register::E, Register::L))), + 0x5E => Some(Instruction::Load(LoadInstruction::Ld8(Register::E, Register::HL))), + + 0x60 => Some(Instruction::Load(LoadInstruction::Ld8(Register::H, Register::B))), + 0x61 => Some(Instruction::Load(LoadInstruction::Ld8(Register::H, Register::C))), + 0x62 => Some(Instruction::Load(LoadInstruction::Ld8(Register::H, Register::D))), + 0x63 => Some(Instruction::Load(LoadInstruction::Ld8(Register::H, Register::E))), + 0x64 => Some(Instruction::Load(LoadInstruction::Ld8(Register::H, Register::H))), + 0x65 => Some(Instruction::Load(LoadInstruction::Ld8(Register::H, Register::L))), + 0x66 => Some(Instruction::Load(LoadInstruction::Ld8(Register::H, Register::HL))), + + 0x68 => Some(Instruction::Load(LoadInstruction::Ld8(Register::L, Register::B))), + 0x69 => Some(Instruction::Load(LoadInstruction::Ld8(Register::L, Register::C))), + 0x6A => Some(Instruction::Load(LoadInstruction::Ld8(Register::L, Register::D))), + 0x6B => Some(Instruction::Load(LoadInstruction::Ld8(Register::L, Register::E))), + 0x6C => Some(Instruction::Load(LoadInstruction::Ld8(Register::L, Register::H))), + 0x6D => Some(Instruction::Load(LoadInstruction::Ld8(Register::L, Register::L))), + 0x6E => Some(Instruction::Load(LoadInstruction::Ld8(Register::L, Register::HL))), + + 0x70 => Some(Instruction::Load(LoadInstruction::Ld8(Register::HL, Register::B))), + 0x71 => Some(Instruction::Load(LoadInstruction::Ld8(Register::HL, Register::C))), + 0x72 => Some(Instruction::Load(LoadInstruction::Ld8(Register::HL, Register::D))), + 0x73 => Some(Instruction::Load(LoadInstruction::Ld8(Register::HL, Register::E))), + 0x74 => Some(Instruction::Load(LoadInstruction::Ld8(Register::HL, Register::H))), + 0x75 => Some(Instruction::Load(LoadInstruction::Ld8(Register::HL, Register::L))), + 0x36 => Some(Instruction::Load(LoadInstruction::Ld8(Register::HL, Register::D8))), + + 0x47 => Some(Instruction::Load(LoadInstruction::Ld8(Register::B, Register::A))), + 0x4F => Some(Instruction::Load(LoadInstruction::Ld8(Register::C, Register::A))), + 0x57 => Some(Instruction::Load(LoadInstruction::Ld8(Register::D, Register::A))), + 0x5F => Some(Instruction::Load(LoadInstruction::Ld8(Register::E, Register::A))), + 0x67 => Some(Instruction::Load(LoadInstruction::Ld8(Register::H, Register::A))), + 0x6F => Some(Instruction::Load(LoadInstruction::Ld8(Register::L, Register::A))), + 0x02 => Some(Instruction::Load(LoadInstruction::Ld8(Register::BC, Register::A))), + 0x12 => Some(Instruction::Load(LoadInstruction::Ld8(Register::DE, Register::A))), + 0x77 => Some(Instruction::Load(LoadInstruction::Ld8(Register::HL, Register::A))), + 0xEA => Some(Instruction::Load(LoadInstruction::Ld8(Register::D16, Register::A))), + + 0xF2 => Some(Instruction::Load(LoadInstruction::LdAc)), + 0xE2 => Some(Instruction::Load(LoadInstruction::LdCa)), + + 0x3A => Some(Instruction::Load(LoadInstruction::LdHd)), + 0x32 => Some(Instruction::Load(LoadInstruction::LdHd)), + + 0x2A => Some(Instruction::Load(LoadInstruction::LdHi)), + 0x22 => Some(Instruction::Load(LoadInstruction::LdHi)), + + 0xE0 => Some(Instruction::Load(LoadInstruction::LdNa)), + 0xF0 => Some(Instruction::Load(LoadInstruction::LdAn)), + + 0x01 => Some(Instruction::Load(LoadInstruction::Ld16(Register::BC, Register::D16))), + 0x11 => Some(Instruction::Load(LoadInstruction::Ld16(Register::DE, Register::D16))), + 0x21 => Some(Instruction::Load(LoadInstruction::Ld16(Register::HL, Register::D16))), + 0x31 => Some(Instruction::Load(LoadInstruction::Ld16(Register::SP, Register::D16))), + + 0xF9 => Some(Instruction::Load(LoadInstruction::Ld16(Register::SP, Register::HL))), + 0xF8 => Some(Instruction::Load(LoadInstruction::Ld16(Register::SP, Register::D8))), + 0x08 => Some(Instruction::Load(LoadInstruction::Ld16(Register::D16, Register::SP))), + + 0xF5 => Some(Instruction::Load(LoadInstruction::Push(Register::AF))), + 0xC5 => Some(Instruction::Load(LoadInstruction::Push(Register::BC))), + 0xD5 => Some(Instruction::Load(LoadInstruction::Push(Register::DE))), + 0xE5 => Some(Instruction::Load(LoadInstruction::Push(Register::HL))), + + 0xF1 => Some(Instruction::Load(LoadInstruction::Pop(Register::AF))), + 0xC1 => Some(Instruction::Load(LoadInstruction::Pop(Register::BC))), + 0xD1 => Some(Instruction::Load(LoadInstruction::Pop(Register::DE))), + 0xE1 => Some(Instruction::Load(LoadInstruction::Pop(Register::HL))), + + 0x87 => Some(Instruction::Arithmetic(ArithmeticInstruction::Add(Register::A))), + 0x80 => Some(Instruction::Arithmetic(ArithmeticInstruction::Add(Register::B))), + 0x81 => Some(Instruction::Arithmetic(ArithmeticInstruction::Add(Register::C))), + 0x82 => Some(Instruction::Arithmetic(ArithmeticInstruction::Add(Register::D))), + 0x83 => Some(Instruction::Arithmetic(ArithmeticInstruction::Add(Register::E))), + 0x84 => Some(Instruction::Arithmetic(ArithmeticInstruction::Add(Register::H))), + 0x85 => Some(Instruction::Arithmetic(ArithmeticInstruction::Add(Register::L))), + 0x86 => Some(Instruction::Arithmetic(ArithmeticInstruction::Add(Register::HL))), + 0xC6 => Some(Instruction::Arithmetic(ArithmeticInstruction::Add(Register::D8))), + + 0x8F => Some(Instruction::Arithmetic(ArithmeticInstruction::Adc(Register::A))), + 0x88 => Some(Instruction::Arithmetic(ArithmeticInstruction::Adc(Register::B))), + 0x89 => Some(Instruction::Arithmetic(ArithmeticInstruction::Adc(Register::C))), + 0x8A => Some(Instruction::Arithmetic(ArithmeticInstruction::Adc(Register::D))), + 0x8B => Some(Instruction::Arithmetic(ArithmeticInstruction::Adc(Register::E))), + 0x8C => Some(Instruction::Arithmetic(ArithmeticInstruction::Adc(Register::H))), + 0x8D => Some(Instruction::Arithmetic(ArithmeticInstruction::Adc(Register::L))), + 0x8E => Some(Instruction::Arithmetic(ArithmeticInstruction::Adc(Register::HL))), + 0xCE => Some(Instruction::Arithmetic(ArithmeticInstruction::Adc(Register::D8))), + + 0x97 => Some(Instruction::Arithmetic(ArithmeticInstruction::Sub(Register::A))), + 0x90 => Some(Instruction::Arithmetic(ArithmeticInstruction::Sub(Register::B))), + 0x91 => Some(Instruction::Arithmetic(ArithmeticInstruction::Sub(Register::C))), + 0x92 => Some(Instruction::Arithmetic(ArithmeticInstruction::Sub(Register::D))), + 0x93 => Some(Instruction::Arithmetic(ArithmeticInstruction::Sub(Register::E))), + 0x94 => Some(Instruction::Arithmetic(ArithmeticInstruction::Sub(Register::H))), + 0x95 => Some(Instruction::Arithmetic(ArithmeticInstruction::Sub(Register::L))), + 0x96 => Some(Instruction::Arithmetic(ArithmeticInstruction::Sub(Register::HL))), + 0xD6 => Some(Instruction::Arithmetic(ArithmeticInstruction::Sub(Register::D8))), + + 0x9F => Some(Instruction::Arithmetic(ArithmeticInstruction::Sbc(Register::A))), + 0x98 => Some(Instruction::Arithmetic(ArithmeticInstruction::Sbc(Register::B))), + 0x99 => Some(Instruction::Arithmetic(ArithmeticInstruction::Sbc(Register::C))), + 0x9A => Some(Instruction::Arithmetic(ArithmeticInstruction::Sbc(Register::D))), + 0x9B => Some(Instruction::Arithmetic(ArithmeticInstruction::Sbc(Register::E))), + 0x9C => Some(Instruction::Arithmetic(ArithmeticInstruction::Sbc(Register::H))), + 0x9D => Some(Instruction::Arithmetic(ArithmeticInstruction::Sbc(Register::L))), + 0x9E => Some(Instruction::Arithmetic(ArithmeticInstruction::Sbc(Register::HL))), + 0xDE => Some(Instruction::Arithmetic(ArithmeticInstruction::Sbc(Register::D8))), + + 0xA7 => Some(Instruction::Arithmetic(ArithmeticInstruction::And(Register::A))), + 0xA0 => Some(Instruction::Arithmetic(ArithmeticInstruction::And(Register::B))), + 0xA1 => Some(Instruction::Arithmetic(ArithmeticInstruction::And(Register::C))), + 0xA2 => Some(Instruction::Arithmetic(ArithmeticInstruction::And(Register::D))), + 0xA3 => Some(Instruction::Arithmetic(ArithmeticInstruction::And(Register::E))), + 0xA4 => Some(Instruction::Arithmetic(ArithmeticInstruction::And(Register::H))), + 0xA5 => Some(Instruction::Arithmetic(ArithmeticInstruction::And(Register::L))), + 0xA6 => Some(Instruction::Arithmetic(ArithmeticInstruction::And(Register::HL))), + 0xE6 => Some(Instruction::Arithmetic(ArithmeticInstruction::And(Register::D8))), + + 0xB7 => Some(Instruction::Arithmetic(ArithmeticInstruction::Or(Register::A))), + 0xB0 => Some(Instruction::Arithmetic(ArithmeticInstruction::Or(Register::B))), + 0xB1 => Some(Instruction::Arithmetic(ArithmeticInstruction::Or(Register::C))), + 0xB2 => Some(Instruction::Arithmetic(ArithmeticInstruction::Or(Register::D))), + 0xB3 => Some(Instruction::Arithmetic(ArithmeticInstruction::Or(Register::E))), + 0xB4 => Some(Instruction::Arithmetic(ArithmeticInstruction::Or(Register::H))), + 0xB5 => Some(Instruction::Arithmetic(ArithmeticInstruction::Or(Register::L))), + 0xB6 => Some(Instruction::Arithmetic(ArithmeticInstruction::Or(Register::HL))), + 0xF6 => Some(Instruction::Arithmetic(ArithmeticInstruction::Or(Register::D8))), + + 0xAF => Some(Instruction::Arithmetic(ArithmeticInstruction::Xor(Register::A))), + 0xA8 => Some(Instruction::Arithmetic(ArithmeticInstruction::Xor(Register::B))), + 0xA9 => Some(Instruction::Arithmetic(ArithmeticInstruction::Xor(Register::C))), + 0xAA => Some(Instruction::Arithmetic(ArithmeticInstruction::Xor(Register::D))), + 0xAB => Some(Instruction::Arithmetic(ArithmeticInstruction::Xor(Register::E))), + 0xAC => Some(Instruction::Arithmetic(ArithmeticInstruction::Xor(Register::H))), + 0xAD => Some(Instruction::Arithmetic(ArithmeticInstruction::Xor(Register::L))), + 0xAE => Some(Instruction::Arithmetic(ArithmeticInstruction::Xor(Register::HL))), + 0xEE => Some(Instruction::Arithmetic(ArithmeticInstruction::Xor(Register::D8))), + + 0xBF => Some(Instruction::Arithmetic(ArithmeticInstruction::Cp(Register::A))), + 0xB8 => Some(Instruction::Arithmetic(ArithmeticInstruction::Cp(Register::B))), + 0xB9 => Some(Instruction::Arithmetic(ArithmeticInstruction::Cp(Register::C))), + 0xBA => Some(Instruction::Arithmetic(ArithmeticInstruction::Cp(Register::D))), + 0xBB => Some(Instruction::Arithmetic(ArithmeticInstruction::Cp(Register::E))), + 0xBC => Some(Instruction::Arithmetic(ArithmeticInstruction::Cp(Register::H))), + 0xBD => Some(Instruction::Arithmetic(ArithmeticInstruction::Cp(Register::L))), + 0xBE => Some(Instruction::Arithmetic(ArithmeticInstruction::Cp(Register::HL))), + 0xFE => Some(Instruction::Arithmetic(ArithmeticInstruction::Cp(Register::D8))), + + 0x3C => Some(Instruction::Arithmetic(ArithmeticInstruction::Inc(Register::A))), + 0x04 => Some(Instruction::Arithmetic(ArithmeticInstruction::Inc(Register::B))), + 0x0C => Some(Instruction::Arithmetic(ArithmeticInstruction::Inc(Register::C))), + 0x14 => Some(Instruction::Arithmetic(ArithmeticInstruction::Inc(Register::D))), + 0x1C => Some(Instruction::Arithmetic(ArithmeticInstruction::Inc(Register::E))), + 0x24 => Some(Instruction::Arithmetic(ArithmeticInstruction::Inc(Register::H))), + 0x2C => Some(Instruction::Arithmetic(ArithmeticInstruction::Inc(Register::L))), + 0x34 => Some(Instruction::Arithmetic(ArithmeticInstruction::Inc(Register::HL))), + + 0x3D => Some(Instruction::Arithmetic(ArithmeticInstruction::Dec(Register::A))), + 0x05 => Some(Instruction::Arithmetic(ArithmeticInstruction::Dec(Register::B))), + 0x0D => Some(Instruction::Arithmetic(ArithmeticInstruction::Dec(Register::C))), + 0x15 => Some(Instruction::Arithmetic(ArithmeticInstruction::Dec(Register::D))), + 0x1D => Some(Instruction::Arithmetic(ArithmeticInstruction::Dec(Register::E))), + 0x25 => Some(Instruction::Arithmetic(ArithmeticInstruction::Dec(Register::H))), + 0x2D => Some(Instruction::Arithmetic(ArithmeticInstruction::Dec(Register::L))), + 0x35 => Some(Instruction::Arithmetic(ArithmeticInstruction::Dec(Register::HL))), + + 0x09 => Some(Instruction::Arithmetic(ArithmeticInstruction::Add16(Register::BC))), + 0x19 => Some(Instruction::Arithmetic(ArithmeticInstruction::Add16(Register::DE))), + 0x29 => Some(Instruction::Arithmetic(ArithmeticInstruction::Add16(Register::HL))), + 0x39 => Some(Instruction::Arithmetic(ArithmeticInstruction::Add16(Register::SP))), + + 0xE8 => Some(Instruction::Arithmetic(ArithmeticInstruction::Add16SP)), + + 0x03 => Some(Instruction::Arithmetic(ArithmeticInstruction::Inc16(Register::BC))), + 0x13 => Some(Instruction::Arithmetic(ArithmeticInstruction::Inc16(Register::DE))), + 0x23 => Some(Instruction::Arithmetic(ArithmeticInstruction::Inc16(Register::HL))), + 0x33 => Some(Instruction::Arithmetic(ArithmeticInstruction::Inc16(Register::SP))), + + 0x0B => Some(Instruction::Arithmetic(ArithmeticInstruction::Dec16(Register::BC))), + 0x1B => Some(Instruction::Arithmetic(ArithmeticInstruction::Dec16(Register::DE))), + 0x2B => Some(Instruction::Arithmetic(ArithmeticInstruction::Dec16(Register::HL))), + 0x3B => Some(Instruction::Arithmetic(ArithmeticInstruction::Dec16(Register::SP))), + + 0x27 => Some(Instruction::Misc(MiscInstruction::DAA)), + 0x2F => Some(Instruction::Misc(MiscInstruction::CPL)), + 0x3F => Some(Instruction::Misc(MiscInstruction::CCF)), + 0x37 => Some(Instruction::Misc(MiscInstruction::SCF)), + + 0x76 => Some(Instruction::Misc(MiscInstruction::HALT)), + 0x10 => Some(Instruction::Misc(MiscInstruction::STOP)), + 0xF3 => Some(Instruction::Misc(MiscInstruction::DI)), + 0xFB => Some(Instruction::Misc(MiscInstruction::EI)), + + 0x07 => Some(Instruction::Rotate(RotateInstruction::RLCA)), + 0x17 => Some(Instruction::Rotate(RotateInstruction::RLA)), + 0x0F => Some(Instruction::Rotate(RotateInstruction::RRCA)), + 0x1F => Some(Instruction::Rotate(RotateInstruction::RRA)), + + 0xC3 => Some(Instruction::Jump(JumpInstruction::Jp)), + 0xC2 => Some(Instruction::Jump(JumpInstruction::JpCond(FlagCondition::NZ))), + 0xCA => Some(Instruction::Jump(JumpInstruction::JpCond(FlagCondition::Z))), + 0xD2 => Some(Instruction::Jump(JumpInstruction::JpCond(FlagCondition::NC))), + 0xDA => Some(Instruction::Jump(JumpInstruction::JpCond(FlagCondition::C))), + + 0xE9 => Some(Instruction::Jump(JumpInstruction::JpHL)), + + 0x18 => Some(Instruction::Jump(JumpInstruction::Jr)), + 0x20 => Some(Instruction::Jump(JumpInstruction::JrCond(FlagCondition::NZ))), + 0x28 => Some(Instruction::Jump(JumpInstruction::JrCond(FlagCondition::Z))), + 0x30 => Some(Instruction::Jump(JumpInstruction::JrCond(FlagCondition::NC))), + 0x38 => Some(Instruction::Jump(JumpInstruction::JrCond(FlagCondition::C))), + + 0xCD => Some(Instruction::Call(CallInstruction::Call)), + 0xC4 => Some(Instruction::Call(CallInstruction::CallCond(FlagCondition::NZ))), + 0xCC => Some(Instruction::Call(CallInstruction::CallCond(FlagCondition::Z))), + 0xD4 => Some(Instruction::Call(CallInstruction::CallCond(FlagCondition::NC))), + 0xDC => Some(Instruction::Call(CallInstruction::CallCond(FlagCondition::C))), + + 0xC7 => Some(Instruction::Return(ReturnInstruction::Rst(0x00))), + 0xCF => Some(Instruction::Return(ReturnInstruction::Rst(0x08))), + 0xD7 => Some(Instruction::Return(ReturnInstruction::Rst(0x10))), + 0xDF => Some(Instruction::Return(ReturnInstruction::Rst(0x18))), + 0xE7 => Some(Instruction::Return(ReturnInstruction::Rst(0x20))), + 0xEF => Some(Instruction::Return(ReturnInstruction::Rst(0x28))), + 0xF7 => Some(Instruction::Return(ReturnInstruction::Rst(0x30))), + 0xFF => Some(Instruction::Return(ReturnInstruction::Rst(0x38))), + + 0xC9 => Some(Instruction::Return(ReturnInstruction::Ret)), + + 0xC0 => Some(Instruction::Return(ReturnInstruction::RetCond(FlagCondition::NZ))), + 0xC8 => Some(Instruction::Return(ReturnInstruction::RetCond(FlagCondition::Z))), + 0xD0 => Some(Instruction::Return(ReturnInstruction::RetCond(FlagCondition::NC))), + 0xD8 => Some(Instruction::Return(ReturnInstruction::RetCond(FlagCondition::C))), + + 0xD9 => Some(Instruction::Return(ReturnInstruction::Reti)), _ => None, } diff --git a/gameboy-lib/src/cpu/mod.rs b/gameboy-lib/src/cpu/mod.rs index eba3f3f..74e8621 100644 --- a/gameboy-lib/src/cpu/mod.rs +++ b/gameboy-lib/src/cpu/mod.rs @@ -1,7 +1,8 @@ use crate::{cpu::instructions::Instruction, memory::Memory}; -use self::registers::Register; +use self::{command::CommandFactory, registers::Register}; +pub mod command; pub mod instructions; pub mod registers; @@ -88,46 +89,9 @@ impl Cpu { } fn execute(&mut self, instruction: Instruction, prefixed: bool) -> u16 { - if prefixed { - self.execute_prefixed(instruction) - } else { - self.execute_unprefixed(instruction) - } - } - - fn execute_unprefixed(&mut self, instruction: Instruction) -> u16 { - match instruction { - Instruction::Nop => self.pc.wrapping_add(1), - Instruction::Ld8(_, _) => self.load_8(instruction), - Instruction::Ld16(_, _) => self.load_16(instruction), - Instruction::LdCa - | Instruction::LdAc - | Instruction::LdNa - | Instruction::LdAn - | Instruction::LdHi - | Instruction::LdHd => self.load_special(instruction), - Instruction::Push(register) => self.push(register), - Instruction::Pop(register) => self.pop(register), - Instruction::Add(_) | Instruction::Adc(_) => self.add(instruction), - Instruction::Add16(_) | Instruction::Add16SP => self.add16(instruction), - Instruction::Sub(_) | Instruction::Sbc(_) => self.sub(instruction), - Instruction::And(_) => self.and(instruction), - Instruction::Or(_) => self.or(instruction), - Instruction::Xor(_) => self.xor(instruction), - Instruction::Cp(_) => self.compare(instruction), - Instruction::Inc(register) => self.inc(register), - Instruction::Inc16(register) => self.inc16(register), - Instruction::Dec(register) => self.dec(register), - Instruction::Dec16(register) => self.dec16(register), - _ => panic!("[CPU] Not implementet {:?}", instruction), - } - } - - fn execute_prefixed(&mut self, instruction: Instruction) -> u16 { - match instruction { - Instruction::Swap(from) => self.swap(&from), - _ => panic!("[CPU] Not implementet {:?}", instruction), - } + let mut factory = CommandFactory::new(self); + let mut command = factory.create_command(&instruction, prefixed); + command.execute() } fn extract_operand(&mut self, from: &Register) -> (u8, u16) { @@ -140,432 +104,6 @@ impl Cpu { _ => (self.registers.get(from), self.pc.wrapping_add(1)), } } - - fn swap(&mut self, from: &Register) -> u16 { - let (value, pc) = self.extract_operand(from); - let upper = value >> 4; - let lower = value << 4; - let result = upper | lower; - - if let Register::HL = from { - self.memory - .write(self.registers.get_16(&Register::HL), result); - } else { - self.registers.set(from, result); - } - - self.registers.f.zero = result == 0; - self.registers.f.subtract = false; - self.registers.f.half_carry = false; - self.registers.f.carry = false; - - return pc; - } - - fn alu_operation16(&mut self, instruction: &Instruction, op: F) -> u16 - where - F: Fn(u16, u16) -> (u16, Vec), - { - let (value, pc) = match instruction { - Instruction::Add16(from) => { - let value = self.registers.get_16(&from); - (value, self.pc.wrapping_add(1)) - } - Instruction::Add16SP => { - let n = self.memory.read(self.pc + 1) as u16; - let sp = self.registers.get_16(&Register::SP); - let result = sp.wrapping_add(n); - (result as u16, self.pc.wrapping_add(2)) - } - _ => panic!("[CPU] Invalid instruction {:?}", instruction), - }; - - let hl = self.registers.get_16(&Register::HL); - let (result, flag_update) = op(hl, value); - - if let Instruction::Add16SP = instruction { - self.registers.set_16(&Register::SP, value) - } else { - self.registers.set_16(&Register::HL, result); - } - - for flag in flag_update { - self.update_flag(flag); - } - - return pc; - } - - fn alu_operation(&mut self, instruction: Instruction, op: F) -> u16 - where - F: Fn(u8, u8) -> (u8, Vec), - { - let (value, pc) = match instruction { - Instruction::Cp(from) - | Instruction::Xor(from) - | Instruction::And(from) - | Instruction::Or(from) - | Instruction::Add(from) - | Instruction::Sub(from) => self.extract_operand(&from), - Instruction::Adc(from) | Instruction::Sbc(from) => { - let (mut value, pc) = self.extract_operand(&from); - if self.registers.f.carry { - value = value.wrapping_add(1); - } - (value, pc) - } - _ => panic!("[CPU] Invalid instruction {:?}", instruction), - }; - - let a = self.registers.get(&Register::A); - let (result, flag_update) = op(a, value); - self.registers.set(&Register::A, result); - - for flag in flag_update { - self.update_flag(flag); - } - - return pc; - } - - fn and(&mut self, instruction: Instruction) -> u16 { - self.alu_operation(instruction, |a, b| { - let result = a & b; - ( - result, - vec![ - FlagUpdate::Zero(result == 0), - FlagUpdate::Subtract(false), - FlagUpdate::HalfCarry(true), - FlagUpdate::Carry(false), - ], - ) - }) - } - - fn or(&mut self, instruction: Instruction) -> u16 { - self.alu_operation(instruction, |a, b| { - let result = a | b; - ( - result, - vec![ - FlagUpdate::Zero(result == 0), - FlagUpdate::Subtract(false), - FlagUpdate::HalfCarry(false), - FlagUpdate::Carry(false), - ], - ) - }) - } - - fn xor(&mut self, instruction: Instruction) -> u16 { - self.alu_operation(instruction, |a, b| { - let result = a ^ b; - ( - result, - vec![ - FlagUpdate::Zero(result == 0), - FlagUpdate::Subtract(false), - FlagUpdate::HalfCarry(false), - FlagUpdate::Carry(false), - ], - ) - }) - } - - fn compare(&mut self, instruction: Instruction) -> u16 { - self.alu_operation(instruction, |a, b| { - let result = a.wrapping_sub(b); - ( - a, - vec![ - FlagUpdate::Zero(result == 0), - FlagUpdate::Subtract(true), - FlagUpdate::HalfCarry((a & 0xF) < (b & 0xF)), - FlagUpdate::Carry(a < b), - ], - ) - }) - } - - fn inc(&mut self, register: Register) -> u16 { - let value = match ®ister { - Register::HL => self.memory.read(self.registers.get_16(&Register::HL)), - _ => self.registers.get(®ister), - }; - - let result = value.wrapping_add(1); - - self.registers.f.zero = result == 0; - self.registers.f.subtract = false; - self.registers.f.half_carry = (value & 0xF) == 0xF; - - if let Register::HL = register { - self.memory - .write(self.registers.get_16(&Register::HL), result); - } else { - self.registers.set(®ister, result); - } - - self.pc.wrapping_add(1) - } - - fn inc16(&mut self, register: Register) -> u16 { - let value = self.registers.get_16(®ister); - let result = value.wrapping_add(1); - self.registers.set_16(®ister, result); - - self.pc.wrapping_add(1) - } - - fn dec(&mut self, register: Register) -> u16 { - let value = match ®ister { - Register::HL => self.memory.read(self.registers.get_16(&Register::HL)), - _ => self.registers.get(®ister), - }; - - let result = value.wrapping_sub(1); - - self.registers.f.zero = result == 0; - self.registers.f.subtract = true; - self.registers.f.half_carry = (value & 0xF) == 0x0; - - if let Register::HL = register { - self.memory - .write(self.registers.get_16(&Register::HL), result); - } else { - self.registers.set(®ister, result); - } - - self.pc.wrapping_add(1) - } - - fn dec16(&mut self, register: Register) -> u16 { - let value = self.registers.get_16(®ister); - let result = value.wrapping_sub(1); - self.registers.set_16(®ister, result); - - self.pc.wrapping_add(1) - } - - fn add(&mut self, instruction: Instruction) -> u16 { - self.alu_operation(instruction, |a, b| { - let (result, did_overflow) = a.overflowing_add(b); - ( - result, - vec![ - FlagUpdate::Zero(result == 0), - FlagUpdate::Subtract(false), - FlagUpdate::HalfCarry(((a & 0x0F) + (b & 0x0F)) & 0x10 == 0x10), - FlagUpdate::Carry(did_overflow), - ], - ) - }) - } - - fn add16(&mut self, instruction: Instruction) -> u16 { - self.alu_operation16(&instruction, |a, b| { - let (result, did_overflow) = a.overflowing_add(b); - ( - result, - vec![ - FlagUpdate::Zero(false), - FlagUpdate::Subtract(false), - FlagUpdate::HalfCarry(((a & 0x0FFF) + (b & 0x0FFF)) & 0x1000 == 0x1000), - FlagUpdate::Carry(did_overflow), - ], - ) - }) - } - - fn sub(&mut self, instruction: Instruction) -> u16 { - self.alu_operation(instruction, |a, b| { - let (result, did_overflow) = a.overflowing_sub(b); - ( - result, - vec![ - FlagUpdate::Zero(result == 0), - FlagUpdate::Subtract(true), - FlagUpdate::HalfCarry((a & 0xF) < (b & 0xF)), - FlagUpdate::Carry(did_overflow), - ], - ) - }) - } - - fn push(&mut self, register: Register) -> u16 { - let value = self.registers.get_16(®ister); - self.registers - .sp - .set(self.registers.sp.get().wrapping_sub(2)); - self.memory.write_16(self.registers.sp.get(), value); - - self.pc.wrapping_add(1) - } - - fn pop(&mut self, register: Register) -> u16 { - let value = self.memory.read_16(self.registers.sp.get()); - self.registers.set_16(®ister, value); - self.registers - .sp - .set(self.registers.sp.get().wrapping_add(2)); - - self.pc.wrapping_add(1) - } - - fn load_8(&mut self, instruction: Instruction) -> u16 { - match instruction { - Instruction::Ld8(to, from) => match (&to, &from) { - (Register::BC | Register::DE | Register::HL | Register::AF, Register::D8) => { - let value = self.memory.read(self.pc + 1); - let address = self.registers.get_16(&to); - self.memory.write(address, value); - - self.pc.wrapping_add(2) - } - (Register::BC | Register::DE | Register::HL | Register::AF, from) => { - let value = self.registers.get(from); - let address = self.registers.get_16(&to); - self.memory.write(address, value); - - self.pc.wrapping_add(1) - } - (Register::D16, from) => { - let value = self.registers.get(from); - let address = self.memory.read_16(self.pc + 1); - self.memory.write(address, value); - - self.pc.wrapping_add(3) - } - (to, Register::HL | Register::BC | Register::DE | Register::AF) => { - let address = self.registers.get_16(&from); - let value = self.memory.read(address); - self.registers.set(to, value); - - self.pc.wrapping_add(1) - } - (to, Register::D8) => { - let value = self.memory.read(self.pc + 1); - self.registers.set(to, value); - - self.pc.wrapping_add(2) - } - (to, Register::D16) => { - let address = self.memory.read_16(self.pc + 1); - let value = self.memory.read(address); - self.registers.set(to, value); - - self.pc.wrapping_add(3) - } - (to, from) => { - let value = self.registers.get(from); - self.registers.set(to, value); - - self.pc.wrapping_add(1) - } - }, - _ => panic!("[CPU] Invalid instruction {:?}", instruction), - } - } - - fn load_16(&mut self, instruction: Instruction) -> u16 { - match instruction { - Instruction::Ld16(to, from) => match (&to, &from) { - (Register::SP, Register::HL) => { - let value = self.registers.get_16(&Register::HL); - self.registers.sp.set(value); - - self.pc.wrapping_add(1) - } - (Register::SP, Register::D8) => { - let n = self.memory.read(self.pc + 1) as u16; - let (address, did_overflow) = self.registers.sp.get().overflowing_add(n); - println!( - "[CPU] SP: 0x{:x} + 0x{:x} = 0x{:x}", - self.registers.sp.get(), - n, - address - ); - self.registers.set_16(&Register::HL, address); - - self.registers.f.zero = false; - self.registers.f.subtract = false; - self.registers.f.half_carry = - (((self.registers.sp.get() & 0xFFF) + (n & 0xFFF)) & 0x1000) == 0x1000; - self.registers.f.carry = did_overflow; - - self.pc.wrapping_add(3) - } - (Register::D16, Register::SP) => { - let address = self.memory.read_16(self.pc + 1); - self.registers.sp.set(address); - - self.pc.wrapping_add(3) - } - (Register::BC | Register::DE | Register::HL | Register::SP, Register::D16) => { - let value = self.memory.read_16(self.pc + 1); - self.registers.set_16(&to, value); - - self.pc.wrapping_add(3) - } - (to, from) => { - let value = self.registers.get_16(from); - self.registers.set_16(to, value); - - self.pc.wrapping_add(1) - } - }, - _ => panic!("[CPU] Invalid instruction {:?}", instruction), - } - } - - fn load_special(&mut self, instruction: Instruction) -> u16 { - match instruction { - Instruction::LdCa => { - let address = 0xFF00 + self.registers.get(&Register::C) as u16; - let value = self.registers.get(&Register::A); - self.memory.write(address, value); - - self.pc.wrapping_add(1) - } - Instruction::LdAc => { - let address = 0xFF00 + self.registers.get(&Register::C) as u16; - let value = self.memory.read(address); - self.registers.set(&Register::A, value); - - self.pc.wrapping_add(1) - } - Instruction::LdNa => { - let address = 0xFF00 + self.memory.read(self.pc + 1) as u16; - let value = self.registers.get(&Register::A); - self.memory.write(address, value); - - self.pc.wrapping_add(2) - } - Instruction::LdAn => { - let address = 0xFF00 + self.memory.read(self.pc + 1) as u16; - let value = self.memory.read(address); - self.registers.set(&Register::A, value); - - self.pc.wrapping_add(2) - } - Instruction::LdHi => { - let address = self.registers.get_16(&Register::HL) + 1; - let value = self.registers.get(&Register::A); - self.memory.write(address, value); - - self.pc.wrapping_add(1) - } - Instruction::LdHd => { - let address = self.registers.get_16(&Register::HL) - 1; - let value = self.registers.get(&Register::A); - self.memory.write(address, value); - - self.pc.wrapping_add(1) - } - _ => panic!("[CPU] Invalid instruction {:?}", instruction), - } - } } #[cfg(test)] @@ -600,7 +138,7 @@ mod tests { fn execute_nop() { let mut cpu = Cpu::new(); let pc = cpu.pc; - let next_pc = cpu.execute(Instruction::Nop, false); + let next_pc = cpu.execute(Instruction::Misc(instructions::MiscInstruction::Nop), false); assert_eq!(next_pc, pc + 1); }