Remove RunnableInstruction, encode cycles as a result of runtime

This is necessary for certain instructions, since they can take a different number of cycles
old-bit-manip
Nick Krichevsky 2023-11-20 14:25:07 -05:00
parent f9cdccb5fd
commit b5117e7cf9
25 changed files with 420 additions and 631 deletions

View File

@ -1,4 +1,4 @@
use instructions::RunnableInstruction; use instructions::Instruction;
use run::Error; use run::Error;
use crate::{ use crate::{
@ -32,7 +32,7 @@ impl Processor {
let (instruction, bytes_read) = let (instruction, bytes_read) =
parse::next_instruction(&memory_view).expect("invalid instruction"); parse::next_instruction(&memory_view).expect("invalid instruction");
self.run_instruction(&instruction); self.run_instruction(instruction);
let (next_pc, _carry) = pc.overflowing_add(bytes_read); let (next_pc, _carry) = pc.overflowing_add(bytes_read);
self.registers.program_counter = next_pc; self.registers.program_counter = next_pc;
@ -42,13 +42,13 @@ impl Processor {
/// ///
/// # Panics /// # Panics
/// Panics if an internal error occurred within the CPU. These are always bugs. /// Panics if an internal error occurred within the CPU. These are always bugs.
pub fn run_instruction(&mut self, instruction: &RunnableInstruction) { pub fn run_instruction(&mut self, instruction: Instruction) {
let run_res = run::run_instruction(self, instruction.instruction); let run_res = run::run_instruction(self, instruction);
if let Err(err) = run_res { if let Err(err) = run_res {
panic!("Fatal CPU error occured: {err}") panic!("Fatal CPU error occured: {err}")
} }
self.num_cycles += u128::from(instruction.cycles); self.num_cycles += u128::from(run_res.unwrap().0);
} }
fn load_from_register_to_register_address( fn load_from_register_to_register_address(

View File

@ -22,14 +22,7 @@ pub enum Instruction {
Misc(misc::MiscInstruction), Misc(misc::MiscInstruction),
} }
/// `RunnableInstruction` is an instruction that can run on the processor, and has any metadata needed to do so impl Instruction {
#[derive(Debug, Clone)]
pub struct RunnableInstruction {
pub(super) instruction: Instruction,
pub(super) cycles: u8,
}
impl RunnableInstruction {
/// `from_data` will produce an instruction from the given data and return the data after /// `from_data` will produce an instruction from the given data and return the data after
/// processing that operation. /// processing that operation.
/// ///
@ -37,7 +30,7 @@ impl RunnableInstruction {
/// ///
/// # Errors /// # Errors
/// Returns an error if the instruction couldn't be parsed. /// Returns an error if the instruction couldn't be parsed.
pub fn from_data(data: &[u8]) -> Result<(RunnableInstruction, &[u8]), Error> { pub fn from_data(data: &[u8]) -> Result<(Self, &[u8]), Error> {
parse::next_instruction(&View::new_from_data(data, 0)) parse::next_instruction(&View::new_from_data(data, 0))
.map(|(ins, offset)| (ins, &data[offset.into()..])) .map(|(ins, offset)| (ins, &data[offset.into()..]))
} }

View File

@ -2,7 +2,7 @@
use crate::memory::View; use crate::memory::View;
use super::instructions::RunnableInstruction; use super::instructions::Instruction;
use thiserror::Error; use thiserror::Error;
mod arith16; mod arith16;
@ -22,7 +22,7 @@ pub enum Error {
} }
/// `ParseResult` is the result of a Parse operation, which includes the parsed instruction and the number of bytes read. /// `ParseResult` is the result of a Parse operation, which includes the parsed instruction and the number of bytes read.
pub(super) type ParseOutput = (RunnableInstruction, u16); pub(super) type ParseOutput = (Instruction, u16);
pub(super) type ParseResult = Result<ParseOutput, Error>; pub(super) type ParseResult = Result<ParseOutput, Error>;
/// `OpcodeParser` takes input data, parses out an opcode (and its associated arguments) if it can, and returns /// `OpcodeParser` takes input data, parses out an opcode (and its associated arguments) if it can, and returns

View File

@ -1,7 +1,7 @@
use crate::{ use crate::{
cpu::{ cpu::{
instructions::arith16::SixteenBitArithmeticInstruction,
instructions::Instruction, instructions::Instruction,
instructions::{arith16::SixteenBitArithmeticInstruction, RunnableInstruction},
parse::{self, Error, OpcodeParser, ParseResult}, parse::{self, Error, OpcodeParser, ParseResult},
register::{Combined, SingleSixteenBit, SixteenBit}, register::{Combined, SingleSixteenBit, SixteenBit},
}, },
@ -49,36 +49,27 @@ impl OpcodeParser for Parser {
fn build_add_hl_to_register_data(operand_register: SixteenBit) -> ParseOutput { fn build_add_hl_to_register_data(operand_register: SixteenBit) -> ParseOutput {
( (
RunnableInstruction { Instruction::SixteenBitArithmetic(SixteenBitArithmeticInstruction::AddRegisterToHL {
instruction: Instruction::SixteenBitArithmetic( operand_register,
SixteenBitArithmeticInstruction::AddRegisterToHL { operand_register }, }),
),
cycles: 8,
},
1, 1,
) )
} }
fn build_inc_register_data(operand_register: SixteenBit) -> ParseOutput { fn build_inc_register_data(operand_register: SixteenBit) -> ParseOutput {
( (
RunnableInstruction { Instruction::SixteenBitArithmetic(SixteenBitArithmeticInstruction::IncrementRegister {
instruction: Instruction::SixteenBitArithmetic( operand_register,
SixteenBitArithmeticInstruction::IncrementRegister { operand_register }, }),
),
cycles: 8,
},
1, 1,
) )
} }
fn build_dec_register_data(operand_register: SixteenBit) -> ParseOutput { fn build_dec_register_data(operand_register: SixteenBit) -> ParseOutput {
( (
RunnableInstruction { Instruction::SixteenBitArithmetic(SixteenBitArithmeticInstruction::DecrementRegister {
instruction: Instruction::SixteenBitArithmetic( operand_register,
SixteenBitArithmeticInstruction::DecrementRegister { operand_register }, }),
),
cycles: 8,
},
1, 1,
) )
} }

View File

@ -3,7 +3,7 @@ use crate::{
arith8::{ arith8::{
AdjustStackPointerInstruction, EightBitArithmeticInstruction, Operand, Operation, AdjustStackPointerInstruction, EightBitArithmeticInstruction, Operand, Operation,
}, },
Instruction, RunnableInstruction, Instruction,
}, },
memory::{GetViewTuple, View}, memory::{GetViewTuple, View},
register, register,
@ -35,28 +35,12 @@ fn parse_eight_bit_arithmetic_instruction(data: &View) -> super::ParseResult {
let operation = operation_for_opcode(opcode)?; let operation = operation_for_opcode(opcode)?;
let operand = operand_for_opcode(opcode)?; let operand = operand_for_opcode(opcode)?;
let parse_data = match (operation, operand) { let parse_data = match operand {
(_operation, OpcodeOperand::SingleRegister(register)) => { OpcodeOperand::SingleRegister(register) => {
build_instruction_between_register_and_a_data(operation, register) build_instruction_between_register_and_a_data(operation, register)
} }
(Operation::Inc | Operation::Dec, OpcodeOperand::HLAddressValue) => { OpcodeOperand::HLAddressValue => build_instruction_between_hl_value_and_a_data(operation),
let (runnable_ins, bytes_read) = OpcodeOperand::Immediate => build_instruction_between_immediate_and_a_data(operation, data),
build_instruction_between_hl_value_and_a_data(operation);
// This is an exception to the other arithmetic instructions
(
RunnableInstruction {
cycles: 12,
..runnable_ins
},
bytes_read,
)
}
(_operation, OpcodeOperand::HLAddressValue) => {
build_instruction_between_hl_value_and_a_data(operation)
}
(_operation, OpcodeOperand::Immediate) => {
build_instruction_between_immediate_and_a_data(operation, data)
}
}; };
Ok(parse_data) Ok(parse_data)
@ -157,13 +141,7 @@ fn build_instruction_between_register_and_a_data(
operation, operation,
}; };
( (Instruction::EightBitArithmetic(instruction), 1)
RunnableInstruction {
instruction: Instruction::EightBitArithmetic(instruction),
cycles: 4,
},
1,
)
} }
fn build_instruction_between_hl_value_and_a_data(operation: Operation) -> ParseOutput { fn build_instruction_between_hl_value_and_a_data(operation: Operation) -> ParseOutput {
@ -172,13 +150,7 @@ fn build_instruction_between_hl_value_and_a_data(operation: Operation) -> ParseO
operation, operation,
}; };
( (Instruction::EightBitArithmetic(instruction), 1)
RunnableInstruction {
instruction: Instruction::EightBitArithmetic(instruction),
cycles: 8,
},
1,
)
} }
fn build_instruction_between_immediate_and_a_data( fn build_instruction_between_immediate_and_a_data(
@ -192,13 +164,7 @@ fn build_instruction_between_immediate_and_a_data(
operation, operation,
}; };
( (Instruction::EightBitArithmetic(instruction), 2)
RunnableInstruction {
instruction: Instruction::EightBitArithmetic(instruction),
cycles: 8,
},
2,
)
} }
fn build_stack_pointer_adjust_data(data: &View) -> ParseOutput { fn build_stack_pointer_adjust_data(data: &View) -> ParseOutput {
@ -207,13 +173,7 @@ fn build_stack_pointer_adjust_data(data: &View) -> ParseOutput {
operand: i8::from_be_bytes([n]), operand: i8::from_be_bytes([n]),
}; };
( (Instruction::StackPointerAdjust(instruction), 2)
RunnableInstruction {
instruction: Instruction::StackPointerAdjust(instruction),
cycles: 16,
},
2,
)
} }
#[cfg(test)] #[cfg(test)]

View File

@ -1,7 +1,7 @@
use crate::cpu::instructions::load16::SixteenBitLoadInstruction; use crate::cpu::instructions::load16::SixteenBitLoadInstruction;
use crate::cpu::parse::ParseOutput; use crate::cpu::parse::ParseOutput;
use crate::cpu::{ use crate::cpu::{
instructions::{Instruction, RunnableInstruction}, instructions::Instruction,
parse::{self, Error, OpcodeParser, ParseResult}, parse::{self, Error, OpcodeParser, ParseResult},
}; };
use crate::memory::{GetViewTuple, View}; use crate::memory::{GetViewTuple, View};
@ -44,12 +44,10 @@ fn make_load_immediate_data(dst: register::SixteenBit, data: &View) -> ParseOutp
// indicates it should be. // indicates it should be.
let value = u16::from_le_bytes([lower_bytes, upper_bytes]); let value = u16::from_le_bytes([lower_bytes, upper_bytes]);
( (
RunnableInstruction { Instruction::SixteenBitLoad(SixteenBitLoadInstruction::LoadImmediateToRegister {
instruction: Instruction::SixteenBitLoad( value,
SixteenBitLoadInstruction::LoadImmediateToRegister { value, dst }, dst,
), }),
cycles: 12,
},
3, 3,
) )
} }
@ -59,15 +57,10 @@ fn make_load_effective_address(dst: register::Combined, data: &View) -> ParseOut
let signed_value = i8::from_be_bytes([unsigned_value]); let signed_value = i8::from_be_bytes([unsigned_value]);
( (
RunnableInstruction { Instruction::SixteenBitLoad(SixteenBitLoadInstruction::LoadEffectiveAddress {
instruction: Instruction::SixteenBitLoad( dst,
SixteenBitLoadInstruction::LoadEffectiveAddress { offset: signed_value,
dst, }),
offset: signed_value,
},
),
cycles: 12,
},
2, 2,
) )
} }

View File

