Fix bug where lower 8 bits of the F register were used
This should never happenold-bit-manip
parent
a8ee2bc391
commit
a593664e43
|
@ -110,6 +110,7 @@ impl InstructionRunner<SixteenBitLoadInstruction> for SixteenBitLoadRunner {
|
|||
];
|
||||
|
||||
let popped_value = u16::from_le_bytes(popped_bytes);
|
||||
println!("{popped_value:x}");
|
||||
|
||||
processor.registers.set_combined_register(dst, popped_value);
|
||||
processor.registers.set_16bit_register(
|
||||
|
|
|
@ -210,7 +210,12 @@ impl Registers {
|
|||
let [left_value, right_value] = value.to_be_bytes();
|
||||
|
||||
*left_register = left_value;
|
||||
*right_register = right_value;
|
||||
if let Combined::AF = registers {
|
||||
// Special case: the lower 4 bits of F can _NEVER_ be set.
|
||||
*right_register = right_value & 0xF0;
|
||||
} else {
|
||||
*right_register = right_value;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: These two could be simplified with macros
|
||||
|
@ -258,12 +263,12 @@ mod tests {
|
|||
#[test_case(Combined::HL)]
|
||||
fn test_combined_registers(registers: Combined) {
|
||||
let mut register = Registers::new();
|
||||
register.set_combined_register(registers, 0xF0_0F);
|
||||
register.set_combined_register(registers, 0xF0_40);
|
||||
|
||||
let stored_value = register.get_combined_register(registers);
|
||||
assert_eq!(
|
||||
0xF0_0F, stored_value,
|
||||
"got {stored_value:0x}, expected 0xF0_0F"
|
||||
0xF0_40, stored_value,
|
||||
"got {stored_value:0x}, expected 0xF0_40"
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -322,7 +327,6 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
#[test_case(Combined::AF)]
|
||||
#[test_case(Combined::BC)]
|
||||
#[test_case(Combined::DE)]
|
||||
#[test_case(Combined::HL)]
|
||||
|
@ -333,6 +337,14 @@ mod tests {
|
|||
assert_eq!(0x1122, registers.get_combined_register(register));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_set_sixteen_bit_register_combined_zeroes_lower_4_bits_on_af() {
|
||||
let mut registers = Registers::new();
|
||||
registers.set_16bit_register(SixteenBit::Combined(Combined::AF), 0x1122);
|
||||
|
||||
assert_eq!(0x1120, registers.get_combined_register(Combined::AF));
|
||||
}
|
||||
|
||||
#[test_case(SingleSixteenBit::StackPointer)]
|
||||
#[test_case(SingleSixteenBit::ProgramCounter)]
|
||||
fn test_set_sixteen_bit_register_single(register: SingleSixteenBit) {
|
||||
|
|
|
@ -157,7 +157,6 @@ fn test_load_effective_address_flags(starting_sp: u16, add_value: i8, half_carry
|
|||
);
|
||||
}
|
||||
|
||||
#[test_case(0xF5, register::Combined::AF)]
|
||||
#[test_case(0xC5, register::Combined::BC)]
|
||||
#[test_case(0xD5, register::Combined::DE)]
|
||||
#[test_case(0xE5, register::Combined::HL)]
|
||||
|
@ -180,7 +179,26 @@ fn test_stack_push(opcode: u8, src: register::Combined) {
|
|||
assert_eq!(0xFFFE - 2, processor.registers.stack_pointer);
|
||||
}
|
||||
|
||||
#[test_case(0xF1, register::Combined::AF)]
|
||||
#[test]
|
||||
fn test_stack_push_from_af() {
|
||||
let mut processor = Processor::default();
|
||||
processor.registers.set_combined_register(register::Combined::AF, 0x1234);
|
||||
processor.registers.stack_pointer = 0xFFFE;
|
||||
let data = [0xF5, 0x01];
|
||||
|
||||
let (ins, extra_data) =
|
||||
RunnableInstruction::from_data(&data).expect("could not parse instruction");
|
||||
|
||||
assert_eq!(extra_data, &[0x01]);
|
||||
processor.run_instruction(&ins);
|
||||
|
||||
// we want to pop the LSB first (i.e. we write the MSB first)
|
||||
// https://rgbds.gbdev.io/docs/v0.5.2/gbz80.7#PUSH_r16
|
||||
assert_eq!(0x12, processor.memory.get(0xFFFE - 1).unwrap());
|
||||
assert_eq!(0x30, processor.memory.get(0xFFFE - 2).unwrap());
|
||||
assert_eq!(0xFFFE - 2, processor.registers.stack_pointer);
|
||||
}
|
||||
|
||||
#[test_case(0xC1, register::Combined::BC)]
|
||||
#[test_case(0xD1, register::Combined::DE)]
|
||||
#[test_case(0xE1, register::Combined::HL)]
|
||||
|
@ -202,3 +220,23 @@ fn test_stack_pop(opcode: u8, dst: register::Combined) {
|
|||
assert_eq!(0x1234, processor.registers.get_combined_register(dst));
|
||||
assert_eq!(0xFFF0 + 2, processor.registers.stack_pointer);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stack_pop_to_af() {
|
||||
let mut processor = Processor::default();
|
||||
processor.registers.stack_pointer = 0xFFF0;
|
||||
processor
|
||||
.memory
|
||||
.set_both(((0xFFF0, 0x34), (0xFFF1, 0x12)))
|
||||
.expect("failed to set values in memory");
|
||||
let data = [0xF1, 0x01];
|
||||
|
||||
let (ins, extra_data) =
|
||||
RunnableInstruction::from_data(&data).expect("could not parse instruction");
|
||||
|
||||
assert_eq!(extra_data, &[0x01]);
|
||||
processor.run_instruction(&ins);
|
||||
|
||||
assert_eq!(0x1230, processor.registers.get_combined_register(register::Combined::AF));
|
||||
assert_eq!(0xFFF0 + 2, processor.registers.stack_pointer);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue