Add 16bit inc/dec instructions
parent
22cfe4ec55
commit
90ec09ff40
|
@ -2,5 +2,7 @@ use crate::register;
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub enum SixteenBitArithmeticInstruction {
|
pub enum SixteenBitArithmeticInstruction {
|
||||||
AddRegisterToHL{operand_register: register::SixteenBit}
|
AddRegisterToHL{operand_register: register::SixteenBit},
|
||||||
|
IncrementRegister{operand_register: register::SixteenBit},
|
||||||
|
DecrementRegister{operand_register: register::SixteenBit}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,32 @@ impl OpcodeParser for Parser {
|
||||||
0x39 => Ok(build_add_hl_to_register_data(SixteenBit::Single(
|
0x39 => Ok(build_add_hl_to_register_data(SixteenBit::Single(
|
||||||
SingleSixteenBit::StackPointer,
|
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)),
|
_ => Err(Error::UnknownOpcode(opcode)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,3 +68,23 @@ fn build_add_hl_to_register_data(operand_register: SixteenBit) -> ParseOutput {
|
||||||
1,
|
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,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
|
@ -5,6 +5,22 @@ use super::{Run, arithutil::CarryingAdd};
|
||||||
impl Run for SixteenBitArithmeticInstruction {
|
impl Run for SixteenBitArithmeticInstruction {
|
||||||
fn run_on(&self, processor: &mut crate::cpu::Processor) -> Result<(), super::Error> {
|
fn run_on(&self, processor: &mut crate::cpu::Processor) -> Result<(), super::Error> {
|
||||||
match *self {
|
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 } => {
|
SixteenBitArithmeticInstruction::AddRegisterToHL { operand_register } => {
|
||||||
let operand1 = processor.registers.get_combined_register(register::Combined::HL);
|
let operand1 = processor.registers.get_combined_register(register::Combined::HL);
|
||||||
let operand2 = processor.registers.get_16bit_register(operand_register);
|
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::HalfCarry, half_carry.into());
|
||||||
processor.registers.set_flag_bit(register::Flag::Subtract, 0);
|
processor.registers.set_flag_bit(register::Flag::Subtract, 0);
|
||||||
|
|
||||||
// TOOO: Flags and such]
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,3 +98,63 @@ fn test_add_hl_to_registers_flags((opcode, operand_register): (u8, register::Six
|
||||||
(register::Flag::Carry, expected_flags.carry),
|
(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());
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue