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 individuallyold-bit-manip
parent
b4b72c73dd
commit
b4a24120a2
|
@ -14,10 +14,7 @@ pub mod load8;
|
||||||
pub enum Instruction {
|
pub enum Instruction {
|
||||||
EightBitLoad(load8::EightBitLoadInstruction),
|
EightBitLoad(load8::EightBitLoadInstruction),
|
||||||
SixteenBitLoad(load16::SixteenBitLoadInstruction),
|
SixteenBitLoad(load16::SixteenBitLoadInstruction),
|
||||||
EightBitAdd(arith8::EightBitAddInstruction),
|
EightBitArithmetic(arith8::EightBitArithmeticInstruction),
|
||||||
EightBitSub(arith8::EightBitSubInstruction),
|
|
||||||
EightBitAnd(arith8::EightBitAndInstruction),
|
|
||||||
EightBitXor(arith8::EightBitXorInstruction),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `RunnableInstruction` is an instruction that can run on the processor, and has any metadata needed to do so
|
/// `RunnableInstruction` is an instruction that can run on the processor, and has any metadata needed to do so
|
||||||
|
|
|
@ -1,40 +1,25 @@
|
||||||
//! The `arith8` module holds instructions related to 8-bit arithmetic
|
//! The `arith8` module holds instructions related to 8-bit arithmetic
|
||||||
use crate::register;
|
use crate::register;
|
||||||
|
|
||||||
// `EightBitAddInstruction` represents one of the Gameboy's instructions for performing addition on
|
#[derive(Debug, Copy, Clone)]
|
||||||
// eight bit numbers
|
pub enum Operation {
|
||||||
#[derive(Debug, Clone, Copy)]
|
Add,
|
||||||
pub enum EightBitAddInstruction {
|
AddWithCarry,
|
||||||
AddSingleRegisterToA { src: register::SingleEightBit },
|
Sub,
|
||||||
AddImmediateToA { n: u8 },
|
SubWithCarry,
|
||||||
AddHLAddressToA,
|
And,
|
||||||
AddSingleRegisterToAWithCarry { src: register::SingleEightBit },
|
Xor,
|
||||||
AddImmediateToAWithCarry { n: u8 },
|
|
||||||
AddHLAddressToAWithCarry,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// `EightBitSubInstruction` represents one of the Gameboy's instructions for performing addition on
|
#[derive(Debug, Copy, Clone)]
|
||||||
// eight bit numbers
|
pub enum Operand {
|
||||||
#[derive(Debug, Clone, Copy)]
|
SingleRegister(register::SingleEightBit),
|
||||||
pub enum EightBitSubInstruction {
|
HLAddressValue,
|
||||||
SubSingleRegisterFromA { src: register::SingleEightBit },
|
Immediate(u8),
|
||||||
SubHLAddressFromA,
|
|
||||||
SubImmediateFromA { n: u8 },
|
|
||||||
SubSingleRegisterFromAWithCarry { src: register::SingleEightBit },
|
|
||||||
SubHLAddressFromAWithCarry,
|
|
||||||
SubImmediateFromAWithCarry { n: u8 },
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub enum EightBitAndInstruction {
|
pub struct EightBitArithmeticInstruction {
|
||||||
AndSingleRegisterWithA { src: register::SingleEightBit },
|
pub operation: Operation,
|
||||||
AndHLAddressWithA,
|
pub operand: Operand,
|
||||||
AndImmediateWithA { n: u8 },
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
|
||||||
pub enum EightBitXorInstruction {
|
|
||||||
XorSingleRegisterWithA { src: register::SingleEightBit },
|
|
||||||
XorHLAddressWithA,
|
|
||||||
XorImmediateWithA { n: u8 },
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
cpu::{
|
cpu::{
|
||||||
instructions::{arith8::EightBitAddInstruction, Instruction},
|
instructions::{
|
||||||
|
arith8::{EightBitArithmeticInstruction, Operand, Operation},
|
||||||
|
Instruction,
|
||||||
|
},
|
||||||
parse::{self, Error, OpcodeParser, ParseOutput, ParseResult},
|
parse::{self, Error, OpcodeParser, ParseOutput, ParseResult},
|
||||||
},
|
},
|
||||||
memory::View,
|
memory::View,
|
||||||
|
@ -56,38 +59,52 @@ impl OpcodeParser for EightBitAddParser {
|
||||||
|
|
||||||
fn build_add_register_to_a_data(src: register::SingleEightBit) -> ParseOutput {
|
fn build_add_register_to_a_data(src: register::SingleEightBit) -> ParseOutput {
|
||||||
super::build_operation_between_register_and_a_data(src, |register| {
|
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 {
|
fn build_add_register_to_a_with_carry_data(src: register::SingleEightBit) -> ParseOutput {
|
||||||
super::build_operation_between_register_and_a_data(src, |register| {
|
super::build_operation_between_register_and_a_data(src, |register| {
|
||||||
Instruction::EightBitAdd(EightBitAddInstruction::AddSingleRegisterToAWithCarry {
|
build_add_with_carry_instruction(Operand::SingleRegister(register))
|
||||||
src: register,
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_add_hl_address_to_a_data() -> ParseOutput {
|
fn build_add_hl_address_to_a_data() -> ParseOutput {
|
||||||
super::build_operation_between_hl_value_and_a_data(Instruction::EightBitAdd(
|
let ins = build_add_instruction(Operand::HLAddressValue);
|
||||||
EightBitAddInstruction::AddHLAddressToA,
|
super::build_operation_between_hl_value_and_a_data(ins)
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_add_hl_address_to_a_with_carry_data() -> ParseOutput {
|
fn build_add_hl_address_to_a_with_carry_data() -> ParseOutput {
|
||||||
super::build_operation_between_hl_value_and_a_data(Instruction::EightBitAdd(
|
let ins = build_add_with_carry_instruction(Operand::HLAddressValue);
|
||||||
EightBitAddInstruction::AddHLAddressToAWithCarry,
|
super::build_operation_between_hl_value_and_a_data(ins)
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_add_immediate_to_a_data(data: &View) -> ParseOutput {
|
fn build_add_immediate_to_a_data(data: &View) -> ParseOutput {
|
||||||
super::build_operation_between_immediate_and_a_data(data, |n| {
|
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 {
|
fn build_add_immediate_to_a_with_carry_data(data: &View) -> ParseOutput {
|
||||||
super::build_operation_between_immediate_and_a_data(data, |n| {
|
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)
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
cpu::{
|
cpu::{
|
||||||
instructions::{arith8::EightBitAndInstruction, Instruction},
|
instructions::{
|
||||||
|
arith8::{EightBitArithmeticInstruction, Operand, Operation},
|
||||||
|
Instruction,
|
||||||
|
},
|
||||||
parse::{self, Error, OpcodeParser, ParseOutput, ParseResult},
|
parse::{self, Error, OpcodeParser, ParseOutput, ParseResult},
|
||||||
},
|
},
|
||||||
memory::View,
|
memory::View,
|
||||||
|
@ -29,18 +32,26 @@ impl OpcodeParser for EightBitAndParser {
|
||||||
|
|
||||||
fn build_and_register_with_a_data(src: register::SingleEightBit) -> ParseOutput {
|
fn build_and_register_with_a_data(src: register::SingleEightBit) -> ParseOutput {
|
||||||
super::build_operation_between_register_and_a_data(src, |register| {
|
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 {
|
fn build_and_hl_value_with_a_data() -> ParseOutput {
|
||||||
super::build_operation_between_hl_value_and_a_data(Instruction::EightBitAnd(
|
let ins = build_and_instruction(Operand::HLAddressValue);
|
||||||
EightBitAndInstruction::AndHLAddressWithA,
|
super::build_operation_between_hl_value_and_a_data(ins)
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_and_immediate_with_a_data(data: &View) -> ParseOutput {
|
fn build_and_immediate_with_a_data(data: &View) -> ParseOutput {
|
||||||
super::build_operation_between_immediate_and_a_data(data, |n| {
|
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)
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
cpu::{
|
cpu::{
|
||||||
instructions::{arith8::EightBitSubInstruction, Instruction},
|
instructions::{
|
||||||
|
arith8::{EightBitArithmeticInstruction, Operand, Operation},
|
||||||
|
Instruction,
|
||||||
|
},
|
||||||
parse::{self, Error, OpcodeParser, ParseOutput, ParseResult},
|
parse::{self, Error, OpcodeParser, ParseOutput, ParseResult},
|
||||||
},
|
},
|
||||||
memory::View,
|
memory::View,
|
||||||
|
@ -52,7 +55,7 @@ impl OpcodeParser for EightBitSubParser {
|
||||||
|
|
||||||
fn build_sub_register_from_a_data(src_register: register::SingleEightBit) -> ParseOutput {
|
fn build_sub_register_from_a_data(src_register: register::SingleEightBit) -> ParseOutput {
|
||||||
super::build_operation_between_register_and_a_data(src_register, |register| {
|
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,
|
src_register: register::SingleEightBit,
|
||||||
) -> ParseOutput {
|
) -> ParseOutput {
|
||||||
super::build_operation_between_register_and_a_data(src_register, |register| {
|
super::build_operation_between_register_and_a_data(src_register, |register| {
|
||||||
Instruction::EightBitSub(EightBitSubInstruction::SubSingleRegisterFromAWithCarry {
|
build_sub_with_carry_instruction(Operand::SingleRegister(register))
|
||||||
src: register,
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_sub_hl_value_from_a_data() -> ParseOutput {
|
fn build_sub_hl_value_from_a_data() -> ParseOutput {
|
||||||
super::build_operation_between_hl_value_and_a_data(Instruction::EightBitSub(
|
let ins = build_sub_instruction(Operand::HLAddressValue);
|
||||||
EightBitSubInstruction::SubHLAddressFromA,
|
super::build_operation_between_hl_value_and_a_data(ins)
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_sub_hl_value_from_a_with_carry_data() -> ParseOutput {
|
fn build_sub_hl_value_from_a_with_carry_data() -> ParseOutput {
|
||||||
super::build_operation_between_hl_value_and_a_data(Instruction::EightBitSub(
|
let ins = build_sub_with_carry_instruction(Operand::HLAddressValue);
|
||||||
EightBitSubInstruction::SubHLAddressFromAWithCarry,
|
super::build_operation_between_hl_value_and_a_data(ins)
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_sub_immediate_from_a_data(data: &View) -> ParseOutput {
|
fn build_sub_immediate_from_a_data(data: &View) -> ParseOutput {
|
||||||
super::build_operation_between_immediate_and_a_data(data, |n| {
|
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 {
|
fn build_sub_immediate_from_a_with_carry_data(data: &View) -> ParseOutput {
|
||||||
super::build_operation_between_immediate_and_a_data(data, |n| {
|
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)
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
cpu::{
|
cpu::{
|
||||||
instructions::{arith8::EightBitXorInstruction, Instruction},
|
instructions::{
|
||||||
|
arith8::{EightBitArithmeticInstruction, Operand, Operation},
|
||||||
|
Instruction,
|
||||||
|
},
|
||||||
parse::{self, Error, OpcodeParser, ParseOutput, ParseResult},
|
parse::{self, Error, OpcodeParser, ParseOutput, ParseResult},
|
||||||
},
|
},
|
||||||
memory::View,
|
memory::View,
|
||||||
|
@ -29,18 +32,26 @@ impl OpcodeParser for EightBitXorParser {
|
||||||
|
|
||||||
fn build_xor_register_with_a_data(src: register::SingleEightBit) -> ParseOutput {
|
fn build_xor_register_with_a_data(src: register::SingleEightBit) -> ParseOutput {
|
||||||
super::build_operation_between_register_and_a_data(src, |register| {
|
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 {
|
fn build_xor_hl_value_with_a_data() -> ParseOutput {
|
||||||
super::build_operation_between_hl_value_and_a_data(Instruction::EightBitXor(
|
let ins = build_xor_instruction(Operand::HLAddressValue);
|
||||||
EightBitXorInstruction::XorHLAddressWithA,
|
super::build_operation_between_hl_value_and_a_data(ins)
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_xor_immediate_with_a_data(data: &View) -> ParseOutput {
|
fn build_xor_immediate_with_a_data(data: &View) -> ParseOutput {
|
||||||
super::build_operation_between_immediate_and_a_data(data, |n| {
|
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)
|
||||||
|
}
|
||||||
|
|
|
@ -41,17 +41,8 @@ pub fn run_instruction(processor: &mut Processor, instruction: Instruction) -> R
|
||||||
Instruction::SixteenBitLoad(load_instruction) => {
|
Instruction::SixteenBitLoad(load_instruction) => {
|
||||||
load16::SixteenBitLoadRunner::run_instruction(processor, load_instruction)
|
load16::SixteenBitLoadRunner::run_instruction(processor, load_instruction)
|
||||||
}
|
}
|
||||||
Instruction::EightBitAdd(add_instruction) => {
|
Instruction::EightBitArithmetic(arith_instruction) => {
|
||||||
arith8::EightBitAddRunner::run_instruction(processor, add_instruction)
|
arith8::EightBitArithmeticRunner::run_instruction(processor, arith_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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
use super::{
|
||||||
pub use and::EightBitAndRunner;
|
arithutil::{self, CarriedNumber},
|
||||||
pub use sub::EightBitSubRunner;
|
InstructionRunner,
|
||||||
pub use xor::EightBitXorRunner;
|
};
|
||||||
|
|
||||||
use super::arithutil::{self, CarriedNumber};
|
|
||||||
|
|
||||||
mod add;
|
mod add;
|
||||||
mod and;
|
mod and;
|
||||||
mod sub;
|
mod sub;
|
||||||
mod xor;
|
mod xor;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
pub struct EightBitArithmeticRunner;
|
||||||
enum EightBitArithmeticOperation {
|
|
||||||
SingleRegisterToA { src: register::SingleEightBit },
|
impl InstructionRunner<EightBitArithmeticInstruction> for EightBitArithmeticRunner {
|
||||||
ImmediateToA { n: u8 },
|
fn run_instruction(
|
||||||
HLAddressToA,
|
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(
|
fn gather_operands(processor: &mut Processor, operand: Operand) -> Result<(u8, u8), Error> {
|
||||||
processor: &mut Processor,
|
match operand {
|
||||||
operation: EightBitArithmeticOperation,
|
Operand::SingleRegister(src) => {
|
||||||
) -> Result<(u8, u8), Error> {
|
|
||||||
match operation {
|
|
||||||
EightBitArithmeticOperation::SingleRegisterToA { src } => {
|
|
||||||
let a_value = processor
|
let a_value = processor
|
||||||
.registers
|
.registers
|
||||||
.get_single_8bit_register(register::SingleEightBit::A);
|
.get_single_8bit_register(register::SingleEightBit::A);
|
||||||
|
@ -33,7 +71,7 @@ fn gather_operands(
|
||||||
Ok((a_value, src_register_value))
|
Ok((a_value, src_register_value))
|
||||||
}
|
}
|
||||||
|
|
||||||
EightBitArithmeticOperation::ImmediateToA { n } => {
|
Operand::Immediate(n) => {
|
||||||
let a_value = processor
|
let a_value = processor
|
||||||
.registers
|
.registers
|
||||||
.get_single_8bit_register(register::SingleEightBit::A);
|
.get_single_8bit_register(register::SingleEightBit::A);
|
||||||
|
@ -41,7 +79,7 @@ fn gather_operands(
|
||||||
Ok((a_value, n))
|
Ok((a_value, n))
|
||||||
}
|
}
|
||||||
|
|
||||||
EightBitArithmeticOperation::HLAddressToA => {
|
Operand::HLAddressValue => {
|
||||||
let a_value = processor
|
let a_value = processor
|
||||||
.registers
|
.registers
|
||||||
.get_single_8bit_register(register::SingleEightBit::A);
|
.get_single_8bit_register(register::SingleEightBit::A);
|
||||||
|
@ -70,9 +108,9 @@ fn gather_operands(
|
||||||
|
|
||||||
fn gather_operands_with_carry(
|
fn gather_operands_with_carry(
|
||||||
processor: &mut Processor,
|
processor: &mut Processor,
|
||||||
operation: EightBitArithmeticOperation,
|
operand: Operand,
|
||||||
) -> Result<(u8, CarriedNumber<u8>), Error> {
|
) -> Result<(u8, CarriedNumber<u8>), 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)?;
|
let rhs = attach_carry_bit_to_operand(processor, no_carry_rhs)?;
|
||||||
|
|
||||||
Ok((lhs, rhs))
|
Ok((lhs, rhs))
|
||||||
|
@ -134,11 +172,8 @@ mod tests {
|
||||||
.registers
|
.registers
|
||||||
.set_single_8bit_register(src_register, 0xBB);
|
.set_single_8bit_register(src_register, 0xBB);
|
||||||
|
|
||||||
let (lhs, rhs) = gather_operands(
|
let (lhs, rhs) = gather_operands(&mut processor, Operand::SingleRegister(src_register))
|
||||||
&mut processor,
|
.expect("failed to gather operands");
|
||||||
EightBitArithmeticOperation::SingleRegisterToA { src: src_register },
|
|
||||||
)
|
|
||||||
.expect("failed to gather operands");
|
|
||||||
|
|
||||||
assert_eq!((0xAA, 0xBB), (lhs, rhs));
|
assert_eq!((0xAA, 0xBB), (lhs, rhs));
|
||||||
}
|
}
|
||||||
|
@ -152,9 +187,7 @@ mod tests {
|
||||||
|
|
||||||
let (lhs, rhs) = gather_operands(
|
let (lhs, rhs) = gather_operands(
|
||||||
&mut processor,
|
&mut processor,
|
||||||
EightBitArithmeticOperation::SingleRegisterToA {
|
Operand::SingleRegister(register::SingleEightBit::A),
|
||||||
src: register::SingleEightBit::A,
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.expect("failed to gather operands");
|
.expect("failed to gather operands");
|
||||||
|
|
||||||
|
@ -167,11 +200,8 @@ mod tests {
|
||||||
processor
|
processor
|
||||||
.registers
|
.registers
|
||||||
.set_single_8bit_register(register::SingleEightBit::A, 0xAA);
|
.set_single_8bit_register(register::SingleEightBit::A, 0xAA);
|
||||||
let (lhs, rhs) = gather_operands(
|
let (lhs, rhs) = gather_operands(&mut processor, Operand::Immediate(0x45))
|
||||||
&mut processor,
|
.expect("failed to gather operands");
|
||||||
EightBitArithmeticOperation::ImmediateToA { n: 0x45 },
|
|
||||||
)
|
|
||||||
.expect("failed to gather operands");
|
|
||||||
|
|
||||||
assert_eq!((0xAA, 0x45), (lhs, rhs));
|
assert_eq!((0xAA, 0x45), (lhs, rhs));
|
||||||
}
|
}
|
||||||
|
@ -190,7 +220,7 @@ mod tests {
|
||||||
.set(0xFFAA, 0xBB)
|
.set(0xFFAA, 0xBB)
|
||||||
.expect("failed to set memory value");
|
.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");
|
.expect("failed to gather operands");
|
||||||
|
|
||||||
assert_eq!((0xAA, 0xBB), (lhs, rhs));
|
assert_eq!((0xAA, 0xBB), (lhs, rhs));
|
||||||
|
@ -223,11 +253,9 @@ mod tests {
|
||||||
.registers
|
.registers
|
||||||
.set_single_8bit_register(src_register, 0xBB);
|
.set_single_8bit_register(src_register, 0xBB);
|
||||||
|
|
||||||
let (lhs, rhs) = gather_operands_with_carry(
|
let (lhs, rhs) =
|
||||||
&mut processor,
|
gather_operands_with_carry(&mut processor, Operand::SingleRegister(src_register))
|
||||||
EightBitArithmeticOperation::SingleRegisterToA { src: src_register },
|
.expect("failed to gather operands");
|
||||||
)
|
|
||||||
.expect("failed to gather operands");
|
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
(0xAA, CarriedNumber::new(0xBB, carry_bit).unwrap()),
|
(0xAA, CarriedNumber::new(0xBB, carry_bit).unwrap()),
|
||||||
|
@ -248,9 +276,7 @@ mod tests {
|
||||||
|
|
||||||
let (lhs, rhs) = gather_operands_with_carry(
|
let (lhs, rhs) = gather_operands_with_carry(
|
||||||
&mut processor,
|
&mut processor,
|
||||||
EightBitArithmeticOperation::SingleRegisterToA {
|
Operand::SingleRegister(register::SingleEightBit::A),
|
||||||
src: register::SingleEightBit::A,
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.expect("failed to gather operands");
|
.expect("failed to gather operands");
|
||||||
|
|
||||||
|
@ -270,11 +296,8 @@ mod tests {
|
||||||
processor
|
processor
|
||||||
.registers
|
.registers
|
||||||
.set_single_8bit_register(register::SingleEightBit::A, 0xAA);
|
.set_single_8bit_register(register::SingleEightBit::A, 0xAA);
|
||||||
let (lhs, rhs) = gather_operands_with_carry(
|
let (lhs, rhs) = gather_operands_with_carry(&mut processor, Operand::Immediate(0x45))
|
||||||
&mut processor,
|
.expect("failed to gather operands");
|
||||||
EightBitArithmeticOperation::ImmediateToA { n: 0x45 },
|
|
||||||
)
|
|
||||||
.expect("failed to gather operands");
|
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
(0xAA, CarriedNumber::new(0x45, carry_bit).unwrap()),
|
(0xAA, CarriedNumber::new(0x45, carry_bit).unwrap()),
|
||||||
|
@ -300,9 +323,8 @@ mod tests {
|
||||||
.set(0xFFAA, 0xBB)
|
.set(0xFFAA, 0xBB)
|
||||||
.expect("failed to set memory value");
|
.expect("failed to set memory value");
|
||||||
|
|
||||||
let (lhs, rhs) =
|
let (lhs, rhs) = gather_operands_with_carry(&mut processor, Operand::HLAddressValue)
|
||||||
gather_operands_with_carry(&mut processor, EightBitArithmeticOperation::HLAddressToA)
|
.expect("failed to gather operands");
|
||||||
.expect("failed to gather operands");
|
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
(0xAA, CarriedNumber::new(0xBB, carry_bit).unwrap()),
|
(0xAA, CarriedNumber::new(0xBB, carry_bit).unwrap()),
|
||||||
|
|
|
@ -1,106 +1,20 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
cpu::{
|
cpu::{run::arithutil::CarryingAdd, Processor},
|
||||||
instructions::arith8::EightBitAddInstruction,
|
|
||||||
run::{arithutil::CarryingAdd, Error, InstructionRunner},
|
|
||||||
Processor,
|
|
||||||
},
|
|
||||||
register,
|
register,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::EightBitArithmeticOperation;
|
pub fn run<T>(processor: &mut Processor, lhs: u8, rhs: T)
|
||||||
|
where
|
||||||
pub struct EightBitAddRunner;
|
u8: CarryingAdd<T, Output = u8>,
|
||||||
|
{
|
||||||
impl EightBitAddRunner {
|
let result = lhs.add_with_carry(rhs);
|
||||||
fn do_add<T>(processor: &mut Processor, lhs: u8, rhs: T)
|
store_addition_result(processor, result);
|
||||||
where
|
|
||||||
u8: CarryingAdd<T, Output = u8>,
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InstructionRunner<EightBitAddInstruction> for EightBitAddRunner {
|
fn store_addition_result(processor: &mut Processor, (total, half_carry, carry): (u8, bool, bool)) {
|
||||||
fn run_instruction(
|
processor
|
||||||
processor: &mut Processor,
|
.registers
|
||||||
instruction: EightBitAddInstruction,
|
.set_single_8bit_register(register::SingleEightBit::A, total);
|
||||||
) -> Result<(), Error> {
|
|
||||||
match instruction {
|
|
||||||
EightBitAddInstruction::AddSingleRegisterToA { src } => {
|
|
||||||
let (lhs, rhs) = super::gather_operands(
|
|
||||||
processor,
|
|
||||||
EightBitArithmeticOperation::SingleRegisterToA { src },
|
|
||||||
)?;
|
|
||||||
|
|
||||||
Self::do_add(processor, lhs, rhs);
|
super::set_addition_flags(processor, total, half_carry, carry);
|
||||||
|
|
||||||
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(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,59 +1,17 @@
|
||||||
use crate::{
|
use crate::{cpu::Processor, register};
|
||||||
cpu::{
|
|
||||||
instructions::arith8::EightBitAndInstruction,
|
|
||||||
run::{Error, InstructionRunner},
|
|
||||||
Processor,
|
|
||||||
},
|
|
||||||
register,
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::EightBitArithmeticOperation;
|
pub fn run(processor: &mut Processor, lhs: u8, rhs: u8) {
|
||||||
|
let result = lhs & rhs;
|
||||||
|
|
||||||
pub struct EightBitAndRunner;
|
processor.registers.a = result;
|
||||||
|
processor
|
||||||
impl From<EightBitAndInstruction> for EightBitArithmeticOperation {
|
.registers
|
||||||
fn from(value: EightBitAndInstruction) -> Self {
|
.set_flag_bit(register::Flag::Zero, (result == 0).into());
|
||||||
match value {
|
processor
|
||||||
EightBitAndInstruction::AndSingleRegisterWithA { src } => {
|
.registers
|
||||||
EightBitArithmeticOperation::SingleRegisterToA { src }
|
.set_flag_bit(register::Flag::Subtract, 0);
|
||||||
}
|
processor
|
||||||
|
.registers
|
||||||
EightBitAndInstruction::AndImmediateWithA { n } => {
|
.set_flag_bit(register::Flag::HalfCarry, 1);
|
||||||
EightBitArithmeticOperation::ImmediateToA { n }
|
processor.registers.set_flag_bit(register::Flag::Carry, 0);
|
||||||
}
|
|
||||||
|
|
||||||
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<EightBitAndInstruction> 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(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,106 +1,23 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
cpu::{
|
cpu::{run::arithutil::CarryingSub, Processor},
|
||||||
instructions::arith8::EightBitSubInstruction,
|
|
||||||
run::{arithutil::CarryingSub, Error, InstructionRunner},
|
|
||||||
Processor,
|
|
||||||
},
|
|
||||||
register,
|
register,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::EightBitArithmeticOperation;
|
pub fn run<T>(processor: &mut Processor, lhs: u8, rhs: T)
|
||||||
|
where
|
||||||
pub struct EightBitSubRunner;
|
u8: CarryingSub<T, Output = u8>,
|
||||||
|
{
|
||||||
impl EightBitSubRunner {
|
let result = lhs.sub_with_carry(rhs);
|
||||||
fn do_sub<T>(processor: &mut Processor, lhs: u8, rhs: T)
|
store_subtraction_result(processor, result);
|
||||||
where
|
|
||||||
u8: CarryingSub<T, Output = u8>,
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InstructionRunner<EightBitSubInstruction> for EightBitSubRunner {
|
fn store_subtraction_result(
|
||||||
fn run_instruction(
|
processor: &mut Processor,
|
||||||
processor: &mut Processor,
|
(total, half_carry, carry): (u8, bool, bool),
|
||||||
instruction: EightBitSubInstruction,
|
) {
|
||||||
) -> Result<(), Error> {
|
processor
|
||||||
match instruction {
|
.registers
|
||||||
EightBitSubInstruction::SubSingleRegisterFromA { src } => {
|
.set_single_8bit_register(register::SingleEightBit::A, total);
|
||||||
let (lhs, rhs) = super::gather_operands(
|
|
||||||
processor,
|
|
||||||
EightBitArithmeticOperation::SingleRegisterToA { src },
|
|
||||||
)?;
|
|
||||||
|
|
||||||
Self::do_sub(processor, lhs, rhs);
|
super::set_subtraction_flags(processor, total, half_carry, carry);
|
||||||
|
|
||||||
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(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,57 +1,16 @@
|
||||||
use crate::{
|
use crate::{cpu::Processor, register};
|
||||||
cpu::{
|
|
||||||
instructions::arith8::EightBitXorInstruction,
|
|
||||||
run::{Error, InstructionRunner},
|
|
||||||
Processor,
|
|
||||||
},
|
|
||||||
register,
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::{gather_operands, EightBitArithmeticOperation};
|
pub fn run(processor: &mut Processor, lhs: u8, rhs: u8) {
|
||||||
|
let result = lhs ^ rhs;
|
||||||
pub struct EightBitXorRunner;
|
processor.registers.a = result;
|
||||||
|
processor
|
||||||
impl From<EightBitXorInstruction> for EightBitArithmeticOperation {
|
.registers
|
||||||
fn from(value: EightBitXorInstruction) -> Self {
|
.set_flag_bit(register::Flag::Zero, (result == 0).into());
|
||||||
match value {
|
processor
|
||||||
EightBitXorInstruction::XorSingleRegisterWithA { src } => {
|
.registers
|
||||||
EightBitArithmeticOperation::SingleRegisterToA { src }
|
.set_flag_bit(register::Flag::Subtract, 0);
|
||||||
}
|
processor
|
||||||
|
.registers
|
||||||
EightBitXorInstruction::XorImmediateWithA { n } => {
|
.set_flag_bit(register::Flag::HalfCarry, 0);
|
||||||
EightBitArithmeticOperation::ImmediateToA { n }
|
processor.registers.set_flag_bit(register::Flag::Carry, 0);
|
||||||
}
|
|
||||||
|
|
||||||
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<EightBitXorInstruction> 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(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue