Implement transfers between HL and SP

jsmoo
Nick Krichevsky 2022-04-09 15:11:03 -04:00
parent 0667a59c6a
commit a7adfb6f90
6 changed files with 73 additions and 3 deletions

View File

@ -42,7 +42,7 @@ impl Processor {
self.registers.set_single_8bit_register(register, value);
}
Instruction::LDr1r2 { dst, src } => {
Instruction::LD8bitr1r2 { dst, src } => {
let src_value = self.registers.get_single_8bit_register(src);
self.registers.set_single_8bit_register(dst, src_value);
}
@ -142,6 +142,11 @@ impl Processor {
Instruction::LD16bitImmediateToRegister { dst, value } => {
self.registers.set_16bit_register(dst, value);
}
Instruction::LD16Bitr1r2 { dst, src } => {
let value = self.registers.get_16bit_register(src);
self.registers.set_16bit_register(dst, value);
}
}
self.num_cycles += u64::from(instruction.cycles);
@ -599,4 +604,21 @@ mod tests {
.get_16bit_register(expected_dst_register)
);
}
#[test]
fn test_load_from_hl_to_sp() {
let mut processor = Processor::default();
processor
.registers
.set_combined_register(register::Combined::HL, 0x1234);
let data = [0xF9, 0x00];
let (ins, extra_data) =
RunnableInstruction::from_data(&data).expect("could not parse instruction");
assert_eq!(extra_data, &[0x00]);
processor.run(&ins);
assert_eq!(0x1234, processor.registers.stack_pointer);
}
}

View File

@ -11,7 +11,7 @@ pub enum Instruction {
},
// 3.3.1.2, excluding the (hl) instructions, 3.3.1.3, excluding the (nn) instructions
// and 3.3.1.4 excluding the (nn) instructions
LDr1r2 {
LD8bitr1r2 {
dst: register::SingleEightBit,
src: register::SingleEightBit,
},
@ -98,6 +98,11 @@ pub enum Instruction {
value: u16,
dst: register::SixteenBit,
},
// 3.3.2.2
LD16Bitr1r2 {
dst: register::SixteenBit,
src: register::SixteenBit,
},
}
pub struct RunnableInstruction {

View File

@ -33,6 +33,7 @@ pub fn next_instruction(data: &[u8]) -> ParseResult {
load8::transfer::Between8BitRegisterParser::parse_opcode,
load8::memory::Memory8BitLoadParser::parse_opcode,
load16::immediate::Immediate16BitLoadParser::parse_opcode,
load16::transfer::Between16BitRegisterParser::parse_opcode,
];
for parse_func in parse_funcs {

View File

@ -1,3 +1,4 @@
//! Holds functions to help produce 16 bit load instructions
pub mod immediate;
pub mod transfer;

View File

@ -0,0 +1,41 @@
use crate::register;
use crate::run::instructions::Instruction;
use crate::run::{
instructions::RunnableInstruction,
parse::{self, Error, OpcodeParser, ParseResult},
};
pub struct Between16BitRegisterParser;
impl OpcodeParser for Between16BitRegisterParser {
/// Parses an opcode that transfers an 8bit values between single 8 bit registers.
fn parse_opcode(data: &[u8]) -> ParseResult {
let opcode = parse::get_opcode_from_data(data)?;
match opcode {
0xF9 => make_ld_r1_r2_data(
register::SixteenBit::Single(register::SingleSixteenBit::StackPointer),
register::SixteenBit::Combined(register::Combined::HL),
data,
),
_ => Err(Error::UnknownOpcode(opcode)),
}
}
}
fn make_ld_r1_r2_data(
dst: register::SixteenBit,
src: register::SixteenBit,
data: &[u8],
) -> ParseResult {
data.get(1..)
.map(|remaining_data| {
(
RunnableInstruction {
instruction: Instruction::LD16Bitr1r2 { dst, src },
cycles: 4,
},
remaining_data,
)
})
.ok_or(Error::NoData)
}

View File

@ -87,7 +87,7 @@ fn make_ldr1r2_data(
.map(|remaining_data| {
(
RunnableInstruction {
instruction: Instruction::LDr1r2 { dst, src },
instruction: Instruction::LD8bitr1r2 { dst, src },
cycles: 4,
},
remaining_data,