Add 16bit inc/dec instructions

old-bit-manip
Nick Krichevsky 2023-11-14 22:15:58 -05:00
parent 22cfe4ec55
commit 90ec09ff40
12 changed files with 125 additions and 3 deletions

View File

@ -2,5 +2,7 @@ use crate::register;
#[derive(Debug, Copy, Clone)]
pub enum SixteenBitArithmeticInstruction {
AddRegisterToHL{operand_register: register::SixteenBit}
AddRegisterToHL{operand_register: register::SixteenBit},
IncrementRegister{operand_register: register::SixteenBit},
DecrementRegister{operand_register: register::SixteenBit}
}

View File

@ -28,6 +28,32 @@ impl OpcodeParser for Parser {
0x39 => Ok(build_add_hl_to_register_data(SixteenBit::Single(
SingleSixteenBit::StackPointer,
))),
0x03 => Ok(build_inc_register_data(SixteenBit::Combined(
Combined::BC,
))),
0x13 => Ok(build_inc_register_data(SixteenBit::Combined(
Combined::DE,
))),
0x23 => Ok(build_inc_register_data(SixteenBit::Combined(
Combined::HL,
))),
0x33 => Ok(build_inc_register_data(SixteenBit::Single(
SingleSixteenBit::StackPointer,
))),
0x0B => Ok(build_dec_register_data(SixteenBit::Combined(
Combined::BC,
))),
0x1B => Ok(build_dec_register_data(SixteenBit::Combined(
Combined::DE,
))),
0x2B => Ok(build_dec_register_data(SixteenBit::Combined(
Combined::HL,
))),
0x3B => Ok(build_dec_register_data(SixteenBit::Single(
SingleSixteenBit::StackPointer,
))),
_ => Err(Error::UnknownOpcode(opcode)),
}
}
@ -42,3 +68,23 @@ fn build_add_hl_to_register_data(operand_register: SixteenBit) -> ParseOutput {
1,
)
}
fn build_inc_register_data(operand_register: SixteenBit) -> ParseOutput {
(
RunnableInstruction {
instruction: Instruction::SixteenBitArithmetic(SixteenBitArithmeticInstruction::IncrementRegister { operand_register }),
cycles: 2,
},
1,
)
}
fn build_dec_register_data(operand_register: SixteenBit) -> ParseOutput {
(
RunnableInstruction {
instruction: Instruction::SixteenBitArithmetic(SixteenBitArithmeticInstruction::DecrementRegister { operand_register }),
cycles: 2,
},
1,
)
}

View File

@ -5,6 +5,22 @@ use super::{Run, arithutil::CarryingAdd};
impl Run for SixteenBitArithmeticInstruction {
fn run_on(&self, processor: &mut crate::cpu::Processor) -> Result<(), super::Error> {
match *self {
SixteenBitArithmeticInstruction::IncrementRegister { operand_register } => {
let register_value = processor.registers.get_16bit_register(operand_register);
let incremented_value = register_value.wrapping_add(1);
processor.registers.set_16bit_register(operand_register, incremented_value);
Ok(())
}
SixteenBitArithmeticInstruction::DecrementRegister { operand_register } => {
let register_value = processor.registers.get_16bit_register(operand_register);
let decremented_value = register_value.wrapping_sub(1);
processor.registers.set_16bit_register(operand_register, decremented_value);
Ok(())
}
SixteenBitArithmeticInstruction::AddRegisterToHL { operand_register } => {
let operand1 = processor.registers.get_combined_register(register::Combined::HL);
let operand2 = processor.registers.get_16bit_register(operand_register);
@ -15,8 +31,6 @@ impl Run for SixteenBitArithmeticInstruction {
processor.registers.set_flag_bit(register::Flag::HalfCarry, half_carry.into());
processor.registers.set_flag_bit(register::Flag::Subtract, 0);
// TOOO: Flags and such]
Ok(())
}
}

View File

@ -98,3 +98,63 @@ fn test_add_hl_to_registers_flags((opcode, operand_register): (u8, register::Six
(register::Flag::Carry, expected_flags.carry),
);
}
#[test_matrix(
[
(0x03, register::SixteenBit::Combined(register::Combined::BC)),
(0x13, register::SixteenBit::Combined(register::Combined::DE)),
(0x23, register::SixteenBit::Combined(register::Combined::HL)),
(0x33, register::SixteenBit::Single(register::SingleSixteenBit::StackPointer)),
],
[
(0xAAAA, 0xAAAB),
(0xFFFF, 0x0000),
(0x0000, 0x0001),
]
)]
fn test_increment((opcode, operand_register): (u8, register::SixteenBit), (start_value, expected): (u16, u16)) {
let mut processor = Processor::default();
processor.registers.set_16bit_register(operand_register, start_value);
processor.registers.set_raw_flag_bits(0xA0).expect("Failed to set flag bits");
let data = [opcode, 0x02];
let (ins, extra_data) =
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x02]);
processor.run_instruction(&ins);
assert_eq!(expected, processor.registers.get_16bit_register(operand_register));
// Flags are untouched
assert_eq!(0xA0, processor.registers.get_raw_flag_bits());
}
#[test_matrix(
[
(0x0B, register::SixteenBit::Combined(register::Combined::BC)),
(0x1B, register::SixteenBit::Combined(register::Combined::DE)),
(0x2B, register::SixteenBit::Combined(register::Combined::HL)),
(0x3B, register::SixteenBit::Single(register::SingleSixteenBit::StackPointer)),
],
[
(0xAAAB, 0xAAAA),
(0x0000, 0xFFFF),
(0x0001, 0x0000),
]
)]
fn test_decrement((opcode, operand_register): (u8, register::SixteenBit), (start_value, expected): (u16, u16)) {
let mut processor = Processor::default();
processor.registers.set_16bit_register(operand_register, start_value);
processor.registers.set_raw_flag_bits(0xA0).expect("Failed to set flag bits");
let data = [opcode, 0x02];
let (ins, extra_data) =
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x02]);
processor.run_instruction(&ins);
assert_eq!(expected, processor.registers.get_16bit_register(operand_register));
// Flags are untouched
assert_eq!(0xA0, processor.registers.get_raw_flag_bits());
}