add support for ADC with immediate
parent
e416e607df
commit
6ac4ed5d7c
|
@ -9,4 +9,5 @@ pub enum EightBitArithmeticInstruction {
|
|||
AddImmediateToA { n: u8 },
|
||||
AddHLAddressToA,
|
||||
AddSingleRegisterToAWithCarry { src: register::SingleEightBit },
|
||||
AddImmediateToAWithCarry { n: u8 },
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ impl OpcodeParser for EightBitAddParser {
|
|||
0x8B => build_add_register_to_a_with_carry_data(register::SingleEightBit::E, data),
|
||||
0x8C => build_add_register_to_a_with_carry_data(register::SingleEightBit::H, data),
|
||||
0x8D => build_add_register_to_a_with_carry_data(register::SingleEightBit::L, data),
|
||||
0xCE => build_add_immediate_to_a_with_carry_data(data),
|
||||
_ => Err(Error::UnknownOpcode(opcode)),
|
||||
}
|
||||
}
|
||||
|
@ -98,3 +99,18 @@ fn build_add_immediate_to_a_data(data: &[u8]) -> ParseResult {
|
|||
&data[2..],
|
||||
))
|
||||
}
|
||||
|
||||
fn build_add_immediate_to_a_with_carry_data(data: &[u8]) -> ParseResult {
|
||||
let opcode = parse::get_opcode_from_data(data)?;
|
||||
let n = data.get(1).copied().ok_or(Error::NotEnoughArgs(opcode))?;
|
||||
|
||||
Ok((
|
||||
RunnableInstruction {
|
||||
instruction: Instruction::EightBitArithmetic(
|
||||
EightBitArithmeticInstruction::AddImmediateToAWithCarry { n },
|
||||
),
|
||||
cycles: 8,
|
||||
},
|
||||
&data[2..],
|
||||
))
|
||||
}
|
||||
|
|
|
@ -97,6 +97,24 @@ impl InstructionRunner<EightBitArithmeticInstruction> for EightBitArithmeticRunn
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
EightBitArithmeticInstruction::AddImmediateToAWithCarry { n } => {
|
||||
let a_value = processor.registers.a;
|
||||
let carried_operand = arithutil::CarriedNumber::new(
|
||||
n,
|
||||
processor.registers.get_flag_bit(register::Flag::Carry),
|
||||
)
|
||||
.map_err(|err| match err {
|
||||
arithutil::Error::InvalidCarryBit(value) => Error::InvalidCarryFlagValue(value),
|
||||
})?;
|
||||
|
||||
let (result, half_carry, carry) = a_value.add_with_carry(carried_operand);
|
||||
|
||||
processor.registers.a = result;
|
||||
set_addition_flags(processor, result, half_carry, carry);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -361,3 +361,57 @@ fn test_add_register_with_carry_to_a_flags(
|
|||
(register::Flag::Carry, expected_flags.carry),
|
||||
);
|
||||
}
|
||||
|
||||
#[test_case(0x01, 0x00, 0x02, 0x03; "no carry")]
|
||||
#[test_case(0x01, 0x01, 0x02, 0x04; "carry")]
|
||||
fn test_add_immediate_with_carry_to_a_value(
|
||||
initial_value: u8,
|
||||
carry_bit: u8,
|
||||
operand: u8,
|
||||
expected_value: u8,
|
||||
) {
|
||||
let mut processor = Processor::default();
|
||||
processor.registers.a = initial_value;
|
||||
processor
|
||||
.registers
|
||||
.set_flag_bit(register::Flag::Carry, carry_bit);
|
||||
let data = [0xCE, operand, 0x01];
|
||||
|
||||
let (ins, extra_data) =
|
||||
RunnableInstruction::from_data(&data).expect("could not parse instruction");
|
||||
assert_eq!(extra_data, &[0x01]);
|
||||
processor.run(&ins);
|
||||
|
||||
assert_eq!(processor.registers.a, expected_value);
|
||||
}
|
||||
|
||||
#[test_case(0x01, 0, 0x02, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "no carry")]
|
||||
#[test_case(0xFF, 1, 0x00, AdditionOperationFlags{zero: 1, half_carry: 1, carry: 1}; "all flags")]
|
||||
#[test_case(0x0F, 1, 0x80, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "half carry flag")]
|
||||
#[test_case(0xF0, 1, 0xF0, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 1}; "full carry flag")]
|
||||
fn test_add_immediate_with_carry_to_a_flags(
|
||||
initial_value: u8,
|
||||
carry_bit: u8,
|
||||
operand: u8,
|
||||
expected_flags: AdditionOperationFlags,
|
||||
) {
|
||||
let mut processor = Processor::default();
|
||||
processor.registers.a = initial_value;
|
||||
processor
|
||||
.registers
|
||||
.set_flag_bit(register::Flag::Carry, carry_bit);
|
||||
let data = [0xCE, operand, 0x01];
|
||||
|
||||
let (ins, extra_data) =
|
||||
RunnableInstruction::from_data(&data).expect("could not parse instruction");
|
||||
assert_eq!(extra_data, &[0x01]);
|
||||
processor.run(&ins);
|
||||
|
||||
testutil::assert_flags_eq!(
|
||||
processor,
|
||||
(register::Flag::Zero, expected_flags.zero),
|
||||
(register::Flag::Subtract, 0),
|
||||
(register::Flag::HalfCarry, expected_flags.half_carry),
|
||||
(register::Flag::Carry, expected_flags.carry),
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue