Add complement A register instruction

old-bit-manip
Nick Krichevsky 2023-11-18 19:22:31 -05:00
parent 1bbd14e5d2
commit e0745e149f
5 changed files with 75 additions and 3 deletions

View File

@ -4,4 +4,5 @@
pub enum MiscInstruction {
SetCarryFlag,
ComplementCarryFlag,
ComplementARegister,
}

View File

@ -12,6 +12,7 @@ impl OpcodeParser for Parser {
match opcode {
0x37 => Ok(build_set_carry_flag_data()),
0x3F => Ok(build_complement_carry_flag_data()),
0x2F => Ok(build_complement_a_register_data()),
_ => Err(super::Error::UnknownOpcode(opcode)),
}
}
@ -36,3 +37,13 @@ fn build_complement_carry_flag_data() -> ParseOutput {
1,
)
}
fn build_complement_a_register_data() -> ParseOutput {
(
RunnableInstruction {
instruction: Instruction::Misc(MiscInstruction::ComplementARegister),
cycles: 4,
},
1,
)
}

View File

@ -16,6 +16,23 @@ impl Run for MiscInstruction {
set_flags_in_carry_bit_instruction(processor, flipped);
Ok(())
}
MiscInstruction::ComplementARegister => {
let current_value = processor
.registers
.get_single_8bit_register(register::SingleEightBit::A);
processor
.registers
.set_single_8bit_register(register::SingleEightBit::A, !current_value);
processor
.registers
.set_flag_bit(register::Flag::HalfCarry, 1);
processor
.registers
.set_flag_bit(register::Flag::Subtract, 1);
Ok(())
}
}
@ -27,6 +44,10 @@ fn set_flags_in_carry_bit_instruction(processor: &mut Processor, carry_flag: u8)
.registers
.set_flag_bit(register::Flag::Carry, carry_flag);
processor.registers.set_flag_bit(register::Flag::HalfCarry, 0);
processor.registers.set_flag_bit(register::Flag::Subtract, 0);
processor
.registers
.set_flag_bit(register::Flag::HalfCarry, 0);
processor
.registers
.set_flag_bit(register::Flag::Subtract, 0);
}

View File

@ -1,9 +1,9 @@
use crate::testutil;
use ferris_boi::{
cpu::{instructions::RunnableInstruction, Processor},
register,
};
use test_case::test_case;
use crate::testutil;
#[test_case(1)]
#[test_case(0)]
@ -66,3 +66,42 @@ fn test_all_carry_bit_instructions_adjust_flags(opcode: u8) {
(register::Flag::Zero, 1),
);
}
#[test]
fn test_complement_a_register_value() {
let mut processor = Processor::default();
processor.registers.a = 0xF0;
let data = [0x2F, 0x03];
let (ins, extra_data) =
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x03]);
processor.run_instruction(&ins);
assert_eq!(0x0F, processor.registers.a);
}
#[test]
fn test_complement_a_register_flags() {
let mut processor = Processor::default();
processor.registers.a = 0xF0;
testutil::set_opposite_of_expected_flags(&mut processor, (0, 1, 1, 0));
let data = [0x2F, 0x03];
let (ins, extra_data) =
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x03]);
processor.run_instruction(&ins);
testutil::assert_flags_eq!(
processor,
// Always 1
(register::Flag::HalfCarry, 1),
(register::Flag::Subtract, 1),
// Value is preserved
(register::Flag::Carry, 1),
(register::Flag::Zero, 1),
);
}