From ec4f9395af2b1379ed7c47304271074df1dbb661 Mon Sep 17 00:00:00 2001 From: Nick Krichevsky Date: Sat, 18 Nov 2023 14:43:48 -0500 Subject: [PATCH] Greatly simplify arith8 parsing --- src/cpu/instructions/arith8.rs | 1 + src/cpu/parse.rs | 9 +- src/cpu/parse/arith8.rs | 223 ++++++++++++++++++++++++++++++-- src/cpu/parse/arith8/add.rs | 79 ----------- src/cpu/parse/arith8/and.rs | 40 ------ src/cpu/parse/arith8/compare.rs | 55 -------- src/cpu/parse/arith8/dec.rs | 37 ------ src/cpu/parse/arith8/inc.rs | 37 ------ src/cpu/parse/arith8/or.rs | 42 ------ src/cpu/parse/arith8/sub.rs | 77 ----------- src/cpu/parse/arith8/xor.rs | 40 ------ 11 files changed, 216 insertions(+), 424 deletions(-) delete mode 100644 src/cpu/parse/arith8/add.rs delete mode 100644 src/cpu/parse/arith8/and.rs delete mode 100644 src/cpu/parse/arith8/compare.rs delete mode 100644 src/cpu/parse/arith8/dec.rs delete mode 100644 src/cpu/parse/arith8/inc.rs delete mode 100644 src/cpu/parse/arith8/or.rs delete mode 100644 src/cpu/parse/arith8/sub.rs delete mode 100644 src/cpu/parse/arith8/xor.rs diff --git a/src/cpu/instructions/arith8.rs b/src/cpu/instructions/arith8.rs index a0ddb1e..ca0e245 100644 --- a/src/cpu/instructions/arith8.rs +++ b/src/cpu/instructions/arith8.rs @@ -2,6 +2,7 @@ use crate::register; #[derive(Debug, Copy, Clone)] +#[cfg_attr(test, derive(Eq, PartialEq))] pub enum Operation { Add, AddWithCarry, diff --git a/src/cpu/parse.rs b/src/cpu/parse.rs index a045bda..7367349 100644 --- a/src/cpu/parse.rs +++ b/src/cpu/parse.rs @@ -42,14 +42,7 @@ pub fn next_instruction(data: &View) -> ParseResult { load16::immediate::Parser::parse_opcode, load16::transfer::Parser::parse_opcode, load16::stack::Parser::parse_opcode, - arith8::add::Parser::parse_opcode, - arith8::sub::Parser::parse_opcode, - arith8::and::Parser::parse_opcode, - arith8::xor::Parser::parse_opcode, - arith8::or::Parser::parse_opcode, - arith8::compare::Parser::parse_opcode, - arith8::inc::Parser::parse_opcode, - arith8::dec::Parser::parse_opcode, + arith8::Parser::parse_opcode, arith16::Parser::parse_opcode, ]; diff --git a/src/cpu/parse/arith8.rs b/src/cpu/parse/arith8.rs index 59628b0..304c118 100644 --- a/src/cpu/parse/arith8.rs +++ b/src/cpu/parse/arith8.rs @@ -7,16 +7,111 @@ use crate::{ register, }; -use super::ParseOutput; +use super::{ParseOutput, OpcodeParser}; -pub mod add; -pub mod and; -pub mod compare; -pub mod dec; -pub mod inc; -pub mod or; -pub mod sub; -pub mod xor; +// similar to `arith8::Operand`, but only for the parts that can be uniquely determined from the opcode +#[derive(Debug, Copy, Clone)] +#[cfg_attr(test, derive(Eq, PartialEq))] +enum OpcodeOperand { + SingleRegister(register::SingleEightBit), + HLAddressValue, + Immediate, +} + +pub struct Parser; + +impl OpcodeParser for Parser { + fn parse_opcode(data: &View) -> super::ParseResult { + let opcode = super::get_opcode_from_data(data); + let operation = operation_for_opcode(opcode)?; + let operand = operand_for_opcode(opcode)?; + + match operand { + OpcodeOperand::SingleRegister(register) => Ok(build_instruction_between_register_and_a_data(operation, register)), + OpcodeOperand::HLAddressValue => Ok(build_instruction_between_hl_value_and_a_data(operation)), + OpcodeOperand::Immediate => Ok(build_instruction_between_immediate_and_a_data(operation, data)), + } + } +} + +fn operation_for_opcode(opcode: u8) -> Result { + operation_for_binary_opcode(opcode) + .or_else(|_err| operation_for_unary_opcode(opcode)) +} + +fn operand_for_opcode(opcode: u8) -> Result { + operand_for_binary_opcode(opcode) + .or_else(|_err| operand_for_unary_opcode(opcode)) +} + + +fn operation_for_unary_opcode(opcode: u8) -> Result { + let operation_nibble = opcode & 0xF0; + let operand_nibble = opcode & 0x0F; + + match operation_nibble { + 0x00..=0x30 if operand_nibble == 0x04 || operand_nibble == 0x0C => Ok(Operation::Inc), + 0x00..=0x30 if operand_nibble == 0x05 || operand_nibble == 0x0D => Ok(Operation::Dec), + _ => Err(super::Error::UnknownOpcode(opcode)) + } +} + +fn operation_for_binary_opcode(opcode: u8) -> Result { + match opcode { + 0x80..=0x87 | 0xC6 => Ok(Operation::Add), + 0x88..=0x8F | 0xCE => Ok(Operation::AddWithCarry), + 0x90..=0x97 | 0xD6 => Ok(Operation::Sub), + 0x98..=0x9F | 0xDE => Ok(Operation::SubWithCarry), + 0xA0..=0xA7 | 0xE6 => Ok(Operation::And), + 0xA8..=0xAF | 0xEE => Ok(Operation::Xor), + 0xB0..=0xB7 | 0xF6 => Ok(Operation::Or), + 0xB8..=0xBF | 0xFE => Ok(Operation::Compare), + _ => Err(super::Error::UnknownOpcode(opcode)) + } +} + +fn operand_for_unary_opcode(opcode: u8) -> Result { + match opcode { + 0x04 | 0x05 => Ok(OpcodeOperand::SingleRegister(register::SingleEightBit::B)), + 0x0C | 0x0D => Ok(OpcodeOperand::SingleRegister(register::SingleEightBit::C)), + 0x14 | 0x15 => Ok(OpcodeOperand::SingleRegister(register::SingleEightBit::D)), + 0x1C | 0x1D => Ok(OpcodeOperand::SingleRegister(register::SingleEightBit::E)), + 0x24 | 0x25 => Ok(OpcodeOperand::SingleRegister(register::SingleEightBit::H)), + 0x2C | 0x2D => Ok(OpcodeOperand::SingleRegister(register::SingleEightBit::L)), + 0x34 | 0x35 => Ok(OpcodeOperand::HLAddressValue), + 0x3C | 0x3D => Ok(OpcodeOperand::SingleRegister(register::SingleEightBit::A)), + _ => Err(super::Error::UnknownOpcode(opcode)) + } +} + +fn operand_for_binary_opcode(opcode: u8) -> Result { + if is_immediate_operation(opcode) { + return Ok(OpcodeOperand::Immediate) + } else if !matches!(opcode & 0xF0, 0x80..=0xB0){ + // If it's not an immediate operation (covered above), or a standard arith operation (covered below), + // we shouldn't try and parse it + return Err(super::Error::UnknownOpcode(opcode)) + } + + match opcode & 0x07 { + 0x00 => Ok(OpcodeOperand::SingleRegister(register::SingleEightBit::B)), + 0x01 => Ok(OpcodeOperand::SingleRegister(register::SingleEightBit::C)), + 0x02 => Ok(OpcodeOperand::SingleRegister(register::SingleEightBit::D)), + 0x03 => Ok(OpcodeOperand::SingleRegister(register::SingleEightBit::E)), + 0x04 => Ok(OpcodeOperand::SingleRegister(register::SingleEightBit::H)), + 0x05 => Ok(OpcodeOperand::SingleRegister(register::SingleEightBit::L)), + 0x06 => Ok(OpcodeOperand::HLAddressValue), + 0x07 => Ok(OpcodeOperand::SingleRegister(register::SingleEightBit::A)), + _ => Err(super::Error::UnknownOpcode(opcode)) + } +} + +fn is_immediate_operation(opcode: u8) -> bool { + let operation_nibble = opcode & 0xF0; + let operand_nibble = opcode & 0x0F; + + (operand_nibble == 0x06 || operand_nibble == 0x0E) && matches!(operation_nibble, 0xC0..=0xF0) +} fn build_instruction_between_register_and_a_data( operation: Operation, @@ -70,3 +165,113 @@ fn build_instruction_between_immediate_and_a_data( 2, ) } + +#[cfg(test)] +mod tests { + use super::*; + use test_case::test_case; + + #[test_case(0x80, (Operation::Add, OpcodeOperand::SingleRegister(register::SingleEightBit::B)))] + #[test_case(0x81, (Operation::Add, OpcodeOperand::SingleRegister(register::SingleEightBit::C)))] + #[test_case(0x82, (Operation::Add, OpcodeOperand::SingleRegister(register::SingleEightBit::D)))] + #[test_case(0x83, (Operation::Add, OpcodeOperand::SingleRegister(register::SingleEightBit::E)))] + #[test_case(0x84, (Operation::Add, OpcodeOperand::SingleRegister(register::SingleEightBit::H)))] + #[test_case(0x85, (Operation::Add, OpcodeOperand::SingleRegister(register::SingleEightBit::L)))] + #[test_case(0x86, (Operation::Add, OpcodeOperand::HLAddressValue))] + #[test_case(0x87, (Operation::Add, OpcodeOperand::SingleRegister(register::SingleEightBit::A)))] + #[test_case(0xC6, (Operation::Add, OpcodeOperand::Immediate))] + + #[test_case(0x88, (Operation::AddWithCarry, OpcodeOperand::SingleRegister(register::SingleEightBit::B)))] + #[test_case(0x89, (Operation::AddWithCarry, OpcodeOperand::SingleRegister(register::SingleEightBit::C)))] + #[test_case(0x8A, (Operation::AddWithCarry, OpcodeOperand::SingleRegister(register::SingleEightBit::D)))] + #[test_case(0x8B, (Operation::AddWithCarry, OpcodeOperand::SingleRegister(register::SingleEightBit::E)))] + #[test_case(0x8C, (Operation::AddWithCarry, OpcodeOperand::SingleRegister(register::SingleEightBit::H)))] + #[test_case(0x8D, (Operation::AddWithCarry, OpcodeOperand::SingleRegister(register::SingleEightBit::L)))] + #[test_case(0x8E, (Operation::AddWithCarry, OpcodeOperand::HLAddressValue))] + #[test_case(0x8F, (Operation::AddWithCarry, OpcodeOperand::SingleRegister(register::SingleEightBit::A)))] + #[test_case(0xCE, (Operation::AddWithCarry, OpcodeOperand::Immediate))] + + #[test_case(0x90, (Operation::Sub, OpcodeOperand::SingleRegister(register::SingleEightBit::B)))] + #[test_case(0x91, (Operation::Sub, OpcodeOperand::SingleRegister(register::SingleEightBit::C)))] + #[test_case(0x92, (Operation::Sub, OpcodeOperand::SingleRegister(register::SingleEightBit::D)))] + #[test_case(0x93, (Operation::Sub, OpcodeOperand::SingleRegister(register::SingleEightBit::E)))] + #[test_case(0x94, (Operation::Sub, OpcodeOperand::SingleRegister(register::SingleEightBit::H)))] + #[test_case(0x95, (Operation::Sub, OpcodeOperand::SingleRegister(register::SingleEightBit::L)))] + #[test_case(0x96, (Operation::Sub, OpcodeOperand::HLAddressValue))] + #[test_case(0x97, (Operation::Sub, OpcodeOperand::SingleRegister(register::SingleEightBit::A)))] + #[test_case(0xD6, (Operation::Sub, OpcodeOperand::Immediate))] + + #[test_case(0x98, (Operation::SubWithCarry, OpcodeOperand::SingleRegister(register::SingleEightBit::B)))] + #[test_case(0x99, (Operation::SubWithCarry, OpcodeOperand::SingleRegister(register::SingleEightBit::C)))] + #[test_case(0x9A, (Operation::SubWithCarry, OpcodeOperand::SingleRegister(register::SingleEightBit::D)))] + #[test_case(0x9B, (Operation::SubWithCarry, OpcodeOperand::SingleRegister(register::SingleEightBit::E)))] + #[test_case(0x9C, (Operation::SubWithCarry, OpcodeOperand::SingleRegister(register::SingleEightBit::H)))] + #[test_case(0x9D, (Operation::SubWithCarry, OpcodeOperand::SingleRegister(register::SingleEightBit::L)))] + #[test_case(0x9E, (Operation::SubWithCarry, OpcodeOperand::HLAddressValue))] + #[test_case(0x9F, (Operation::SubWithCarry, OpcodeOperand::SingleRegister(register::SingleEightBit::A)))] + #[test_case(0xDE, (Operation::SubWithCarry, OpcodeOperand::Immediate))] + + #[test_case(0xA0, (Operation::And, OpcodeOperand::SingleRegister(register::SingleEightBit::B)))] + #[test_case(0xA1, (Operation::And, OpcodeOperand::SingleRegister(register::SingleEightBit::C)))] + #[test_case(0xA2, (Operation::And, OpcodeOperand::SingleRegister(register::SingleEightBit::D)))] + #[test_case(0xA3, (Operation::And, OpcodeOperand::SingleRegister(register::SingleEightBit::E)))] + #[test_case(0xA4, (Operation::And, OpcodeOperand::SingleRegister(register::SingleEightBit::H)))] + #[test_case(0xA5, (Operation::And, OpcodeOperand::SingleRegister(register::SingleEightBit::L)))] + #[test_case(0xA6, (Operation::And, OpcodeOperand::HLAddressValue))] + #[test_case(0xA7, (Operation::And, OpcodeOperand::SingleRegister(register::SingleEightBit::A)))] + #[test_case(0xE6, (Operation::And, OpcodeOperand::Immediate))] + + #[test_case(0xA8, (Operation::Xor, OpcodeOperand::SingleRegister(register::SingleEightBit::B)))] + #[test_case(0xA9, (Operation::Xor, OpcodeOperand::SingleRegister(register::SingleEightBit::C)))] + #[test_case(0xAA, (Operation::Xor, OpcodeOperand::SingleRegister(register::SingleEightBit::D)))] + #[test_case(0xAB, (Operation::Xor, OpcodeOperand::SingleRegister(register::SingleEightBit::E)))] + #[test_case(0xAC, (Operation::Xor, OpcodeOperand::SingleRegister(register::SingleEightBit::H)))] + #[test_case(0xAD, (Operation::Xor, OpcodeOperand::SingleRegister(register::SingleEightBit::L)))] + #[test_case(0xAE, (Operation::Xor, OpcodeOperand::HLAddressValue))] + #[test_case(0xAF, (Operation::Xor, OpcodeOperand::SingleRegister(register::SingleEightBit::A)))] + #[test_case(0xEE, (Operation::Xor, OpcodeOperand::Immediate))] + + #[test_case(0xB0, (Operation::Or, OpcodeOperand::SingleRegister(register::SingleEightBit::B)))] + #[test_case(0xB1, (Operation::Or, OpcodeOperand::SingleRegister(register::SingleEightBit::C)))] + #[test_case(0xB2, (Operation::Or, OpcodeOperand::SingleRegister(register::SingleEightBit::D)))] + #[test_case(0xB3, (Operation::Or, OpcodeOperand::SingleRegister(register::SingleEightBit::E)))] + #[test_case(0xB4, (Operation::Or, OpcodeOperand::SingleRegister(register::SingleEightBit::H)))] + #[test_case(0xB5, (Operation::Or, OpcodeOperand::SingleRegister(register::SingleEightBit::L)))] + #[test_case(0xB6, (Operation::Or, OpcodeOperand::HLAddressValue))] + #[test_case(0xB7, (Operation::Or, OpcodeOperand::SingleRegister(register::SingleEightBit::A)))] + #[test_case(0xF6, (Operation::Or, OpcodeOperand::Immediate))] + + #[test_case(0xB8, (Operation::Compare, OpcodeOperand::SingleRegister(register::SingleEightBit::B)))] + #[test_case(0xB9, (Operation::Compare, OpcodeOperand::SingleRegister(register::SingleEightBit::C)))] + #[test_case(0xBA, (Operation::Compare, OpcodeOperand::SingleRegister(register::SingleEightBit::D)))] + #[test_case(0xBB, (Operation::Compare, OpcodeOperand::SingleRegister(register::SingleEightBit::E)))] + #[test_case(0xBC, (Operation::Compare, OpcodeOperand::SingleRegister(register::SingleEightBit::H)))] + #[test_case(0xBD, (Operation::Compare, OpcodeOperand::SingleRegister(register::SingleEightBit::L)))] + #[test_case(0xBE, (Operation::Compare, OpcodeOperand::HLAddressValue))] + #[test_case(0xBF, (Operation::Compare, OpcodeOperand::SingleRegister(register::SingleEightBit::A)))] + #[test_case(0xFE, (Operation::Compare, OpcodeOperand::Immediate))] + + #[test_case(0x04, (Operation::Inc, OpcodeOperand::SingleRegister(register::SingleEightBit::B)))] + #[test_case(0x0C, (Operation::Inc, OpcodeOperand::SingleRegister(register::SingleEightBit::C)))] + #[test_case(0x14, (Operation::Inc, OpcodeOperand::SingleRegister(register::SingleEightBit::D)))] + #[test_case(0x1C, (Operation::Inc, OpcodeOperand::SingleRegister(register::SingleEightBit::E)))] + #[test_case(0x24, (Operation::Inc, OpcodeOperand::SingleRegister(register::SingleEightBit::H)))] + #[test_case(0x2C, (Operation::Inc, OpcodeOperand::SingleRegister(register::SingleEightBit::L)))] + #[test_case(0x34, (Operation::Inc, OpcodeOperand::HLAddressValue))] + #[test_case(0x3C, (Operation::Inc, OpcodeOperand::SingleRegister(register::SingleEightBit::A)))] + + #[test_case(0x05, (Operation::Dec, OpcodeOperand::SingleRegister(register::SingleEightBit::B)))] + #[test_case(0x0D, (Operation::Dec, OpcodeOperand::SingleRegister(register::SingleEightBit::C)))] + #[test_case(0x15, (Operation::Dec, OpcodeOperand::SingleRegister(register::SingleEightBit::D)))] + #[test_case(0x1D, (Operation::Dec, OpcodeOperand::SingleRegister(register::SingleEightBit::E)))] + #[test_case(0x25, (Operation::Dec, OpcodeOperand::SingleRegister(register::SingleEightBit::H)))] + #[test_case(0x2D, (Operation::Dec, OpcodeOperand::SingleRegister(register::SingleEightBit::L)))] + #[test_case(0x35, (Operation::Dec, OpcodeOperand::HLAddressValue))] + #[test_case(0x3D, (Operation::Dec, OpcodeOperand::SingleRegister(register::SingleEightBit::A)))] + fn test_opcode_operand_and_operation(opcode: u8, expected: (Operation, OpcodeOperand)) { + let operation = operation_for_opcode(opcode).expect("could not parse"); + let operand = operand_for_opcode(opcode).expect("could not parse"); + + assert_eq!(expected, (operation, operand)); + } +} diff --git a/src/cpu/parse/arith8/add.rs b/src/cpu/parse/arith8/add.rs deleted file mode 100644 index 1f9957e..0000000 --- a/src/cpu/parse/arith8/add.rs +++ /dev/null @@ -1,79 +0,0 @@ -use crate::{ - cpu::{ - instructions::arith8::Operation, - parse::{self, Error, OpcodeParser, ParseOutput, ParseResult}, - }, - memory::View, - register, -}; - -pub struct Parser; - -impl OpcodeParser for Parser { - fn parse_opcode(data: &View) -> ParseResult { - let opcode = parse::get_opcode_from_data(data); - match opcode { - 0x87 => Ok(build_add_register_to_a_data(register::SingleEightBit::A)), - 0x80 => Ok(build_add_register_to_a_data(register::SingleEightBit::B)), - 0x81 => Ok(build_add_register_to_a_data(register::SingleEightBit::C)), - 0x82 => Ok(build_add_register_to_a_data(register::SingleEightBit::D)), - 0x83 => Ok(build_add_register_to_a_data(register::SingleEightBit::E)), - 0x84 => Ok(build_add_register_to_a_data(register::SingleEightBit::H)), - 0x85 => Ok(build_add_register_to_a_data(register::SingleEightBit::L)), - 0x86 => Ok(build_add_hl_address_to_a_data()), - 0xC6 => Ok(build_add_immediate_to_a_data(data)), - - 0x8F => Ok(build_add_register_to_a_with_carry_data( - register::SingleEightBit::A, - )), - - 0x88 => Ok(build_add_register_to_a_with_carry_data( - register::SingleEightBit::B, - )), - 0x89 => Ok(build_add_register_to_a_with_carry_data( - register::SingleEightBit::C, - )), - 0x8A => Ok(build_add_register_to_a_with_carry_data( - register::SingleEightBit::D, - )), - 0x8B => Ok(build_add_register_to_a_with_carry_data( - register::SingleEightBit::E, - )), - 0x8C => Ok(build_add_register_to_a_with_carry_data( - register::SingleEightBit::H, - )), - 0x8D => Ok(build_add_register_to_a_with_carry_data( - register::SingleEightBit::L, - )), - - 0xCE => Ok(build_add_immediate_to_a_with_carry_data(data)), - 0x8E => Ok(build_add_hl_address_to_a_with_carry_data()), - - _ => Err(Error::UnknownOpcode(opcode)), - } - } -} - -fn build_add_register_to_a_data(src: register::SingleEightBit) -> ParseOutput { - super::build_instruction_between_register_and_a_data(Operation::Add, src) -} - -fn build_add_register_to_a_with_carry_data(src: register::SingleEightBit) -> ParseOutput { - super::build_instruction_between_register_and_a_data(Operation::AddWithCarry, src) -} - -fn build_add_hl_address_to_a_data() -> ParseOutput { - super::build_instruction_between_hl_value_and_a_data(Operation::Add) -} - -fn build_add_hl_address_to_a_with_carry_data() -> ParseOutput { - super::build_instruction_between_hl_value_and_a_data(Operation::AddWithCarry) -} - -fn build_add_immediate_to_a_data(data: &View) -> ParseOutput { - super::build_instruction_between_immediate_and_a_data(Operation::Add, data) -} - -fn build_add_immediate_to_a_with_carry_data(data: &View) -> ParseOutput { - super::build_instruction_between_immediate_and_a_data(Operation::AddWithCarry, data) -} diff --git a/src/cpu/parse/arith8/and.rs b/src/cpu/parse/arith8/and.rs deleted file mode 100644 index cfec2bb..0000000 --- a/src/cpu/parse/arith8/and.rs +++ /dev/null @@ -1,40 +0,0 @@ -use crate::{ - cpu::{ - instructions::arith8::Operation, - parse::{self, Error, OpcodeParser, ParseOutput, ParseResult}, - }, - memory::View, - register, -}; - -pub struct Parser; - -impl OpcodeParser for Parser { - fn parse_opcode(data: &View) -> ParseResult { - let opcode = parse::get_opcode_from_data(data); - match opcode { - 0xA0 => Ok(build_and_register_with_a_data(register::SingleEightBit::B)), - 0xA1 => Ok(build_and_register_with_a_data(register::SingleEightBit::C)), - 0xA2 => Ok(build_and_register_with_a_data(register::SingleEightBit::D)), - 0xA3 => Ok(build_and_register_with_a_data(register::SingleEightBit::E)), - 0xA4 => Ok(build_and_register_with_a_data(register::SingleEightBit::H)), - 0xA5 => Ok(build_and_register_with_a_data(register::SingleEightBit::L)), - 0xA7 => Ok(build_and_register_with_a_data(register::SingleEightBit::A)), - 0xA6 => Ok(build_and_hl_value_with_a_data()), - 0xE6 => Ok(build_and_immediate_with_a_data(data)), - _ => Err(Error::UnknownOpcode(opcode)), - } - } -} - -fn build_and_register_with_a_data(src: register::SingleEightBit) -> ParseOutput { - super::build_instruction_between_register_and_a_data(Operation::And, src) -} - -fn build_and_hl_value_with_a_data() -> ParseOutput { - super::build_instruction_between_hl_value_and_a_data(Operation::And) -} - -fn build_and_immediate_with_a_data(data: &View) -> ParseOutput { - super::build_instruction_between_immediate_and_a_data(Operation::And, data) -} diff --git a/src/cpu/parse/arith8/compare.rs b/src/cpu/parse/arith8/compare.rs deleted file mode 100644 index 104b1dc..0000000 --- a/src/cpu/parse/arith8/compare.rs +++ /dev/null @@ -1,55 +0,0 @@ -use crate::{ - cpu::{ - instructions::arith8::Operation, - parse::{self, Error, OpcodeParser, ParseOutput, ParseResult}, - }, - memory::View, - register, -}; - -pub struct Parser; - -impl OpcodeParser for Parser { - fn parse_opcode(data: &View) -> ParseResult { - let opcode = parse::get_opcode_from_data(data); - match opcode { - 0xB8 => Ok(build_compare_register_with_a_data( - register::SingleEightBit::B, - )), - 0xB9 => Ok(build_compare_register_with_a_data( - register::SingleEightBit::C, - )), - 0xBA => Ok(build_compare_register_with_a_data( - register::SingleEightBit::D, - )), - 0xBB => Ok(build_compare_register_with_a_data( - register::SingleEightBit::E, - )), - 0xBC => Ok(build_compare_register_with_a_data( - register::SingleEightBit::H, - )), - 0xBD => Ok(build_compare_register_with_a_data( - register::SingleEightBit::L, - )), - 0xBF => Ok(build_compare_register_with_a_data( - register::SingleEightBit::A, - )), - - 0xBE => Ok(build_compare_hl_value_with_a_data()), - 0xFE => Ok(build_compare_immediate_with_a_data(data)), - _ => Err(Error::UnknownOpcode(opcode)), - } - } -} - -fn build_compare_register_with_a_data(src: register::SingleEightBit) -> ParseOutput { - super::build_instruction_between_register_and_a_data(Operation::Compare, src) -} - -fn build_compare_hl_value_with_a_data() -> ParseOutput { - super::build_instruction_between_hl_value_and_a_data(Operation::Compare) -} - -fn build_compare_immediate_with_a_data(data: &View) -> ParseOutput { - super::build_instruction_between_immediate_and_a_data(Operation::Compare, data) -} diff --git a/src/cpu/parse/arith8/dec.rs b/src/cpu/parse/arith8/dec.rs deleted file mode 100644 index 4cb81b5..0000000 --- a/src/cpu/parse/arith8/dec.rs +++ /dev/null @@ -1,37 +0,0 @@ -use crate::{ - cpu::{ - instructions::arith8::Operation, - parse::{self, Error, OpcodeParser, ParseOutput, ParseResult}, - }, - memory::View, - register, -}; - -pub struct Parser; - -impl OpcodeParser for Parser { - fn parse_opcode(data: &View) -> ParseResult { - let opcode = parse::get_opcode_from_data(data); - match opcode { - 0x05 => Ok(build_dec_single_register_data(register::SingleEightBit::B)), - 0x0D => Ok(build_dec_single_register_data(register::SingleEightBit::C)), - 0x15 => Ok(build_dec_single_register_data(register::SingleEightBit::D)), - 0x1D => Ok(build_dec_single_register_data(register::SingleEightBit::E)), - 0x25 => Ok(build_dec_single_register_data(register::SingleEightBit::H)), - 0x2D => Ok(build_dec_single_register_data(register::SingleEightBit::L)), - 0x3D => Ok(build_dec_single_register_data(register::SingleEightBit::A)), - - 0x35 => Ok(build_dec_hl_value_data()), - - _ => Err(Error::UnknownOpcode(opcode)), - } - } -} - -fn build_dec_single_register_data(src: register::SingleEightBit) -> ParseOutput { - super::build_instruction_between_register_and_a_data(Operation::Dec, src) -} - -fn build_dec_hl_value_data() -> ParseOutput { - super::build_instruction_between_hl_value_and_a_data(Operation::Dec) -} diff --git a/src/cpu/parse/arith8/inc.rs b/src/cpu/parse/arith8/inc.rs deleted file mode 100644 index 9ae000c..0000000 --- a/src/cpu/parse/arith8/inc.rs +++ /dev/null @@ -1,37 +0,0 @@ -use crate::{ - cpu::{ - instructions::arith8::Operation, - parse::{self, Error, OpcodeParser, ParseOutput, ParseResult}, - }, - memory::View, - register, -}; - -pub struct Parser; - -impl OpcodeParser for Parser { - fn parse_opcode(data: &View) -> ParseResult { - let opcode = parse::get_opcode_from_data(data); - match opcode { - 0x04 => Ok(build_inc_single_register_data(register::SingleEightBit::B)), - 0x0C => Ok(build_inc_single_register_data(register::SingleEightBit::C)), - 0x14 => Ok(build_inc_single_register_data(register::SingleEightBit::D)), - 0x1C => Ok(build_inc_single_register_data(register::SingleEightBit::E)), - 0x24 => Ok(build_inc_single_register_data(register::SingleEightBit::H)), - 0x2C => Ok(build_inc_single_register_data(register::SingleEightBit::L)), - 0x3C => Ok(build_inc_single_register_data(register::SingleEightBit::A)), - - 0x34 => Ok(build_inc_hl_value_data()), - - _ => Err(Error::UnknownOpcode(opcode)), - } - } -} - -fn build_inc_single_register_data(src: register::SingleEightBit) -> ParseOutput { - super::build_instruction_between_register_and_a_data(Operation::Inc, src) -} - -fn build_inc_hl_value_data() -> ParseOutput { - super::build_instruction_between_hl_value_and_a_data(Operation::Inc) -} diff --git a/src/cpu/parse/arith8/or.rs b/src/cpu/parse/arith8/or.rs deleted file mode 100644 index 5b457c6..0000000 --- a/src/cpu/parse/arith8/or.rs +++ /dev/null @@ -1,42 +0,0 @@ -use crate::{ - cpu::{ - instructions::arith8::Operation, - parse::{self, Error, OpcodeParser, ParseOutput, ParseResult}, - }, - memory::View, - register, -}; - -pub struct Parser; - -impl OpcodeParser for Parser { - fn parse_opcode(data: &View) -> ParseResult { - let opcode = parse::get_opcode_from_data(data); - match opcode { - 0xB0 => Ok(build_or_register_with_a_data(register::SingleEightBit::B)), - 0xB1 => Ok(build_or_register_with_a_data(register::SingleEightBit::C)), - 0xB2 => Ok(build_or_register_with_a_data(register::SingleEightBit::D)), - 0xB3 => Ok(build_or_register_with_a_data(register::SingleEightBit::E)), - 0xB4 => Ok(build_or_register_with_a_data(register::SingleEightBit::H)), - 0xB5 => Ok(build_or_register_with_a_data(register::SingleEightBit::L)), - 0xB7 => Ok(build_or_register_with_a_data(register::SingleEightBit::A)), - - 0xB6 => Ok(build_or_hl_value_with_a_data()), - 0xF6 => Ok(build_or_immediate_with_a_data(data)), - - _ => Err(Error::UnknownOpcode(opcode)), - } - } -} - -fn build_or_register_with_a_data(src: register::SingleEightBit) -> ParseOutput { - super::build_instruction_between_register_and_a_data(Operation::Or, src) -} - -fn build_or_hl_value_with_a_data() -> ParseOutput { - super::build_instruction_between_hl_value_and_a_data(Operation::Or) -} - -fn build_or_immediate_with_a_data(data: &View) -> ParseOutput { - super::build_instruction_between_immediate_and_a_data(Operation::Or, data) -} diff --git a/src/cpu/parse/arith8/sub.rs b/src/cpu/parse/arith8/sub.rs deleted file mode 100644 index 311b56e..0000000 --- a/src/cpu/parse/arith8/sub.rs +++ /dev/null @@ -1,77 +0,0 @@ -use crate::{ - cpu::{ - instructions::arith8::Operation, - parse::{self, Error, OpcodeParser, ParseOutput, ParseResult}, - }, - memory::View, - register, -}; - -pub struct Parser; - -impl OpcodeParser for Parser { - fn parse_opcode(data: &View) -> ParseResult { - let opcode = parse::get_opcode_from_data(data); - match opcode { - 0x90 => Ok(build_sub_register_from_a_data(register::SingleEightBit::B)), - 0x91 => Ok(build_sub_register_from_a_data(register::SingleEightBit::C)), - 0x92 => Ok(build_sub_register_from_a_data(register::SingleEightBit::D)), - 0x93 => Ok(build_sub_register_from_a_data(register::SingleEightBit::E)), - 0x94 => Ok(build_sub_register_from_a_data(register::SingleEightBit::H)), - 0x95 => Ok(build_sub_register_from_a_data(register::SingleEightBit::L)), - 0x97 => Ok(build_sub_register_from_a_data(register::SingleEightBit::A)), - 0x98 => Ok(build_sub_register_from_a_with_carry_data( - register::SingleEightBit::B, - )), - 0x99 => Ok(build_sub_register_from_a_with_carry_data( - register::SingleEightBit::C, - )), - 0x9A => Ok(build_sub_register_from_a_with_carry_data( - register::SingleEightBit::D, - )), - 0x9B => Ok(build_sub_register_from_a_with_carry_data( - register::SingleEightBit::E, - )), - 0x9C => Ok(build_sub_register_from_a_with_carry_data( - register::SingleEightBit::H, - )), - 0x9D => Ok(build_sub_register_from_a_with_carry_data( - register::SingleEightBit::L, - )), - 0x9F => Ok(build_sub_register_from_a_with_carry_data( - register::SingleEightBit::A, - )), - 0x96 => Ok(build_sub_hl_value_from_a_data()), - 0x9E => Ok(build_sub_hl_value_from_a_with_carry_data()), - 0xD6 => Ok(build_sub_immediate_from_a_data(data)), - 0xDE => Ok(build_sub_immediate_from_a_with_carry_data(data)), - _ => Err(Error::UnknownOpcode(opcode)), - } - } -} - -fn build_sub_register_from_a_data(src_register: register::SingleEightBit) -> ParseOutput { - super::build_instruction_between_register_and_a_data(Operation::Sub, src_register) -} - -fn build_sub_register_from_a_with_carry_data( - src_register: register::SingleEightBit, -) -> ParseOutput { - super::build_instruction_between_register_and_a_data(Operation::SubWithCarry, src_register) -} - -fn build_sub_hl_value_from_a_data() -> ParseOutput { - super::build_instruction_between_hl_value_and_a_data(Operation::Sub) -} - -fn build_sub_hl_value_from_a_with_carry_data() -> ParseOutput { - super::build_instruction_between_hl_value_and_a_data(Operation::SubWithCarry) -} - -fn build_sub_immediate_from_a_data(data: &View) -> ParseOutput { - super::build_instruction_between_immediate_and_a_data(Operation::Sub, data) -} - -fn build_sub_immediate_from_a_with_carry_data(data: &View) -> ParseOutput { - super::build_instruction_between_immediate_and_a_data(Operation::SubWithCarry, data) -} diff --git a/src/cpu/parse/arith8/xor.rs b/src/cpu/parse/arith8/xor.rs deleted file mode 100644 index 29cdcae..0000000 --- a/src/cpu/parse/arith8/xor.rs +++ /dev/null @@ -1,40 +0,0 @@ -use crate::{ - cpu::{ - instructions::arith8::Operation, - parse::{self, Error, OpcodeParser, ParseOutput, ParseResult}, - }, - memory::View, - register, -}; - -pub struct Parser; - -impl OpcodeParser for Parser { - fn parse_opcode(data: &View) -> ParseResult { - let opcode = parse::get_opcode_from_data(data); - match opcode { - 0xA8 => Ok(build_xor_register_with_a_data(register::SingleEightBit::B)), - 0xA9 => Ok(build_xor_register_with_a_data(register::SingleEightBit::C)), - 0xAA => Ok(build_xor_register_with_a_data(register::SingleEightBit::D)), - 0xAB => Ok(build_xor_register_with_a_data(register::SingleEightBit::E)), - 0xAC => Ok(build_xor_register_with_a_data(register::SingleEightBit::H)), - 0xAD => Ok(build_xor_register_with_a_data(register::SingleEightBit::L)), - 0xAF => Ok(build_xor_register_with_a_data(register::SingleEightBit::A)), - 0xAE => Ok(build_xor_hl_value_with_a_data()), - 0xEE => Ok(build_xor_immediate_with_a_data(data)), - _ => Err(Error::UnknownOpcode(opcode)), - } - } -} - -fn build_xor_register_with_a_data(src: register::SingleEightBit) -> ParseOutput { - super::build_instruction_between_register_and_a_data(Operation::Xor, src) -} - -fn build_xor_hl_value_with_a_data() -> ParseOutput { - super::build_instruction_between_hl_value_and_a_data(Operation::Xor) -} - -fn build_xor_immediate_with_a_data(data: &View) -> ParseOutput { - super::build_instruction_between_immediate_and_a_data(Operation::Xor, data) -}