Add load to (hl) instructions
parent
1dc176fd74
commit
dcaf0588de
62
src/run.rs
62
src/run.rs
|
@ -29,6 +29,10 @@ pub enum Instruction {
|
|||
LDFromHLAddress {
|
||||
dst: register::Single,
|
||||
},
|
||||
// 3.3.1.2, only the loading to (hl) instructions
|
||||
LDToHLAddress {
|
||||
src: register::Single,
|
||||
},
|
||||
}
|
||||
|
||||
struct RunnableInstruction {
|
||||
|
@ -101,6 +105,12 @@ impl RunnableInstruction {
|
|||
0x6C => Self::make_ldr1r2_data(register::Single::L, register::Single::H, data),
|
||||
0x6D => Self::make_ldr1r2_data(register::Single::L, register::Single::L, data),
|
||||
0x6E => Self::make_ld_from_hl_address(register::Single::L, data),
|
||||
0x70 => Self::make_ld_to_hl_address(register::Single::B, data),
|
||||
0x71 => Self::make_ld_to_hl_address(register::Single::C, data),
|
||||
0x72 => Self::make_ld_to_hl_address(register::Single::D, data),
|
||||
0x73 => Self::make_ld_to_hl_address(register::Single::E, data),
|
||||
0x74 => Self::make_ld_to_hl_address(register::Single::H, data),
|
||||
0x75 => Self::make_ld_to_hl_address(register::Single::L, data),
|
||||
_ => panic!("invalid opcode {opcode:0x}"),
|
||||
}
|
||||
}
|
||||
|
@ -141,6 +151,16 @@ impl RunnableInstruction {
|
|||
&data[1..],
|
||||
)
|
||||
}
|
||||
|
||||
fn make_ld_to_hl_address(src: register::Single, data: &[u8]) -> (RunnableInstruction, &[u8]) {
|
||||
(
|
||||
RunnableInstruction {
|
||||
instruction: Instruction::LDToHLAddress { src },
|
||||
cycles: 8,
|
||||
},
|
||||
&data[1..],
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Processor {
|
||||
|
@ -165,6 +185,16 @@ impl Processor {
|
|||
self.registers
|
||||
.set_single_register(dst, memory_value.unwrap());
|
||||
}
|
||||
|
||||
Instruction::LDToHLAddress { src } => {
|
||||
let value = self.registers.get_single_register(src);
|
||||
let dst_address = self.registers.get_combined_register(register::Combined::HL);
|
||||
|
||||
let memory_value = self.memory.set(dst_address.into(), value);
|
||||
if memory_value.is_none() {
|
||||
panic!("invalid address stored in (hl): {dst_address}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.num_cycles += u64::from(instruction.cycles);
|
||||
|
@ -267,7 +297,7 @@ mod tests {
|
|||
#[test_case(0x5E, register::Single::E)]
|
||||
#[test_case(0x66, register::Single::H)]
|
||||
#[test_case(0x6E, register::Single::L)]
|
||||
fn test_load_from_memory(opcode: u8, expected_reigster: register::Single) {
|
||||
fn test_load_from_memory(opcode: u8, expected_register: register::Single) {
|
||||
let mut processor = Processor::default();
|
||||
let set_val = processor.memory.set(0xCCDD, 105);
|
||||
assert_eq!(Some(105), set_val);
|
||||
|
@ -284,7 +314,35 @@ mod tests {
|
|||
processor.run(&ins);
|
||||
assert_eq!(
|
||||
105,
|
||||
processor.registers.get_single_register(expected_reigster)
|
||||
processor.registers.get_single_register(expected_register)
|
||||
);
|
||||
}
|
||||
|
||||
#[test_case(0x70, register::Single::B)]
|
||||
#[test_case(0x71, register::Single::C)]
|
||||
#[test_case(0x72, register::Single::D)]
|
||||
#[test_case(0x73, register::Single::E)]
|
||||
#[test_case(0x74, register::Single::H)]
|
||||
#[test_case(0x75, register::Single::L)]
|
||||
fn test_load_to_memory(opcode: u8, expected_register: register::Single) {
|
||||
let mut processor = Processor::default();
|
||||
// This test does a bit of a sneaky - because we want to use CC as the high/low addresses
|
||||
// in the H/L variants of these tests, but we also want to use it store addreses, we must
|
||||
// be careful that the stored immediate value is also part of the address in these cases.
|
||||
processor
|
||||
.registers
|
||||
.set_single_register(expected_register, 0xCC);
|
||||
|
||||
processor
|
||||
.registers
|
||||
.set_combined_register(register::Combined::HL, 0xCCCC);
|
||||
|
||||
let data = [opcode, 0x10, 0x20];
|
||||
let (ins, extra_data) = RunnableInstruction::from_data(&data);
|
||||
|
||||
assert_eq!(extra_data, &[0x10, 0x20]);
|
||||
|
||||
processor.run(&ins);
|
||||
assert_eq!(Some(0xCC), processor.memory.get(0xCCCC));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue