Simplify control flow parsing logic

old-bit-manip
Nick Krichevsky 2023-11-21 20:57:16 -05:00
parent fc76248853
commit 01cf67ca35
1 changed files with 61 additions and 78 deletions

View File

@ -1,93 +1,76 @@
use crate::{ use crate::{
cpu::{ cpu::{
instructions::{control::ControlFlowInstruction, Instruction}, instructions::{control::ControlFlowInstruction, Instruction},
parse, register, parse,
}, },
memory::{GetViewTuple, View}, memory::{GetViewTuple, View},
register::Flag,
}; };
use super::{OpcodeParser, ParseOutput, ParseResult}; use super::{OpcodeParser, OrParse, ParseOutput, ParseResult};
pub struct Parser; pub struct Parser;
enum ConditionalControlFlowType {
Call,
Jump,
}
impl OpcodeParser for Parser { impl OpcodeParser for Parser {
fn parse_opcode(data: &View) -> ParseResult { fn parse_opcode(data: &View) -> ParseResult {
let opcode = parse::get_opcode_from_data(data); parse_unconditional_control_operation(data)
match opcode { .or_parse(|_opcode| parse_conditional_control_operation(data))
0xC3 => Ok(build_immediate_parameterized_control_flow_data( }
data, }
|addr| ControlFlowInstruction::JumpToImmediate { addr },
)), fn parse_unconditional_control_operation(data: &View) -> ParseResult {
0xCD => Ok(build_immediate_parameterized_control_flow_data( let opcode = parse::get_opcode_from_data(data);
data,
|addr| ControlFlowInstruction::Call { addr }, match opcode {
)), 0xC3 => Ok(build_immediate_parameterized_control_flow_data(
0xC2 => Ok(build_immediate_parameterized_control_flow_data( data,
data, |addr| ControlFlowInstruction::JumpToImmediate { addr },
|addr| ControlFlowInstruction::JumpToImmediateIfFlagMatches { )),
flag: register::Flag::Zero, 0xCD => Ok(build_immediate_parameterized_control_flow_data(
value: 0, data,
addr, |addr| ControlFlowInstruction::Call { addr },
}, )),
)), _ => Err(parse::Error::UnknownOpcode(opcode)),
0xD2 => Ok(build_immediate_parameterized_control_flow_data( }
data, }
|addr| ControlFlowInstruction::JumpToImmediateIfFlagMatches {
flag: register::Flag::Carry, fn parse_conditional_control_operation(data: &View) -> ParseResult {
value: 0, let opcode = parse::get_opcode_from_data(data);
addr,
}, let (flag, value) = conditional_control_flow_flag_for_opcode(opcode)?;
)), let control_flow_type = conditional_control_flow_type_for_opcode(opcode)?;
0xCA => Ok(build_immediate_parameterized_control_flow_data( match control_flow_type {
data, ConditionalControlFlowType::Jump => Ok(build_immediate_parameterized_control_flow_data(
|addr| ControlFlowInstruction::JumpToImmediateIfFlagMatches { data,
flag: register::Flag::Zero, |addr| ControlFlowInstruction::JumpToImmediateIfFlagMatches { flag, value, addr },
value: 1, )),
addr, ConditionalControlFlowType::Call => Ok(build_immediate_parameterized_control_flow_data(
}, data,
)), |addr| ControlFlowInstruction::CallIfFlagMatches { flag, value, addr },
0xDA => Ok(build_immediate_parameterized_control_flow_data( )),
data, }
|addr| ControlFlowInstruction::JumpToImmediateIfFlagMatches { }
flag: register::Flag::Carry,
value: 1, fn conditional_control_flow_type_for_opcode(opcode: u8) -> Result<ConditionalControlFlowType, parse::Error> {
addr, match opcode {
}, 0xC2 | 0xD2 | 0xCA | 0xDA => Ok(ConditionalControlFlowType::Jump),
)), 0xC4 | 0xD4 | 0xCC | 0xDC => Ok(ConditionalControlFlowType::Call),
0xC4 => Ok(build_immediate_parameterized_control_flow_data( _ => Err(parse::Error::UnknownOpcode(opcode)),
data, }
|addr| ControlFlowInstruction::CallIfFlagMatches { }
flag: register::Flag::Zero,
value: 0, fn conditional_control_flow_flag_for_opcode(opcode: u8) -> Result<(Flag, u8), parse::Error> {
addr, match opcode {
}, 0xC2 | 0xC4 => Ok((Flag::Zero, 0)),
)), 0xD2 | 0xD4 => Ok((Flag::Carry, 0)),
0xD4 => Ok(build_immediate_parameterized_control_flow_data( 0xCA | 0xCC => Ok((Flag::Zero, 1)),
data, 0xDA | 0xDC => Ok((Flag::Carry, 1)),
|addr| ControlFlowInstruction::CallIfFlagMatches { _ => Err(parse::Error::UnknownOpcode(opcode)),
flag: register::Flag::Carry,
value: 0,
addr,
},
)),
0xCC => Ok(build_immediate_parameterized_control_flow_data(
data,
|addr| ControlFlowInstruction::CallIfFlagMatches {
flag: register::Flag::Zero,
value: 1,
addr,
},
)),
0xDC => Ok(build_immediate_parameterized_control_flow_data(
data,
|addr| ControlFlowInstruction::CallIfFlagMatches {
flag: register::Flag::Carry,
value: 1,
addr,
},
)),
_ => Err(parse::Error::UnknownOpcode(opcode)),
}
} }
} }