chore: clean up some instruction code

This commit is contained in:
Rekai Nyangadzayi Musuka 2021-03-23 02:11:40 -05:00
parent 6f11640f24
commit 1b7d778c1d
1 changed files with 139 additions and 140 deletions

View File

@ -132,11 +132,10 @@ impl Instruction {
} }
(LDTarget::RegisterPair(pair), LDTarget::ImmediateWord(nn)) => { (LDTarget::RegisterPair(pair), LDTarget::ImmediateWord(nn)) => {
// LD rp[p], nn | Put value nn into register pair // LD rp[p], nn | Put value nn into register pair
use RegisterPair::*;
match pair { match pair {
RegisterPair::BC BC | DE | HL | SP => cpu.set_register_pair(pair, nn),
| RegisterPair::DE
| RegisterPair::HL
| RegisterPair::SP => cpu.set_register_pair(pair, nn),
_ => unreachable!("There is no \"LD {:?}, nn\" instruction", pair), _ => unreachable!("There is no \"LD {:?}, nn\" instruction", pair),
} }
Cycles::new(12) Cycles::new(12)
@ -231,38 +230,40 @@ impl Instruction {
} }
(LDTarget::Register(lhs), LDTarget::Register(rhs)) => { (LDTarget::Register(lhs), LDTarget::Register(rhs)) => {
// LD r[y], r[z] | Store value of RHS Register in LHS Register // LD r[y], r[z] | Store value of RHS Register in LHS Register
use InstrRegister::*;
let rhs_value = { match rhs {
match rhs { B | C | D | E | H | L | A => {
InstrRegister::B let right = cpu.register(rhs.to_register());
| InstrRegister::C
| InstrRegister::D match lhs {
| InstrRegister::E B | C | D | E | H | L | A => {
| InstrRegister::H cpu.set_register(lhs.to_register(), right);
| InstrRegister::L Cycles::new(4)
| InstrRegister::A => cpu.register(rhs.to_register()), }
InstrRegister::IndirectHL => { IndirectHL => {
let addr = cpu.register_pair(RegisterPair::HL); let addr = cpu.register_pair(RegisterPair::HL);
cpu.read_byte(addr) cpu.write_byte(addr, right);
Cycles::new(8)
}
} }
} }
}; IndirectHL => {
match lhs {
InstrRegister::B
| InstrRegister::C
| InstrRegister::D
| InstrRegister::E
| InstrRegister::H
| InstrRegister::L
| InstrRegister::A => {
cpu.set_register(lhs.to_register(), rhs_value);
Cycles::new(4)
}
InstrRegister::IndirectHL => {
let addr = cpu.register_pair(RegisterPair::HL); let addr = cpu.register_pair(RegisterPair::HL);
cpu.write_byte(addr, rhs_value); let right = cpu.read_byte(addr);
Cycles::new(8)
match lhs {
B | C | D | E | H | L | A => {
cpu.set_register(lhs.to_register(), right);
Cycles::new(8)
}
IndirectHL => {
unreachable!(
"There is no \"LD ({:?}), ({:?})\" instruction",
lhs, rhs
)
}
}
} }
} }
} }
@ -300,43 +301,47 @@ impl Instruction {
Instruction::JR(cond, offset) => { Instruction::JR(cond, offset) => {
// JR cc[y - 4], d | If condition is true, then add d to current address and jump // JR cc[y - 4], d | If condition is true, then add d to current address and jump
// JR d | Add d to current address and jump // JR d | Add d to current address and jump
let prev = cpu.register_pair(RegisterPair::PC);
let flags: &Flags = cpu.flags(); let flags: &Flags = cpu.flags();
let new_addr = Self::add_u16_i8_no_flags(prev, offset);
let prev = cpu.register_pair(RegisterPair::PC);
let addr = Self::add_u16_i8_no_flags(prev, offset);
match cond { match cond {
JumpCondition::Always => { JumpCondition::Always => {
cpu.set_register_pair(RegisterPair::PC, new_addr); cpu.set_register_pair(RegisterPair::PC, addr);
Cycles::new(12) Cycles::new(12)
} }
JumpCondition::NotZero => { JumpCondition::NotZero => {
if !flags.z() { if !flags.z() {
cpu.set_register_pair(RegisterPair::PC, new_addr); cpu.set_register_pair(RegisterPair::PC, addr);
return Cycles::new(12); Cycles::new(12)
} else {
Cycles::new(8)
} }
Cycles::new(8)
} }
JumpCondition::Zero => { JumpCondition::Zero => {
if flags.z() { if flags.z() {
cpu.set_register_pair(RegisterPair::PC, new_addr); cpu.set_register_pair(RegisterPair::PC, addr);
return Cycles::new(12); Cycles::new(12)
} else {
Cycles::new(8)
} }
Cycles::new(8)
} }
JumpCondition::NotCarry => { JumpCondition::NotCarry => {
if !flags.c() { if !flags.c() {
cpu.set_register_pair(RegisterPair::PC, new_addr); cpu.set_register_pair(RegisterPair::PC, addr);
return Cycles::new(12); Cycles::new(12)
} else {
Cycles::new(8)
} }
Cycles::new(8)
} }
JumpCondition::Carry => { JumpCondition::Carry => {
if flags.c() { if flags.c() {
cpu.set_register_pair(RegisterPair::PC, new_addr); cpu.set_register_pair(RegisterPair::PC, addr);
return Cycles::new(12); Cycles::new(12)
} else {
Cycles::new(8)
} }
Cycles::new(8)
} }
} }
} }
@ -408,40 +413,36 @@ impl Instruction {
match registers { match registers {
Registers::Byte(reg) => { Registers::Byte(reg) => {
// INC r[y] | Increment Register // INC r[y] | Increment Register
let mut flags: Flags = *cpu.flags(); use InstrRegister::*;
let cycles: Cycles;
match reg { let mut flags: Flags = *cpu.flags();
InstrRegister::B
| InstrRegister::C let cycles = match reg {
| InstrRegister::D B | C | D | E | H | L | A => {
| InstrRegister::E
| InstrRegister::H
| InstrRegister::L
| InstrRegister::A => {
let reg = reg.to_register(); let reg = reg.to_register();
let value = cpu.register(reg); let value = cpu.register(reg);
cpu.set_register(reg, Self::inc_register(value, &mut flags)); cpu.set_register(reg, Self::inc_register(value, &mut flags));
cycles = Cycles::new(4) Cycles::new(4)
} }
InstrRegister::IndirectHL => { IndirectHL => {
let addr = cpu.register_pair(RegisterPair::HL); let addr = cpu.register_pair(RegisterPair::HL);
let byte = Self::inc_register(cpu.read_byte(addr), &mut flags); let byte = Self::inc_register(cpu.read_byte(addr), &mut flags);
cpu.write_byte(addr, byte); cpu.write_byte(addr, byte);
cycles = Cycles::new(12) Cycles::new(12)
} }
} };
cpu.set_flags(flags); cpu.set_flags(flags);
cycles cycles
} }
Registers::Word(pair) => { Registers::Word(pair) => {
// INC rp[p] | Increment Register Pair // INC rp[p] | Increment Register Pair
// Note: According to RGBDS, no flags are set here.
use RegisterPair::*;
match pair { match pair {
RegisterPair::BC BC | DE | HL | SP => {
| RegisterPair::DE
| RegisterPair::HL
| RegisterPair::SP => {
let value = cpu.register_pair(pair); let value = cpu.register_pair(pair);
cpu.set_register_pair(pair, value + 1); cpu.set_register_pair(pair, value + 1);
} }
@ -451,45 +452,47 @@ impl Instruction {
} }
} }
} }
Instruction::DEC(Registers::Word(pair)) => { Instruction::DEC(registers) => {
// DEC rp[p] | Decrement Register Pair match registers {
match pair { Registers::Byte(reg) => {
RegisterPair::BC | RegisterPair::DE | RegisterPair::HL | RegisterPair::SP => { // DEC r[y] | Decrement Register
let value = cpu.register_pair(pair); use InstrRegister::*;
cpu.set_register_pair(pair, value - 1);
}
_ => unreachable!("There is no \"DEC {:?}\" instruction", pair),
}
Cycles::new(8)
}
Instruction::DEC(Registers::Byte(reg)) => {
// DEC r[y] | Decrement Register
let mut flags: Flags = *cpu.flags();
let cycles: Cycles;
match reg { let mut flags: Flags = *cpu.flags();
InstrRegister::B
| InstrRegister::C
| InstrRegister::D
| InstrRegister::E
| InstrRegister::H
| InstrRegister::L
| InstrRegister::A => {
let reg = reg.to_register();
let value = cpu.register(reg); let cycles = match reg {
cpu.set_register(reg, Self::dec_register(value, &mut flags)); B | C | D | E | H | L | A => {
cycles = Cycles::new(4); let reg = reg.to_register();
let value = cpu.register(reg);
cpu.set_register(reg, Self::dec_register(value, &mut flags));
Cycles::new(4)
}
IndirectHL => {
let addr = cpu.register_pair(RegisterPair::HL);
let byte = cpu.read_byte(addr);
cpu.write_byte(addr, Self::dec_register(byte, &mut flags));
Cycles::new(12)
}
};
cpu.set_flags(flags);
cycles
} }
InstrRegister::IndirectHL => { Registers::Word(pair) => {
let addr = cpu.register_pair(RegisterPair::HL); // DEC rp[p] | Decrement Register Pair
let byte = cpu.read_byte(addr); use RegisterPair::*;
cpu.write_byte(addr, Self::dec_register(byte, &mut flags));
cycles = Cycles::new(12); match pair {
BC | DE | HL | SP => {
let value = cpu.register_pair(pair);
cpu.set_register_pair(pair, value - 1);
}
_ => unreachable!("There is no \"DEC {:?}\" instruction", pair),
};
Cycles::new(8)
} }
} }
cpu.set_flags(flags);
cycles
} }
Instruction::RLCA => { Instruction::RLCA => {
// Rotate Register A left // Rotate Register A left
@ -710,33 +713,25 @@ impl Instruction {
Instruction::AND(target) => match target { Instruction::AND(target) => match target {
MATHTarget::Register(reg) => { MATHTarget::Register(reg) => {
// AND r[z] | Bitwise AND register r[z] and register A, store in register A // AND r[z] | Bitwise AND register r[z] and register A, store in register A
use InstrRegister::*;
let mut flags: Flags = *cpu.flags(); let mut flags: Flags = *cpu.flags();
let a_value = cpu.register(Register::A); let a_value = cpu.register(Register::A);
let cycles: Cycles;
let result;
match reg { let (cycles, result) = match reg {
InstrRegister::B B | C | D | E | H | L | A => {
| InstrRegister::C
| InstrRegister::D
| InstrRegister::E
| InstrRegister::H
| InstrRegister::L
| InstrRegister::A => {
let value = cpu.register(reg.to_register()); let value = cpu.register(reg.to_register());
result = a_value & value; (Cycles::new(4), a_value & value)
cycles = Cycles::new(4);
} }
InstrRegister::IndirectHL => { IndirectHL => {
let value = cpu.read_byte(cpu.register_pair(RegisterPair::HL)); let value = cpu.read_byte(cpu.register_pair(RegisterPair::HL));
result = a_value & value; (Cycles::new(8), a_value & value)
cycles = Cycles::new(8);
} }
} };
flags.update(result == 0, false, true, false); flags.update(result == 0, false, true, false);
cpu.set_flags(flags);
cpu.set_register(Register::A, result); cpu.set_register(Register::A, result);
cpu.set_flags(flags);
cycles cycles
} }
MATHTarget::ImmediateByte(n) => { MATHTarget::ImmediateByte(n) => {
@ -745,8 +740,8 @@ impl Instruction {
let result = cpu.register(Register::A) & n; let result = cpu.register(Register::A) & n;
flags.update(result == 0, false, true, false); flags.update(result == 0, false, true, false);
cpu.set_flags(flags);
cpu.set_register(Register::A, result); cpu.set_register(Register::A, result);
cpu.set_flags(flags);
Cycles::new(8) Cycles::new(8)
} }
_ => unreachable!("There is no \"AND {:?}\" instruction", target), _ => unreachable!("There is no \"AND {:?}\" instruction", target),
@ -842,22 +837,18 @@ impl Instruction {
Instruction::CP(target) => match target { Instruction::CP(target) => match target {
MATHTarget::Register(reg) => { MATHTarget::Register(reg) => {
// CP r[z] | Same behaviour as SUB, except the result is not stored. // CP r[z] | Same behaviour as SUB, except the result is not stored.
use InstrRegister::*;
let mut flags: Flags = *cpu.flags(); let mut flags: Flags = *cpu.flags();
let a_value = cpu.register(Register::A); let a_value = cpu.register(Register::A);
let cycles = match reg { let cycles = match reg {
InstrRegister::B B | C | D | E | H | L | A => {
| InstrRegister::C
| InstrRegister::D
| InstrRegister::E
| InstrRegister::H
| InstrRegister::L
| InstrRegister::A => {
let value = cpu.register(reg.to_register()); let value = cpu.register(reg.to_register());
let _ = Self::sub_u8s(a_value, value, &mut flags); let _ = Self::sub_u8s(a_value, value, &mut flags);
Cycles::new(4) Cycles::new(4)
} }
InstrRegister::IndirectHL => { IndirectHL => {
let value = cpu.read_byte(cpu.register_pair(RegisterPair::HL)); let value = cpu.read_byte(cpu.register_pair(RegisterPair::HL));
let _ = Self::sub_u8s(a_value, value, &mut flags); let _ = Self::sub_u8s(a_value, value, &mut flags);
Cycles::new(8) Cycles::new(8)
@ -952,7 +943,9 @@ impl Instruction {
Instruction::JP(cond, target) => match target { Instruction::JP(cond, target) => match target {
JPTarget::RegisterPair(RegisterPair::HL) => { JPTarget::RegisterPair(RegisterPair::HL) => {
// JP HL | Load register pair HL into program counter // JP HL | Load register pair HL into program counter
cpu.set_register_pair(RegisterPair::PC, cpu.register_pair(RegisterPair::HL)); let addr = cpu.register_pair(RegisterPair::HL);
cpu.set_register_pair(RegisterPair::PC, addr);
Cycles::new(4) Cycles::new(4)
} }
JPTarget::ImmediateWord(nn) => { JPTarget::ImmediateWord(nn) => {
@ -964,30 +957,34 @@ impl Instruction {
JumpCondition::NotZero => { JumpCondition::NotZero => {
if !flags.z() { if !flags.z() {
cpu.set_register_pair(RegisterPair::PC, nn); cpu.set_register_pair(RegisterPair::PC, nn);
return Cycles::new(16); Cycles::new(16)
} else {
Cycles::new(12)
} }
Cycles::new(12)
} }
JumpCondition::Zero => { JumpCondition::Zero => {
if flags.z() { if flags.z() {
cpu.set_register_pair(RegisterPair::PC, nn); cpu.set_register_pair(RegisterPair::PC, nn);
return Cycles::new(16); Cycles::new(16)
} else {
Cycles::new(12)
} }
Cycles::new(12)
} }
JumpCondition::NotCarry => { JumpCondition::NotCarry => {
if !flags.c() { if !flags.c() {
cpu.set_register_pair(RegisterPair::PC, nn); cpu.set_register_pair(RegisterPair::PC, nn);
return Cycles::new(16); Cycles::new(16)
} else {
Cycles::new(12)
} }
Cycles::new(12)
} }
JumpCondition::Carry => { JumpCondition::Carry => {
if flags.c() { if flags.c() {
cpu.set_register_pair(RegisterPair::PC, nn); cpu.set_register_pair(RegisterPair::PC, nn);
return Cycles::new(16); Cycles::new(16)
} else {
Cycles::new(12)
} }
Cycles::new(12)
} }
JumpCondition::Always => { JumpCondition::Always => {
cpu.set_register_pair(RegisterPair::PC, nn); cpu.set_register_pair(RegisterPair::PC, nn);
@ -1056,8 +1053,10 @@ impl Instruction {
} }
Instruction::PUSH(pair) => { Instruction::PUSH(pair) => {
// PUSH rp2[p] | Push register pair onto the stack // PUSH rp2[p] | Push register pair onto the stack
use RegisterPair::*;
match pair { match pair {
RegisterPair::BC | RegisterPair::DE | RegisterPair::HL | RegisterPair::AF => { BC | DE | HL | AF => {
let value = cpu.register_pair(pair); let value = cpu.register_pair(pair);
Self::push(cpu, value); Self::push(cpu, value);
} }
@ -1524,12 +1523,12 @@ impl Instruction {
(high as u16) << 8 | low as u16 (high as u16) << 8 | low as u16
} }
fn dec_register(reg: u8, flags: &mut Flags) -> u8 { fn dec_register(byte: u8, flags: &mut Flags) -> u8 {
Self::sub_u8s_no_carry(reg, 1, flags) Self::sub_u8s_no_carry(byte, 1, flags)
} }
fn inc_register(reg: u8, flags: &mut Flags) -> u8 { fn inc_register(byte: u8, flags: &mut Flags) -> u8 {
Self::add_u8s_no_carry(reg, 1, flags) Self::add_u8s_no_carry(byte, 1, flags)
} }
fn sub_u8s_no_carry(left: u8, right: u8, flags: &mut Flags) -> u8 { fn sub_u8s_no_carry(left: u8, right: u8, flags: &mut Flags) -> u8 {