Cargo fmt
parent
dab6005233
commit
8187596952
|
@ -2,7 +2,13 @@ use crate::register;
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub enum SixteenBitArithmeticInstruction {
|
pub enum SixteenBitArithmeticInstruction {
|
||||||
AddRegisterToHL{operand_register: register::SixteenBit},
|
AddRegisterToHL {
|
||||||
IncrementRegister{operand_register: register::SixteenBit},
|
operand_register: register::SixteenBit,
|
||||||
DecrementRegister{operand_register: register::SixteenBit}
|
},
|
||||||
|
IncrementRegister {
|
||||||
|
operand_register: register::SixteenBit,
|
||||||
|
},
|
||||||
|
DecrementRegister {
|
||||||
|
operand_register: register::SixteenBit,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,28 +29,16 @@ impl OpcodeParser for Parser {
|
||||||
SingleSixteenBit::StackPointer,
|
SingleSixteenBit::StackPointer,
|
||||||
))),
|
))),
|
||||||
|
|
||||||
0x03 => Ok(build_inc_register_data(SixteenBit::Combined(
|
0x03 => Ok(build_inc_register_data(SixteenBit::Combined(Combined::BC))),
|
||||||
Combined::BC,
|
0x13 => Ok(build_inc_register_data(SixteenBit::Combined(Combined::DE))),
|
||||||
))),
|
0x23 => Ok(build_inc_register_data(SixteenBit::Combined(Combined::HL))),
|
||||||
0x13 => Ok(build_inc_register_data(SixteenBit::Combined(
|
|
||||||
Combined::DE,
|
|
||||||
))),
|
|
||||||
0x23 => Ok(build_inc_register_data(SixteenBit::Combined(
|
|
||||||
Combined::HL,
|
|
||||||
))),
|
|
||||||
0x33 => Ok(build_inc_register_data(SixteenBit::Single(
|
0x33 => Ok(build_inc_register_data(SixteenBit::Single(
|
||||||
SingleSixteenBit::StackPointer,
|
SingleSixteenBit::StackPointer,
|
||||||
))),
|
))),
|
||||||
|
|
||||||
0x0B => Ok(build_dec_register_data(SixteenBit::Combined(
|
0x0B => Ok(build_dec_register_data(SixteenBit::Combined(Combined::BC))),
|
||||||
Combined::BC,
|
0x1B => Ok(build_dec_register_data(SixteenBit::Combined(Combined::DE))),
|
||||||
))),
|
0x2B => Ok(build_dec_register_data(SixteenBit::Combined(Combined::HL))),
|
||||||
0x1B => Ok(build_dec_register_data(SixteenBit::Combined(
|
|
||||||
Combined::DE,
|
|
||||||
))),
|
|
||||||
0x2B => Ok(build_dec_register_data(SixteenBit::Combined(
|
|
||||||
Combined::HL,
|
|
||||||
))),
|
|
||||||
0x3B => Ok(build_dec_register_data(SixteenBit::Single(
|
0x3B => Ok(build_dec_register_data(SixteenBit::Single(
|
||||||
SingleSixteenBit::StackPointer,
|
SingleSixteenBit::StackPointer,
|
||||||
))),
|
))),
|
||||||
|
@ -62,7 +50,9 @@ impl OpcodeParser for Parser {
|
||||||
fn build_add_hl_to_register_data(operand_register: SixteenBit) -> ParseOutput {
|
fn build_add_hl_to_register_data(operand_register: SixteenBit) -> ParseOutput {
|
||||||
(
|
(
|
||||||
RunnableInstruction {
|
RunnableInstruction {
|
||||||
instruction: Instruction::SixteenBitArithmetic(SixteenBitArithmeticInstruction::AddRegisterToHL { operand_register }),
|
instruction: Instruction::SixteenBitArithmetic(
|
||||||
|
SixteenBitArithmeticInstruction::AddRegisterToHL { operand_register },
|
||||||
|
),
|
||||||
cycles: 2,
|
cycles: 2,
|
||||||
},
|
},
|
||||||
1,
|
1,
|
||||||
|
@ -72,7 +62,9 @@ fn build_add_hl_to_register_data(operand_register: SixteenBit) -> ParseOutput {
|
||||||
fn build_inc_register_data(operand_register: SixteenBit) -> ParseOutput {
|
fn build_inc_register_data(operand_register: SixteenBit) -> ParseOutput {
|
||||||
(
|
(
|
||||||
RunnableInstruction {
|
RunnableInstruction {
|
||||||
instruction: Instruction::SixteenBitArithmetic(SixteenBitArithmeticInstruction::IncrementRegister { operand_register }),
|
instruction: Instruction::SixteenBitArithmetic(
|
||||||
|
SixteenBitArithmeticInstruction::IncrementRegister { operand_register },
|
||||||
|
),
|
||||||
cycles: 2,
|
cycles: 2,
|
||||||
},
|
},
|
||||||
1,
|
1,
|
||||||
|
@ -82,7 +74,9 @@ fn build_inc_register_data(operand_register: SixteenBit) -> ParseOutput {
|
||||||
fn build_dec_register_data(operand_register: SixteenBit) -> ParseOutput {
|
fn build_dec_register_data(operand_register: SixteenBit) -> ParseOutput {
|
||||||
(
|
(
|
||||||
RunnableInstruction {
|
RunnableInstruction {
|
||||||
instruction: Instruction::SixteenBitArithmetic(SixteenBitArithmeticInstruction::DecrementRegister { operand_register }),
|
instruction: Instruction::SixteenBitArithmetic(
|
||||||
|
SixteenBitArithmeticInstruction::DecrementRegister { operand_register },
|
||||||
|
),
|
||||||
cycles: 2,
|
cycles: 2,
|
||||||
},
|
},
|
||||||
1,
|
1,
|
||||||
|
|
|
@ -7,7 +7,7 @@ use crate::{
|
||||||
register,
|
register,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{ParseOutput, OpcodeParser};
|
use super::{OpcodeParser, ParseOutput};
|
||||||
|
|
||||||
// similar to `arith8::Operand`, but only for the parts that can be uniquely determined from the opcode
|
// similar to `arith8::Operand`, but only for the parts that can be uniquely determined from the opcode
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
@ -48,16 +48,13 @@ impl OpcodeParser for Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn operation_for_opcode(opcode: u8) -> Result<Operation, super::Error> {
|
fn operation_for_opcode(opcode: u8) -> Result<Operation, super::Error> {
|
||||||
operation_for_binary_opcode(opcode)
|
operation_for_binary_opcode(opcode).or_else(|_err| operation_for_unary_opcode(opcode))
|
||||||
.or_else(|_err| operation_for_unary_opcode(opcode))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn operand_for_opcode(opcode: u8) -> Result<OpcodeOperand, super::Error> {
|
fn operand_for_opcode(opcode: u8) -> Result<OpcodeOperand, super::Error> {
|
||||||
operand_for_binary_opcode(opcode)
|
operand_for_binary_opcode(opcode).or_else(|_err| operand_for_unary_opcode(opcode))
|
||||||
.or_else(|_err| operand_for_unary_opcode(opcode))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn operation_for_unary_opcode(opcode: u8) -> Result<Operation, super::Error> {
|
fn operation_for_unary_opcode(opcode: u8) -> Result<Operation, super::Error> {
|
||||||
let operation_nibble = opcode & 0xF0;
|
let operation_nibble = opcode & 0xF0;
|
||||||
let operand_nibble = opcode & 0x0F;
|
let operand_nibble = opcode & 0x0F;
|
||||||
|
@ -65,7 +62,7 @@ fn operation_for_unary_opcode(opcode: u8) -> Result<Operation, super::Error> {
|
||||||
match operation_nibble {
|
match operation_nibble {
|
||||||
0x00..=0x30 if operand_nibble == 0x04 || operand_nibble == 0x0C => Ok(Operation::Inc),
|
0x00..=0x30 if operand_nibble == 0x04 || operand_nibble == 0x0C => Ok(Operation::Inc),
|
||||||
0x00..=0x30 if operand_nibble == 0x05 || operand_nibble == 0x0D => Ok(Operation::Dec),
|
0x00..=0x30 if operand_nibble == 0x05 || operand_nibble == 0x0D => Ok(Operation::Dec),
|
||||||
_ => Err(super::Error::UnknownOpcode(opcode))
|
_ => Err(super::Error::UnknownOpcode(opcode)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,7 +76,7 @@ fn operation_for_binary_opcode(opcode: u8) -> Result<Operation, super::Error> {
|
||||||
0xA8..=0xAF | 0xEE => Ok(Operation::Xor),
|
0xA8..=0xAF | 0xEE => Ok(Operation::Xor),
|
||||||
0xB0..=0xB7 | 0xF6 => Ok(Operation::Or),
|
0xB0..=0xB7 | 0xF6 => Ok(Operation::Or),
|
||||||
0xB8..=0xBF | 0xFE => Ok(Operation::Compare),
|
0xB8..=0xBF | 0xFE => Ok(Operation::Compare),
|
||||||
_ => Err(super::Error::UnknownOpcode(opcode))
|
_ => Err(super::Error::UnknownOpcode(opcode)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,17 +90,17 @@ fn operand_for_unary_opcode(opcode: u8) -> Result<OpcodeOperand, super::Error> {
|
||||||
0x2C | 0x2D => Ok(OpcodeOperand::SingleRegister(register::SingleEightBit::L)),
|
0x2C | 0x2D => Ok(OpcodeOperand::SingleRegister(register::SingleEightBit::L)),
|
||||||
0x34 | 0x35 => Ok(OpcodeOperand::HLAddressValue),
|
0x34 | 0x35 => Ok(OpcodeOperand::HLAddressValue),
|
||||||
0x3C | 0x3D => Ok(OpcodeOperand::SingleRegister(register::SingleEightBit::A)),
|
0x3C | 0x3D => Ok(OpcodeOperand::SingleRegister(register::SingleEightBit::A)),
|
||||||
_ => Err(super::Error::UnknownOpcode(opcode))
|
_ => Err(super::Error::UnknownOpcode(opcode)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn operand_for_binary_opcode(opcode: u8) -> Result<OpcodeOperand, super::Error> {
|
fn operand_for_binary_opcode(opcode: u8) -> Result<OpcodeOperand, super::Error> {
|
||||||
if is_immediate_operation(opcode) {
|
if is_immediate_operation(opcode) {
|
||||||
return Ok(OpcodeOperand::Immediate)
|
return Ok(OpcodeOperand::Immediate);
|
||||||
} else if !matches!(opcode & 0xF0, 0x80..=0xB0){
|
} else if !matches!(opcode & 0xF0, 0x80..=0xB0) {
|
||||||
// If it's not an immediate operation (covered above), or a standard arith operation (covered below),
|
// If it's not an immediate operation (covered above), or a standard arith operation (covered below),
|
||||||
// we shouldn't try and parse it
|
// we shouldn't try and parse it
|
||||||
return Err(super::Error::UnknownOpcode(opcode))
|
return Err(super::Error::UnknownOpcode(opcode));
|
||||||
}
|
}
|
||||||
|
|
||||||
match opcode & 0x07 {
|
match opcode & 0x07 {
|
||||||
|
@ -115,7 +112,7 @@ fn operand_for_binary_opcode(opcode: u8) -> Result<OpcodeOperand, super::Error>
|
||||||
0x05 => Ok(OpcodeOperand::SingleRegister(register::SingleEightBit::L)),
|
0x05 => Ok(OpcodeOperand::SingleRegister(register::SingleEightBit::L)),
|
||||||
0x06 => Ok(OpcodeOperand::HLAddressValue),
|
0x06 => Ok(OpcodeOperand::HLAddressValue),
|
||||||
0x07 => Ok(OpcodeOperand::SingleRegister(register::SingleEightBit::A)),
|
0x07 => Ok(OpcodeOperand::SingleRegister(register::SingleEightBit::A)),
|
||||||
_ => Err(super::Error::UnknownOpcode(opcode))
|
_ => Err(super::Error::UnknownOpcode(opcode)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,7 +190,7 @@ mod tests {
|
||||||
#[test_case(0x86, (Operation::Add, OpcodeOperand::HLAddressValue))]
|
#[test_case(0x86, (Operation::Add, OpcodeOperand::HLAddressValue))]
|
||||||
#[test_case(0x87, (Operation::Add, OpcodeOperand::SingleRegister(register::SingleEightBit::A)))]
|
#[test_case(0x87, (Operation::Add, OpcodeOperand::SingleRegister(register::SingleEightBit::A)))]
|
||||||
#[test_case(0xC6, (Operation::Add, OpcodeOperand::Immediate))]
|
#[test_case(0xC6, (Operation::Add, OpcodeOperand::Immediate))]
|
||||||
|
//
|
||||||
#[test_case(0x88, (Operation::AddWithCarry, OpcodeOperand::SingleRegister(register::SingleEightBit::B)))]
|
#[test_case(0x88, (Operation::AddWithCarry, OpcodeOperand::SingleRegister(register::SingleEightBit::B)))]
|
||||||
#[test_case(0x89, (Operation::AddWithCarry, OpcodeOperand::SingleRegister(register::SingleEightBit::C)))]
|
#[test_case(0x89, (Operation::AddWithCarry, OpcodeOperand::SingleRegister(register::SingleEightBit::C)))]
|
||||||
#[test_case(0x8A, (Operation::AddWithCarry, OpcodeOperand::SingleRegister(register::SingleEightBit::D)))]
|
#[test_case(0x8A, (Operation::AddWithCarry, OpcodeOperand::SingleRegister(register::SingleEightBit::D)))]
|
||||||
|
@ -203,7 +200,7 @@ mod tests {
|
||||||
#[test_case(0x8E, (Operation::AddWithCarry, OpcodeOperand::HLAddressValue))]
|
#[test_case(0x8E, (Operation::AddWithCarry, OpcodeOperand::HLAddressValue))]
|
||||||
#[test_case(0x8F, (Operation::AddWithCarry, OpcodeOperand::SingleRegister(register::SingleEightBit::A)))]
|
#[test_case(0x8F, (Operation::AddWithCarry, OpcodeOperand::SingleRegister(register::SingleEightBit::A)))]
|
||||||
#[test_case(0xCE, (Operation::AddWithCarry, OpcodeOperand::Immediate))]
|
#[test_case(0xCE, (Operation::AddWithCarry, OpcodeOperand::Immediate))]
|
||||||
|
//
|
||||||
#[test_case(0x90, (Operation::Sub, OpcodeOperand::SingleRegister(register::SingleEightBit::B)))]
|
#[test_case(0x90, (Operation::Sub, OpcodeOperand::SingleRegister(register::SingleEightBit::B)))]
|
||||||
#[test_case(0x91, (Operation::Sub, OpcodeOperand::SingleRegister(register::SingleEightBit::C)))]
|
#[test_case(0x91, (Operation::Sub, OpcodeOperand::SingleRegister(register::SingleEightBit::C)))]
|
||||||
#[test_case(0x92, (Operation::Sub, OpcodeOperand::SingleRegister(register::SingleEightBit::D)))]
|
#[test_case(0x92, (Operation::Sub, OpcodeOperand::SingleRegister(register::SingleEightBit::D)))]
|
||||||
|
@ -213,7 +210,7 @@ mod tests {
|
||||||
#[test_case(0x96, (Operation::Sub, OpcodeOperand::HLAddressValue))]
|
#[test_case(0x96, (Operation::Sub, OpcodeOperand::HLAddressValue))]
|
||||||
#[test_case(0x97, (Operation::Sub, OpcodeOperand::SingleRegister(register::SingleEightBit::A)))]
|
#[test_case(0x97, (Operation::Sub, OpcodeOperand::SingleRegister(register::SingleEightBit::A)))]
|
||||||
#[test_case(0xD6, (Operation::Sub, OpcodeOperand::Immediate))]
|
#[test_case(0xD6, (Operation::Sub, OpcodeOperand::Immediate))]
|
||||||
|
//
|
||||||
#[test_case(0x98, (Operation::SubWithCarry, OpcodeOperand::SingleRegister(register::SingleEightBit::B)))]
|
#[test_case(0x98, (Operation::SubWithCarry, OpcodeOperand::SingleRegister(register::SingleEightBit::B)))]
|
||||||
#[test_case(0x99, (Operation::SubWithCarry, OpcodeOperand::SingleRegister(register::SingleEightBit::C)))]
|
#[test_case(0x99, (Operation::SubWithCarry, OpcodeOperand::SingleRegister(register::SingleEightBit::C)))]
|
||||||
#[test_case(0x9A, (Operation::SubWithCarry, OpcodeOperand::SingleRegister(register::SingleEightBit::D)))]
|
#[test_case(0x9A, (Operation::SubWithCarry, OpcodeOperand::SingleRegister(register::SingleEightBit::D)))]
|
||||||
|
@ -223,7 +220,7 @@ mod tests {
|
||||||
#[test_case(0x9E, (Operation::SubWithCarry, OpcodeOperand::HLAddressValue))]
|
#[test_case(0x9E, (Operation::SubWithCarry, OpcodeOperand::HLAddressValue))]
|
||||||
#[test_case(0x9F, (Operation::SubWithCarry, OpcodeOperand::SingleRegister(register::SingleEightBit::A)))]
|
#[test_case(0x9F, (Operation::SubWithCarry, OpcodeOperand::SingleRegister(register::SingleEightBit::A)))]
|
||||||
#[test_case(0xDE, (Operation::SubWithCarry, OpcodeOperand::Immediate))]
|
#[test_case(0xDE, (Operation::SubWithCarry, OpcodeOperand::Immediate))]
|
||||||
|
//
|
||||||
#[test_case(0xA0, (Operation::And, OpcodeOperand::SingleRegister(register::SingleEightBit::B)))]
|
#[test_case(0xA0, (Operation::And, OpcodeOperand::SingleRegister(register::SingleEightBit::B)))]
|
||||||
#[test_case(0xA1, (Operation::And, OpcodeOperand::SingleRegister(register::SingleEightBit::C)))]
|
#[test_case(0xA1, (Operation::And, OpcodeOperand::SingleRegister(register::SingleEightBit::C)))]
|
||||||
#[test_case(0xA2, (Operation::And, OpcodeOperand::SingleRegister(register::SingleEightBit::D)))]
|
#[test_case(0xA2, (Operation::And, OpcodeOperand::SingleRegister(register::SingleEightBit::D)))]
|
||||||
|
@ -233,7 +230,7 @@ mod tests {
|
||||||
#[test_case(0xA6, (Operation::And, OpcodeOperand::HLAddressValue))]
|
#[test_case(0xA6, (Operation::And, OpcodeOperand::HLAddressValue))]
|
||||||
#[test_case(0xA7, (Operation::And, OpcodeOperand::SingleRegister(register::SingleEightBit::A)))]
|
#[test_case(0xA7, (Operation::And, OpcodeOperand::SingleRegister(register::SingleEightBit::A)))]
|
||||||
#[test_case(0xE6, (Operation::And, OpcodeOperand::Immediate))]
|
#[test_case(0xE6, (Operation::And, OpcodeOperand::Immediate))]
|
||||||
|
//
|
||||||
#[test_case(0xA8, (Operation::Xor, OpcodeOperand::SingleRegister(register::SingleEightBit::B)))]
|
#[test_case(0xA8, (Operation::Xor, OpcodeOperand::SingleRegister(register::SingleEightBit::B)))]
|
||||||
#[test_case(0xA9, (Operation::Xor, OpcodeOperand::SingleRegister(register::SingleEightBit::C)))]
|
#[test_case(0xA9, (Operation::Xor, OpcodeOperand::SingleRegister(register::SingleEightBit::C)))]
|
||||||
#[test_case(0xAA, (Operation::Xor, OpcodeOperand::SingleRegister(register::SingleEightBit::D)))]
|
#[test_case(0xAA, (Operation::Xor, OpcodeOperand::SingleRegister(register::SingleEightBit::D)))]
|
||||||
|
@ -243,7 +240,7 @@ mod tests {
|
||||||
#[test_case(0xAE, (Operation::Xor, OpcodeOperand::HLAddressValue))]
|
#[test_case(0xAE, (Operation::Xor, OpcodeOperand::HLAddressValue))]
|
||||||
#[test_case(0xAF, (Operation::Xor, OpcodeOperand::SingleRegister(register::SingleEightBit::A)))]
|
#[test_case(0xAF, (Operation::Xor, OpcodeOperand::SingleRegister(register::SingleEightBit::A)))]
|
||||||
#[test_case(0xEE, (Operation::Xor, OpcodeOperand::Immediate))]
|
#[test_case(0xEE, (Operation::Xor, OpcodeOperand::Immediate))]
|
||||||
|
//
|
||||||
#[test_case(0xB0, (Operation::Or, OpcodeOperand::SingleRegister(register::SingleEightBit::B)))]
|
#[test_case(0xB0, (Operation::Or, OpcodeOperand::SingleRegister(register::SingleEightBit::B)))]
|
||||||
#[test_case(0xB1, (Operation::Or, OpcodeOperand::SingleRegister(register::SingleEightBit::C)))]
|
#[test_case(0xB1, (Operation::Or, OpcodeOperand::SingleRegister(register::SingleEightBit::C)))]
|
||||||
#[test_case(0xB2, (Operation::Or, OpcodeOperand::SingleRegister(register::SingleEightBit::D)))]
|
#[test_case(0xB2, (Operation::Or, OpcodeOperand::SingleRegister(register::SingleEightBit::D)))]
|
||||||
|
@ -253,7 +250,7 @@ mod tests {
|
||||||
#[test_case(0xB6, (Operation::Or, OpcodeOperand::HLAddressValue))]
|
#[test_case(0xB6, (Operation::Or, OpcodeOperand::HLAddressValue))]
|
||||||
#[test_case(0xB7, (Operation::Or, OpcodeOperand::SingleRegister(register::SingleEightBit::A)))]
|
#[test_case(0xB7, (Operation::Or, OpcodeOperand::SingleRegister(register::SingleEightBit::A)))]
|
||||||
#[test_case(0xF6, (Operation::Or, OpcodeOperand::Immediate))]
|
#[test_case(0xF6, (Operation::Or, OpcodeOperand::Immediate))]
|
||||||
|
//
|
||||||
#[test_case(0xB8, (Operation::Compare, OpcodeOperand::SingleRegister(register::SingleEightBit::B)))]
|
#[test_case(0xB8, (Operation::Compare, OpcodeOperand::SingleRegister(register::SingleEightBit::B)))]
|
||||||
#[test_case(0xB9, (Operation::Compare, OpcodeOperand::SingleRegister(register::SingleEightBit::C)))]
|
#[test_case(0xB9, (Operation::Compare, OpcodeOperand::SingleRegister(register::SingleEightBit::C)))]
|
||||||
#[test_case(0xBA, (Operation::Compare, OpcodeOperand::SingleRegister(register::SingleEightBit::D)))]
|
#[test_case(0xBA, (Operation::Compare, OpcodeOperand::SingleRegister(register::SingleEightBit::D)))]
|
||||||
|
@ -263,7 +260,7 @@ mod tests {
|
||||||
#[test_case(0xBE, (Operation::Compare, OpcodeOperand::HLAddressValue))]
|
#[test_case(0xBE, (Operation::Compare, OpcodeOperand::HLAddressValue))]
|
||||||
#[test_case(0xBF, (Operation::Compare, OpcodeOperand::SingleRegister(register::SingleEightBit::A)))]
|
#[test_case(0xBF, (Operation::Compare, OpcodeOperand::SingleRegister(register::SingleEightBit::A)))]
|
||||||
#[test_case(0xFE, (Operation::Compare, OpcodeOperand::Immediate))]
|
#[test_case(0xFE, (Operation::Compare, OpcodeOperand::Immediate))]
|
||||||
|
//
|
||||||
#[test_case(0x04, (Operation::Inc, OpcodeOperand::SingleRegister(register::SingleEightBit::B)))]
|
#[test_case(0x04, (Operation::Inc, OpcodeOperand::SingleRegister(register::SingleEightBit::B)))]
|
||||||
#[test_case(0x0C, (Operation::Inc, OpcodeOperand::SingleRegister(register::SingleEightBit::C)))]
|
#[test_case(0x0C, (Operation::Inc, OpcodeOperand::SingleRegister(register::SingleEightBit::C)))]
|
||||||
#[test_case(0x14, (Operation::Inc, OpcodeOperand::SingleRegister(register::SingleEightBit::D)))]
|
#[test_case(0x14, (Operation::Inc, OpcodeOperand::SingleRegister(register::SingleEightBit::D)))]
|
||||||
|
@ -272,7 +269,7 @@ mod tests {
|
||||||
#[test_case(0x2C, (Operation::Inc, OpcodeOperand::SingleRegister(register::SingleEightBit::L)))]
|
#[test_case(0x2C, (Operation::Inc, OpcodeOperand::SingleRegister(register::SingleEightBit::L)))]
|
||||||
#[test_case(0x34, (Operation::Inc, OpcodeOperand::HLAddressValue))]
|
#[test_case(0x34, (Operation::Inc, OpcodeOperand::HLAddressValue))]
|
||||||
#[test_case(0x3C, (Operation::Inc, OpcodeOperand::SingleRegister(register::SingleEightBit::A)))]
|
#[test_case(0x3C, (Operation::Inc, OpcodeOperand::SingleRegister(register::SingleEightBit::A)))]
|
||||||
|
//
|
||||||
#[test_case(0x05, (Operation::Dec, OpcodeOperand::SingleRegister(register::SingleEightBit::B)))]
|
#[test_case(0x05, (Operation::Dec, OpcodeOperand::SingleRegister(register::SingleEightBit::B)))]
|
||||||
#[test_case(0x0D, (Operation::Dec, OpcodeOperand::SingleRegister(register::SingleEightBit::C)))]
|
#[test_case(0x0D, (Operation::Dec, OpcodeOperand::SingleRegister(register::SingleEightBit::C)))]
|
||||||
#[test_case(0x15, (Operation::Dec, OpcodeOperand::SingleRegister(register::SingleEightBit::D)))]
|
#[test_case(0x15, (Operation::Dec, OpcodeOperand::SingleRegister(register::SingleEightBit::D)))]
|
||||||
|
|
|
@ -31,7 +31,7 @@ fn parse_destination_register(opcode: u8) -> Result<register::SingleEightBit, pa
|
||||||
0x60 if offset <= 7 => Ok(register::SingleEightBit::H),
|
0x60 if offset <= 7 => Ok(register::SingleEightBit::H),
|
||||||
0x60 if offset > 7 => Ok(register::SingleEightBit::L),
|
0x60 if offset > 7 => Ok(register::SingleEightBit::L),
|
||||||
0x70 if offset > 7 => Ok(register::SingleEightBit::A),
|
0x70 if offset > 7 => Ok(register::SingleEightBit::A),
|
||||||
_ => Err(Error::UnknownOpcode(opcode))
|
_ => Err(Error::UnknownOpcode(opcode)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ fn parse_source_register(opcode: u8) -> Result<register::SingleEightBit, parse::
|
||||||
0x04 => Ok(register::SingleEightBit::H),
|
0x04 => Ok(register::SingleEightBit::H),
|
||||||
0x05 => Ok(register::SingleEightBit::L),
|
0x05 => Ok(register::SingleEightBit::L),
|
||||||
0x07 => Ok(register::SingleEightBit::A),
|
0x07 => Ok(register::SingleEightBit::A),
|
||||||
_ => Err(Error::UnknownOpcode(opcode))
|
_ => Err(Error::UnknownOpcode(opcode)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,6 @@ pub fn run_instruction(processor: &mut Processor, instruction: Instruction) -> R
|
||||||
Instruction::EightBitLoad(load_instruction) => load_instruction.run_on(processor),
|
Instruction::EightBitLoad(load_instruction) => load_instruction.run_on(processor),
|
||||||
Instruction::SixteenBitLoad(load_instruction) => load_instruction.run_on(processor),
|
Instruction::SixteenBitLoad(load_instruction) => load_instruction.run_on(processor),
|
||||||
Instruction::EightBitArithmetic(arith_instruction) => arith_instruction.run_on(processor),
|
Instruction::EightBitArithmetic(arith_instruction) => arith_instruction.run_on(processor),
|
||||||
Instruction::SixteenBitArithmetic(arith_instruction) => arith_instruction.run_on(processor)
|
Instruction::SixteenBitArithmetic(arith_instruction) => arith_instruction.run_on(processor),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{cpu::instructions::arith16::SixteenBitArithmeticInstruction, register};
|
use crate::{cpu::instructions::arith16::SixteenBitArithmeticInstruction, register};
|
||||||
|
|
||||||
use super::{Run, arithutil::CarryingAdd};
|
use super::{arithutil::CarryingAdd, Run};
|
||||||
|
|
||||||
impl Run for SixteenBitArithmeticInstruction {
|
impl Run for SixteenBitArithmeticInstruction {
|
||||||
fn run_on(&self, processor: &mut crate::cpu::Processor) -> Result<(), super::Error> {
|
fn run_on(&self, processor: &mut crate::cpu::Processor) -> Result<(), super::Error> {
|
||||||
|
@ -8,7 +8,9 @@ impl Run for SixteenBitArithmeticInstruction {
|
||||||
SixteenBitArithmeticInstruction::IncrementRegister { operand_register } => {
|
SixteenBitArithmeticInstruction::IncrementRegister { operand_register } => {
|
||||||
let register_value = processor.registers.get_16bit_register(operand_register);
|
let register_value = processor.registers.get_16bit_register(operand_register);
|
||||||
let incremented_value = register_value.wrapping_add(1);
|
let incremented_value = register_value.wrapping_add(1);
|
||||||
processor.registers.set_16bit_register(operand_register, incremented_value);
|
processor
|
||||||
|
.registers
|
||||||
|
.set_16bit_register(operand_register, incremented_value);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -16,20 +18,32 @@ impl Run for SixteenBitArithmeticInstruction {
|
||||||
SixteenBitArithmeticInstruction::DecrementRegister { operand_register } => {
|
SixteenBitArithmeticInstruction::DecrementRegister { operand_register } => {
|
||||||
let register_value = processor.registers.get_16bit_register(operand_register);
|
let register_value = processor.registers.get_16bit_register(operand_register);
|
||||||
let decremented_value = register_value.wrapping_sub(1);
|
let decremented_value = register_value.wrapping_sub(1);
|
||||||
processor.registers.set_16bit_register(operand_register, decremented_value);
|
processor
|
||||||
|
.registers
|
||||||
|
.set_16bit_register(operand_register, decremented_value);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
SixteenBitArithmeticInstruction::AddRegisterToHL { operand_register } => {
|
SixteenBitArithmeticInstruction::AddRegisterToHL { operand_register } => {
|
||||||
let operand1 = processor.registers.get_combined_register(register::Combined::HL);
|
let operand1 = processor
|
||||||
|
.registers
|
||||||
|
.get_combined_register(register::Combined::HL);
|
||||||
let operand2 = processor.registers.get_16bit_register(operand_register);
|
let operand2 = processor.registers.get_16bit_register(operand_register);
|
||||||
let (value, half_carry, carry) = operand1.add_with_carry(operand2);
|
let (value, half_carry, carry) = operand1.add_with_carry(operand2);
|
||||||
processor.registers.set_combined_register(register::Combined::HL, value);
|
processor
|
||||||
|
.registers
|
||||||
|
.set_combined_register(register::Combined::HL, value);
|
||||||
|
|
||||||
processor.registers.set_flag_bit(register::Flag::Carry, carry.into());
|
processor
|
||||||
processor.registers.set_flag_bit(register::Flag::HalfCarry, half_carry.into());
|
.registers
|
||||||
processor.registers.set_flag_bit(register::Flag::Subtract, 0);
|
.set_flag_bit(register::Flag::Carry, carry.into());
|
||||||
|
processor
|
||||||
|
.registers
|
||||||
|
.set_flag_bit(register::Flag::HalfCarry, half_carry.into());
|
||||||
|
processor
|
||||||
|
.registers
|
||||||
|
.set_flag_bit(register::Flag::Subtract, 0);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,10 @@ struct AdditionOperationFlags {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_add_hl_to_itself() {
|
fn test_add_hl_to_itself() {
|
||||||
let mut processor = Processor::default();
|
let mut processor = Processor::default();
|
||||||
processor.registers.set_16bit_register(register::SixteenBit::Combined(register::Combined::HL), 0x2244);
|
processor.registers.set_16bit_register(
|
||||||
|
register::SixteenBit::Combined(register::Combined::HL),
|
||||||
|
0x2244,
|
||||||
|
);
|
||||||
let data = [0x29, 0x02];
|
let data = [0x29, 0x02];
|
||||||
|
|
||||||
let (ins, extra_data) =
|
let (ins, extra_data) =
|
||||||
|
@ -24,7 +27,12 @@ fn test_add_hl_to_itself() {
|
||||||
|
|
||||||
processor.run_instruction(&ins);
|
processor.run_instruction(&ins);
|
||||||
|
|
||||||
assert_eq!(0x4488, processor.registers.get_combined_register(register::Combined::HL));
|
assert_eq!(
|
||||||
|
0x4488,
|
||||||
|
processor
|
||||||
|
.registers
|
||||||
|
.get_combined_register(register::Combined::HL)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test_matrix(
|
#[test_matrix(
|
||||||
|
@ -38,10 +46,18 @@ fn test_add_hl_to_itself() {
|
||||||
(0xFFFF, 0x0002, 0x0001),
|
(0xFFFF, 0x0002, 0x0001),
|
||||||
]
|
]
|
||||||
)]
|
)]
|
||||||
fn test_add_hl_to_registers_value((opcode, operand_register): (u8, register::SixteenBit), (hl_value, operand_value, expected): (u16, u16, u16)) {
|
fn test_add_hl_to_registers_value(
|
||||||
|
(opcode, operand_register): (u8, register::SixteenBit),
|
||||||
|
(hl_value, operand_value, expected): (u16, u16, u16),
|
||||||
|
) {
|
||||||
let mut processor = Processor::default();
|
let mut processor = Processor::default();
|
||||||
processor.registers.set_16bit_register(register::SixteenBit::Combined(register::Combined::HL), hl_value);
|
processor.registers.set_16bit_register(
|
||||||
processor.registers.set_16bit_register(operand_register, operand_value);
|
register::SixteenBit::Combined(register::Combined::HL),
|
||||||
|
hl_value,
|
||||||
|
);
|
||||||
|
processor
|
||||||
|
.registers
|
||||||
|
.set_16bit_register(operand_register, operand_value);
|
||||||
let data = [opcode, 0x02];
|
let data = [opcode, 0x02];
|
||||||
|
|
||||||
let (ins, extra_data) =
|
let (ins, extra_data) =
|
||||||
|
@ -50,7 +66,12 @@ fn test_add_hl_to_registers_value((opcode, operand_register): (u8, register::Six
|
||||||
|
|
||||||
processor.run_instruction(&ins);
|
processor.run_instruction(&ins);
|
||||||
|
|
||||||
assert_eq!(expected, processor.registers.get_combined_register(register::Combined::HL));
|
assert_eq!(
|
||||||
|
expected,
|
||||||
|
processor
|
||||||
|
.registers
|
||||||
|
.get_combined_register(register::Combined::HL)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test_matrix(
|
#[test_matrix(
|
||||||
|
@ -67,10 +88,18 @@ fn test_add_hl_to_registers_value((opcode, operand_register): (u8, register::Six
|
||||||
(0x8000, 0xC000, AdditionOperationFlags{ half_carry: 0, carry: 1}),
|
(0x8000, 0xC000, AdditionOperationFlags{ half_carry: 0, carry: 1}),
|
||||||
]
|
]
|
||||||
)]
|
)]
|
||||||
fn test_add_hl_to_registers_flags((opcode, operand_register): (u8, register::SixteenBit), (hl_value, operand_value, expected_flags): (u16, u16, AdditionOperationFlags)) {
|
fn test_add_hl_to_registers_flags(
|
||||||
|
(opcode, operand_register): (u8, register::SixteenBit),
|
||||||
|
(hl_value, operand_value, expected_flags): (u16, u16, AdditionOperationFlags),
|
||||||
|
) {
|
||||||
let mut processor = Processor::default();
|
let mut processor = Processor::default();
|
||||||
processor.registers.set_16bit_register(register::SixteenBit::Combined(register::Combined::HL), hl_value);
|
processor.registers.set_16bit_register(
|
||||||
processor.registers.set_16bit_register(operand_register, operand_value);
|
register::SixteenBit::Combined(register::Combined::HL),
|
||||||
|
hl_value,
|
||||||
|
);
|
||||||
|
processor
|
||||||
|
.registers
|
||||||
|
.set_16bit_register(operand_register, operand_value);
|
||||||
let data = [opcode, 0x02];
|
let data = [opcode, 0x02];
|
||||||
|
|
||||||
let (ins, extra_data) =
|
let (ins, extra_data) =
|
||||||
|
@ -80,12 +109,7 @@ fn test_add_hl_to_registers_flags((opcode, operand_register): (u8, register::Six
|
||||||
// Set all the register to the opposite we expect to ensure they all get set
|
// Set all the register to the opposite we expect to ensure they all get set
|
||||||
testutil::set_opposite_of_expected_flags(
|
testutil::set_opposite_of_expected_flags(
|
||||||
&mut processor,
|
&mut processor,
|
||||||
(
|
(0, 0, expected_flags.half_carry, expected_flags.carry),
|
||||||
0,
|
|
||||||
0,
|
|
||||||
expected_flags.half_carry,
|
|
||||||
expected_flags.carry,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
processor.run_instruction(&ins);
|
processor.run_instruction(&ins);
|
||||||
|
@ -112,10 +136,18 @@ fn test_add_hl_to_registers_flags((opcode, operand_register): (u8, register::Six
|
||||||
(0x0000, 0x0001),
|
(0x0000, 0x0001),
|
||||||
]
|
]
|
||||||
)]
|
)]
|
||||||
fn test_increment((opcode, operand_register): (u8, register::SixteenBit), (start_value, expected): (u16, u16)) {
|
fn test_increment(
|
||||||
|
(opcode, operand_register): (u8, register::SixteenBit),
|
||||||
|
(start_value, expected): (u16, u16),
|
||||||
|
) {
|
||||||
let mut processor = Processor::default();
|
let mut processor = Processor::default();
|
||||||
processor.registers.set_16bit_register(operand_register, start_value);
|
processor
|
||||||
processor.registers.set_raw_flag_bits(0xA0).expect("Failed to set flag bits");
|
.registers
|
||||||
|
.set_16bit_register(operand_register, start_value);
|
||||||
|
processor
|
||||||
|
.registers
|
||||||
|
.set_raw_flag_bits(0xA0)
|
||||||
|
.expect("Failed to set flag bits");
|
||||||
let data = [opcode, 0x02];
|
let data = [opcode, 0x02];
|
||||||
|
|
||||||
let (ins, extra_data) =
|
let (ins, extra_data) =
|
||||||
|
@ -124,7 +156,10 @@ fn test_increment((opcode, operand_register): (u8, register::SixteenBit), (start
|
||||||
|
|
||||||
processor.run_instruction(&ins);
|
processor.run_instruction(&ins);
|
||||||
|
|
||||||
assert_eq!(expected, processor.registers.get_16bit_register(operand_register));
|
assert_eq!(
|
||||||
|
expected,
|
||||||
|
processor.registers.get_16bit_register(operand_register)
|
||||||
|
);
|
||||||
// Flags are untouched
|
// Flags are untouched
|
||||||
assert_eq!(0xA0, processor.registers.get_raw_flag_bits());
|
assert_eq!(0xA0, processor.registers.get_raw_flag_bits());
|
||||||
}
|
}
|
||||||
|
@ -142,10 +177,18 @@ fn test_increment((opcode, operand_register): (u8, register::SixteenBit), (start
|
||||||
(0x0001, 0x0000),
|
(0x0001, 0x0000),
|
||||||
]
|
]
|
||||||
)]
|
)]
|
||||||
fn test_decrement((opcode, operand_register): (u8, register::SixteenBit), (start_value, expected): (u16, u16)) {
|
fn test_decrement(
|
||||||
|
(opcode, operand_register): (u8, register::SixteenBit),
|
||||||
|
(start_value, expected): (u16, u16),
|
||||||
|
) {
|
||||||
let mut processor = Processor::default();
|
let mut processor = Processor::default();
|
||||||
processor.registers.set_16bit_register(operand_register, start_value);
|
processor
|
||||||
processor.registers.set_raw_flag_bits(0xA0).expect("Failed to set flag bits");
|
.registers
|
||||||
|
.set_16bit_register(operand_register, start_value);
|
||||||
|
processor
|
||||||
|
.registers
|
||||||
|
.set_raw_flag_bits(0xA0)
|
||||||
|
.expect("Failed to set flag bits");
|
||||||
let data = [opcode, 0x02];
|
let data = [opcode, 0x02];
|
||||||
|
|
||||||
let (ins, extra_data) =
|
let (ins, extra_data) =
|
||||||
|
@ -154,7 +197,10 @@ fn test_decrement((opcode, operand_register): (u8, register::SixteenBit), (start
|
||||||
|
|
||||||
processor.run_instruction(&ins);
|
processor.run_instruction(&ins);
|
||||||
|
|
||||||
assert_eq!(expected, processor.registers.get_16bit_register(operand_register));
|
assert_eq!(
|
||||||
|
expected,
|
||||||
|
processor.registers.get_16bit_register(operand_register)
|
||||||
|
);
|
||||||
// Flags are untouched
|
// Flags are untouched
|
||||||
assert_eq!(0xA0, processor.registers.get_raw_flag_bits());
|
assert_eq!(0xA0, processor.registers.get_raw_flag_bits());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
mod arith8;
|
|
||||||
mod arith16;
|
mod arith16;
|
||||||
|
mod arith8;
|
||||||
mod jsmoo;
|
mod jsmoo;
|
||||||
mod load16;
|
mod load16;
|
||||||
mod load8;
|
mod load8;
|
||||||
|
|
Loading…
Reference in New Issue