Implement transfers between HL and SP
parent
0667a59c6a
commit
a7adfb6f90
24
src/run.rs
24
src/run.rs
|
@ -42,7 +42,7 @@ impl Processor {
|
||||||
self.registers.set_single_8bit_register(register, value);
|
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);
|
let src_value = self.registers.get_single_8bit_register(src);
|
||||||
self.registers.set_single_8bit_register(dst, src_value);
|
self.registers.set_single_8bit_register(dst, src_value);
|
||||||
}
|
}
|
||||||
|
@ -142,6 +142,11 @@ impl Processor {
|
||||||
Instruction::LD16bitImmediateToRegister { dst, value } => {
|
Instruction::LD16bitImmediateToRegister { dst, value } => {
|
||||||
self.registers.set_16bit_register(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);
|
self.num_cycles += u64::from(instruction.cycles);
|
||||||
|
@ -599,4 +604,21 @@ mod tests {
|
||||||
.get_16bit_register(expected_dst_register)
|
.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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ pub enum Instruction {
|
||||||
},
|
},
|
||||||
// 3.3.1.2, excluding the (hl) instructions, 3.3.1.3, excluding the (nn) instructions
|
// 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
|
// and 3.3.1.4 excluding the (nn) instructions
|
||||||
LDr1r2 {
|
LD8bitr1r2 {
|
||||||
dst: register::SingleEightBit,
|
dst: register::SingleEightBit,
|
||||||
src: register::SingleEightBit,
|
src: register::SingleEightBit,
|
||||||
},
|
},
|
||||||
|
@ -98,6 +98,11 @@ pub enum Instruction {
|
||||||
value: u16,
|
value: u16,
|
||||||
dst: register::SixteenBit,
|
dst: register::SixteenBit,
|
||||||
},
|
},
|
||||||
|
// 3.3.2.2
|
||||||
|
LD16Bitr1r2 {
|
||||||
|
dst: register::SixteenBit,
|
||||||
|
src: register::SixteenBit,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct RunnableInstruction {
|
pub struct RunnableInstruction {
|
||||||
|
|
|
@ -33,6 +33,7 @@ pub fn next_instruction(data: &[u8]) -> ParseResult {
|
||||||
load8::transfer::Between8BitRegisterParser::parse_opcode,
|
load8::transfer::Between8BitRegisterParser::parse_opcode,
|
||||||
load8::memory::Memory8BitLoadParser::parse_opcode,
|
load8::memory::Memory8BitLoadParser::parse_opcode,
|
||||||
load16::immediate::Immediate16BitLoadParser::parse_opcode,
|
load16::immediate::Immediate16BitLoadParser::parse_opcode,
|
||||||
|
load16::transfer::Between16BitRegisterParser::parse_opcode,
|
||||||
];
|
];
|
||||||
|
|
||||||
for parse_func in parse_funcs {
|
for parse_func in parse_funcs {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
//! Holds functions to help produce 16 bit load instructions
|
//! Holds functions to help produce 16 bit load instructions
|
||||||
|
|
||||||
pub mod immediate;
|
pub mod immediate;
|
||||||
|
pub mod transfer;
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
|
@ -87,7 +87,7 @@ fn make_ldr1r2_data(
|
||||||
.map(|remaining_data| {
|
.map(|remaining_data| {
|
||||||
(
|
(
|
||||||
RunnableInstruction {
|
RunnableInstruction {
|
||||||
instruction: Instruction::LDr1r2 { dst, src },
|
instruction: Instruction::LD8bitr1r2 { dst, src },
|
||||||
cycles: 4,
|
cycles: 4,
|
||||||
},
|
},
|
||||||
remaining_data,
|
remaining_data,
|
||||||
|
|
Loading…
Reference in New Issue