From 90ec09ff409a28b5627804c9debde648ee2fd2d8 Mon Sep 17 00:00:00 2001 From: Nick Krichevsky Date: Tue, 14 Nov 2023 22:15:58 -0500 Subject: [PATCH] Add 16bit inc/dec instructions --- src/cpu/instructions/arith16.rs | 4 +- src/cpu/parse/arith16.rs | 46 ++++++++++++++ src/cpu/run/arith16.rs | 18 +++++- tests/cpu/arith16.rs | 60 +++++++++++++++++++ .../cpu/jsmoo/testdata/{disabled => }/03.json | 0 .../cpu/jsmoo/testdata/{disabled => }/0b.json | 0 .../cpu/jsmoo/testdata/{disabled => }/13.json | 0 .../cpu/jsmoo/testdata/{disabled => }/1b.json | 0 .../cpu/jsmoo/testdata/{disabled => }/23.json | 0 .../cpu/jsmoo/testdata/{disabled => }/2b.json | 0 .../cpu/jsmoo/testdata/{disabled => }/33.json | 0 .../cpu/jsmoo/testdata/{disabled => }/3b.json | 0 12 files changed, 125 insertions(+), 3 deletions(-) rename tests/cpu/jsmoo/testdata/{disabled => }/03.json (100%) rename tests/cpu/jsmoo/testdata/{disabled => }/0b.json (100%) rename tests/cpu/jsmoo/testdata/{disabled => }/13.json (100%) rename tests/cpu/jsmoo/testdata/{disabled => }/1b.json (100%) rename tests/cpu/jsmoo/testdata/{disabled => }/23.json (100%) rename tests/cpu/jsmoo/testdata/{disabled => }/2b.json (100%) rename tests/cpu/jsmoo/testdata/{disabled => }/33.json (100%) rename tests/cpu/jsmoo/testdata/{disabled => }/3b.json (100%) diff --git a/src/cpu/instructions/arith16.rs b/src/cpu/instructions/arith16.rs index 815ed7a..eb20147 100644 --- a/src/cpu/instructions/arith16.rs +++ b/src/cpu/instructions/arith16.rs @@ -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} } diff --git a/src/cpu/parse/arith16.rs b/src/cpu/parse/arith16.rs index 02b6e73..d6bbaad 100644 --- a/src/cpu/parse/arith16.rs +++ b/src/cpu/parse/arith16.rs @@ -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, + ) +} diff --git a/src/cpu/run/arith16.rs b/src/cpu/run/arith16.rs index ef52c1d..92e2f89 100644 --- a/src/cpu/run/arith16.rs +++ b/src/cpu/run/arith16.rs @@ -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(()) } } diff --git a/tests/cpu/arith16.rs b/tests/cpu/arith16.rs index 6b13269..0ca432e 100644 --- a/tests/cpu/arith16.rs +++ b/tests/cpu/arith16.rs @@ -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()); +} diff --git a/tests/cpu/jsmoo/testdata/disabled/03.json b/tests/cpu/jsmoo/testdata/03.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/03.json rename to tests/cpu/jsmoo/testdata/03.json diff --git a/tests/cpu/jsmoo/testdata/disabled/0b.json b/tests/cpu/jsmoo/testdata/0b.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/0b.json rename to tests/cpu/jsmoo/testdata/0b.json diff --git a/tests/cpu/jsmoo/testdata/disabled/13.json b/tests/cpu/jsmoo/testdata/13.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/13.json rename to tests/cpu/jsmoo/testdata/13.json diff --git a/tests/cpu/jsmoo/testdata/disabled/1b.json b/tests/cpu/jsmoo/testdata/1b.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/1b.json rename to tests/cpu/jsmoo/testdata/1b.json diff --git a/tests/cpu/jsmoo/testdata/disabled/23.json b/tests/cpu/jsmoo/testdata/23.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/23.json rename to tests/cpu/jsmoo/testdata/23.json diff --git a/tests/cpu/jsmoo/testdata/disabled/2b.json b/tests/cpu/jsmoo/testdata/2b.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/2b.json rename to tests/cpu/jsmoo/testdata/2b.json diff --git a/tests/cpu/jsmoo/testdata/disabled/33.json b/tests/cpu/jsmoo/testdata/33.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/33.json rename to tests/cpu/jsmoo/testdata/33.json diff --git a/tests/cpu/jsmoo/testdata/disabled/3b.json b/tests/cpu/jsmoo/testdata/3b.json similarity index 100% rename from tests/cpu/jsmoo/testdata/disabled/3b.json rename to tests/cpu/jsmoo/testdata/3b.json