From b4a24120a278a289bd44e56aae885251c58ed70f Mon Sep 17 00:00:00 2001 From: Nick Krichevsky Date: Sat, 13 May 2023 13:27:13 -0400 Subject: [PATCH] Refactor arithmetic instructions to deduplicate implementations There are now no longer instructions for each individual operand - we break it into operand and operations to be handled individually --- src/cpu/instructions.rs | 5 +- src/cpu/instructions/arith8.rs | 49 +++++-------- src/cpu/parse/arith8/add.rs | 43 +++++++---- src/cpu/parse/arith8/and.rs | 23 ++++-- src/cpu/parse/arith8/sub.rs | 43 +++++++---- src/cpu/parse/arith8/xor.rs | 23 ++++-- src/cpu/run.rs | 13 +--- src/cpu/run/arith8.rs | 126 +++++++++++++++++++-------------- src/cpu/run/arith8/add.rs | 110 ++++------------------------ src/cpu/run/arith8/and.rs | 70 ++++-------------- src/cpu/run/arith8/sub.rs | 113 ++++------------------------- src/cpu/run/arith8/xor.rs | 69 ++++-------------- 12 files changed, 243 insertions(+), 444 deletions(-) diff --git a/src/cpu/instructions.rs b/src/cpu/instructions.rs index 1391138..9115903 100644 --- a/src/cpu/instructions.rs +++ b/src/cpu/instructions.rs @@ -14,10 +14,7 @@ pub mod load8; pub enum Instruction { EightBitLoad(load8::EightBitLoadInstruction), SixteenBitLoad(load16::SixteenBitLoadInstruction), - EightBitAdd(arith8::EightBitAddInstruction), - EightBitSub(arith8::EightBitSubInstruction), - EightBitAnd(arith8::EightBitAndInstruction), - EightBitXor(arith8::EightBitXorInstruction), + EightBitArithmetic(arith8::EightBitArithmeticInstruction), } /// `RunnableInstruction` is an instruction that can run on the processor, and has any metadata needed to do so diff --git a/src/cpu/instructions/arith8.rs b/src/cpu/instructions/arith8.rs index 4550d68..79ae33f 100644 --- a/src/cpu/instructions/arith8.rs +++ b/src/cpu/instructions/arith8.rs @@ -1,40 +1,25 @@ //! The `arith8` module holds instructions related to 8-bit arithmetic use crate::register; -// `EightBitAddInstruction` represents one of the Gameboy's instructions for performing addition on -// eight bit numbers -#[derive(Debug, Clone, Copy)] -pub enum EightBitAddInstruction { - AddSingleRegisterToA { src: register::SingleEightBit }, - AddImmediateToA { n: u8 }, - AddHLAddressToA, - AddSingleRegisterToAWithCarry { src: register::SingleEightBit }, - AddImmediateToAWithCarry { n: u8 }, - AddHLAddressToAWithCarry, +#[derive(Debug, Copy, Clone)] +pub enum Operation { + Add, + AddWithCarry, + Sub, + SubWithCarry, + And, + Xor, } -// `EightBitSubInstruction` represents one of the Gameboy's instructions for performing addition on -// eight bit numbers -#[derive(Debug, Clone, Copy)] -pub enum EightBitSubInstruction { - SubSingleRegisterFromA { src: register::SingleEightBit }, - SubHLAddressFromA, - SubImmediateFromA { n: u8 }, - SubSingleRegisterFromAWithCarry { src: register::SingleEightBit }, - SubHLAddressFromAWithCarry, - SubImmediateFromAWithCarry { n: u8 }, +#[derive(Debug, Copy, Clone)] +pub enum Operand { + SingleRegister(register::SingleEightBit), + HLAddressValue, + Immediate(u8), } -#[derive(Debug, Clone, Copy)] -pub enum EightBitAndInstruction { - AndSingleRegisterWithA { src: register::SingleEightBit }, - AndHLAddressWithA, - AndImmediateWithA { n: u8 }, -} - -#[derive(Debug, Clone, Copy)] -pub enum EightBitXorInstruction { - XorSingleRegisterWithA { src: register::SingleEightBit }, - XorHLAddressWithA, - XorImmediateWithA { n: u8 }, +#[derive(Debug, Copy, Clone)] +pub struct EightBitArithmeticInstruction { + pub operation: Operation, + pub operand: Operand, } diff --git a/src/cpu/parse/arith8/add.rs b/src/cpu/parse/arith8/add.rs index 8fa73d7..89bd16b 100644 --- a/src/cpu/parse/arith8/add.rs +++ b/src/cpu/parse/arith8/add.rs @@ -1,6 +1,9 @@ use crate::{ cpu::{ - instructions::{arith8::EightBitAddInstruction, Instruction}, + instructions::{ + arith8::{EightBitArithmeticInstruction, Operand, Operation}, + Instruction, + }, parse::{self, Error, OpcodeParser, ParseOutput, ParseResult}, }, memory::View, @@ -56,38 +59,52 @@ impl OpcodeParser for EightBitAddParser { fn build_add_register_to_a_data(src: register::SingleEightBit) -> ParseOutput { super::build_operation_between_register_and_a_data(src, |register| { - Instruction::EightBitAdd(EightBitAddInstruction::AddSingleRegisterToA { src: register }) + build_add_instruction(Operand::SingleRegister(register)) }) } fn build_add_register_to_a_with_carry_data(src: register::SingleEightBit) -> ParseOutput { super::build_operation_between_register_and_a_data(src, |register| { - Instruction::EightBitAdd(EightBitAddInstruction::AddSingleRegisterToAWithCarry { - src: register, - }) + build_add_with_carry_instruction(Operand::SingleRegister(register)) }) } fn build_add_hl_address_to_a_data() -> ParseOutput { - super::build_operation_between_hl_value_and_a_data(Instruction::EightBitAdd( - EightBitAddInstruction::AddHLAddressToA, - )) + let ins = build_add_instruction(Operand::HLAddressValue); + super::build_operation_between_hl_value_and_a_data(ins) } fn build_add_hl_address_to_a_with_carry_data() -> ParseOutput { - super::build_operation_between_hl_value_and_a_data(Instruction::EightBitAdd( - EightBitAddInstruction::AddHLAddressToAWithCarry, - )) + let ins = build_add_with_carry_instruction(Operand::HLAddressValue); + super::build_operation_between_hl_value_and_a_data(ins) } fn build_add_immediate_to_a_data(data: &View) -> ParseOutput { super::build_operation_between_immediate_and_a_data(data, |n| { - Instruction::EightBitAdd(EightBitAddInstruction::AddImmediateToA { n }) + build_add_instruction(Operand::Immediate(n)) }) } fn build_add_immediate_to_a_with_carry_data(data: &View) -> ParseOutput { super::build_operation_between_immediate_and_a_data(data, |n| { - Instruction::EightBitAdd(EightBitAddInstruction::AddImmediateToAWithCarry { n }) + build_add_with_carry_instruction(Operand::Immediate(n)) }) } + +fn build_add_instruction(operand: Operand) -> Instruction { + let arith_instruction = EightBitArithmeticInstruction { + operand, + operation: Operation::Add, + }; + + Instruction::EightBitArithmetic(arith_instruction) +} + +fn build_add_with_carry_instruction(operand: Operand) -> Instruction { + let arith_instruction = EightBitArithmeticInstruction { + operand, + operation: Operation::AddWithCarry, + }; + + Instruction::EightBitArithmetic(arith_instruction) +} diff --git a/src/cpu/parse/arith8/and.rs b/src/cpu/parse/arith8/and.rs index f3a2b22..ddf0160 100644 --- a/src/cpu/parse/arith8/and.rs +++ b/src/cpu/parse/arith8/and.rs @@ -1,6 +1,9 @@ use crate::{ cpu::{ - instructions::{arith8::EightBitAndInstruction, Instruction}, + instructions::{ + arith8::{EightBitArithmeticInstruction, Operand, Operation}, + Instruction, + }, parse::{self, Error, OpcodeParser, ParseOutput, ParseResult}, }, memory::View, @@ -29,18 +32,26 @@ impl OpcodeParser for EightBitAndParser { fn build_and_register_with_a_data(src: register::SingleEightBit) -> ParseOutput { super::build_operation_between_register_and_a_data(src, |register| { - Instruction::EightBitAnd(EightBitAndInstruction::AndSingleRegisterWithA { src: register }) + build_and_instruction(Operand::SingleRegister(register)) }) } fn build_and_hl_value_with_a_data() -> ParseOutput { - super::build_operation_between_hl_value_and_a_data(Instruction::EightBitAnd( - EightBitAndInstruction::AndHLAddressWithA, - )) + let ins = build_and_instruction(Operand::HLAddressValue); + super::build_operation_between_hl_value_and_a_data(ins) } fn build_and_immediate_with_a_data(data: &View) -> ParseOutput { super::build_operation_between_immediate_and_a_data(data, |n| { - Instruction::EightBitAnd(EightBitAndInstruction::AndImmediateWithA { n }) + build_and_instruction(Operand::Immediate(n)) }) } + +fn build_and_instruction(operand: Operand) -> Instruction { + let arith_instruction = EightBitArithmeticInstruction { + operand, + operation: Operation::And, + }; + + Instruction::EightBitArithmetic(arith_instruction) +} diff --git a/src/cpu/parse/arith8/sub.rs b/src/cpu/parse/arith8/sub.rs index cc7d8a3..5c5d833 100644 --- a/src/cpu/parse/arith8/sub.rs +++ b/src/cpu/parse/arith8/sub.rs @@ -1,6 +1,9 @@ use crate::{ cpu::{ - instructions::{arith8::EightBitSubInstruction, Instruction}, + instructions::{ + arith8::{EightBitArithmeticInstruction, Operand, Operation}, + Instruction, + }, parse::{self, Error, OpcodeParser, ParseOutput, ParseResult}, }, memory::View, @@ -52,7 +55,7 @@ impl OpcodeParser for EightBitSubParser { fn build_sub_register_from_a_data(src_register: register::SingleEightBit) -> ParseOutput { super::build_operation_between_register_and_a_data(src_register, |register| { - Instruction::EightBitSub(EightBitSubInstruction::SubSingleRegisterFromA { src: register }) + build_sub_instruction(Operand::SingleRegister(register)) }) } @@ -60,32 +63,46 @@ fn build_sub_register_from_a_with_carry_data( src_register: register::SingleEightBit, ) -> ParseOutput { super::build_operation_between_register_and_a_data(src_register, |register| { - Instruction::EightBitSub(EightBitSubInstruction::SubSingleRegisterFromAWithCarry { - src: register, - }) + build_sub_with_carry_instruction(Operand::SingleRegister(register)) }) } fn build_sub_hl_value_from_a_data() -> ParseOutput { - super::build_operation_between_hl_value_and_a_data(Instruction::EightBitSub( - EightBitSubInstruction::SubHLAddressFromA, - )) + let ins = build_sub_instruction(Operand::HLAddressValue); + super::build_operation_between_hl_value_and_a_data(ins) } fn build_sub_hl_value_from_a_with_carry_data() -> ParseOutput { - super::build_operation_between_hl_value_and_a_data(Instruction::EightBitSub( - EightBitSubInstruction::SubHLAddressFromAWithCarry, - )) + let ins = build_sub_with_carry_instruction(Operand::HLAddressValue); + super::build_operation_between_hl_value_and_a_data(ins) } fn build_sub_immediate_from_a_data(data: &View) -> ParseOutput { super::build_operation_between_immediate_and_a_data(data, |n| { - Instruction::EightBitSub(EightBitSubInstruction::SubImmediateFromA { n }) + build_sub_instruction(Operand::Immediate(n)) }) } fn build_sub_immediate_from_a_with_carry_data(data: &View) -> ParseOutput { super::build_operation_between_immediate_and_a_data(data, |n| { - Instruction::EightBitSub(EightBitSubInstruction::SubImmediateFromAWithCarry { n }) + build_sub_with_carry_instruction(Operand::Immediate(n)) }) } + +fn build_sub_instruction(operand: Operand) -> Instruction { + let arith_instruction = EightBitArithmeticInstruction { + operand, + operation: Operation::Sub, + }; + + Instruction::EightBitArithmetic(arith_instruction) +} + +fn build_sub_with_carry_instruction(operand: Operand) -> Instruction { + let arith_instruction = EightBitArithmeticInstruction { + operand, + operation: Operation::SubWithCarry, + }; + + Instruction::EightBitArithmetic(arith_instruction) +} diff --git a/src/cpu/parse/arith8/xor.rs b/src/cpu/parse/arith8/xor.rs index 10229a0..b34b938 100644 --- a/src/cpu/parse/arith8/xor.rs +++ b/src/cpu/parse/arith8/xor.rs @@ -1,6 +1,9 @@ use crate::{ cpu::{ - instructions::{arith8::EightBitXorInstruction, Instruction}, + instructions::{ + arith8::{EightBitArithmeticInstruction, Operand, Operation}, + Instruction, + }, parse::{self, Error, OpcodeParser, ParseOutput, ParseResult}, }, memory::View, @@ -29,18 +32,26 @@ impl OpcodeParser for EightBitXorParser { fn build_xor_register_with_a_data(src: register::SingleEightBit) -> ParseOutput { super::build_operation_between_register_and_a_data(src, |register| { - Instruction::EightBitXor(EightBitXorInstruction::XorSingleRegisterWithA { src: register }) + build_xor_instruction(Operand::SingleRegister(register)) }) } fn build_xor_hl_value_with_a_data() -> ParseOutput { - super::build_operation_between_hl_value_and_a_data(Instruction::EightBitXor( - EightBitXorInstruction::XorHLAddressWithA, - )) + let ins = build_xor_instruction(Operand::HLAddressValue); + super::build_operation_between_hl_value_and_a_data(ins) } fn build_xor_immediate_with_a_data(data: &View) -> ParseOutput { super::build_operation_between_immediate_and_a_data(data, |n| { - Instruction::EightBitXor(EightBitXorInstruction::XorImmediateWithA { n }) + build_xor_instruction(Operand::Immediate(n)) }) } + +fn build_xor_instruction(operand: Operand) -> Instruction { + let arith_instruction = EightBitArithmeticInstruction { + operand, + operation: Operation::Xor, + }; + + Instruction::EightBitArithmetic(arith_instruction) +} diff --git a/src/cpu/run.rs b/src/cpu/run.rs index ae0f942..862427e 100644 --- a/src/cpu/run.rs +++ b/src/cpu/run.rs @@ -41,17 +41,8 @@ pub fn run_instruction(processor: &mut Processor, instruction: Instruction) -> R Instruction::SixteenBitLoad(load_instruction) => { load16::SixteenBitLoadRunner::run_instruction(processor, load_instruction) } - Instruction::EightBitAdd(add_instruction) => { - arith8::EightBitAddRunner::run_instruction(processor, add_instruction) - } - Instruction::EightBitSub(sub_instruction) => { - arith8::EightBitSubRunner::run_instruction(processor, sub_instruction) - } - Instruction::EightBitAnd(and_instruction) => { - arith8::EightBitAndRunner::run_instruction(processor, and_instruction) - } - Instruction::EightBitXor(xor_instruction) => { - arith8::EightBitXorRunner::run_instruction(processor, xor_instruction) + Instruction::EightBitArithmetic(arith_instruction) => { + arith8::EightBitArithmeticRunner::run_instruction(processor, arith_instruction) } } } diff --git a/src/cpu/run/arith8.rs b/src/cpu/run/arith8.rs index 15c667d..6e12a16 100644 --- a/src/cpu/run/arith8.rs +++ b/src/cpu/run/arith8.rs @@ -1,30 +1,68 @@ -use crate::{cpu::run::Error, cpu::Processor, memory, register}; +use crate::{ + cpu::{instructions::arith8::EightBitArithmeticInstruction, run::Error}, + cpu::{ + instructions::arith8::{Operand, Operation}, + Processor, + }, + memory, register, +}; -pub use add::EightBitAddRunner; -pub use and::EightBitAndRunner; -pub use sub::EightBitSubRunner; -pub use xor::EightBitXorRunner; - -use super::arithutil::{self, CarriedNumber}; +use super::{ + arithutil::{self, CarriedNumber}, + InstructionRunner, +}; mod add; mod and; mod sub; mod xor; -#[derive(Debug, Clone, Copy)] -enum EightBitArithmeticOperation { - SingleRegisterToA { src: register::SingleEightBit }, - ImmediateToA { n: u8 }, - HLAddressToA, +pub struct EightBitArithmeticRunner; + +impl InstructionRunner for EightBitArithmeticRunner { + fn run_instruction( + processor: &mut Processor, + instruction: EightBitArithmeticInstruction, + ) -> Result<(), Error> { + match instruction.operation { + Operation::And => { + let (lhs, rhs) = gather_operands(processor, instruction.operand)?; + and::run(processor, lhs, rhs); + } + + Operation::Xor => { + let (lhs, rhs) = gather_operands(processor, instruction.operand)?; + xor::run(processor, lhs, rhs); + } + + Operation::Add => { + let (lhs, rhs) = gather_operands(processor, instruction.operand)?; + add::run(processor, lhs, rhs); + } + + Operation::AddWithCarry => { + let (lhs, rhs) = gather_operands_with_carry(processor, instruction.operand)?; + add::run(processor, lhs, rhs); + } + + Operation::Sub => { + let (lhs, rhs) = gather_operands(processor, instruction.operand)?; + sub::run(processor, lhs, rhs); + } + + Operation::SubWithCarry => { + let (lhs, rhs) = gather_operands_with_carry(processor, instruction.operand)?; + sub::run(processor, lhs, rhs); + } + } + + Ok(()) + } } -fn gather_operands( - processor: &mut Processor, - operation: EightBitArithmeticOperation, -) -> Result<(u8, u8), Error> { - match operation { - EightBitArithmeticOperation::SingleRegisterToA { src } => { +fn gather_operands(processor: &mut Processor, operand: Operand) -> Result<(u8, u8), Error> { + match operand { + Operand::SingleRegister(src) => { let a_value = processor .registers .get_single_8bit_register(register::SingleEightBit::A); @@ -33,7 +71,7 @@ fn gather_operands( Ok((a_value, src_register_value)) } - EightBitArithmeticOperation::ImmediateToA { n } => { + Operand::Immediate(n) => { let a_value = processor .registers .get_single_8bit_register(register::SingleEightBit::A); @@ -41,7 +79,7 @@ fn gather_operands( Ok((a_value, n)) } - EightBitArithmeticOperation::HLAddressToA => { + Operand::HLAddressValue => { let a_value = processor .registers .get_single_8bit_register(register::SingleEightBit::A); @@ -70,9 +108,9 @@ fn gather_operands( fn gather_operands_with_carry( processor: &mut Processor, - operation: EightBitArithmeticOperation, + operand: Operand, ) -> Result<(u8, CarriedNumber), Error> { - let (lhs, no_carry_rhs) = gather_operands(processor, operation)?; + let (lhs, no_carry_rhs) = gather_operands(processor, operand)?; let rhs = attach_carry_bit_to_operand(processor, no_carry_rhs)?; Ok((lhs, rhs)) @@ -134,11 +172,8 @@ mod tests { .registers .set_single_8bit_register(src_register, 0xBB); - let (lhs, rhs) = gather_operands( - &mut processor, - EightBitArithmeticOperation::SingleRegisterToA { src: src_register }, - ) - .expect("failed to gather operands"); + let (lhs, rhs) = gather_operands(&mut processor, Operand::SingleRegister(src_register)) + .expect("failed to gather operands"); assert_eq!((0xAA, 0xBB), (lhs, rhs)); } @@ -152,9 +187,7 @@ mod tests { let (lhs, rhs) = gather_operands( &mut processor, - EightBitArithmeticOperation::SingleRegisterToA { - src: register::SingleEightBit::A, - }, + Operand::SingleRegister(register::SingleEightBit::A), ) .expect("failed to gather operands"); @@ -167,11 +200,8 @@ mod tests { processor .registers .set_single_8bit_register(register::SingleEightBit::A, 0xAA); - let (lhs, rhs) = gather_operands( - &mut processor, - EightBitArithmeticOperation::ImmediateToA { n: 0x45 }, - ) - .expect("failed to gather operands"); + let (lhs, rhs) = gather_operands(&mut processor, Operand::Immediate(0x45)) + .expect("failed to gather operands"); assert_eq!((0xAA, 0x45), (lhs, rhs)); } @@ -190,7 +220,7 @@ mod tests { .set(0xFFAA, 0xBB) .expect("failed to set memory value"); - let (lhs, rhs) = gather_operands(&mut processor, EightBitArithmeticOperation::HLAddressToA) + let (lhs, rhs) = gather_operands(&mut processor, Operand::HLAddressValue) .expect("failed to gather operands"); assert_eq!((0xAA, 0xBB), (lhs, rhs)); @@ -223,11 +253,9 @@ mod tests { .registers .set_single_8bit_register(src_register, 0xBB); - let (lhs, rhs) = gather_operands_with_carry( - &mut processor, - EightBitArithmeticOperation::SingleRegisterToA { src: src_register }, - ) - .expect("failed to gather operands"); + let (lhs, rhs) = + gather_operands_with_carry(&mut processor, Operand::SingleRegister(src_register)) + .expect("failed to gather operands"); assert_eq!( (0xAA, CarriedNumber::new(0xBB, carry_bit).unwrap()), @@ -248,9 +276,7 @@ mod tests { let (lhs, rhs) = gather_operands_with_carry( &mut processor, - EightBitArithmeticOperation::SingleRegisterToA { - src: register::SingleEightBit::A, - }, + Operand::SingleRegister(register::SingleEightBit::A), ) .expect("failed to gather operands"); @@ -270,11 +296,8 @@ mod tests { processor .registers .set_single_8bit_register(register::SingleEightBit::A, 0xAA); - let (lhs, rhs) = gather_operands_with_carry( - &mut processor, - EightBitArithmeticOperation::ImmediateToA { n: 0x45 }, - ) - .expect("failed to gather operands"); + let (lhs, rhs) = gather_operands_with_carry(&mut processor, Operand::Immediate(0x45)) + .expect("failed to gather operands"); assert_eq!( (0xAA, CarriedNumber::new(0x45, carry_bit).unwrap()), @@ -300,9 +323,8 @@ mod tests { .set(0xFFAA, 0xBB) .expect("failed to set memory value"); - let (lhs, rhs) = - gather_operands_with_carry(&mut processor, EightBitArithmeticOperation::HLAddressToA) - .expect("failed to gather operands"); + let (lhs, rhs) = gather_operands_with_carry(&mut processor, Operand::HLAddressValue) + .expect("failed to gather operands"); assert_eq!( (0xAA, CarriedNumber::new(0xBB, carry_bit).unwrap()), diff --git a/src/cpu/run/arith8/add.rs b/src/cpu/run/arith8/add.rs index ca10b4f..defb7df 100644 --- a/src/cpu/run/arith8/add.rs +++ b/src/cpu/run/arith8/add.rs @@ -1,106 +1,20 @@ use crate::{ - cpu::{ - instructions::arith8::EightBitAddInstruction, - run::{arithutil::CarryingAdd, Error, InstructionRunner}, - Processor, - }, + cpu::{run::arithutil::CarryingAdd, Processor}, register, }; -use super::EightBitArithmeticOperation; - -pub struct EightBitAddRunner; - -impl EightBitAddRunner { - fn do_add(processor: &mut Processor, lhs: u8, rhs: T) - where - u8: CarryingAdd, - { - let result = lhs.add_with_carry(rhs); - Self::store_addition_result(processor, result); - } - - fn store_addition_result( - processor: &mut Processor, - (total, half_carry, carry): (u8, bool, bool), - ) { - processor - .registers - .set_single_8bit_register(register::SingleEightBit::A, total); - - super::set_addition_flags(processor, total, half_carry, carry); - } +pub fn run(processor: &mut Processor, lhs: u8, rhs: T) +where + u8: CarryingAdd, +{ + let result = lhs.add_with_carry(rhs); + store_addition_result(processor, result); } -impl InstructionRunner for EightBitAddRunner { - fn run_instruction( - processor: &mut Processor, - instruction: EightBitAddInstruction, - ) -> Result<(), Error> { - match instruction { - EightBitAddInstruction::AddSingleRegisterToA { src } => { - let (lhs, rhs) = super::gather_operands( - processor, - EightBitArithmeticOperation::SingleRegisterToA { src }, - )?; +fn store_addition_result(processor: &mut Processor, (total, half_carry, carry): (u8, bool, bool)) { + processor + .registers + .set_single_8bit_register(register::SingleEightBit::A, total); - Self::do_add(processor, lhs, rhs); - - Ok(()) - } - - EightBitAddInstruction::AddImmediateToA { n } => { - let (lhs, rhs) = super::gather_operands( - processor, - EightBitArithmeticOperation::ImmediateToA { n }, - )?; - - Self::do_add(processor, lhs, rhs); - - Ok(()) - } - - EightBitAddInstruction::AddHLAddressToA => { - let (lhs, rhs) = - super::gather_operands(processor, EightBitArithmeticOperation::HLAddressToA)?; - - Self::do_add(processor, lhs, rhs); - - Ok(()) - } - - EightBitAddInstruction::AddSingleRegisterToAWithCarry { src } => { - let (lhs, rhs) = super::gather_operands_with_carry( - processor, - EightBitArithmeticOperation::SingleRegisterToA { src }, - )?; - - Self::do_add(processor, lhs, rhs); - - Ok(()) - } - - EightBitAddInstruction::AddImmediateToAWithCarry { n } => { - let (lhs, rhs) = super::gather_operands_with_carry( - processor, - EightBitArithmeticOperation::ImmediateToA { n }, - )?; - - Self::do_add(processor, lhs, rhs); - - Ok(()) - } - - EightBitAddInstruction::AddHLAddressToAWithCarry => { - let (lhs, rhs) = super::gather_operands_with_carry( - processor, - EightBitArithmeticOperation::HLAddressToA, - )?; - - Self::do_add(processor, lhs, rhs); - - Ok(()) - } - } - } + super::set_addition_flags(processor, total, half_carry, carry); } diff --git a/src/cpu/run/arith8/and.rs b/src/cpu/run/arith8/and.rs index a89cb14..0222d01 100644 --- a/src/cpu/run/arith8/and.rs +++ b/src/cpu/run/arith8/and.rs @@ -1,59 +1,17 @@ -use crate::{ - cpu::{ - instructions::arith8::EightBitAndInstruction, - run::{Error, InstructionRunner}, - Processor, - }, - register, -}; +use crate::{cpu::Processor, register}; -use super::EightBitArithmeticOperation; +pub fn run(processor: &mut Processor, lhs: u8, rhs: u8) { + let result = lhs & rhs; -pub struct EightBitAndRunner; - -impl From for EightBitArithmeticOperation { - fn from(value: EightBitAndInstruction) -> Self { - match value { - EightBitAndInstruction::AndSingleRegisterWithA { src } => { - EightBitArithmeticOperation::SingleRegisterToA { src } - } - - EightBitAndInstruction::AndImmediateWithA { n } => { - EightBitArithmeticOperation::ImmediateToA { n } - } - - EightBitAndInstruction::AndHLAddressWithA => EightBitArithmeticOperation::HLAddressToA, - } - } -} - -impl EightBitAndRunner { - fn do_and(processor: &mut Processor, lhs: u8, rhs: u8) { - let result = lhs & rhs; - - processor.registers.a = result; - processor - .registers - .set_flag_bit(register::Flag::Zero, (result == 0).into()); - processor - .registers - .set_flag_bit(register::Flag::Subtract, 0); - processor - .registers - .set_flag_bit(register::Flag::HalfCarry, 1); - processor.registers.set_flag_bit(register::Flag::Carry, 0); - } -} - -impl InstructionRunner for EightBitAndRunner { - fn run_instruction( - processor: &mut Processor, - instruction: EightBitAndInstruction, - ) -> Result<(), Error> { - let (lhs, rhs) = super::gather_operands(processor, instruction.into())?; - - Self::do_and(processor, lhs, rhs); - - Ok(()) - } + processor.registers.a = result; + processor + .registers + .set_flag_bit(register::Flag::Zero, (result == 0).into()); + processor + .registers + .set_flag_bit(register::Flag::Subtract, 0); + processor + .registers + .set_flag_bit(register::Flag::HalfCarry, 1); + processor.registers.set_flag_bit(register::Flag::Carry, 0); } diff --git a/src/cpu/run/arith8/sub.rs b/src/cpu/run/arith8/sub.rs index 0ceab47..0c74ab4 100644 --- a/src/cpu/run/arith8/sub.rs +++ b/src/cpu/run/arith8/sub.rs @@ -1,106 +1,23 @@ use crate::{ - cpu::{ - instructions::arith8::EightBitSubInstruction, - run::{arithutil::CarryingSub, Error, InstructionRunner}, - Processor, - }, + cpu::{run::arithutil::CarryingSub, Processor}, register, }; -use super::EightBitArithmeticOperation; - -pub struct EightBitSubRunner; - -impl EightBitSubRunner { - fn do_sub(processor: &mut Processor, lhs: u8, rhs: T) - where - u8: CarryingSub, - { - let result = lhs.sub_with_carry(rhs); - Self::store_subtraction_result(processor, result); - } - - fn store_subtraction_result( - processor: &mut Processor, - (total, half_carry, carry): (u8, bool, bool), - ) { - processor - .registers - .set_single_8bit_register(register::SingleEightBit::A, total); - - super::set_subtraction_flags(processor, total, half_carry, carry); - } +pub fn run(processor: &mut Processor, lhs: u8, rhs: T) +where + u8: CarryingSub, +{ + let result = lhs.sub_with_carry(rhs); + store_subtraction_result(processor, result); } -impl InstructionRunner for EightBitSubRunner { - fn run_instruction( - processor: &mut Processor, - instruction: EightBitSubInstruction, - ) -> Result<(), Error> { - match instruction { - EightBitSubInstruction::SubSingleRegisterFromA { src } => { - let (lhs, rhs) = super::gather_operands( - processor, - EightBitArithmeticOperation::SingleRegisterToA { src }, - )?; +fn store_subtraction_result( + processor: &mut Processor, + (total, half_carry, carry): (u8, bool, bool), +) { + processor + .registers + .set_single_8bit_register(register::SingleEightBit::A, total); - Self::do_sub(processor, lhs, rhs); - - Ok(()) - } - - EightBitSubInstruction::SubImmediateFromA { n } => { - let (lhs, rhs) = super::gather_operands( - processor, - EightBitArithmeticOperation::ImmediateToA { n }, - )?; - - Self::do_sub(processor, lhs, rhs); - - Ok(()) - } - - EightBitSubInstruction::SubHLAddressFromA => { - let (lhs, rhs) = - super::gather_operands(processor, EightBitArithmeticOperation::HLAddressToA)?; - - Self::do_sub(processor, lhs, rhs); - - Ok(()) - } - - EightBitSubInstruction::SubSingleRegisterFromAWithCarry { src } => { - let (lhs, rhs) = super::gather_operands_with_carry( - processor, - EightBitArithmeticOperation::SingleRegisterToA { src }, - )?; - - Self::do_sub(processor, lhs, rhs); - - Ok(()) - } - - EightBitSubInstruction::SubImmediateFromAWithCarry { n } => { - let (lhs, rhs) = super::gather_operands_with_carry( - processor, - EightBitArithmeticOperation::ImmediateToA { n }, - )?; - - Self::do_sub(processor, lhs, rhs); - - Ok(()) - } - - EightBitSubInstruction::SubHLAddressFromAWithCarry => { - let (lhs, rhs) = super::gather_operands_with_carry( - processor, - EightBitArithmeticOperation::HLAddressToA, - )?; - - Self::do_sub(processor, lhs, rhs); - - Ok(()) - } - } - } + super::set_subtraction_flags(processor, total, half_carry, carry); } diff --git a/src/cpu/run/arith8/xor.rs b/src/cpu/run/arith8/xor.rs index 70a3feb..d820d52 100644 --- a/src/cpu/run/arith8/xor.rs +++ b/src/cpu/run/arith8/xor.rs @@ -1,57 +1,16 @@ -use crate::{ - cpu::{ - instructions::arith8::EightBitXorInstruction, - run::{Error, InstructionRunner}, - Processor, - }, - register, -}; +use crate::{cpu::Processor, register}; -use super::{gather_operands, EightBitArithmeticOperation}; - -pub struct EightBitXorRunner; - -impl From for EightBitArithmeticOperation { - fn from(value: EightBitXorInstruction) -> Self { - match value { - EightBitXorInstruction::XorSingleRegisterWithA { src } => { - EightBitArithmeticOperation::SingleRegisterToA { src } - } - - EightBitXorInstruction::XorImmediateWithA { n } => { - EightBitArithmeticOperation::ImmediateToA { n } - } - - EightBitXorInstruction::XorHLAddressWithA => EightBitArithmeticOperation::HLAddressToA, - } - } -} - -impl EightBitXorRunner { - fn do_xor(processor: &mut Processor, lhs: u8, rhs: u8) { - let result = lhs ^ rhs; - processor.registers.a = result; - processor - .registers - .set_flag_bit(register::Flag::Zero, (result == 0).into()); - processor - .registers - .set_flag_bit(register::Flag::Subtract, 0); - processor - .registers - .set_flag_bit(register::Flag::HalfCarry, 0); - processor.registers.set_flag_bit(register::Flag::Carry, 0); - } -} - -impl InstructionRunner for EightBitXorRunner { - fn run_instruction( - processor: &mut Processor, - instruction: EightBitXorInstruction, - ) -> Result<(), Error> { - let (lhs, rhs) = gather_operands(processor, instruction.into())?; - Self::do_xor(processor, lhs, rhs); - - Ok(()) - } +pub fn run(processor: &mut Processor, lhs: u8, rhs: u8) { + let result = lhs ^ rhs; + processor.registers.a = result; + processor + .registers + .set_flag_bit(register::Flag::Zero, (result == 0).into()); + processor + .registers + .set_flag_bit(register::Flag::Subtract, 0); + processor + .registers + .set_flag_bit(register::Flag::HalfCarry, 0); + processor.registers.set_flag_bit(register::Flag::Carry, 0); }