Fix bug where lower 8 bits of the F register were used

This should never happen
old-bit-manip
Nick Krichevsky 2023-04-30 21:13:01 -04:00
parent a8ee2bc391
commit a593664e43
3 changed files with 58 additions and 7 deletions

View File

@ -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(

View File

@ -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) {

View File

@ -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);
}