Add conditional jumps
parent
a5e838dda4
commit
827aef74f8
|
@ -14,4 +14,9 @@ pub enum ControlFlowInstruction {
|
||||||
value: u8,
|
value: u8,
|
||||||
addr: u16,
|
addr: u16,
|
||||||
},
|
},
|
||||||
|
JumpToImmediateIfFlagMatches {
|
||||||
|
flag: register::Flag,
|
||||||
|
value: u8,
|
||||||
|
addr: u16,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,38 @@ impl OpcodeParser for Parser {
|
||||||
data,
|
data,
|
||||||
|addr| ControlFlowInstruction::Call { addr },
|
|addr| ControlFlowInstruction::Call { addr },
|
||||||
)),
|
)),
|
||||||
|
0xC2 => Ok(build_immediate_parameterized_control_flow_data(
|
||||||
|
data,
|
||||||
|
|addr| ControlFlowInstruction::JumpToImmediateIfFlagMatches {
|
||||||
|
flag: register::Flag::Zero,
|
||||||
|
value: 0,
|
||||||
|
addr,
|
||||||
|
},
|
||||||
|
)),
|
||||||
|
0xD2 => Ok(build_immediate_parameterized_control_flow_data(
|
||||||
|
data,
|
||||||
|
|addr| ControlFlowInstruction::JumpToImmediateIfFlagMatches {
|
||||||
|
flag: register::Flag::Carry,
|
||||||
|
value: 0,
|
||||||
|
addr,
|
||||||
|
},
|
||||||
|
)),
|
||||||
|
0xCA => Ok(build_immediate_parameterized_control_flow_data(
|
||||||
|
data,
|
||||||
|
|addr| ControlFlowInstruction::JumpToImmediateIfFlagMatches {
|
||||||
|
flag: register::Flag::Zero,
|
||||||
|
value: 1,
|
||||||
|
addr,
|
||||||
|
},
|
||||||
|
)),
|
||||||
|
0xDA => Ok(build_immediate_parameterized_control_flow_data(
|
||||||
|
data,
|
||||||
|
|addr| ControlFlowInstruction::JumpToImmediateIfFlagMatches {
|
||||||
|
flag: register::Flag::Carry,
|
||||||
|
value: 1,
|
||||||
|
addr,
|
||||||
|
},
|
||||||
|
)),
|
||||||
0xC4 => Ok(build_immediate_parameterized_control_flow_data(
|
0xC4 => Ok(build_immediate_parameterized_control_flow_data(
|
||||||
data,
|
data,
|
||||||
|addr| ControlFlowInstruction::CallIfFlagMatches {
|
|addr| ControlFlowInstruction::CallIfFlagMatches {
|
||||||
|
|
|
@ -12,6 +12,17 @@ impl Run for ControlFlowInstruction {
|
||||||
|
|
||||||
Ok(Cycles(16))
|
Ok(Cycles(16))
|
||||||
}
|
}
|
||||||
|
Self::JumpToImmediateIfFlagMatches { flag, value, addr } => {
|
||||||
|
if processor.registers.get_flag_bit(flag) == value {
|
||||||
|
processor.registers.set_single_16bit_register(
|
||||||
|
register::SingleSixteenBit::ProgramCounter,
|
||||||
|
addr,
|
||||||
|
);
|
||||||
|
Ok(Cycles(16))
|
||||||
|
} else {
|
||||||
|
Ok(Cycles(12))
|
||||||
|
}
|
||||||
|
}
|
||||||
Self::Call { addr } => {
|
Self::Call { addr } => {
|
||||||
do_call(processor, addr)?;
|
do_call(processor, addr)?;
|
||||||
Ok(Cycles(24))
|
Ok(Cycles(24))
|
||||||
|
|
|
@ -56,7 +56,11 @@ fn test_call_pushes_pc_onto_stack() {
|
||||||
#[test_case(0xDC, Flag::Carry, 1; "CALL C")]
|
#[test_case(0xDC, Flag::Carry, 1; "CALL C")]
|
||||||
#[test_case(0xC4, Flag::Zero, 0; "CALL NZ")]
|
#[test_case(0xC4, Flag::Zero, 0; "CALL NZ")]
|
||||||
#[test_case(0xD4, Flag::Carry, 0; "CALL NC")]
|
#[test_case(0xD4, Flag::Carry, 0; "CALL NC")]
|
||||||
fn test_call_jumps_if_condition_matches(opcode: u8, flag: Flag, expected_value: u8) {
|
#[test_case(0xCA, Flag::Zero, 1; "JP Z")]
|
||||||
|
#[test_case(0xDA, Flag::Carry, 1; "JP C")]
|
||||||
|
#[test_case(0xC2, Flag::Zero, 0; "JP NZ")]
|
||||||
|
#[test_case(0xD2, Flag::Carry, 0; "JP NC")]
|
||||||
|
fn test_call_and_jump_jumps_if_condition_matches(opcode: u8, flag: Flag, expected_value: u8) {
|
||||||
let mut processor = Processor::default();
|
let mut processor = Processor::default();
|
||||||
processor.registers.set_flag_bit(flag, expected_value);
|
processor.registers.set_flag_bit(flag, expected_value);
|
||||||
|
|
||||||
|
@ -93,7 +97,11 @@ fn test_call_grows_stack_if_condition_matches(opcode: u8, flag: Flag, expected_v
|
||||||
#[test_case(0xDC, Flag::Carry, 1; "CALL C")]
|
#[test_case(0xDC, Flag::Carry, 1; "CALL C")]
|
||||||
#[test_case(0xC4, Flag::Zero, 0; "CALL NZ")]
|
#[test_case(0xC4, Flag::Zero, 0; "CALL NZ")]
|
||||||
#[test_case(0xD4, Flag::Carry, 0; "CALL NC")]
|
#[test_case(0xD4, Flag::Carry, 0; "CALL NC")]
|
||||||
fn test_call_does_nothing_if_condition_fails(opcode: u8, flag: Flag, expected_value: u8) {
|
#[test_case(0xCA, Flag::Zero, 1; "JP Z")]
|
||||||
|
#[test_case(0xDA, Flag::Carry, 1; "JP C")]
|
||||||
|
#[test_case(0xC2, Flag::Zero, 0; "JP NZ")]
|
||||||
|
#[test_case(0xD2, Flag::Carry, 0; "JP NC")]
|
||||||
|
fn test_call_and_jump_does_nothing_if_condition_fails(opcode: u8, flag: Flag, expected_value: u8) {
|
||||||
let mut processor = Processor::default();
|
let mut processor = Processor::default();
|
||||||
processor
|
processor
|
||||||
.registers
|
.registers
|
||||||
|
|
Loading…
Reference in New Issue