@ -1,5 +1,5 @@
use crate::cpu::instructions::load16::SixteenBitLoadInstruction; use crate::cpu::instructions::load16::SixteenBitLoadInstruction;
use crate::cpu::instructions::{Instruction, RunnableInstruction}; use crate::cpu::instructions::Instruction;
use crate::cpu::parse::{self, Error, OpcodeParser, ParseOutput, ParseResult}; use crate::cpu::parse::{self, Error, OpcodeParser, ParseOutput, ParseResult};
use crate::memory::{GetViewTuple, View}; use crate::memory::{GetViewTuple, View};
use crate::register; use crate::register;
@ -59,14 +59,10 @@ impl OpcodeParser for Parser {
fn make_stack_operation_data(operation: Operation, reg: register::Combined) -> ParseOutput { fn make_stack_operation_data(operation: Operation, reg: register::Combined) -> ParseOutput {
let instruction = match operation { let instruction = match operation {
Operation::Push => RunnableInstruction { Operation::Push => {
instruction: Instruction::SixteenBitLoad(SixteenBitLoadInstruction::Push { src: reg }), Instruction::SixteenBitLoad(SixteenBitLoadInstruction::Push { src: reg })
cycles: 16, }
}, Operation::Pop => Instruction::SixteenBitLoad(SixteenBitLoadInstruction::Pop { dst: reg }),
Operation::Pop => RunnableInstruction {
instruction: Instruction::SixteenBitLoad(SixteenBitLoadInstruction::Pop { dst: reg }),
cycles: 12,
},
}; };
(instruction, 1) (instruction, 1)
@ -77,12 +73,9 @@ fn make_load_sp_to_address_data(data: &View) -> ParseOutput {
let dst_address = u16::from_le_bytes([address_half1, address_half2]); let dst_address = u16::from_le_bytes([address_half1, address_half2]);
( (
RunnableInstruction { Instruction::SixteenBitLoad(
instruction: Instruction::SixteenBitLoad( SixteenBitLoadInstruction::LoadStackPointerToImmediateAddress { dst_address },
SixteenBitLoadInstruction::LoadStackPointerToImmediateAddress { dst_address }, ),
),
cycles: 20,
},
3, 3,
) )
} }

View File

@ -1,10 +1,7 @@
use crate::cpu::instructions::load16::SixteenBitLoadInstruction; use crate::cpu::instructions::load16::SixteenBitLoadInstruction;
use crate::cpu::instructions::Instruction; use crate::cpu::instructions::Instruction;
use crate::cpu::parse::ParseOutput; use crate::cpu::parse::ParseOutput;
use crate::cpu::{ use crate::cpu::parse::{self, Error, OpcodeParser, ParseResult};
instructions::RunnableInstruction,
parse::{self, Error, OpcodeParser, ParseResult},
};
use crate::memory::View; use crate::memory::View;
use crate::register; use crate::register;
@ -29,12 +26,7 @@ fn make_load_between_register_data(
src: register::SixteenBit, src: register::SixteenBit,
) -> ParseOutput { ) -> ParseOutput {
( (
RunnableInstruction { Instruction::SixteenBitLoad(SixteenBitLoadInstruction::LoadBetweenRegisters { dst, src }),
instruction: Instruction::SixteenBitLoad(
SixteenBitLoadInstruction::LoadBetweenRegisters { dst, src },
),
cycles: 8,
},
1, 1,
) )
} }

View File

@ -1,10 +1,7 @@
use crate::cpu::instructions::load8::EightBitLoadInstruction; use crate::cpu::instructions::load8::EightBitLoadInstruction;
use crate::cpu::instructions::Instruction; use crate::cpu::instructions::Instruction;
use crate::cpu::parse::ParseOutput; use crate::cpu::parse::ParseOutput;
use crate::cpu::{ use crate::cpu::parse::{self, Error, OpcodeParser, ParseResult};
instructions::RunnableInstruction,
parse::{self, Error, OpcodeParser, ParseResult},
};
use crate::memory::{GetViewTuple, View}; use crate::memory::{GetViewTuple, View};
use crate::register; use crate::register;
@ -34,16 +31,10 @@ fn make_load_immediate_data(register: register::SingleEightBit, data: &View) ->
let (_opcode, value) = data.get_tuple(); let (_opcode, value) = data.get_tuple();
( (
RunnableInstruction { Instruction::EightBitLoad(EightBitLoadInstruction::LoadImmediateToRegister {
instruction: Instruction::EightBitLoad( register,
EightBitLoadInstruction::LoadImmediateToRegister { register, value }, value,
), }),
// TODO: I don't love that the cycles are in a parsing function,
// but ultimately I want the cycles to be as close to the opcode as possible
// so that it's easier to change. Maybe I can change this once I end up with
// more of the instructions complete
cycles: 8,
},
2, 2,
) )
} }

View File

@ -1,5 +1,5 @@
use crate::cpu::instructions::load8::EightBitLoadInstruction; use crate::cpu::instructions::load8::EightBitLoadInstruction;
use crate::cpu::instructions::{Instruction, RunnableInstruction}; use crate::cpu::instructions::Instruction;
use crate::cpu::parse::{self, Error, OpcodeParser, ParseOutput, ParseResult}; use crate::cpu::parse::{self, Error, OpcodeParser, ParseOutput, ParseResult};
use crate::memory::{GetViewTuple, View}; use crate::memory::{GetViewTuple, View};
use crate::register; use crate::register;
@ -186,12 +186,7 @@ fn make_load_from_register_address(
src: register::Combined, src: register::Combined,
) -> ParseOutput { ) -> ParseOutput {
( (
RunnableInstruction { Instruction::EightBitLoad(EightBitLoadInstruction::LoadFromRegisterAddress { src, dst }),
instruction: Instruction::EightBitLoad(
EightBitLoadInstruction::LoadFromRegisterAddress { src, dst },
),
cycles: 8,
},
1, 1,
) )
} }
@ -201,12 +196,7 @@ fn make_load_to_register_address(
src: register::SingleEightBit, src: register::SingleEightBit,
) -> ParseOutput { ) -> ParseOutput {
( (
RunnableInstruction { Instruction::EightBitLoad(EightBitLoadInstruction::LoadToRegisterAddress { src, dst }),
instruction: Instruction::EightBitLoad(
EightBitLoadInstruction::LoadToRegisterAddress { src, dst },
),
cycles: 8,
},
1, 1,
) )
} }
@ -217,12 +207,10 @@ fn make_load_from_immediate_address(dst: register::SingleEightBit, data: &View)
// The manual states that the LSB of the address is specified first (i.e. little endian) // The manual states that the LSB of the address is specified first (i.e. little endian)
let src_address = u16::from_le_bytes([lower_bytes, upper_bytes]); let src_address = u16::from_le_bytes([lower_bytes, upper_bytes]);
( (
RunnableInstruction { Instruction::EightBitLoad(EightBitLoadInstruction::LoadFromImmediateAddress {
instruction: Instruction::EightBitLoad( src_address,
EightBitLoadInstruction::LoadFromImmediateAddress { src_address, dst }, dst,
), }),
cycles: 16,
},
3, 3,
) )
} }
@ -233,12 +221,10 @@ fn make_load_to_immediate_address(src: register::SingleEightBit, data: &View) ->
// The manual states that the LSB of the address is specified first (i.e. little endian) // The manual states that the LSB of the address is specified first (i.e. little endian)
let dst_address = u16::from_le_bytes([lower_bytes, upper_bytes]); let dst_address = u16::from_le_bytes([lower_bytes, upper_bytes]);
( (
RunnableInstruction { Instruction::EightBitLoad(EightBitLoadInstruction::LoadToImmediateAddress {
instruction: Instruction::EightBitLoad( src,
EightBitLoadInstruction::LoadToImmediateAddress { src, dst_address }, dst_address,
), }),
cycles: 16,
},
3, 3,
) )
} }
@ -246,12 +232,7 @@ fn make_load_to_immediate_address(src: register::SingleEightBit, data: &View) ->
fn make_load_n_to_hl_address(data: &View) -> ParseOutput { fn make_load_n_to_hl_address(data: &View) -> ParseOutput {
let (_opcode, value) = data.get_tuple(); let (_opcode, value) = data.get_tuple();
( (
RunnableInstruction { Instruction::EightBitLoad(EightBitLoadInstruction::LoadnToHLAddress { value }),
instruction: Instruction::EightBitLoad(EightBitLoadInstruction::LoadnToHLAddress {
value,
}),
cycles: 12,
},
2, 2,
) )
} }
@ -261,16 +242,12 @@ fn make_load_from_memory_relative_to_io_register_start(
dst: register::SingleEightBit, dst: register::SingleEightBit,
) -> ParseOutput { ) -> ParseOutput {
( (
RunnableInstruction { Instruction::EightBitLoad(
instruction: Instruction::EightBitLoad( EightBitLoadInstruction::LoadFromMemoryRelativeToIORegisterStart {
EightBitLoadInstruction::LoadFromMemoryRelativeToIORegisterStart { offset_register,
offset_register, dst,
dst, },
}, ),
),
cycles: 8,
},
// guaranteed to succeed given we found the opcode
1, 1,
) )
} }
@ -280,15 +257,12 @@ fn make_load_to_memory_relative_to_io_register_start(
src: register::SingleEightBit, src: register::SingleEightBit,
) -> ParseOutput { ) -> ParseOutput {
( (
RunnableInstruction { Instruction::EightBitLoad(
instruction: Instruction::EightBitLoad( EightBitLoadInstruction::LoadToMemoryRelativeToIORegisterStart {
EightBitLoadInstruction::LoadToMemoryRelativeToIORegisterStart { src,
src, offset_register,
offset_register, },
}, ),
),
cycles: 8,
},
// guaranteed to succeed given we found the opcode // guaranteed to succeed given we found the opcode
1, 1,
) )
@ -301,16 +275,12 @@ fn make_load_to_memory_relative_to_io_register_start_by_immediate(
let (_opcode, offset) = data.get_tuple(); let (_opcode, offset) = data.get_tuple();
( (
RunnableInstruction { Instruction::EightBitLoad(
instruction: Instruction::EightBitLoad( EightBitLoadInstruction::LoadToMemoryRelativeToIORegisterStartByImmediate {
EightBitLoadInstruction::LoadToMemoryRelativeToIORegisterStartByImmediate { src,
src, offset,
offset, },
}, ),
),
// guaranteed to succeed given we got the value
cycles: 12,
},
2, 2,
) )
} }
@ -322,15 +292,12 @@ fn make_load_from_memory_relative_to_io_register_start_by_immediate(
let (_opcode, offset) = data.get_tuple(); let (_opcode, offset) = data.get_tuple();
( (
RunnableInstruction { Instruction::EightBitLoad(
instruction: Instruction::EightBitLoad( EightBitLoadInstruction::LoadFromMemoryRelativeToIORegisterStartByImmediate {
EightBitLoadInstruction::LoadFromMemoryRelativeToIORegisterStartByImmediate { offset,
offset, dst,
dst, },
}, ),
),
cycles: 12,
},
2, 2,
) )
} }
@ -364,11 +331,5 @@ fn make_load_from_address_and_do_arithmetic<
fn make_load_and_do_arithmetic<F: Fn() -> EightBitLoadInstruction>(make: F) -> ParseOutput { fn make_load_and_do_arithmetic<F: Fn() -> EightBitLoadInstruction>(make: F) -> ParseOutput {
let load_instruction = make(); let load_instruction = make();
( (Instruction::EightBitLoad(load_instruction), 1)
RunnableInstruction {
instruction: Instruction::EightBitLoad(load_instruction),
cycles: 8,
},
1,
)
} }

View File

@ -1,10 +1,7 @@
use crate::cpu::instructions::load8::EightBitLoadInstruction; use crate::cpu::instructions::load8::EightBitLoadInstruction;
use crate::cpu::instructions::Instruction; use crate::cpu::instructions::Instruction;
use crate::cpu::parse::ParseOutput; use crate::cpu::parse::ParseOutput;
use crate::cpu::{ use crate::cpu::parse::{self, Error, OpcodeParser, ParseResult};
instructions::RunnableInstruction,
parse::{self, Error, OpcodeParser, ParseResult},
};
use crate::memory::View; use crate::memory::View;
use crate::register; use crate::register;
@ -54,13 +51,7 @@ fn make_load_between_register_data(
src: register::SingleEightBit, src: register::SingleEightBit,
) -> ParseOutput { ) -> ParseOutput {
( (
RunnableInstruction { Instruction::EightBitLoad(EightBitLoadInstruction::LoadBetweenRegisters { dst, src }),
instruction: Instruction::EightBitLoad(EightBitLoadInstruction::LoadBetweenRegisters {
dst,
src,
}),
cycles: 4,
},
1, 1,
) )
} }

View File

@ -1,6 +1,6 @@
use super::{OpcodeParser, ParseOutput, ParseResult}; use super::{OpcodeParser, ParseOutput, ParseResult};
use crate::{ use crate::{
cpu::instructions::{misc::MiscInstruction, Instruction, RunnableInstruction}, cpu::instructions::{misc::MiscInstruction, Instruction},
memory::View, memory::View,
}; };
@ -20,41 +20,20 @@ impl OpcodeParser for Parser {
} }
fn build_set_carry_flag_data() -> ParseOutput { fn build_set_carry_flag_data() -> ParseOutput {
( (Instruction::Misc(MiscInstruction::SetCarryFlag), 1)
RunnableInstruction {
instruction: Instruction::Misc(MiscInstruction::SetCarryFlag),
cycles: 4,
},
1,
)
} }
fn build_complement_carry_flag_data() -> ParseOutput { fn build_complement_carry_flag_data() -> ParseOutput {
( (Instruction::Misc(MiscInstruction::ComplementCarryFlag), 1)
RunnableInstruction {
instruction: Instruction::Misc(MiscInstruction::ComplementCarryFlag),
cycles: 4,
},
1,
)
} }
fn build_complement_a_register_data() -> ParseOutput { fn build_complement_a_register_data() -> ParseOutput {
( (Instruction::Misc(MiscInstruction::ComplementARegister), 1)
RunnableInstruction {
instruction: Instruction::Misc(MiscInstruction::ComplementARegister),
cycles: 4,
},
1,
)
} }
fn build_daa_data() -> ParseOutput { fn build_daa_data() -> ParseOutput {
( (
RunnableInstruction { Instruction::Misc(MiscInstruction::DecimalAdjustAccumulator),
instruction: Instruction::Misc(MiscInstruction::DecimalAdjustAccumulator),
cycles: 4,
},
1, 1,
) )
} }

