Rename Single to SingleEightBit

jsmoo
Nick Krichevsky 2022-04-09 13:32:12 -04:00
parent 3803abfa1d
commit ef2aff5a8e
6 changed files with 479 additions and 233 deletions

View File

@ -12,7 +12,7 @@ pub enum Flag {
}
#[derive(Debug, Clone, Copy, strum_macros::Display)]
pub enum Single {
pub enum SingleEightBit {
A,
B,
C,
@ -23,7 +23,7 @@ pub enum Single {
L,
}
// Combined represents a pair of two registers taht can be acted on as a single
// Combined represents a pair of two registers taht can be acted on as a single 8 bit
// 16 bit register.
#[derive(Debug, Clone, Copy, strum_macros::Display)]
pub enum Combined {
@ -113,29 +113,29 @@ impl Registers {
self.flags |= bit << pos;
}
pub fn get_single_register(&self, register: Single) -> u8 {
pub fn get_single_8bit_register(&self, register: SingleEightBit) -> u8 {
match register {
Single::A => self.a,
Single::B => self.b,
Single::C => self.c,
Single::D => self.d,
Single::E => self.e,
Single::F => self.f,
Single::H => self.h,
Single::L => self.l,
SingleEightBit::A => self.a,
SingleEightBit::B => self.b,
SingleEightBit::C => self.c,
SingleEightBit::D => self.d,
SingleEightBit::E => self.e,
SingleEightBit::F => self.f,
SingleEightBit::H => self.h,
SingleEightBit::L => self.l,
}
}
pub fn set_single_register(&mut self, register: Single, value: u8) {
pub fn set_single_8bit_register(&mut self, register: SingleEightBit, value: u8) {
let register_ref = match register {
Single::A => &mut self.a,
Single::B => &mut self.b,
Single::C => &mut self.c,
Single::D => &mut self.d,
Single::E => &mut self.e,
Single::F => &mut self.f,
Single::H => &mut self.h,
Single::L => &mut self.l,
SingleEightBit::A => &mut self.a,
SingleEightBit::B => &mut self.b,
SingleEightBit::C => &mut self.c,
SingleEightBit::D => &mut self.d,
SingleEightBit::E => &mut self.e,
SingleEightBit::F => &mut self.f,
SingleEightBit::H => &mut self.h,
SingleEightBit::L => &mut self.l,
};
*register_ref = value;

View File

@ -39,12 +39,12 @@ impl Processor {
fn run(&mut self, instruction: &RunnableInstruction) {
match instruction.instruction {
Instruction::LD8BitImmediateToRegister { value, register } => {
self.registers.set_single_register(register, value);
self.registers.set_single_8bit_register(register, value);
}
Instruction::LDr1r2 { dst, src } => {
let src_value = self.registers.get_single_register(src);
self.registers.set_single_register(dst, src_value);
let src_value = self.registers.get_single_8bit_register(src);
self.registers.set_single_8bit_register(dst, src_value);
}
Instruction::LDFromRegisterAddress { src, dst } => {
@ -77,7 +77,7 @@ impl Processor {
offset_register,
dst,
} => {
let src_address_offset = self.registers.get_single_register(offset_register);
let src_address_offset = self.registers.get_single_8bit_register(offset_register);
let src_address =
memory::IO_REGISTER_START_ADDRESS + usize::from(src_address_offset);
let load_res = self.load_from_address_to_register(dst, src_address);
@ -87,7 +87,7 @@ impl Processor {
src,
offset_register,
} => {
let dst_address_offset = self.registers.get_single_register(offset_register);
let dst_address_offset = self.registers.get_single_8bit_register(offset_register);
let dst_address =
memory::IO_REGISTER_START_ADDRESS + usize::from(dst_address_offset);
let load_res = self.load_from_register_to_address(dst_address, src);
@ -128,7 +128,7 @@ impl Processor {
fn load_from_register_to_register_address(
&mut self,
register_with_dst_address: register::Combined,
src: register::Single,
src: register::SingleEightBit,
) -> Result<(), Error> {
let dst_address = self
.registers
@ -150,9 +150,9 @@ impl Processor {
fn load_from_register_to_address(
&mut self,
dst_address: usize,
src: register::Single,
src: register::SingleEightBit,
) -> Result<(), Error> {
let register_value = self.registers.get_single_register(src);
let register_value = self.registers.get_single_8bit_register(src);
self.load_8bit_immediate_to_address(dst_address, register_value)
}
@ -170,7 +170,7 @@ impl Processor {
fn load_from_address_to_register(
&mut self,
dst: register::Single,
dst: register::SingleEightBit,
src_address: usize,
) -> Result<(), Error> {
let memory_value = self.memory.get(src_address);
@ -179,7 +179,7 @@ impl Processor {
None => Err(Error::InvalidImmediateAddress(src_address)),
Some(value) => {
// technically this could be done with map but I think this is more readable
self.registers.set_single_register(dst, value);
self.registers.set_single_8bit_register(dst, value);
Ok(())
}
}
@ -187,7 +187,7 @@ impl Processor {
fn load_from_register_address_to_register(
&mut self,
dst: register::Single,
dst: register::SingleEightBit,
register_with_src_address: register::Combined,
) -> Result<(), Error> {
let src_address = self
@ -213,14 +213,14 @@ mod tests {
use super::*;
use test_case::test_case;
#[test_case(0x3E, register::Single::A)]
#[test_case(0x06, register::Single::B)]
#[test_case(0x0E, register::Single::C)]
#[test_case(0x16, register::Single::D)]
#[test_case(0x1E, register::Single::E)]
#[test_case(0x26, register::Single::H)]
#[test_case(0x2E, register::Single::L)]
fn test_load_immediate(ld_opcode: u8, expected_register: register::Single) {
#[test_case(0x3E, register::SingleEightBit::A)]
#[test_case(0x06, register::SingleEightBit::B)]
#[test_case(0x0E, register::SingleEightBit::C)]
#[test_case(0x16, register::SingleEightBit::D)]
#[test_case(0x1E, register::SingleEightBit::E)]
#[test_case(0x26, register::SingleEightBit::H)]
#[test_case(0x2E, register::SingleEightBit::L)]
fn test_load_immediate(ld_opcode: u8, expected_register: register::SingleEightBit) {
let mut processor = Processor::default();
let data = [ld_opcode, 0x23, 0x00, 0x01];
let (ins, extra_data) =
@ -233,67 +233,71 @@ mod tests {
processor.run(&ins);
assert_eq!(
0x23,
processor.registers.get_single_register(expected_register)
processor
.registers
.get_single_8bit_register(expected_register)
);
}
// lol going from a register to itself is kind of a weird thing to test
#[test_case(0x7F, register::Single::A, register::Single::A)]
#[test_case(0x78, register::Single::A, register::Single::B)]
#[test_case(0x79, register::Single::A, register::Single::C)]
#[test_case(0x7A, register::Single::A, register::Single::D)]
#[test_case(0x7B, register::Single::A, register::Single::E)]
#[test_case(0x7C, register::Single::A, register::Single::H)]
#[test_case(0x7D, register::Single::A, register::Single::L)]
#[test_case(0x40, register::Single::B, register::Single::B)]
#[test_case(0x41, register::Single::B, register::Single::C)]
#[test_case(0x42, register::Single::B, register::Single::D)]
#[test_case(0x43, register::Single::B, register::Single::E)]
#[test_case(0x44, register::Single::B, register::Single::H)]
#[test_case(0x45, register::Single::B, register::Single::L)]
#[test_case(0x48, register::Single::C, register::Single::B)]
#[test_case(0x49, register::Single::C, register::Single::C)]
#[test_case(0x4A, register::Single::C, register::Single::D)]
#[test_case(0x4B, register::Single::C, register::Single::E)]
#[test_case(0x4C, register::Single::C, register::Single::H)]
#[test_case(0x4D, register::Single::C, register::Single::L)]
#[test_case(0x50, register::Single::D, register::Single::B)]
#[test_case(0x51, register::Single::D, register::Single::C)]
#[test_case(0x52, register::Single::D, register::Single::D)]
#[test_case(0x53, register::Single::D, register::Single::E)]
#[test_case(0x54, register::Single::D, register::Single::H)]
#[test_case(0x55, register::Single::D, register::Single::L)]
#[test_case(0x58, register::Single::E, register::Single::B)]
#[test_case(0x59, register::Single::E, register::Single::C)]
#[test_case(0x5A, register::Single::E, register::Single::D)]
#[test_case(0x5B, register::Single::E, register::Single::E)]
#[test_case(0x5C, register::Single::E, register::Single::H)]
#[test_case(0x5D, register::Single::E, register::Single::L)]
#[test_case(0x60, register::Single::H, register::Single::B)]
#[test_case(0x61, register::Single::H, register::Single::C)]
#[test_case(0x62, register::Single::H, register::Single::D)]
#[test_case(0x63, register::Single::H, register::Single::E)]
#[test_case(0x64, register::Single::H, register::Single::H)]
#[test_case(0x65, register::Single::H, register::Single::L)]
#[test_case(0x68, register::Single::L, register::Single::B)]
#[test_case(0x69, register::Single::L, register::Single::C)]
#[test_case(0x6A, register::Single::L, register::Single::D)]
#[test_case(0x6B, register::Single::L, register::Single::E)]
#[test_case(0x6C, register::Single::L, register::Single::H)]
#[test_case(0x6D, register::Single::L, register::Single::L)]
#[test_case(0x47, register::Single::B, register::Single::A)]
#[test_case(0x4F, register::Single::C, register::Single::A)]
#[test_case(0x57, register::Single::D, register::Single::A)]
#[test_case(0x5F, register::Single::E, register::Single::A)]
#[test_case(0x67, register::Single::H, register::Single::A)]
#[test_case(0x6F, register::Single::L, register::Single::A)]
#[test_case(0x7F, register::SingleEightBit::A, register::SingleEightBit::A)]
#[test_case(0x78, register::SingleEightBit::A, register::SingleEightBit::B)]
#[test_case(0x79, register::SingleEightBit::A, register::SingleEightBit::C)]
#[test_case(0x7A, register::SingleEightBit::A, register::SingleEightBit::D)]
#[test_case(0x7B, register::SingleEightBit::A, register::SingleEightBit::E)]
#[test_case(0x7C, register::SingleEightBit::A, register::SingleEightBit::H)]
#[test_case(0x7D, register::SingleEightBit::A, register::SingleEightBit::L)]
#[test_case(0x40, register::SingleEightBit::B, register::SingleEightBit::B)]
#[test_case(0x41, register::SingleEightBit::B, register::SingleEightBit::C)]
#[test_case(0x42, register::SingleEightBit::B, register::SingleEightBit::D)]
#[test_case(0x43, register::SingleEightBit::B, register::SingleEightBit::E)]
#[test_case(0x44, register::SingleEightBit::B, register::SingleEightBit::H)]
#[test_case(0x45, register::SingleEightBit::B, register::SingleEightBit::L)]
#[test_case(0x48, register::SingleEightBit::C, register::SingleEightBit::B)]
#[test_case(0x49, register::SingleEightBit::C, register::SingleEightBit::C)]
#[test_case(0x4A, register::SingleEightBit::C, register::SingleEightBit::D)]
#[test_case(0x4B, register::SingleEightBit::C, register::SingleEightBit::E)]
#[test_case(0x4C, register::SingleEightBit::C, register::SingleEightBit::H)]
#[test_case(0x4D, register::SingleEightBit::C, register::SingleEightBit::L)]
#[test_case(0x50, register::SingleEightBit::D, register::SingleEightBit::B)]
#[test_case(0x51, register::SingleEightBit::D, register::SingleEightBit::C)]
#[test_case(0x52, register::SingleEightBit::D, register::SingleEightBit::D)]
#[test_case(0x53, register::SingleEightBit::D, register::SingleEightBit::E)]
#[test_case(0x54, register::SingleEightBit::D, register::SingleEightBit::H)]
#[test_case(0x55, register::SingleEightBit::D, register::SingleEightBit::L)]
#[test_case(0x58, register::SingleEightBit::E, register::SingleEightBit::B)]
#[test_case(0x59, register::SingleEightBit::E, register::SingleEightBit::C)]
#[test_case(0x5A, register::SingleEightBit::E, register::SingleEightBit::D)]
#[test_case(0x5B, register::SingleEightBit::E, register::SingleEightBit::E)]
#[test_case(0x5C, register::SingleEightBit::E, register::SingleEightBit::H)]
#[test_case(0x5D, register::SingleEightBit::E, register::SingleEightBit::L)]
#[test_case(0x60, register::SingleEightBit::H, register::SingleEightBit::B)]
#[test_case(0x61, register::SingleEightBit::H, register::SingleEightBit::C)]
#[test_case(0x62, register::SingleEightBit::H, register::SingleEightBit::D)]
#[test_case(0x63, register::SingleEightBit::H, register::SingleEightBit::E)]
#[test_case(0x64, register::SingleEightBit::H, register::SingleEightBit::H)]
#[test_case(0x65, register::SingleEightBit::H, register::SingleEightBit::L)]
#[test_case(0x68, register::SingleEightBit::L, register::SingleEightBit::B)]
#[test_case(0x69, register::SingleEightBit::L, register::SingleEightBit::C)]
#[test_case(0x6A, register::SingleEightBit::L, register::SingleEightBit::D)]
#[test_case(0x6B, register::SingleEightBit::L, register::SingleEightBit::E)]
#[test_case(0x6C, register::SingleEightBit::L, register::SingleEightBit::H)]
#[test_case(0x6D, register::SingleEightBit::L, register::SingleEightBit::L)]
#[test_case(0x47, register::SingleEightBit::B, register::SingleEightBit::A)]
#[test_case(0x4F, register::SingleEightBit::C, register::SingleEightBit::A)]
#[test_case(0x57, register::SingleEightBit::D, register::SingleEightBit::A)]
#[test_case(0x5F, register::SingleEightBit::E, register::SingleEightBit::A)]
#[test_case(0x67, register::SingleEightBit::H, register::SingleEightBit::A)]
#[test_case(0x6F, register::SingleEightBit::L, register::SingleEightBit::A)]
fn test_load_register(
ld_opcode: u8,
dst_register: register::Single,
src_register: register::Single,
dst_register: register::SingleEightBit,
src_register: register::SingleEightBit,
) {
let mut processor = Processor::default();
processor.registers.set_single_register(src_register, 0x45);
processor
.registers
.set_single_8bit_register(src_register, 0x45);
let data = [ld_opcode, 0x00];
let (ins, extra_data) =
@ -303,22 +307,25 @@ mod tests {
assert_eq!(extra_data, &[0x00]);
processor.run(&ins);
assert_eq!(0x45, processor.registers.get_single_register(dst_register));
assert_eq!(
0x45,
processor.registers.get_single_8bit_register(dst_register)
);
}
#[test_case(0x7E, register::Combined::HL, register::Single::A)]
#[test_case(0x46, register::Combined::HL, register::Single::B)]
#[test_case(0x4E, register::Combined::HL, register::Single::C)]
#[test_case(0x56, register::Combined::HL, register::Single::D)]
#[test_case(0x5E, register::Combined::HL, register::Single::E)]
#[test_case(0x66, register::Combined::HL, register::Single::H)]
#[test_case(0x6E, register::Combined::HL, register::Single::L)]
#[test_case(0x0A, register::Combined::BC, register::Single::A)]
#[test_case(0x1A, register::Combined::DE, register::Single::A)]
#[test_case(0x7E, register::Combined::HL, register::SingleEightBit::A)]
#[test_case(0x46, register::Combined::HL, register::SingleEightBit::B)]
#[test_case(0x4E, register::Combined::HL, register::SingleEightBit::C)]
#[test_case(0x56, register::Combined::HL, register::SingleEightBit::D)]
#[test_case(0x5E, register::Combined::HL, register::SingleEightBit::E)]
#[test_case(0x66, register::Combined::HL, register::SingleEightBit::H)]
#[test_case(0x6E, register::Combined::HL, register::SingleEightBit::L)]
#[test_case(0x0A, register::Combined::BC, register::SingleEightBit::A)]
#[test_case(0x1A, register::Combined::DE, register::SingleEightBit::A)]
fn test_load_from_memory(
opcode: u8,
expected_deref_register: register::Combined,
expected_register: register::Single,
expected_register: register::SingleEightBit,
) {
let mut processor = Processor::default();
let set_val = processor.memory.set(0xCCDD, 105);
@ -337,23 +344,25 @@ mod tests {
processor.run(&ins);
assert_eq!(
105,
processor.registers.get_single_register(expected_register)
processor
.registers
.get_single_8bit_register(expected_register)
);
}
#[test_case(0x70, register::Combined::HL, register::Single::B)]
#[test_case(0x71, register::Combined::HL, register::Single::C)]
#[test_case(0x72, register::Combined::HL, register::Single::D)]
#[test_case(0x73, register::Combined::HL, register::Single::E)]
#[test_case(0x74, register::Combined::HL, register::Single::H)]
#[test_case(0x75, register::Combined::HL, register::Single::L)]
#[test_case(0x02, register::Combined::BC, register::Single::A)]
#[test_case(0x12, register::Combined::DE, register::Single::A)]
#[test_case(0x77, register::Combined::HL, register::Single::A)]
#[test_case(0x70, register::Combined::HL, register::SingleEightBit::B)]
#[test_case(0x71, register::Combined::HL, register::SingleEightBit::C)]
#[test_case(0x72, register::Combined::HL, register::SingleEightBit::D)]
#[test_case(0x73, register::Combined::HL, register::SingleEightBit::E)]
#[test_case(0x74, register::Combined::HL, register::SingleEightBit::H)]
#[test_case(0x75, register::Combined::HL, register::SingleEightBit::L)]
#[test_case(0x02, register::Combined::BC, register::SingleEightBit::A)]
#[test_case(0x12, register::Combined::DE, register::SingleEightBit::A)]
#[test_case(0x77, register::Combined::HL, register::SingleEightBit::A)]
fn test_load_to_memory(
opcode: u8,
expected_deref_register: register::Combined,
expected_register: register::Single,
expected_register: register::SingleEightBit,
) {
let mut processor = Processor::default();
// This test does a bit of a sneaky - because we want to use CC as the high/low addresses
@ -361,7 +370,7 @@ mod tests {
// be careful that the stored immediate value is also part of the address in these cases.
processor
.registers
.set_single_register(expected_register, 0xCC);
.set_single_8bit_register(expected_register, 0xCC);
processor
.registers

View File

@ -7,58 +7,58 @@ pub enum Instruction {
// 3.3.1.1
LD8BitImmediateToRegister {
value: u8,
register: register::Single,
register: register::SingleEightBit,
},
// 3.3.1.2, excluding the (hl) instructions, 3.3.1.3, excluding the (nn) instructions
// and 3.3.1.4 excluding the (nn) instructions
LDr1r2 {
dst: register::Single,
src: register::Single,
dst: register::SingleEightBit,
src: register::SingleEightBit,
},
// 3.3.1.2/3.3.1.3, only the loading from (nn) instructions
LDFromRegisterAddress {
// src, unlike some of the other instructions, is a 16bit combined register that will be
// dereferenced to get the value to place into the dst register
src: register::Combined,
dst: register::Single,
dst: register::SingleEightBit,
},
// 3.3.1.5 - load to register relative to $FF00 (the address of the i/o registers)
LDFromMemoryRelativeToIORegisterStart {
// A register whose value will be used to get the address relative to FF00
offset_register: register::Single,
dst: register::Single,
offset_register: register::SingleEightBit,
dst: register::SingleEightBit,
},
// 3.3.1.6 - load to memory relative to $FF00 (the address of the i/o registers)
LDToMemoryRelativeToIORegisterStart {
src: register::Single,
src: register::SingleEightBit,
// A register whose value will be used to get the address relative to FF00
offset_register: register::Single,
offset_register: register::SingleEightBit,
},
// 3.3.1.20
LDFromMemoryRelativeToIORegisterStartByImmediate {
dst: register::Single,
dst: register::SingleEightBit,
offset: u8,
},
// 3.3.1.19
LDToMemoryRelativeToIORegisterStartByImmediate {
offset: u8,
src: register::Single,
src: register::SingleEightBit,
},
LDFromImmediateAddress {
src_address: u16,
dst: register::Single,
dst: register::SingleEightBit,
},
// 3.3.1.2, only the loading to (hl) instructions
// 3.3.1.4, only the loading to (nn) instructions
LDToRegisterAddress {
src: register::Single,
src: register::SingleEightBit,
// dst, unlike some other instructions, is a 16bit combined register that holds
// the address we will write the value to
dst: register::Combined,
},
// 3.3.1.4, only the loading to (nn) immediate instrution
LDToImmediateAddress {
src: register::Single,
src: register::SingleEightBit,
dst_address: u16,
},
// 3.3.1.2, but the (hl), n instruction [why is this in this section? it's so out of place]
@ -67,14 +67,14 @@ pub enum Instruction {
},
// 3.3.1.{10,11,12}
LDToRegisterAddressThenDec {
src: register::Single,
src: register::SingleEightBit,
// The destination, unlike some other destination instructions, refers to a register
// whose address will be dereferenced (and then decremented after the load)
dst: register::Combined,
},
// 3.3.1.{13,14,15}
LDToRegisterAddressThenInc {
src: register::Single,
src: register::SingleEightBit,
// The destination, unlike some other destination instructions, refers to a register
// whose address will be dereferenced (and then incremented after the load)
dst: register::Combined,

View File

@ -10,25 +10,25 @@ use crate::run::{
pub struct Immediate8BitLoadParser;
impl OpcodeParser for Immediate8BitLoadParser {
/// Parses an opcode that will transfer an immediate 8 bit value into a single register.
/// Parses an opcode that will transfer an immediate 8 bit value into a single 8 bit register.
fn parse_opcode(data: &[u8]) -> ParseResult {
let opcode = parse::get_opcode_from_data(data)?;
match opcode {
0x3E => make_load_immediate_data(register::Single::A, data),
0x06 => make_load_immediate_data(register::Single::B, data),
0x0E => make_load_immediate_data(register::Single::C, data),
0x16 => make_load_immediate_data(register::Single::D, data),
0x1E => make_load_immediate_data(register::Single::E, data),
0x26 => make_load_immediate_data(register::Single::H, data),
0x2E => make_load_immediate_data(register::Single::L, data),
0x3E => make_load_immediate_data(register::SingleEightBit::A, data),
0x06 => make_load_immediate_data(register::SingleEightBit::B, data),
0x0E => make_load_immediate_data(register::SingleEightBit::C, data),
0x16 => make_load_immediate_data(register::SingleEightBit::D, data),
0x1E => make_load_immediate_data(register::SingleEightBit::E, data),
0x26 => make_load_immediate_data(register::SingleEightBit::H, data),
0x2E => make_load_immediate_data(register::SingleEightBit::L, data),
_ => Err(Error::UnknownOpcode(opcode)),
}
}
}
fn make_load_immediate_data(register: register::Single, data: &[u8]) -> ParseResult {
fn make_load_immediate_data(register: register::SingleEightBit, data: &[u8]) -> ParseResult {
let opcode = parse::get_opcode_from_data(data)?;
let value = data.get(1).ok_or(Error::NotEnoughArgs(opcode))?;

View File

@ -6,7 +6,7 @@ use crate::run::parse::{self, Error, OpcodeParser, ParseResult};
pub struct Memory8BitLoadParser;
impl OpcodeParser for Memory8BitLoadParser {
// Parses a single instruction to load an 8 bit value to/from memory
// Parses a single 8 bit instruction to load an 8 bit value to/from memory
fn parse_opcode(data: &[u8]) -> ParseResult {
let parse_funcs = &[
parse_load_from_register_to_address,
@ -32,15 +32,33 @@ impl OpcodeParser for Memory8BitLoadParser {
fn parse_load_from_register_to_address(data: &[u8]) -> ParseResult {
let opcode = parse::get_opcode_from_data(data)?;
match opcode {
0x02 => make_ld_to_register_address(register::Combined::BC, register::Single::A, data),
0x12 => make_ld_to_register_address(register::Combined::DE, register::Single::A, data),
0x70 => make_ld_to_register_address(register::Combined::HL, register::Single::B, data),
0x71 => make_ld_to_register_address(register::Combined::HL, register::Single::C, data),
0x72 => make_ld_to_register_address(register::Combined::HL, register::Single::D, data),
0x73 => make_ld_to_register_address(register::Combined::HL, register::Single::E, data),
0x74 => make_ld_to_register_address(register::Combined::HL, register::Single::H, data),
0x75 => make_ld_to_register_address(register::Combined::HL, register::Single::L, data),
0x77 => make_ld_to_register_address(register::Combined::HL, register::Single::A, data),
0x02 => {
make_ld_to_register_address(register::Combined::BC, register::SingleEightBit::A, data)
}
0x12 => {
make_ld_to_register_address(register::Combined::DE, register::SingleEightBit::A, data)
}
0x70 => {
make_ld_to_register_address(register::Combined::HL, register::SingleEightBit::B, data)
}
0x71 => {
make_ld_to_register_address(register::Combined::HL, register::SingleEightBit::C, data)
}
0x72 => {
make_ld_to_register_address(register::Combined::HL, register::SingleEightBit::D, data)
}
0x73 => {
make_ld_to_register_address(register::Combined::HL, register::SingleEightBit::E, data)
}
0x74 => {
make_ld_to_register_address(register::Combined::HL, register::SingleEightBit::H, data)
}
0x75 => {
make_ld_to_register_address(register::Combined::HL, register::SingleEightBit::L, data)
}
0x77 => {
make_ld_to_register_address(register::Combined::HL, register::SingleEightBit::A, data)
}
_ => Err(Error::UnknownOpcode(opcode)),
}
}
@ -48,33 +66,52 @@ fn parse_load_from_register_to_address(data: &[u8]) -> ParseResult {
fn parse_load_from_address_to_register(data: &[u8]) -> ParseResult {
let opcode = parse::get_opcode_from_data(data)?;
match opcode {
0x0A => make_ld_from_register_address(register::Single::A, register::Combined::BC, data),
0x1A => make_ld_from_register_address(register::Single::A, register::Combined::DE, data),
0x46 => make_ld_from_register_address(register::Single::B, register::Combined::HL, data),
0x4E => make_ld_from_register_address(register::Single::C, register::Combined::HL, data),
0x56 => make_ld_from_register_address(register::Single::D, register::Combined::HL, data),
0x5E => make_ld_from_register_address(register::Single::E, register::Combined::HL, data),
0x66 => make_ld_from_register_address(register::Single::H, register::Combined::HL, data),
0x6E => make_ld_from_register_address(register::Single::L, register::Combined::HL, data),
0x7E => make_ld_from_register_address(register::Single::A, register::Combined::HL, data),
0x0A => {
make_ld_from_register_address(register::SingleEightBit::A, register::Combined::BC, data)
}
0x1A => {
make_ld_from_register_address(register::SingleEightBit::A, register::Combined::DE, data)
}
0x46 => {
make_ld_from_register_address(register::SingleEightBit::B, register::Combined::HL, data)
}
0x4E => {
make_ld_from_register_address(register::SingleEightBit::C, register::Combined::HL, data)
}
0x56 => {
make_ld_from_register_address(register::SingleEightBit::D, register::Combined::HL, data)
}
0x5E => {
make_ld_from_register_address(register::SingleEightBit::E, register::Combined::HL, data)
}
0x66 => {
make_ld_from_register_address(register::SingleEightBit::H, register::Combined::HL, data)
}
0x6E => {
make_ld_from_register_address(register::SingleEightBit::L, register::Combined::HL, data)
}
0x7E => {
make_ld_from_register_address(register::SingleEightBit::A, register::Combined::HL, data)
}
0xF2 => make_ld_from_memory_relative_to_io_register_start(
register::Single::C,
register::Single::A,
register::SingleEightBit::C,
register::SingleEightBit::A,
data,
),
0xE2 => make_ld_to_memory_relative_to_io_register_start(
register::Single::C,
register::Single::A,
register::SingleEightBit::C,
register::SingleEightBit::A,
data,
),
0xF0 => make_ld_from_memory_relative_to_io_register_start_by_immediate(
register::Single::A,
register::SingleEightBit::A,
data,
),
0xE0 => make_ld_to_memory_relative_to_io_register_start_by_immediate(
register::SingleEightBit::A,
data,
),
0xE0 => {
make_ld_to_memory_relative_to_io_register_start_by_immediate(register::Single::A, data)
}
_ => Err(Error::UnknownOpcode(opcode)),
}
@ -84,8 +121,8 @@ fn parse_load_immediate_instructions(data: &[u8]) -> ParseResult {
let opcode = parse::get_opcode_from_data(data)?;
match opcode {
0x36 => make_ld_n_to_hl_address(data),
0xFA => make_ld_from_immediate_address(register::Single::A, data),
0xEA => make_ld_to_immediate_address(register::Single::A, data),
0xFA => make_ld_from_immediate_address(register::SingleEightBit::A, data),
0xEA => make_ld_to_immediate_address(register::SingleEightBit::A, data),
_ => Err(Error::UnknownOpcode(opcode)),
}
}
@ -95,13 +132,13 @@ fn parse_load_from_register_to_address_then_do_arithmetic(data: &[u8]) -> ParseR
match opcode {
0x32 => make_ld_to_address_then_do_arithmetic(
register::Combined::HL,
register::Single::A,
register::SingleEightBit::A,
|dst, src| Instruction::LDToRegisterAddressThenDec { dst, src },
data,
),
0x2A => make_ld_to_address_then_do_arithmetic(
register::Combined::HL,
register::Single::A,
register::SingleEightBit::A,
|dst, src| Instruction::LDToRegisterAddressThenInc { dst, src },
data,
),
@ -110,7 +147,7 @@ fn parse_load_from_register_to_address_then_do_arithmetic(data: &[u8]) -> ParseR
}
fn make_ld_from_register_address(
dst: register::Single,
dst: register::SingleEightBit,
src: register::Combined,
data: &[u8],
) -> ParseResult {
@ -129,7 +166,7 @@ fn make_ld_from_register_address(
fn make_ld_to_register_address(
dst: register::Combined,
src: register::Single,
src: register::SingleEightBit,
data: &[u8],
) -> ParseResult {
data.get(1..)
@ -145,7 +182,7 @@ fn make_ld_to_register_address(
.ok_or(Error::NoData)
}
fn make_ld_from_immediate_address(dst: register::Single, data: &[u8]) -> ParseResult {
fn make_ld_from_immediate_address(dst: register::SingleEightBit, data: &[u8]) -> ParseResult {
let opcode = parse::get_opcode_from_data(data)?;
let args = data.get(1..=2).ok_or(Error::NotEnoughArgs(opcode))?;
@ -161,7 +198,7 @@ fn make_ld_from_immediate_address(dst: register::Single, data: &[u8]) -> ParseRe
))
}
fn make_ld_to_immediate_address(src: register::Single, data: &[u8]) -> ParseResult {
fn make_ld_to_immediate_address(src: register::SingleEightBit, data: &[u8]) -> ParseResult {
let opcode = parse::get_opcode_from_data(data)?;
let args = data.get(1..=2).ok_or(Error::NotEnoughArgs(opcode))?;
@ -191,8 +228,8 @@ fn make_ld_n_to_hl_address(data: &[u8]) -> ParseResult {
}
fn make_ld_from_memory_relative_to_io_register_start(
offset_register: register::Single,
dst: register::Single,
offset_register: register::SingleEightBit,
dst: register::SingleEightBit,
data: &[u8],
) -> ParseResult {
data.get(1..)
@ -213,8 +250,8 @@ fn make_ld_from_memory_relative_to_io_register_start(
}
fn make_ld_to_memory_relative_to_io_register_start(
offset_register: register::Single,
src: register::Single,
offset_register: register::SingleEightBit,
src: register::SingleEightBit,
data: &[u8],
) -> ParseResult {
data.get(1..)
@ -235,7 +272,7 @@ fn make_ld_to_memory_relative_to_io_register_start(
}
fn make_ld_to_memory_relative_to_io_register_start_by_immediate(
src: register::Single,
src: register::SingleEightBit,
data: &[u8],
) -> ParseResult {
let opcode = parse::get_opcode_from_data(data)?;
@ -255,7 +292,7 @@ fn make_ld_to_memory_relative_to_io_register_start_by_immediate(
}
fn make_ld_from_memory_relative_to_io_register_start_by_immediate(
dst: register::Single,
dst: register::SingleEightBit,
data: &[u8],
) -> ParseResult {
let opcode = parse::get_opcode_from_data(data)?;
@ -275,10 +312,10 @@ fn make_ld_from_memory_relative_to_io_register_start_by_immediate(
}
fn make_ld_to_address_then_do_arithmetic<
F: Fn(register::Combined, register::Single) -> Instruction,
F: Fn(register::Combined, register::SingleEightBit) -> Instruction,
>(
dst: register::Combined,
src: register::Single,
src: register::SingleEightBit,
make: F,
data: &[u8],
) -> ParseResult {

View File

@ -8,72 +8,272 @@ use crate::run::{
pub struct Between8BitRegisterParser;
impl OpcodeParser for Between8BitRegisterParser {
/// Parses an opcode that transfers an 8bit values between single registers.
/// Parses an opcode that transfers an 8bit values between single 8 bit registers.
fn parse_opcode(data: &[u8]) -> ParseResult {
let opcode = parse::get_opcode_from_data(data)?;
match opcode {
0x7f => make_ldr1r2_data(register::Single::A, register::Single::A, data),
0x78 => make_ldr1r2_data(register::Single::A, register::Single::B, data),
0x79 => make_ldr1r2_data(register::Single::A, register::Single::C, data),
0x7A => make_ldr1r2_data(register::Single::A, register::Single::D, data),
0x7B => make_ldr1r2_data(register::Single::A, register::Single::E, data),
0x7C => make_ldr1r2_data(register::Single::A, register::Single::H, data),
0x7D => make_ldr1r2_data(register::Single::A, register::Single::L, data),
0x7f => make_ldr1r2_data(
register::SingleEightBit::A,
register::SingleEightBit::A,
data,
),
0x78 => make_ldr1r2_data(
register::SingleEightBit::A,
register::SingleEightBit::B,
data,
),
0x79 => make_ldr1r2_data(
register::SingleEightBit::A,
register::SingleEightBit::C,
data,
),
0x7A => make_ldr1r2_data(
register::SingleEightBit::A,
register::SingleEightBit::D,
data,
),
0x7B => make_ldr1r2_data(
register::SingleEightBit::A,
register::SingleEightBit::E,
data,
),
0x7C => make_ldr1r2_data(
register::SingleEightBit::A,
register::SingleEightBit::H,
data,
),
0x7D => make_ldr1r2_data(
register::SingleEightBit::A,
register::SingleEightBit::L,
data,
),
0x47 => make_ldr1r2_data(register::Single::B, register::Single::A, data),
0x40 => make_ldr1r2_data(register::Single::B, register::Single::B, data),
0x41 => make_ldr1r2_data(register::Single::B, register::Single::C, data),
0x42 => make_ldr1r2_data(register::Single::B, register::Single::D, data),
0x43 => make_ldr1r2_data(register::Single::B, register::Single::E, data),
0x44 => make_ldr1r2_data(register::Single::B, register::Single::H, data),
0x45 => make_ldr1r2_data(register::Single::B, register::Single::L, data),
0x47 => make_ldr1r2_data(
register::SingleEightBit::B,
register::SingleEightBit::A,
data,
),
0x40 => make_ldr1r2_data(
register::SingleEightBit::B,
register::SingleEightBit::B,
data,
),
0x41 => make_ldr1r2_data(
register::SingleEightBit::B,
register::SingleEightBit::C,
data,
),
0x42 => make_ldr1r2_data(
register::SingleEightBit::B,
register::SingleEightBit::D,
data,
),
0x43 => make_ldr1r2_data(
register::SingleEightBit::B,
register::SingleEightBit::E,
data,
),
0x44 => make_ldr1r2_data(
register::SingleEightBit::B,
register::SingleEightBit::H,
data,
),
0x45 => make_ldr1r2_data(
register::SingleEightBit::B,
register::SingleEightBit::L,
data,
),
0x4F => make_ldr1r2_data(register::Single::C, register::Single::A, data),
0x48 => make_ldr1r2_data(register::Single::C, register::Single::B, data),
0x49 => make_ldr1r2_data(register::Single::C, register::Single::C, data),
0x4A => make_ldr1r2_data(register::Single::C, register::Single::D, data),
0x4B => make_ldr1r2_data(register::Single::C, register::Single::E, data),
0x4C => make_ldr1r2_data(register::Single::C, register::Single::H, data),
0x4D => make_ldr1r2_data(register::Single::C, register::Single::L, data),
0x4F => make_ldr1r2_data(
register::SingleEightBit::C,
register::SingleEightBit::A,
data,
),
0x48 => make_ldr1r2_data(
register::SingleEightBit::C,
register::SingleEightBit::B,
data,
),
0x49 => make_ldr1r2_data(
register::SingleEightBit::C,
register::SingleEightBit::C,
data,
),
0x4A => make_ldr1r2_data(
register::SingleEightBit::C,
register::SingleEightBit::D,
data,
),
0x4B => make_ldr1r2_data(
register::SingleEightBit::C,
register::SingleEightBit::E,
data,
),
0x4C => make_ldr1r2_data(
register::SingleEightBit::C,
register::SingleEightBit::H,
data,
),
0x4D => make_ldr1r2_data(
register::SingleEightBit::C,
register::SingleEightBit::L,
data,
),
0x57 => make_ldr1r2_data(register::Single::D, register::Single::A, data),
0x50 => make_ldr1r2_data(register::Single::D, register::Single::B, data),
0x51 => make_ldr1r2_data(register::Single::D, register::Single::C, data),
0x52 => make_ldr1r2_data(register::Single::D, register::Single::D, data),
0x53 => make_ldr1r2_data(register::Single::D, register::Single::E, data),
0x54 => make_ldr1r2_data(register::Single::D, register::Single::H, data),
0x55 => make_ldr1r2_data(register::Single::D, register::Single::L, data),
0x57 => make_ldr1r2_data(
register::SingleEightBit::D,
register::SingleEightBit::A,
data,
),
0x50 => make_ldr1r2_data(
register::SingleEightBit::D,
register::SingleEightBit::B,
data,
),
0x51 => make_ldr1r2_data(
register::SingleEightBit::D,
register::SingleEightBit::C,
data,
),
0x52 => make_ldr1r2_data(
register::SingleEightBit::D,
register::SingleEightBit::D,
data,
),
0x53 => make_ldr1r2_data(
register::SingleEightBit::D,
register::SingleEightBit::E,
data,
),
0x54 => make_ldr1r2_data(
register::SingleEightBit::D,
register::SingleEightBit::H,
data,
),
0x55 => make_ldr1r2_data(
register::SingleEightBit::D,
register::SingleEightBit::L,
data,
),
0x5F => make_ldr1r2_data(register::Single::E, register::Single::A, data),
0x58 => make_ldr1r2_data(register::Single::E, register::Single::B, data),
0x59 => make_ldr1r2_data(register::Single::E, register::Single::C, data),
0x5A => make_ldr1r2_data(register::Single::E, register::Single::D, data),
0x5B => make_ldr1r2_data(register::Single::E, register::Single::E, data),
0x5C => make_ldr1r2_data(register::Single::E, register::Single::H, data),
0x5D => make_ldr1r2_data(register::Single::E, register::Single::L, data),
0x5F => make_ldr1r2_data(
register::SingleEightBit::E,
register::SingleEightBit::A,
data,
),
0x58 => make_ldr1r2_data(
register::SingleEightBit::E,
register::SingleEightBit::B,
data,
),
0x59 => make_ldr1r2_data(
register::SingleEightBit::E,
register::SingleEightBit::C,
data,
),
0x5A => make_ldr1r2_data(
register::SingleEightBit::E,
register::SingleEightBit::D,
data,
),
0x5B => make_ldr1r2_data(
register::SingleEightBit::E,
register::SingleEightBit::E,
data,
),
0x5C => make_ldr1r2_data(
register::SingleEightBit::E,
register::SingleEightBit::H,
data,
),
0x5D => make_ldr1r2_data(
register::SingleEightBit::E,
register::SingleEightBit::L,
data,
),
0x67 => make_ldr1r2_data(register::Single::H, register::Single::A, data),
0x60 => make_ldr1r2_data(register::Single::H, register::Single::B, data),
0x61 => make_ldr1r2_data(register::Single::H, register::Single::C, data),
0x62 => make_ldr1r2_data(register::Single::H, register::Single::D, data),
0x63 => make_ldr1r2_data(register::Single::H, register::Single::E, data),
0x64 => make_ldr1r2_data(register::Single::H, register::Single::H, data),
0x65 => make_ldr1r2_data(register::Single::H, register::Single::L, data),
0x67 => make_ldr1r2_data(
register::SingleEightBit::H,
register::SingleEightBit::A,
data,
),
0x60 => make_ldr1r2_data(
register::SingleEightBit::H,
register::SingleEightBit::B,
data,
),
0x61 => make_ldr1r2_data(
register::SingleEightBit::H,
register::SingleEightBit::C,
data,
),
0x62 => make_ldr1r2_data(
register::SingleEightBit::H,
register::SingleEightBit::D,
data,
),
0x63 => make_ldr1r2_data(
register::SingleEightBit::H,
register::SingleEightBit::E,
data,
),
0x64 => make_ldr1r2_data(
register::SingleEightBit::H,
register::SingleEightBit::H,
data,
),
0x65 => make_ldr1r2_data(
register::SingleEightBit::H,
register::SingleEightBit::L,
data,
),
0x6F => make_ldr1r2_data(register::Single::L, register::Single::A, data),
0x68 => make_ldr1r2_data(register::Single::L, register::Single::B, data),
0x69 => make_ldr1r2_data(register::Single::L, register::Single::C, data),
0x6A => make_ldr1r2_data(register::Single::L, register::Single::D, data),
0x6B => make_ldr1r2_data(register::Single::L, register::Single::E, data),
0x6c => make_ldr1r2_data(register::Single::L, register::Single::H, data),
0x6D => make_ldr1r2_data(register::Single::L, register::Single::L, data),
0x6F => make_ldr1r2_data(
register::SingleEightBit::L,
register::SingleEightBit::A,
data,
),
0x68 => make_ldr1r2_data(
register::SingleEightBit::L,
register::SingleEightBit::B,
data,
),
0x69 => make_ldr1r2_data(
register::SingleEightBit::L,
register::SingleEightBit::C,
data,
),
0x6A => make_ldr1r2_data(
register::SingleEightBit::L,
register::SingleEightBit::D,
data,
),
0x6B => make_ldr1r2_data(
register::SingleEightBit::L,
register::SingleEightBit::E,
data,
),
0x6c => make_ldr1r2_data(
register::SingleEightBit::L,
register::SingleEightBit::H,
data,
),
0x6D => make_ldr1r2_data(
register::SingleEightBit::L,
register::SingleEightBit::L,
data,
),
_ => Err(Error::UnknownOpcode(opcode)),
}
}
}
fn make_ldr1r2_data(dst: register::Single, src: register::Single, data: &[u8]) -> ParseResult {
fn make_ldr1r2_data(
dst: register::SingleEightBit,
src: register::SingleEightBit,
data: &[u8],
) -> ParseResult {
data.get(1..)
.map(|remaining_data| {
(