Greatly simplify arith8 parsing
parent
9a6ccf6d48
commit
ec4f9395af
|
@ -2,6 +2,7 @@
|
||||||
use crate::register;
|
use crate::register;
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
#[cfg_attr(test, derive(Eq, PartialEq))]
|
||||||
pub enum Operation {
|
pub enum Operation {
|
||||||
Add,
|
Add,
|
||||||
AddWithCarry,
|
AddWithCarry,
|
||||||
|
|
|
@ -42,14 +42,7 @@ pub fn next_instruction(data: &View) -> ParseResult {
|
||||||
load16::immediate::Parser::parse_opcode,
|
load16::immediate::Parser::parse_opcode,
|
||||||
load16::transfer::Parser::parse_opcode,
|
load16::transfer::Parser::parse_opcode,
|
||||||
load16::stack::Parser::parse_opcode,
|
load16::stack::Parser::parse_opcode,
|
||||||
arith8::add::Parser::parse_opcode,
|
arith8::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,
|
|
||||||
arith16::Parser::parse_opcode,
|
arith16::Parser::parse_opcode,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -7,16 +7,111 @@ use crate::{
|
||||||
register,
|
register,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::ParseOutput;
|
use super::{ParseOutput, OpcodeParser};
|
||||||
|
|
||||||
pub mod add;
|
// similar to `arith8::Operand`, but only for the parts that can be uniquely determined from the opcode
|
||||||
pub mod and;
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub mod compare;
|
#[cfg_attr(test, derive(Eq, PartialEq))]
|
||||||
pub mod dec;
|
enum OpcodeOperand {
|
||||||
pub mod inc;
|
SingleRegister(register::SingleEightBit),
|
||||||
pub mod or;
|
HLAddressValue,
|
||||||
pub mod sub;
|
Immediate,
|
||||||
pub mod xor;
|
}
|
||||||
|
|
||||||
|
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, super::Error> {
|
||||||
|
operation_for_binary_opcode(opcode)
|
||||||
|
.or_else(|_err| operation_for_unary_opcode(opcode))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn operand_for_opcode(opcode: u8) -> Result<OpcodeOperand, super::Error> {
|
||||||
|
operand_for_binary_opcode(opcode)
|
||||||
|
.or_else(|_err| operand_for_unary_opcode(opcode))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn operation_for_unary_opcode(opcode: u8) -> Result<Operation, super::Error> {
|
||||||
|
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<Operation, super::Error> {
|
||||||
|
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<OpcodeOperand, super::Error> {
|
||||||
|
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<OpcodeOperand, super::Error> {
|
||||||
|
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(
|
fn build_instruction_between_register_and_a_data(
|
||||||
operation: Operation,
|
operation: Operation,
|
||||||
|
@ -70,3 +165,113 @@ fn build_instruction_between_immediate_and_a_data(
|
||||||
2,
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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)
|
|
||||||
}
|
|
|
@ -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)
|
|
||||||
}
|
|
|
@ -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)
|
|
||||||
}
|
|
|
@ -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)
|
|
||||||
}
|
|
|
@ -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)
|
|
||||||
}
|
|
|
@ -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)
|
|
||||||
}
|
|
|
@ -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)
|
|
||||||
}
|
|
|
@ -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)
|
|
||||||
}
|
|
Loading…
Reference in New Issue