View File

@ -30,12 +30,18 @@ pub enum Error {
/// `Run` takes a single instruction and runs it on the given processor. /// `Run` takes a single instruction and runs it on the given processor.
trait Run { trait Run {
fn run_on(&self, processor: &mut Processor) -> Result<(), Error>; fn run_on(&self, processor: &mut Processor) -> Result<Cycles, Error>;
} }
/// `Cycles` represents the number of cycles an operation took
pub struct Cycles(pub u8);
/// `run_instruction` will run the given instruction on the processor. /// `run_instruction` will run the given instruction on the processor.
#[allow(clippy::module_name_repetitions)] #[allow(clippy::module_name_repetitions)]
pub fn run_instruction(processor: &mut Processor, instruction: Instruction) -> Result<(), Error> { pub fn run_instruction(
processor: &mut Processor,
instruction: Instruction,
) -> Result<Cycles, Error> {
match instruction { match instruction {
Instruction::EightBitLoad(load_instruction) => load_instruction.run_on(processor), Instruction::EightBitLoad(load_instruction) => load_instruction.run_on(processor),
Instruction::SixteenBitLoad(load_instruction) => load_instruction.run_on(processor), Instruction::SixteenBitLoad(load_instruction) => load_instruction.run_on(processor),

View File

@ -1,9 +1,9 @@
use crate::{cpu::instructions::arith16::SixteenBitArithmeticInstruction, register}; use crate::{cpu::instructions::arith16::SixteenBitArithmeticInstruction, register};
use super::{arithutil::CarryingAdd, Run}; use super::{arithutil::CarryingAdd, Cycles, Run};
impl Run for SixteenBitArithmeticInstruction { impl Run for SixteenBitArithmeticInstruction {
fn run_on(&self, processor: &mut crate::cpu::Processor) -> Result<(), super::Error> { fn run_on(&self, processor: &mut crate::cpu::Processor) -> Result<Cycles, super::Error> {
match *self { match *self {
SixteenBitArithmeticInstruction::IncrementRegister { operand_register } => { SixteenBitArithmeticInstruction::IncrementRegister { operand_register } => {
let register_value = processor.registers.get_16bit_register(operand_register); let register_value = processor.registers.get_16bit_register(operand_register);
@ -12,7 +12,7 @@ impl Run for SixteenBitArithmeticInstruction {
.registers .registers
.set_16bit_register(operand_register, incremented_value); .set_16bit_register(operand_register, incremented_value);
Ok(()) Ok(Cycles(8))
} }
SixteenBitArithmeticInstruction::DecrementRegister { operand_register } => { SixteenBitArithmeticInstruction::DecrementRegister { operand_register } => {
@ -22,7 +22,7 @@ impl Run for SixteenBitArithmeticInstruction {
.registers .registers
.set_16bit_register(operand_register, decremented_value); .set_16bit_register(operand_register, decremented_value);
Ok(()) Ok(Cycles(8))
} }
SixteenBitArithmeticInstruction::AddRegisterToHL { operand_register } => { SixteenBitArithmeticInstruction::AddRegisterToHL { operand_register } => {
@ -45,7 +45,7 @@ impl Run for SixteenBitArithmeticInstruction {
.registers .registers
.set_flag_bit(register::Flag::Subtract, 0); .set_flag_bit(register::Flag::Subtract, 0);
Ok(()) Ok(Cycles(8))
} }
} }
} }

View File

@ -7,7 +7,7 @@ use crate::{
register, register,
}; };
use super::{arithutil::CarryingAdd, Run}; use super::{arithutil::CarryingAdd, Cycles, Run};
mod binary; mod binary;
mod unary; mod unary;
@ -26,7 +26,7 @@ struct OperationFlagOutput {
} }
impl Run for EightBitArithmeticInstruction { impl Run for EightBitArithmeticInstruction {
fn run_on(&self, processor: &mut Processor) -> Result<(), Error> { fn run_on(&self, processor: &mut Processor) -> Result<Cycles, Error> {
match self.operation { match self.operation {
Operation::Add => binary::run_add(processor, self.operand), Operation::Add => binary::run_add(processor, self.operand),
@ -52,7 +52,7 @@ impl Run for EightBitArithmeticInstruction {
} }
impl Run for AdjustStackPointerInstruction { impl Run for AdjustStackPointerInstruction {
fn run_on(&self, processor: &mut Processor) -> Result<(), Error> { fn run_on(&self, processor: &mut Processor) -> Result<Cycles, Error> {
let stack_pointer = processor let stack_pointer = processor
.registers .registers
.get_single_16bit_register(register::SingleSixteenBit::StackPointer); .get_single_16bit_register(register::SingleSixteenBit::StackPointer);
@ -72,7 +72,7 @@ impl Run for AdjustStackPointerInstruction {
}, },
); );
Ok(()) Ok(Cycles(16))
} }
} }

View File

@ -3,7 +3,7 @@ use crate::{
instructions::arith8::Operand, instructions::arith8::Operand,
run::{ run::{
arithutil::{self, CarriedNumber, CarryingAdd, CarryingSub}, arithutil::{self, CarriedNumber, CarryingAdd, CarryingSub},
Error, Cycles, Error,
}, },
Processor, Processor,
}, },
@ -12,11 +12,11 @@ use crate::{
use super::{OperationFlagOutput, OperationOutput}; use super::{OperationFlagOutput, OperationOutput};
pub fn run_add(processor: &mut Processor, operand: Operand) -> Result<(), Error> { pub fn run_add(processor: &mut Processor, operand: Operand) -> Result<Cycles, Error> {
run_operation(processor, operand, run_add_on_operands) run_operation(processor, operand, run_add_on_operands)
} }
pub fn run_add_with_carry(processor: &mut Processor, operand: Operand) -> Result<(), Error> { pub fn run_add_with_carry(processor: &mut Processor, operand: Operand) -> Result<Cycles, Error> {
run_operation_with_carry(processor, operand, run_add_on_operands) run_operation_with_carry(processor, operand, run_add_on_operands)
} }
@ -32,11 +32,11 @@ where
} }
} }
pub fn run_sub(processor: &mut Processor, operand: Operand) -> Result<(), Error> { pub fn run_sub(processor: &mut Processor, operand: Operand) -> Result<Cycles, Error> {
run_operation(processor, operand, run_sub_on_operands) run_operation(processor, operand, run_sub_on_operands)
} }
pub fn run_sub_with_carry(processor: &mut Processor, operand: Operand) -> Result<(), Error> { pub fn run_sub_with_carry(processor: &mut Processor, operand: Operand) -> Result<Cycles, Error> {
run_operation_with_carry(processor, operand, run_sub_on_operands) run_operation_with_carry(processor, operand, run_sub_on_operands)
} }
@ -51,20 +51,20 @@ where
} }
} }
pub fn run_compare(processor: &mut Processor, operand: Operand) -> Result<(), Error> { pub fn run_compare(processor: &mut Processor, operand: Operand) -> Result<Cycles, Error> {
let a_value = processor.registers.a; let a_value = processor.registers.a;
// A compare is just a sub, preserving the A value, so we can just do a sub // A compare is just a sub, preserving the A value, so we can just do a sub
// and restore the original value // and restore the original value
run_sub(processor, operand)?; let sub_cycles = run_sub(processor, operand)?;
processor processor
.registers .registers
.set_single_8bit_register(register::SingleEightBit::A, a_value); .set_single_8bit_register(register::SingleEightBit::A, a_value);
Ok(()) Ok(sub_cycles)
} }
pub fn run_and(processor: &mut Processor, operand: Operand) -> Result<(), Error> { pub fn run_and(processor: &mut Processor, operand: Operand) -> Result<Cycles, Error> {
run_operation(processor, operand, |lhs, rhs| { run_operation(processor, operand, |lhs, rhs| {
let total = lhs & rhs; let total = lhs & rhs;
@ -80,7 +80,7 @@ pub fn run_and(processor: &mut Processor, operand: Operand) -> Result<(), Error>
}) })
} }
pub fn run_or(processor: &mut Processor, operand: Operand) -> Result<(), Error> { pub fn run_or(processor: &mut Processor, operand: Operand) -> Result<Cycles, Error> {
run_operation(processor, operand, |lhs, rhs| { run_operation(processor, operand, |lhs, rhs| {
let total = lhs | rhs; let total = lhs | rhs;
@ -96,7 +96,7 @@ pub fn run_or(processor: &mut Processor, operand: Operand) -> Result<(), Error>
}) })
} }
pub fn run_xor(processor: &mut Processor, operand: Operand) -> Result<(), Error> { pub fn run_xor(processor: &mut Processor, operand: Operand) -> Result<Cycles, Error> {
run_operation(processor, operand, |lhs, rhs| { run_operation(processor, operand, |lhs, rhs| {
let total = lhs ^ rhs; let total = lhs ^ rhs;
@ -112,28 +112,32 @@ pub fn run_xor(processor: &mut Processor, operand: Operand) -> Result<(), Error>
}) })
} }
fn run_operation<F>(processor: &mut Processor, operand: Operand, operation: F) -> Result<(), Error> fn run_operation<F>(
processor: &mut Processor,
operand: Operand,
operation: F,
) -> Result<Cycles, Error>
where where
F: FnOnce(u8, u8) -> OperationOutput, F: FnOnce(u8, u8) -> OperationOutput,
{ {
let operand_values = gather_operand_values(processor, operand)?; let operand_values = gather_operand_values(processor, operand)?;
run_operation_on_operands(processor, operand_values, operation); run_operation_on_operands(processor, operand_values, operation);
Ok(()) Ok(cycles_for_operand(operand))
} }
fn run_operation_with_carry<F>( fn run_operation_with_carry<F>(
processor: &mut Processor, processor: &mut Processor,
operand: Operand, operand: Operand,
operation: F, operation: F,
) -> Result<(), Error> ) -> Result<Cycles, Error>
where where
F: FnOnce(u8, CarriedNumber<u8>) -> OperationOutput, F: FnOnce(u8, CarriedNumber<u8>) -> OperationOutput,
{ {
let operand_values = gather_operands_with_carry(processor, operand)?; let operand_values = gather_operands_with_carry(processor, operand)?;
run_operation_on_operands(processor, operand_values, operation); run_operation_on_operands(processor, operand_values, operation);
Ok(()) Ok(cycles_for_operand(operand))
} }
fn run_operation_on_operands<F, L, R>(processor: &mut Processor, (lhs, rhs): (L, R), operation: F) fn run_operation_on_operands<F, L, R>(processor: &mut Processor, (lhs, rhs): (L, R), operation: F)
@ -235,6 +239,14 @@ fn addition_flags(total: u8, half_carry: bool, carry: bool) -> OperationFlagOutp
} }
} }
fn cycles_for_operand(operand: Operand) -> Cycles {
match operand {
Operand::SingleRegister(_register) => Cycles(4),
Operand::HLAddressValue => Cycles(8),
Operand::Immediate(_val) => Cycles(8),
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;

View File

@ -3,7 +3,7 @@ use crate::{
instructions::arith8::Operand, instructions::arith8::Operand,
run::{ run::{
arithutil::{CarryingAdd, CarryingSub}, arithutil::{CarryingAdd, CarryingSub},
Error, Cycles, Error,
}, },
Processor, Processor,
}, },
@ -12,7 +12,7 @@ use crate::{
use super::{OperationFlagOutput, OperationOutput}; use super::{OperationFlagOutput, OperationOutput};
pub fn run_inc(processor: &mut Processor, operand: Operand) -> Result<(), Error> { pub fn run_inc(processor: &mut Processor, operand: Operand) -> Result<Cycles, Error> {
let current_carry_flag = processor.registers.get_flag_bit(register::Flag::Carry); let current_carry_flag = processor.registers.get_flag_bit(register::Flag::Carry);
run_operation(processor, operand, |value| { run_operation(processor, operand, |value| {
let (result, half_carry, _full_carry) = value.add_with_carry(1); let (result, half_carry, _full_carry) = value.add_with_carry(1);
@ -29,7 +29,7 @@ pub fn run_inc(processor: &mut Processor, operand: Operand) -> Result<(), Error>
}) })
} }
pub fn run_dec(processor: &mut Processor, operand: Operand) -> Result<(), Error> { pub fn run_dec(processor: &mut Processor, operand: Operand) -> Result<Cycles, Error> {
let current_carry_flag = processor.registers.get_flag_bit(register::Flag::Carry); let current_carry_flag = processor.registers.get_flag_bit(register::Flag::Carry);
run_operation(processor, operand, |value| { run_operation(processor, operand, |value| {
let (result, half_carry, _full_carry) = value.sub_with_carry(1); let (result, half_carry, _full_carry) = value.sub_with_carry(1);
@ -46,7 +46,11 @@ pub fn run_dec(processor: &mut Processor, operand: Operand) -> Result<(), Error>
}) })
} }
fn run_operation<F>(processor: &mut Processor, operand: Operand, operation: F) -> Result<(), Error> fn run_operation<F>(
processor: &mut Processor,
operand: Operand,
operation: F,
) -> Result<Cycles, Error>
where where
F: Fn(u8) -> OperationOutput, F: Fn(u8) -> OperationOutput,
{ {
@ -56,7 +60,7 @@ where
store_output_value(processor, operand, output.value)?; store_output_value(processor, operand, output.value)?;
super::store_flags(processor, output.flags); super::store_flags(processor, output.flags);
Ok(()) Ok(cycles_for_operand(operand))
} }
fn gather_operand_value(processor: &mut Processor, operand: Operand) -> Result<u8, Error> { fn gather_operand_value(processor: &mut Processor, operand: Operand) -> Result<u8, Error> {
@ -122,3 +126,11 @@ fn store_output_value(
Operand::Immediate(_) => unreachable!("cannot perform unary operation on an immediate"), Operand::Immediate(_) => unreachable!("cannot perform unary operation on an immediate"),
} }
} }
fn cycles_for_operand(operand: Operand) -> Cycles {
match operand {
Operand::SingleRegister(_register) => Cycles(4),
Operand::HLAddressValue => Cycles(12),
Operand::Immediate(_val) => unreachable!("Cannot perform unary on immediate"),
}
}

View File

@ -1,24 +1,24 @@
use super::arithutil::CarryingAdd; use super::arithutil::CarryingAdd;
use super::{Error, Run}; use super::{Cycles, Error, Run};
use crate::cpu::{instructions::load16::SixteenBitLoadInstruction, Processor}; use crate::cpu::{instructions::load16::SixteenBitLoadInstruction, Processor};
use crate::{memory, register}; use crate::{memory, register};
impl Run for SixteenBitLoadInstruction { impl Run for SixteenBitLoadInstruction {
// TODO: Fix this // TODO: Fix this
#[allow(clippy::too_many_lines)] #[allow(clippy::too_many_lines)]
fn run_on(&self, processor: &mut Processor) -> Result<(), Error> { fn run_on(&self, processor: &mut Processor) -> Result<Cycles, Error> {
match *self { match *self {
SixteenBitLoadInstruction::LoadImmediateToRegister { dst, value } => { SixteenBitLoadInstruction::LoadImmediateToRegister { dst, value } => {
processor.registers.set_16bit_register(dst, value); processor.registers.set_16bit_register(dst, value);
Ok(()) Ok(Cycles(12))
} }
SixteenBitLoadInstruction::LoadBetweenRegisters { dst, src } => { SixteenBitLoadInstruction::LoadBetweenRegisters { dst, src } => {
let value = processor.registers.get_16bit_register(src); let value = processor.registers.get_16bit_register(src);
processor.registers.set_16bit_register(dst, value); processor.registers.set_16bit_register(dst, value);
Ok(()) Ok(Cycles(8))
} }
SixteenBitLoadInstruction::LoadEffectiveAddress { dst, offset } => { SixteenBitLoadInstruction::LoadEffectiveAddress { dst, offset } => {
@ -43,7 +43,7 @@ impl Run for SixteenBitLoadInstruction {
processor.registers.set_combined_register(dst, new_sp); processor.registers.set_combined_register(dst, new_sp);
Ok(()) Ok(Cycles(12))
} }
SixteenBitLoadInstruction::Push { src } => { SixteenBitLoadInstruction::Push { src } => {
@ -74,7 +74,7 @@ impl Run for SixteenBitLoadInstruction {
current_sp - 2, current_sp - 2,
); );
Ok(()) Ok(Cycles(16))
} }
SixteenBitLoadInstruction::Pop { dst } => { SixteenBitLoadInstruction::Pop { dst } => {
@ -112,7 +112,7 @@ impl Run for SixteenBitLoadInstruction {
current_sp + 2, current_sp + 2,
); );
Ok(()) Ok(Cycles(12))
} }
SixteenBitLoadInstruction::LoadStackPointerToImmediateAddress { dst_address } => { SixteenBitLoadInstruction::LoadStackPointerToImmediateAddress { dst_address } => {
let current_sp = processor let current_sp = processor
@ -126,7 +126,7 @@ impl Run for SixteenBitLoadInstruction {
)); ));
match memory_res { match memory_res {
Ok(_) => Ok(()), Ok(_) => Ok(Cycles(20)),
Err(memory::Error::GetInvalidAddress(bad_addr)) => { Err(memory::Error::GetInvalidAddress(bad_addr)) => {
Err(Error::InvalidImmediateAddress(bad_addr)) Err(Error::InvalidImmediateAddress(bad_addr))
} }

View File

@ -1,4 +1,4 @@
use super::{Error, Run}; use super::{Cycles, Error, Run};
use crate::{ use crate::{
cpu::{instructions::load8::EightBitLoadInstruction, Processor}, cpu::{instructions::load8::EightBitLoadInstruction, Processor},
memory, register, memory, register,
@ -7,35 +7,45 @@ use crate::{
impl Run for EightBitLoadInstruction { impl Run for EightBitLoadInstruction {
// TODO: Break this up somehow // TODO: Break this up somehow
#[allow(clippy::too_many_lines)] #[allow(clippy::too_many_lines)]
fn run_on(&self, processor: &mut Processor) -> Result<(), Error> { fn run_on(&self, processor: &mut Processor) -> Result<Cycles, Error> {
match *self { match *self {
EightBitLoadInstruction::LoadImmediateToRegister { value, register } => { EightBitLoadInstruction::LoadImmediateToRegister { value, register } => {
processor processor
.registers .registers
.set_single_8bit_register(register, value); .set_single_8bit_register(register, value);
Ok(())
Ok(Cycles(8))
} }
EightBitLoadInstruction::LoadBetweenRegisters { dst, src } => { EightBitLoadInstruction::LoadBetweenRegisters { dst, src } => {
let src_value = processor.registers.get_single_8bit_register(src); let src_value = processor.registers.get_single_8bit_register(src);
processor.registers.set_single_8bit_register(dst, src_value); processor.registers.set_single_8bit_register(dst, src_value);
Ok(())
Ok(Cycles(4))
} }
EightBitLoadInstruction::LoadFromRegisterAddress { src, dst } => { EightBitLoadInstruction::LoadFromRegisterAddress { src, dst } => {
processor.load_from_register_address_to_register(dst, src) processor.load_from_register_address_to_register(dst, src)?;
Ok(Cycles(8))
} }
EightBitLoadInstruction::LoadFromImmediateAddress { src_address, dst } => { EightBitLoadInstruction::LoadFromImmediateAddress { src_address, dst } => {
processor.load_from_address_to_register(dst, src_address.into()) processor.load_from_address_to_register(dst, src_address.into())?;
Ok(Cycles(16))
} }
EightBitLoadInstruction::LoadToRegisterAddress { src, dst } => { EightBitLoadInstruction::LoadToRegisterAddress { src, dst } => {
processor.load_from_register_to_register_address(dst, src) processor.load_from_register_to_register_address(dst, src)?;
Ok(Cycles(8))
} }
EightBitLoadInstruction::LoadToImmediateAddress { src, dst_address } => { EightBitLoadInstruction::LoadToImmediateAddress { src, dst_address } => {
processor.load_from_register_to_address(dst_address.into(), src) processor.load_from_register_to_address(dst_address.into(), src)?;
Ok(Cycles(16))
} }
EightBitLoadInstruction::LoadnToHLAddress { value } => { EightBitLoadInstruction::LoadnToHLAddress { value } => {
@ -43,7 +53,9 @@ impl Run for EightBitLoadInstruction {
.registers .registers
.get_combined_register(register::Combined::HL); .get_combined_register(register::Combined::HL);
processor.load_8bit_immediate_to_address(dest_address.into(), value) processor.load_8bit_immediate_to_address(dest_address.into(), value)?;
Ok(Cycles(12))
} }
EightBitLoadInstruction::LoadFromMemoryRelativeToIORegisterStart { EightBitLoadInstruction::LoadFromMemoryRelativeToIORegisterStart {
@ -56,7 +68,8 @@ impl Run for EightBitLoadInstruction {
let src_address = let src_address =
memory::IO_REGISTER_START_ADDRESS + usize::from(src_address_offset); memory::IO_REGISTER_START_ADDRESS + usize::from(src_address_offset);
processor.load_from_address_to_register(dst, src_address) processor.load_from_address_to_register(dst, src_address)?;
Ok(Cycles(8))
} }
EightBitLoadInstruction::LoadToMemoryRelativeToIORegisterStart { EightBitLoadInstruction::LoadToMemoryRelativeToIORegisterStart {
@ -69,7 +82,9 @@ impl Run for EightBitLoadInstruction {
let dst_address = let dst_address =
memory::IO_REGISTER_START_ADDRESS + usize::from(dst_address_offset); memory::IO_REGISTER_START_ADDRESS + usize::from(dst_address_offset);
processor.load_from_register_to_address(dst_address, src) processor.load_from_register_to_address(dst_address, src)?;
Ok(Cycles(8))
} }
EightBitLoadInstruction::LoadFromRegisterAddressThenDec { dst, src } => { EightBitLoadInstruction::LoadFromRegisterAddressThenDec { dst, src } => {
@ -80,7 +95,7 @@ impl Run for EightBitLoadInstruction {
.registers .registers
.set_combined_register(src, src_address - 1); .set_combined_register(src, src_address - 1);
Ok(()) Ok(Cycles(8))
} }
EightBitLoadInstruction::LoadFromRegisterAddressThenInc { dst, src } => { EightBitLoadInstruction::LoadFromRegisterAddressThenInc { dst, src } => {
@ -91,7 +106,7 @@ impl Run for EightBitLoadInstruction {
.registers .registers
.set_combined_register(src, src_address + 1); .set_combined_register(src, src_address + 1);
Ok(()) Ok(Cycles(8))
} }
EightBitLoadInstruction::LoadToRegisterAddressThenDec { dst, src } => { EightBitLoadInstruction::LoadToRegisterAddressThenDec { dst, src } => {
@ -102,7 +117,7 @@ impl Run for EightBitLoadInstruction {
.registers .registers
.set_combined_register(dst, dst_address - 1); .set_combined_register(dst, dst_address - 1);
Ok(()) Ok(Cycles(8))
} }
EightBitLoadInstruction::LoadToRegisterAddressThenInc { dst, src } => { EightBitLoadInstruction::LoadToRegisterAddressThenInc { dst, src } => {
@ -113,7 +128,7 @@ impl Run for EightBitLoadInstruction {
.registers .registers
.set_combined_register(dst, dst_address + 1); .set_combined_register(dst, dst_address + 1);
Ok(()) Ok(Cycles(8))
} }
EightBitLoadInstruction::LoadToMemoryRelativeToIORegisterStartByImmediate { EightBitLoadInstruction::LoadToMemoryRelativeToIORegisterStartByImmediate {
@ -121,7 +136,9 @@ impl Run for EightBitLoadInstruction {
offset, offset,
} => { } => {
let dst_address = memory::IO_REGISTER_START_ADDRESS + usize::from(offset); let dst_address = memory::IO_REGISTER_START_ADDRESS + usize::from(offset);
processor.load_from_register_to_address(dst_address, src) processor.load_from_register_to_address(dst_address, src)?;
Ok(Cycles(12))
} }
EightBitLoadInstruction::LoadFromMemoryRelativeToIORegisterStartByImmediate { EightBitLoadInstruction::LoadFromMemoryRelativeToIORegisterStartByImmediate {
@ -129,7 +146,9 @@ impl Run for EightBitLoadInstruction {
offset, offset,
} => { } => {
let src_address = memory::IO_REGISTER_START_ADDRESS + usize::from(offset); let src_address = memory::IO_REGISTER_START_ADDRESS + usize::from(offset);
processor.load_from_address_to_register(dst, src_address) processor.load_from_address_to_register(dst, src_address)?;
Ok(Cycles(12))
} }
} }
} }

View File

@ -3,15 +3,15 @@ use crate::{
register::Registers, register::Registers,
}; };
use super::Run; use super::{Cycles, Run};
impl Run for MiscInstruction { impl Run for MiscInstruction {
fn run_on(&self, processor: &mut Processor) -> Result<(), Error> { fn run_on(&self, processor: &mut Processor) -> Result<Cycles, Error> {
match *self { match *self {
MiscInstruction::SetCarryFlag => { MiscInstruction::SetCarryFlag => {
set_flags_in_carry_bit_instruction(processor, 1); set_flags_in_carry_bit_instruction(processor, 1);
Ok(()) Ok(Cycles(4))
} }
MiscInstruction::ComplementCarryFlag => { MiscInstruction::ComplementCarryFlag => {
let current_carry_flag = processor.registers.get_flag_bit(register::Flag::Carry); let current_carry_flag = processor.registers.get_flag_bit(register::Flag::Carry);
@ -19,7 +19,7 @@ impl Run for MiscInstruction {
set_flags_in_carry_bit_instruction(processor, flipped); set_flags_in_carry_bit_instruction(processor, flipped);
Ok(()) Ok(Cycles(4))
} }
MiscInstruction::ComplementARegister => { MiscInstruction::ComplementARegister => {
let current_value = processor let current_value = processor
@ -36,7 +36,7 @@ impl Run for MiscInstruction {
.registers .registers
.set_flag_bit(register::Flag::Subtract, 1); .set_flag_bit(register::Flag::Subtract, 1);
Ok(()) Ok(Cycles(4))
} }
MiscInstruction::DecimalAdjustAccumulator => { MiscInstruction::DecimalAdjustAccumulator => {
let (adjusted_a_value, carry) = get_daa_value(&processor.registers); let (adjusted_a_value, carry) = get_daa_value(&processor.registers);
@ -57,7 +57,7 @@ impl Run for MiscInstruction {
.registers .registers
.set_flag_bit(register::Flag::Zero, (adjusted_a_value == 0).into()); .set_flag_bit(register::Flag::Zero, (adjusted_a_value == 0).into());
Ok(()) Ok(Cycles(4))
} }
} }
} }

View File

@ -1,5 +1,5 @@
use ferris_boi::{ use ferris_boi::{
cpu::{instructions::RunnableInstruction, Processor}, cpu::{instructions::Instruction, Processor},
register, register,
}; };
@ -21,11 +21,10 @@ fn test_add_hl_to_itself() {
); );
let data = [0x29, 0x02]; let data = [0x29, 0x02];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x02]); assert_eq!(extra_data, &[0x02]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!( assert_eq!(
0x4488, 0x4488,
@ -60,11 +59,10 @@ fn test_add_hl_to_registers_value(
.set_16bit_register(operand_register, operand_value); .set_16bit_register(operand_register, operand_value);
let data = [opcode, 0x02]; let data = [opcode, 0x02];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x02]); assert_eq!(extra_data, &[0x02]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!( assert_eq!(
expected, expected,
@ -102,8 +100,7 @@ fn test_add_hl_to_registers_flags(
.set_16bit_register(operand_register, operand_value); .set_16bit_register(operand_register, operand_value);
let data = [opcode, 0x02]; let data = [opcode, 0x02];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x02]); assert_eq!(extra_data, &[0x02]);
// Set all the register to the opposite we expect to ensure they all get set // Set all the register to the opposite we expect to ensure they all get set
@ -112,7 +109,7 @@ fn test_add_hl_to_registers_flags(
(0, 0, expected_flags.half_carry, expected_flags.carry), (0, 0, expected_flags.half_carry, expected_flags.carry),
); );
processor.run_instruction(&ins); processor.run_instruction(ins);
testutil::assert_flags_eq!( testutil::assert_flags_eq!(
processor, processor,
@ -150,11 +147,10 @@ fn test_increment(
.expect("Failed to set flag bits"); .expect("Failed to set flag bits");
let data = [opcode, 0x02]; let data = [opcode, 0x02];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x02]); assert_eq!(extra_data, &[0x02]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!( assert_eq!(
expected, expected,
@ -191,11 +187,10 @@ fn test_decrement(
.expect("Failed to set flag bits"); .expect("Failed to set flag bits");
let data = [opcode, 0x02]; let data = [opcode, 0x02];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x02]); assert_eq!(extra_data, &[0x02]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!( assert_eq!(
expected, expected,

View File

@ -1,5 +1,5 @@
use ferris_boi::{ use ferris_boi::{
cpu::{instructions::RunnableInstruction, Processor}, cpu::{instructions::Instruction, Processor},
register, register,
}; };
@ -25,11 +25,10 @@ fn test_add_a_to_itself() {
processor.registers.a = 10; processor.registers.a = 10;
let data = [0x87, 0x02]; let data = [0x87, 0x02];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x02]); assert_eq!(extra_data, &[0x02]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!(20, processor.registers.a); assert_eq!(20, processor.registers.a);
} }
@ -46,11 +45,10 @@ fn test_add_to_a_value(opcode: u8, src: register::SingleEightBit) {
processor.registers.set_single_8bit_register(src, 20); processor.registers.set_single_8bit_register(src, 20);
let data = [opcode, 0x02]; let data = [opcode, 0x02];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x02]); assert_eq!(extra_data, &[0x02]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!(30, processor.registers.a); assert_eq!(30, processor.registers.a);
} }
@ -93,11 +91,10 @@ fn test_add_register_to_a_flags(
processor.registers.set_single_8bit_register(src, src_value); processor.registers.set_single_8bit_register(src, src_value);
let data = [opcode, 0x02]; let data = [opcode, 0x02];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x02]); assert_eq!(extra_data, &[0x02]);
processor.run_instruction(&ins); processor.run_instruction(ins);
testutil::assert_flags_eq!( testutil::assert_flags_eq!(
processor, processor,
@ -123,11 +120,10 @@ fn test_add_hl_addr_to_a_value() {
let data = [0x86, 0x02]; let data = [0x86, 0x02];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x02]); assert_eq!(extra_data, &[0x02]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!(0x46, processor.registers.a); assert_eq!(0x46, processor.registers.a);
} }
@ -166,11 +162,10 @@ fn test_add_hl_addr_to_a_flags(
); );
let data = [0x86, 0x01]; let data = [0x86, 0x01];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x01]); assert_eq!(extra_data, &[0x01]);
processor.run_instruction(&ins); processor.run_instruction(ins);
testutil::assert_flags_eq!( testutil::assert_flags_eq!(
processor, processor,
@ -187,11 +182,10 @@ fn test_add_immediate_to_a_value() {
processor.registers.a = 50; processor.registers.a = 50;
let data = [0xC6, 0x13, 0x01]; let data = [0xC6, 0x13, 0x01];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x01]); assert_eq!(extra_data, &[0x01]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!(69, processor.registers.a); assert_eq!(69, processor.registers.a);
} }
@ -217,11 +211,10 @@ fn test_add_immediate_to_a_flags(a_value: u8, n: u8, expected_flags: AdditionOpe
); );
let data = [0xC6, n, 0x01]; let data = [0xC6, n, 0x01];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x01]); assert_eq!(extra_data, &[0x01]);
processor.run_instruction(&ins); processor.run_instruction(ins);
testutil::assert_flags_eq!( testutil::assert_flags_eq!(
processor, processor,
@ -260,10 +253,9 @@ fn test_add_register_with_carry_to_a_value(
.set_flag_bit(register::Flag::Carry, carry_bit); .set_flag_bit(register::Flag::Carry, carry_bit);
let data = [opcode, 0x01]; let data = [opcode, 0x01];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x01]); assert_eq!(extra_data, &[0x01]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!(expected_value, processor.registers.a); assert_eq!(expected_value, processor.registers.a);
} }
@ -323,10 +315,9 @@ fn test_add_register_with_carry_to_a_flags(
.set_flag_bit(register::Flag::Carry, carry_bit); .set_flag_bit(register::Flag::Carry, carry_bit);
let data = [opcode, 0x01]; let data = [opcode, 0x01];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x01]); assert_eq!(extra_data, &[0x01]);
processor.run_instruction(&ins); processor.run_instruction(ins);
testutil::assert_flags_eq!( testutil::assert_flags_eq!(
processor, processor,
@ -347,10 +338,9 @@ fn test_add_a_to_itself_with_carry_value(initial_value: u8, carry_bit: u8, expec
.set_flag_bit(register::Flag::Carry, carry_bit); .set_flag_bit(register::Flag::Carry, carry_bit);
let data = [0x8F, 0x01]; let data = [0x8F, 0x01];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x01]); assert_eq!(extra_data, &[0x01]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!(processor.registers.a, expected_value); assert_eq!(processor.registers.a, expected_value);
} }
@ -381,10 +371,9 @@ fn test_add_a_to_itself_with_carry_flags(
.set_flag_bit(register::Flag::Carry, carry_bit); .set_flag_bit(register::Flag::Carry, carry_bit);
let data = [0x8F, 0x01]; let data = [0x8F, 0x01];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x01]); assert_eq!(extra_data, &[0x01]);
processor.run_instruction(&ins); processor.run_instruction(ins);
testutil::assert_flags_eq!( testutil::assert_flags_eq!(
processor, processor,
@ -410,10 +399,9 @@ fn test_add_immediate_with_carry_to_a_value(
.set_flag_bit(register::Flag::Carry, carry_bit); .set_flag_bit(register::Flag::Carry, carry_bit);
let data = [0xCE, operand, 0x01]; let data = [0xCE, operand, 0x01];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x01]); assert_eq!(extra_data, &[0x01]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!(processor.registers.a, expected_value); assert_eq!(processor.registers.a, expected_value);
} }
@ -446,10 +434,9 @@ fn test_add_immediate_with_carry_to_a_flags(
.set_flag_bit(register::Flag::Carry, carry_bit); .set_flag_bit(register::Flag::Carry, carry_bit);
let data = [0xCE, operand, 0x01]; let data = [0xCE, operand, 0x01];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x01]); assert_eq!(extra_data, &[0x01]);
processor.run_instruction(&ins); processor.run_instruction(ins);
testutil::assert_flags_eq!( testutil::assert_flags_eq!(
processor, processor,
@ -479,11 +466,10 @@ fn test_add_hl_addr_to_a_with_carry_value(carry_flag: u8, expected: u8) {
let data = [0x8E, 0x02]; let data = [0x8E, 0x02];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x02]); assert_eq!(extra_data, &[0x02]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!(expected, processor.registers.a); assert_eq!(expected, processor.registers.a);
} }
@ -526,11 +512,10 @@ fn test_add_hl_addr_to_a_with_carry_flags(
let data = [0x8E, 0x02]; let data = [0x8E, 0x02];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x02]); assert_eq!(extra_data, &[0x02]);
processor.run_instruction(&ins); processor.run_instruction(ins);
testutil::assert_flags_eq!( testutil::assert_flags_eq!(
processor, processor,
@ -567,11 +552,10 @@ fn test_sub_register_from_a_value(
let data = [opcode, 0x02]; let data = [opcode, 0x02];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x02]); assert_eq!(extra_data, &[0x02]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!(processor.registers.a, expected); assert_eq!(processor.registers.a, expected);
} }
@ -613,11 +597,10 @@ fn test_sub_register_from_a_flags(
); );
let data = [opcode, 0x02]; let data = [opcode, 0x02];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x02]); assert_eq!(extra_data, &[0x02]);
processor.run_instruction(&ins); processor.run_instruction(ins);
testutil::assert_flags_eq!( testutil::assert_flags_eq!(
processor, processor,
@ -634,14 +617,13 @@ fn test_sub_a_from_itself() {
processor.registers.a = 0xFF; processor.registers.a = 0xFF;
let data = [0x97, 0x02]; let data = [0x97, 0x02];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x02]); assert_eq!(extra_data, &[0x02]);
// Set all the register to the opposite we expect to ensure they all get set // Set all the register to the opposite we expect to ensure they all get set
testutil::set_opposite_of_expected_flags(&mut processor, (0, 0, 1, 1)); testutil::set_opposite_of_expected_flags(&mut processor, (0, 0, 1, 1));
processor.run_instruction(&ins); processor.run_instruction(ins);
testutil::assert_flags_eq!( testutil::assert_flags_eq!(
processor, processor,
@ -681,11 +663,10 @@ fn test_sub_register_with_carry_from_a_value(
let data = [opcode, 0x02]; let data = [opcode, 0x02];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x02]); assert_eq!(extra_data, &[0x02]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!(processor.registers.a, expected); assert_eq!(processor.registers.a, expected);
} }
#[test_matrix( #[test_matrix(
@ -739,10 +720,9 @@ fn test_sub_register_from_carry_from_a_flags(
.set_flag_bit(register::Flag::Carry, carry_bit); .set_flag_bit(register::Flag::Carry, carry_bit);
let data = [opcode, 0x01]; let data = [opcode, 0x01];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x01]); assert_eq!(extra_data, &[0x01]);
processor.run_instruction(&ins); processor.run_instruction(ins);
testutil::assert_flags_eq!( testutil::assert_flags_eq!(
processor, processor,
@ -759,11 +739,10 @@ fn test_subtract_immediate_from_a_value() {
processor.registers.a = 0xFF; processor.registers.a = 0xFF;
let data = [0xD6, 0x0F, 0x02]; let data = [0xD6, 0x0F, 0x02];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x02]); assert_eq!(extra_data, &[0x02]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!(processor.registers.a, 0xF0); assert_eq!(processor.registers.a, 0xF0);
} }
@ -791,10 +770,9 @@ fn test_sub_immediate_from_a_flags(
); );
let data = [0xD6, operand, 0x01]; let data = [0xD6, operand, 0x01];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x01]); assert_eq!(extra_data, &[0x01]);
processor.run_instruction(&ins); processor.run_instruction(ins);
testutil::assert_flags_eq!( testutil::assert_flags_eq!(
processor, processor,
@ -821,11 +799,10 @@ fn test_sub_immediate_with_carry_from_a_value(
let data = [0xDE, operand, 0x02]; let data = [0xDE, operand, 0x02];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x02]); assert_eq!(extra_data, &[0x02]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!(processor.registers.a, expected); assert_eq!(processor.registers.a, expected);
} }
@ -864,10 +841,9 @@ fn test_sub_immediate_from_carry_from_a_flags(
.set_flag_bit(register::Flag::Carry, carry_bit); .set_flag_bit(register::Flag::Carry, carry_bit);
let data = [0xDE, operand, 0x01]; let data = [0xDE, operand, 0x01];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x01]); assert_eq!(extra_data, &[0x01]);
processor.run_instruction(&ins); processor.run_instruction(ins);
testutil::assert_flags_eq!( testutil::assert_flags_eq!(
processor, processor,
@ -888,10 +864,9 @@ fn test_sub_a_register_from_itself_with_carry_value(carry_bit: u8, expected: u8)
.set_flag_bit(register::Flag::Carry, carry_bit); .set_flag_bit(register::Flag::Carry, carry_bit);
let data = [0x9F, 0x01]; let data = [0x9F, 0x01];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x01]); assert_eq!(extra_data, &[0x01]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!(expected, processor.registers.a); assert_eq!(expected, processor.registers.a);
} }
@ -920,10 +895,9 @@ fn test_sub_a_register_from_itself_with_carry_flags(
.set_flag_bit(register::Flag::Carry, carry_bit); .set_flag_bit(register::Flag::Carry, carry_bit);
let data = [0x9F, 0x01]; let data = [0x9F, 0x01];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x01]); assert_eq!(extra_data, &[0x01]);
processor.run_instruction(&ins); processor.run_instruction(ins);
testutil::assert_flags_eq!( testutil::assert_flags_eq!(
processor, processor,
@ -948,10 +922,9 @@ fn test_sub_hl_addr_from_a_value() {
.set_combined_register(register::Combined::HL, 0xABCD); .set_combined_register(register::Combined::HL, 0xABCD);
let data = [0x96, 0x01]; let data = [0x96, 0x01];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x01]); assert_eq!(extra_data, &[0x01]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!(0x11, processor.registers.a); assert_eq!(0x11, processor.registers.a);
} }
@ -988,10 +961,9 @@ fn test_sub_hl_addr_from_a_flags(
.set_combined_register(register::Combined::HL, 0xABCD); .set_combined_register(register::Combined::HL, 0xABCD);
let data = [0x96, 0x01]; let data = [0x96, 0x01];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x01]); assert_eq!(extra_data, &[0x01]);
processor.run_instruction(&ins); processor.run_instruction(ins);
testutil::assert_flags_eq!( testutil::assert_flags_eq!(
processor, processor,
@ -1020,10 +992,9 @@ fn test_sub_hl_from_a_flags(a_value: u8, operand_value: u8, carry_bit: u8, expec
.set_combined_register(register::Combined::HL, 0xABCD); .set_combined_register(register::Combined::HL, 0xABCD);
let data = [0x9E, 0x01]; let data = [0x9E, 0x01];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x01]); assert_eq!(extra_data, &[0x01]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!(expected_value, processor.registers.a); assert_eq!(expected_value, processor.registers.a);
} }
@ -1069,10 +1040,9 @@ fn test_sub_hl_addr_from_a_with_carry_flags(
.set_combined_register(register::Combined::HL, 0xABCD); .set_combined_register(register::Combined::HL, 0xABCD);
let data = [0x9E, 0x01]; let data = [0x9E, 0x01];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x01]); assert_eq!(extra_data, &[0x01]);
processor.run_instruction(&ins); processor.run_instruction(ins);
testutil::assert_flags_eq!( testutil::assert_flags_eq!(
processor, processor,
@ -1103,10 +1073,9 @@ fn test_and_single_register_with_a_value(
.set_single_8bit_register(operand_register, operand); .set_single_8bit_register(operand_register, operand);
let data = [opcode, 0x01]; let data = [opcode, 0x01];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x01]); assert_eq!(extra_data, &[0x01]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!(expected_value, processor.registers.a); assert_eq!(expected_value, processor.registers.a);
} }
@ -1137,10 +1106,9 @@ fn test_and_single_register_with_a_flags(
.set_single_8bit_register(operand_register, operand); .set_single_8bit_register(operand_register, operand);
let data = [opcode, 0x01]; let data = [opcode, 0x01];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x01]); assert_eq!(extra_data, &[0x01]);
processor.run_instruction(&ins); processor.run_instruction(ins);
testutil::assert_flags_eq!( testutil::assert_flags_eq!(
processor, processor,
@ -1157,10 +1125,9 @@ fn test_and_a_with_itself_value() {
processor.registers.a = 0xAB; processor.registers.a = 0xAB;
let data = [0xA7, 0x01]; let data = [0xA7, 0x01];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x01]); assert_eq!(extra_data, &[0x01]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!(0xAB, processor.registers.a); assert_eq!(0xAB, processor.registers.a);
} }
@ -1174,10 +1141,9 @@ fn test_and_a_with_itself_flags() {
processor.registers.a = 0xAB; processor.registers.a = 0xAB;
let data = [0xA7, 0x01]; let data = [0xA7, 0x01];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x01]); assert_eq!(extra_data, &[0x01]);
processor.run_instruction(&ins); processor.run_instruction(ins);
testutil::assert_flags_eq!( testutil::assert_flags_eq!(
processor, processor,
@ -1201,10 +1167,9 @@ fn test_and_hl_value_with_a_value() {
.expect("failed to set value"); .expect("failed to set value");
let data = [0xA6, 0x01]; let data = [0xA6, 0x01];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x01]); assert_eq!(extra_data, &[0x01]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!(0xA0, processor.registers.a); assert_eq!(0xA0, processor.registers.a);
} }
@ -1226,10 +1191,9 @@ fn test_and_hl_value_with_a_flags(a_value: u8, operand: u8, expected_zero_flag:
testutil::set_opposite_of_expected_flags(&mut processor, (expected_zero_flag, 0, 1, 0)); testutil::set_opposite_of_expected_flags(&mut processor, (expected_zero_flag, 0, 1, 0));
let data = [0xA6, 0x01]; let data = [0xA6, 0x01];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x01]); assert_eq!(extra_data, &[0x01]);
processor.run_instruction(&ins); processor.run_instruction(ins);
testutil::assert_flags_eq!( testutil::assert_flags_eq!(
processor, processor,
@ -1246,10 +1210,9 @@ fn test_and_immediate_with_a_value() {
processor.registers.a = 0xAB; processor.registers.a = 0xAB;
let data = [0xE6, 0x0F, 0x01]; let data = [0xE6, 0x0F, 0x01];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x01]); assert_eq!(extra_data, &[0x01]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!(0x0B, processor.registers.a); assert_eq!(0x0B, processor.registers.a);
} }
@ -1264,10 +1227,9 @@ fn test_and_immediate_with_a_flags(a_value: u8, operand: u8, expected_zero_flag:
testutil::set_opposite_of_expected_flags(&mut processor, (expected_zero_flag, 0, 1, 0)); testutil::set_opposite_of_expected_flags(&mut processor, (expected_zero_flag, 0, 1, 0));
let data = [0xE6, operand, 0x01]; let data = [0xE6, operand, 0x01];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x01]); assert_eq!(extra_data, &[0x01]);
processor.run_instruction(&ins); processor.run_instruction(ins);
testutil::assert_flags_eq!( testutil::assert_flags_eq!(
processor, processor,
@ -1300,10 +1262,9 @@ fn test_xor_register_with_a_value(
.set_single_8bit_register(operand_register, operand); .set_single_8bit_register(operand_register, operand);
let data = [opcode, 0x03]; let data = [opcode, 0x03];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x03]); assert_eq!(extra_data, &[0x03]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!(expected_value, processor.registers.a); assert_eq!(expected_value, processor.registers.a);
} }
@ -1336,10 +1297,9 @@ fn test_xor_register_with_a_flags(
.set_single_8bit_register(operand_register, operand); .set_single_8bit_register(operand_register, operand);
let data = [opcode, 0x03]; let data = [opcode, 0x03];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x03]); assert_eq!(extra_data, &[0x03]);
processor.run_instruction(&ins); processor.run_instruction(ins);
testutil::assert_flags_eq!( testutil::assert_flags_eq!(
processor, processor,
@ -1356,10 +1316,9 @@ fn test_xor_register_a_with_itself_value() {
processor.registers.a = 0x45; processor.registers.a = 0x45;
let data = [0xAF, 0x01]; let data = [0xAF, 0x01];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x01]); assert_eq!(extra_data, &[0x01]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!(0, processor.registers.a); assert_eq!(0, processor.registers.a);
} }
@ -1372,10 +1331,9 @@ fn test_xor_register_a_with_itself_flags() {
processor.registers.a = 0x45; processor.registers.a = 0x45;
let data = [0xAF, 0x01]; let data = [0xAF, 0x01];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x01]); assert_eq!(extra_data, &[0x01]);
processor.run_instruction(&ins); processor.run_instruction(ins);
testutil::assert_flags_eq!( testutil::assert_flags_eq!(
processor, processor,
@ -1402,10 +1360,9 @@ fn test_xor_hl_value_with_a_value() {
.expect("failed to set memory value"); .expect("failed to set memory value");
let data = [0xAE, 0x03]; let data = [0xAE, 0x03];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x03]); assert_eq!(extra_data, &[0x03]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!(0x55, processor.registers.a); assert_eq!(0x55, processor.registers.a);
} }
@ -1428,10 +1385,9 @@ fn test_xor_hl_value_with_a_flags(a_value: u8, operand: u8, expected_zero_flag:
.expect("failed to set memory value"); .expect("failed to set memory value");
let data = [0xAE, 0x03]; let data = [0xAE, 0x03];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x03]); assert_eq!(extra_data, &[0x03]);
processor.run_instruction(&ins); processor.run_instruction(ins);
testutil::assert_flags_eq!( testutil::assert_flags_eq!(
processor, processor,
@ -1450,10 +1406,9 @@ fn test_xor_immediate_value_with_a_value() {
.set_single_8bit_register(register::SingleEightBit::A, 0x22); .set_single_8bit_register(register::SingleEightBit::A, 0x22);
let data = [0xEE, 0xEE, 0x03]; let data = [0xEE, 0xEE, 0x03];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x03]); assert_eq!(extra_data, &[0x03]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!(0xCC, processor.registers.a); assert_eq!(0xCC, processor.registers.a);
} }
@ -1468,10 +1423,9 @@ fn test_xor_immediate_value_with_a_flags(a_value: u8, operand: u8, expected_zero
.set_single_8bit_register(register::SingleEightBit::A, a_value); .set_single_8bit_register(register::SingleEightBit::A, a_value);
let data = [0xEE, operand, 0x03]; let data = [0xEE, operand, 0x03];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x03]); assert_eq!(extra_data, &[0x03]);
processor.run_instruction(&ins); processor.run_instruction(ins);
testutil::assert_flags_eq!( testutil::assert_flags_eq!(
processor, processor,
@ -1509,10 +1463,9 @@ fn test_or_register_with_a_value(
.set_single_8bit_register(operand_register, operand); .set_single_8bit_register(operand_register, operand);
let data = [opcode, 0x03]; let data = [opcode, 0x03];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x03]); assert_eq!(extra_data, &[0x03]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!(expected_value, processor.registers.a); assert_eq!(expected_value, processor.registers.a);
} }
@ -1545,10 +1498,9 @@ fn test_or_register_with_a_flags(
.set_single_8bit_register(operand_register, operand); .set_single_8bit_register(operand_register, operand);
let data = [opcode, 0x03]; let data = [opcode, 0x03];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x03]); assert_eq!(extra_data, &[0x03]);
processor.run_instruction(&ins); processor.run_instruction(ins);
testutil::assert_flags_eq!( testutil::assert_flags_eq!(
processor, processor,
@ -1565,10 +1517,9 @@ fn test_or_register_a_with_itself_value() {
processor.registers.a = 0x45; processor.registers.a = 0x45;
let data = [0xB7, 0x01]; let data = [0xB7, 0x01];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x01]); assert_eq!(extra_data, &[0x01]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!(0x45, processor.registers.a); assert_eq!(0x45, processor.registers.a);
} }
@ -1582,10 +1533,9 @@ fn test_or_register_a_with_itself_flags(operand: u8, expected_zero_flag: u8) {
processor.registers.a = operand; processor.registers.a = operand;
let data = [0xB7, 0x01]; let data = [0xB7, 0x01];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x01]); assert_eq!(extra_data, &[0x01]);
processor.run_instruction(&ins); processor.run_instruction(ins);
testutil::assert_flags_eq!( testutil::assert_flags_eq!(
processor, processor,
@ -1612,10 +1562,9 @@ fn test_or_hl_value_with_a_value() {
.expect("failed to set memory value"); .expect("failed to set memory value");
let data = [0xB6, 0x03]; let data = [0xB6, 0x03];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x03]); assert_eq!(extra_data, &[0x03]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!(0xBB, processor.registers.a); assert_eq!(0xBB, processor.registers.a);
} }
@ -1639,10 +1588,9 @@ fn test_or_hl_value_with_a_flags(a_value: u8, hl_value: u8, expected_zero_flag:
.expect("failed to set memory value"); .expect("failed to set memory value");
let data = [0xB7, 0x01]; let data = [0xB7, 0x01];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x01]); assert_eq!(extra_data, &[0x01]);
processor.run_instruction(&ins); processor.run_instruction(ins);
testutil::assert_flags_eq!( testutil::assert_flags_eq!(
processor, processor,
@ -1661,10 +1609,9 @@ fn test_or_immediate_value_with_a_value() {
.set_single_8bit_register(register::SingleEightBit::A, 0x33); .set_single_8bit_register(register::SingleEightBit::A, 0x33);
let data = [0xF6, 0xAA, 0x03]; let data = [0xF6, 0xAA, 0x03];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x03]); assert_eq!(extra_data, &[0x03]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!(0xBB, processor.registers.a); assert_eq!(0xBB, processor.registers.a);
} }
@ -1679,10 +1626,9 @@ fn test_or_immediate_value_with_a_flags(a_value: u8, operand: u8, expected_zero_
.set_single_8bit_register(register::SingleEightBit::A, a_value); .set_single_8bit_register(register::SingleEightBit::A, a_value);
let data = [0xF6, operand, 0x03]; let data = [0xF6, operand, 0x03];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x03]); assert_eq!(extra_data, &[0x03]);
processor.run_instruction(&ins); processor.run_instruction(ins);
testutil::assert_flags_eq!( testutil::assert_flags_eq!(
processor, processor,
@ -1710,10 +1656,9 @@ fn test_compare_register_instructions_do_not_modify_register_values(
processor.registers.set_single_8bit_register(register, 0x22); processor.registers.set_single_8bit_register(register, 0x22);
let data = [opcode, 0x03]; let data = [opcode, 0x03];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x03]); assert_eq!(extra_data, &[0x03]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!( assert_eq!(
0xFF, 0xFF,
@ -1733,10 +1678,9 @@ fn test_compare_register_with_itself_does_not_modify_value() {
.set_single_8bit_register(register::SingleEightBit::A, 0xFF); .set_single_8bit_register(register::SingleEightBit::A, 0xFF);
let data = [0xBF, 0x03]; let data = [0xBF, 0x03];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x03]); assert_eq!(extra_data, &[0x03]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!( assert_eq!(
0xFF, 0xFF,
@ -1767,10 +1711,9 @@ fn test_comparing_equal_values_between_registers_sets_zero_flag(
processor.registers.set_single_8bit_register(register, 0xFF); processor.registers.set_single_8bit_register(register, 0xFF);
let data = [opcode, 0x03]; let data = [opcode, 0x03];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x03]); assert_eq!(extra_data, &[0x03]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!( assert_eq!(
0xFF, 0xFF,
@ -1808,10 +1751,9 @@ fn test_comparing_extremely_less_than_values_between_registers_should_set_no_fla
processor.registers.set_single_8bit_register(register, 0x01); processor.registers.set_single_8bit_register(register, 0x01);
let data = [opcode, 0x03]; let data = [opcode, 0x03];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x03]); assert_eq!(extra_data, &[0x03]);
processor.run_instruction(&ins); processor.run_instruction(ins);
testutil::assert_flags_eq!( testutil::assert_flags_eq!(
processor, processor,
@ -1842,10 +1784,9 @@ fn test_comparing_extremely_somewhat_less_than_values_between_registers_should_s
processor.registers.set_single_8bit_register(register, 0x1F); processor.registers.set_single_8bit_register(register, 0x1F);
let data = [opcode, 0x03]; let data = [opcode, 0x03];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x03]); assert_eq!(extra_data, &[0x03]);
processor.run_instruction(&ins); processor.run_instruction(ins);
testutil::assert_flags_eq!( testutil::assert_flags_eq!(
processor, processor,
@ -1876,10 +1817,9 @@ fn test_comparing_greater_than_values_between_registers_should_set_carry_flag(
processor.registers.set_single_8bit_register(register, 0xFF); processor.registers.set_single_8bit_register(register, 0xFF);
let data = [opcode, 0x03]; let data = [opcode, 0x03];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x03]); assert_eq!(extra_data, &[0x03]);
processor.run_instruction(&ins); processor.run_instruction(ins);
testutil::assert_flags_eq!( testutil::assert_flags_eq!(
processor, processor,
@ -1910,10 +1850,9 @@ fn test_comparing_lower_nibble_greater_than_values_between_registers_should_set_
processor.registers.set_single_8bit_register(register, 0x2F); processor.registers.set_single_8bit_register(register, 0x2F);
let data = [opcode, 0x03]; let data = [opcode, 0x03];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x03]); assert_eq!(extra_data, &[0x03]);
processor.run_instruction(&ins); processor.run_instruction(ins);
testutil::assert_flags_eq!( testutil::assert_flags_eq!(
processor, processor,
@ -1940,10 +1879,9 @@ fn test_comparing_hl_value_to_a_does_not_change_value() {
.expect("failde to set value"); .expect("failde to set value");
let data = [0xBE, 0x03]; let data = [0xBE, 0x03];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x03]); assert_eq!(extra_data, &[0x03]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!( assert_eq!(
0xFF, 0xFF,
@ -1984,10 +1922,9 @@ fn test_comparing_hl_value_to_a(a_value: u8, operand: u8, expected_flags: Additi
); );
let data = [0xBE, 0x03]; let data = [0xBE, 0x03];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x03]); assert_eq!(extra_data, &[0x03]);
processor.run_instruction(&ins); processor.run_instruction(ins);
testutil::assert_flags_eq!( testutil::assert_flags_eq!(
processor, processor,
@ -2006,10 +1943,9 @@ fn test_comparing_immediate_value_to_a_does_not_change_value() {
.set_single_8bit_register(register::SingleEightBit::A, 0xFF); .set_single_8bit_register(register::SingleEightBit::A, 0xFF);
let data = [0xFE, 0xBB, 0x03]; let data = [0xFE, 0xBB, 0x03];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x03]); assert_eq!(extra_data, &[0x03]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!( assert_eq!(
0xFF, 0xFF,
@ -2046,10 +1982,9 @@ fn test_comparing_immediate_value_to_a(
); );
let data = [0xFE, operand, 0x03]; let data = [0xFE, operand, 0x03];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x03]); assert_eq!(extra_data, &[0x03]);
processor.run_instruction(&ins); processor.run_instruction(ins);
testutil::assert_flags_eq!( testutil::assert_flags_eq!(
processor, processor,
@ -2102,10 +2037,9 @@ fn test_increment_decrement_single_register_value(
.set_single_8bit_register(register, initial_value); .set_single_8bit_register(register, initial_value);
let data = [opcode, 0x03]; let data = [opcode, 0x03];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x03]); assert_eq!(extra_data, &[0x03]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!( assert_eq!(
expected_value, expected_value,
@ -2168,10 +2102,9 @@ fn test_increment_decrement_single_register_flags(
); );
let data = [opcode, 0x03]; let data = [opcode, 0x03];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x03]); assert_eq!(extra_data, &[0x03]);
processor.run_instruction(&ins); processor.run_instruction(ins);
testutil::assert_flags_eq!( testutil::assert_flags_eq!(
processor, processor,
@ -2198,10 +2131,9 @@ fn test_increment_decrement_hl_value(opcode: u8, initial_value: u8, expected_val
.expect("failed to set memory value"); .expect("failed to set memory value");
let data = [opcode, 0x03]; let data = [opcode, 0x03];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x03]); assert_eq!(extra_data, &[0x03]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!( assert_eq!(
expected_value, expected_value,
@ -2246,10 +2178,9 @@ fn test_increment_decrement_hl_flags(
); );
let data = [opcode, 0x03]; let data = [opcode, 0x03];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x03]); assert_eq!(extra_data, &[0x03]);
processor.run_instruction(&ins); processor.run_instruction(ins);
testutil::assert_flags_eq!( testutil::assert_flags_eq!(
processor, processor,
@ -2273,10 +2204,9 @@ fn test_adjust_stack_pointer_value(initial_sp: u16, adjustment: i8, expected_sp:
let twos_comp_adjustment = adjustment.to_be_bytes()[0]; let twos_comp_adjustment = adjustment.to_be_bytes()[0];
let data = [0xE8, twos_comp_adjustment, 0x03]; let data = [0xE8, twos_comp_adjustment, 0x03];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x03]); assert_eq!(extra_data, &[0x03]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!(expected_sp, processor.registers.stack_pointer); assert_eq!(expected_sp, processor.registers.stack_pointer);
} }
@ -2298,10 +2228,9 @@ fn test_adjust_stack_pointer(initial_sp: u16, adjustment: i8, half_carry: bool,
let twos_comp_adjustment = adjustment.to_be_bytes()[0]; let twos_comp_adjustment = adjustment.to_be_bytes()[0];
let data = [0xE8, twos_comp_adjustment, 0x03]; let data = [0xE8, twos_comp_adjustment, 0x03];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x03]); assert_eq!(extra_data, &[0x03]);
processor.run_instruction(&ins); processor.run_instruction(ins);
testutil::assert_flags_eq!( testutil::assert_flags_eq!(
processor, processor,

View File

@ -1,5 +1,5 @@
use ferris_boi::{ use ferris_boi::{
cpu::{instructions::RunnableInstruction, Processor}, cpu::{instructions::Instruction, Processor},
register, register,
}; };
@ -21,11 +21,10 @@ fn test_load_to_register_address_then_do_arithmetic(
processor.registers.a = 10; processor.registers.a = 10;
let data = [opcode, 0x00]; let data = [opcode, 0x00];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x00]); assert_eq!(extra_data, &[0x00]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!(10, processor.memory.get(hl_value_before.into()).unwrap()); assert_eq!(10, processor.memory.get(hl_value_before.into()).unwrap());
assert_eq!( assert_eq!(
hl_value_after, hl_value_after,
@ -51,11 +50,10 @@ fn test_load_16bit_immediate_to_register(opcode: u8, expected_dst_register: regi
// l05c0: ld hl,0ff02h ; 05c0 21 02 ff !.. // l05c0: ld hl,0ff02h ; 05c0 21 02 ff !..
let data = [opcode, 0x34, 0x12, 0x05]; let data = [opcode, 0x34, 0x12, 0x05];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x05]); assert_eq!(extra_data, &[0x05]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!( assert_eq!(
0x1234, 0x1234,
@ -73,11 +71,10 @@ fn test_load_from_hl_to_sp() {
.set_combined_register(register::Combined::HL, 0x1234); .set_combined_register(register::Combined::HL, 0x1234);
let data = [0xF9, 0x00]; let data = [0xF9, 0x00];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x00]); assert_eq!(extra_data, &[0x00]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!(0x1234, processor.registers.stack_pointer); assert_eq!(0x1234, processor.registers.stack_pointer);
} }
@ -106,11 +103,10 @@ fn test_load_effective_address(start_sp: u16, value: i8, expected_sp: u16) {
let data = [0xF8, unsigned_value, 0x00]; let data = [0xF8, unsigned_value, 0x00];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x00]); assert_eq!(extra_data, &[0x00]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!( assert_eq!(
expected_sp, expected_sp,
@ -142,11 +138,10 @@ fn test_load_effective_address_flags(starting_sp: u16, add_value: i8, half_carry
}; };
let data = [0xF8, unsigned_value, 0x00]; let data = [0xF8, unsigned_value, 0x00];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x00]); assert_eq!(extra_data, &[0x00]);
processor.run_instruction(&ins); processor.run_instruction(ins);
testutil::assert_flags_eq!( testutil::assert_flags_eq!(
processor, processor,
@ -166,11 +161,10 @@ fn test_stack_push(opcode: u8, src: register::Combined) {
processor.registers.stack_pointer = 0xFFFE; processor.registers.stack_pointer = 0xFFFE;
let data = [opcode, 0x01]; let data = [opcode, 0x01];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x01]); assert_eq!(extra_data, &[0x01]);
processor.run_instruction(&ins); processor.run_instruction(ins);
// we want to pop the LSB first (i.e. we write the MSB first) // we want to pop the LSB first (i.e. we write the MSB first)
// https://rgbds.gbdev.io/docs/v0.5.2/gbz80.7#PUSH_r16 // https://rgbds.gbdev.io/docs/v0.5.2/gbz80.7#PUSH_r16
@ -188,11 +182,10 @@ fn test_stack_push_from_af() {
processor.registers.stack_pointer = 0xFFFE; processor.registers.stack_pointer = 0xFFFE;
let data = [0xF5, 0x01]; let data = [0xF5, 0x01];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x01]); assert_eq!(extra_data, &[0x01]);
processor.run_instruction(&ins); processor.run_instruction(ins);
// we want to pop the LSB first (i.e. we write the MSB first) // we want to pop the LSB first (i.e. we write the MSB first)
// https://rgbds.gbdev.io/docs/v0.5.2/gbz80.7#PUSH_r16 // https://rgbds.gbdev.io/docs/v0.5.2/gbz80.7#PUSH_r16
@ -213,11 +206,10 @@ fn test_stack_pop(opcode: u8, dst: register::Combined) {
.expect("failed to set values in memory"); .expect("failed to set values in memory");
let data = [opcode, 0x01]; let data = [opcode, 0x01];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x01]); assert_eq!(extra_data, &[0x01]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!(0x1234, processor.registers.get_combined_register(dst)); assert_eq!(0x1234, processor.registers.get_combined_register(dst));
assert_eq!(0xFFF0 + 2, processor.registers.stack_pointer); assert_eq!(0xFFF0 + 2, processor.registers.stack_pointer);
@ -233,11 +225,10 @@ fn test_stack_pop_to_af() {
.expect("failed to set values in memory"); .expect("failed to set values in memory");
let data = [0xF1, 0x01]; let data = [0xF1, 0x01];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x01]); assert_eq!(extra_data, &[0x01]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!( assert_eq!(
0x1230, 0x1230,

View File

@ -1,5 +1,5 @@
use ferris_boi::{ use ferris_boi::{
cpu::{instructions::RunnableInstruction, Processor}, cpu::{instructions::Instruction, Processor},
register, register,
}; };
use test_case::test_case; use test_case::test_case;
@ -65,13 +65,12 @@ fn test_load_register(
.set_single_8bit_register(src_register, 0x45); .set_single_8bit_register(src_register, 0x45);
let data = [load_opcode, 0x00]; let data = [load_opcode, 0x00];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
// assert our extra data after the instruction is returned // assert our extra data after the instruction is returned
assert_eq!(extra_data, &[0x00]); assert_eq!(extra_data, &[0x00]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!( assert_eq!(
0x45, 0x45,
processor.registers.get_single_8bit_register(dst_register) processor.registers.get_single_8bit_register(dst_register)
@ -88,14 +87,13 @@ fn test_load_register(
fn test_load_immediate(load_opcode: u8, expected_register: register::SingleEightBit) { fn test_load_immediate(load_opcode: u8, expected_register: register::SingleEightBit) {
let mut processor = Processor::default(); let mut processor = Processor::default();
let data = [load_opcode, 0x23, 0x00, 0x01]; let data = [load_opcode, 0x23, 0x00, 0x01];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
// assert our extra data after the instruction is returned // assert our extra data after the instruction is returned
// this data is just garbage; no idea if it's a valid instruction // this data is just garbage; no idea if it's a valid instruction
assert_eq!(extra_data, &[0x00, 0x01]); assert_eq!(extra_data, &[0x00, 0x01]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!( assert_eq!(
0x23, 0x23,
processor processor
@ -127,12 +125,11 @@ fn test_load_from_memory(
.set_combined_register(expected_deref_register, 0xCCDD); .set_combined_register(expected_deref_register, 0xCCDD);
let data = [opcode, 0x10, 0x20]; let data = [opcode, 0x10, 0x20];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse isntruction");
RunnableInstruction::from_data(&data).expect("could not parse isntruction");
assert_eq!(extra_data, &[0x10, 0x20]); assert_eq!(extra_data, &[0x10, 0x20]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!( assert_eq!(
105, 105,
processor processor
@ -168,12 +165,11 @@ fn test_load_to_memory(
.set_combined_register(expected_deref_register, 0xCCCC); .set_combined_register(expected_deref_register, 0xCCCC);
let data = [opcode, 0x10, 0x20]; let data = [opcode, 0x10, 0x20];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x10, 0x20]); assert_eq!(extra_data, &[0x10, 0x20]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!(0xCC, processor.memory.get(0xCCCC).unwrap()); assert_eq!(0xCC, processor.memory.get(0xCCCC).unwrap());
} }
@ -185,11 +181,10 @@ fn test_load_immediate_to_memory() {
.set_combined_register(register::Combined::HL, 0xCCDE); .set_combined_register(register::Combined::HL, 0xCCDE);
let data = [0x36, 0x1D, 0x00]; let data = [0x36, 0x1D, 0x00];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x00]); assert_eq!(extra_data, &[0x00]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!(0x1D, processor.memory.get(0xCCDE).unwrap()); assert_eq!(0x1D, processor.memory.get(0xCCDE).unwrap());
} }
@ -202,11 +197,10 @@ fn test_load_from_immediate_address() {
.expect("failed to set memory value"); .expect("failed to set memory value");
let data = [0xFA, 0xDE, 0xCC, 0x00]; let data = [0xFA, 0xDE, 0xCC, 0x00];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x00]); assert_eq!(extra_data, &[0x00]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!(105, processor.registers.a); assert_eq!(105, processor.registers.a);
} }
@ -215,11 +209,10 @@ fn test_load_to_immadiate_address() {
let mut processor = Processor::default(); let mut processor = Processor::default();
processor.registers.a = 105; processor.registers.a = 105;
let data = [0xEA, 0xDE, 0xCC, 0x00]; let data = [0xEA, 0xDE, 0xCC, 0x00];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x00]); assert_eq!(extra_data, &[0x00]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!(105, processor.memory.get(0xCCDE).unwrap()); assert_eq!(105, processor.memory.get(0xCCDE).unwrap());
} }
@ -233,11 +226,10 @@ fn test_load_from_io_register_zone() {
processor.registers.c = 0x64; processor.registers.c = 0x64;
let data = [0xF2, 0x00]; let data = [0xF2, 0x00];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x00]); assert_eq!(extra_data, &[0x00]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!(10, processor.registers.a); assert_eq!(10, processor.registers.a);
} }
@ -248,11 +240,10 @@ fn test_load_to_io_register_zone() {
processor.registers.a = 10; processor.registers.a = 10;
let data = [0xE2, 0x00]; let data = [0xE2, 0x00];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x00]); assert_eq!(extra_data, &[0x00]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!(10, processor.memory.get(0xFF64).unwrap()); assert_eq!(10, processor.memory.get(0xFF64).unwrap());
} }
@ -273,11 +264,10 @@ fn test_load_from_register_address_then_do_arithmetic(
.expect("failed to set memory value"); .expect("failed to set memory value");
let data = [opcode, 0x00]; let data = [opcode, 0x00];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x00]); assert_eq!(extra_data, &[0x00]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!(10, processor.registers.a); assert_eq!(10, processor.registers.a);
assert_eq!( assert_eq!(
hl_value_after, hl_value_after,
@ -293,11 +283,10 @@ fn test_load_to_io_register_zone_by_immediate() {
processor.registers.a = 0xAF; processor.registers.a = 0xAF;
let data = [0xE0, 0x05, 0x06]; let data = [0xE0, 0x05, 0x06];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x06]); assert_eq!(extra_data, &[0x06]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!(0xAF, processor.memory.get(0xFF05).unwrap()); assert_eq!(0xAF, processor.memory.get(0xFF05).unwrap());
} }
@ -311,11 +300,10 @@ fn test_load_from_io_register_zone_by_immediate() {
.expect("failed to set memory value"); .expect("failed to set memory value");
let data = [0xF0, 0x05, 0x06]; let data = [0xF0, 0x05, 0x06];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x06]); assert_eq!(extra_data, &[0x06]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!(0xAF, processor.registers.a); assert_eq!(0xAF, processor.registers.a);
} }
@ -326,12 +314,11 @@ fn test_load_from_bottom_of_so_to_immediate_address() {
processor.registers.stack_pointer = 0xABCD; processor.registers.stack_pointer = 0xABCD;
let data = [0x08, 0xAA, 0xFF, 0x06]; let data = [0x08, 0xAA, 0xFF, 0x06];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x06]); assert_eq!(extra_data, &[0x06]);
processor.run_instruction(&ins); processor.run_instruction(ins);
let bottom_stored_value = processor.memory.get_from(0xFFAA).unwrap().get(); let bottom_stored_value = processor.memory.get_from(0xFFAA).unwrap().get();
let top_stored_value = processor.memory.get_from(0xFFAB).unwrap().get(); let top_stored_value = processor.memory.get_from(0xFFAB).unwrap().get();

View File

@ -1,6 +1,6 @@
use crate::testutil::{self, assert_flags_eq}; use crate::testutil::{self, assert_flags_eq};
use ferris_boi::{ use ferris_boi::{
cpu::{instructions::RunnableInstruction, Processor}, cpu::{instructions::Instruction, Processor},
register, register,
}; };
use test_case::test_case; use test_case::test_case;
@ -25,11 +25,10 @@ fn test_set_carry_flag_always_sets_to_1(starting_value: u8) {
.set_flag_bit(register::Flag::Carry, starting_value); .set_flag_bit(register::Flag::Carry, starting_value);
let data = [0x37, 0x03]; let data = [0x37, 0x03];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x03]); assert_eq!(extra_data, &[0x03]);
processor.run_instruction(&ins); processor.run_instruction(ins);
let new_carry_bit = processor.registers.get_flag_bit(register::Flag::Carry); let new_carry_bit = processor.registers.get_flag_bit(register::Flag::Carry);
assert_eq!(1, new_carry_bit); assert_eq!(1, new_carry_bit);
@ -44,11 +43,10 @@ fn test_complement_carry_bit(starting_value: u8, expected_value: u8) {
.set_flag_bit(register::Flag::Carry, starting_value); .set_flag_bit(register::Flag::Carry, starting_value);
let data = [0x3F, 0x03]; let data = [0x3F, 0x03];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x03]); assert_eq!(extra_data, &[0x03]);
processor.run_instruction(&ins); processor.run_instruction(ins);
let new_carry_bit = processor.registers.get_flag_bit(register::Flag::Carry); let new_carry_bit = processor.registers.get_flag_bit(register::Flag::Carry);
assert_eq!(expected_value, new_carry_bit); assert_eq!(expected_value, new_carry_bit);
@ -61,11 +59,10 @@ fn test_all_carry_bit_instructions_adjust_flags(opcode: u8) {
testutil::set_opposite_of_expected_flags(&mut processor, (0, 0, 0, 1)); testutil::set_opposite_of_expected_flags(&mut processor, (0, 0, 0, 1));
let data = [opcode, 0x03]; let data = [opcode, 0x03];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x03]); assert_eq!(extra_data, &[0x03]);
processor.run_instruction(&ins); processor.run_instruction(ins);
testutil::assert_flags_eq!( testutil::assert_flags_eq!(
processor, processor,
@ -84,11 +81,10 @@ fn test_complement_a_register_value() {
processor.registers.a = 0xF0; processor.registers.a = 0xF0;
let data = [0x2F, 0x03]; let data = [0x2F, 0x03];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x03]); assert_eq!(extra_data, &[0x03]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!(0x0F, processor.registers.a); assert_eq!(0x0F, processor.registers.a);
} }
@ -100,11 +96,10 @@ fn test_complement_a_register_flags() {
testutil::set_opposite_of_expected_flags(&mut processor, (0, 1, 1, 0)); testutil::set_opposite_of_expected_flags(&mut processor, (0, 1, 1, 0));
let data = [0x2F, 0x03]; let data = [0x2F, 0x03];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x03]); assert_eq!(extra_data, &[0x03]);
processor.run_instruction(&ins); processor.run_instruction(ins);
testutil::assert_flags_eq!( testutil::assert_flags_eq!(
processor, processor,
@ -150,11 +145,10 @@ fn test_daa(
.set_flag_bit(register::Flag::Zero, (!expected_flags.zero).into()); .set_flag_bit(register::Flag::Zero, (!expected_flags.zero).into());
let data = [0x27, 0x06]; let data = [0x27, 0x06];
let (ins, extra_data) = let (ins, extra_data) = Instruction::from_data(&data).expect("could not parse instruction");
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x06]); assert_eq!(extra_data, &[0x06]);
processor.run_instruction(&ins); processor.run_instruction(ins);
assert_eq!(expected_a_value, processor.registers.a); assert_eq!(expected_a_value, processor.registers.a);
assert_flags_eq!( assert_flags_eq!(