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,41 +230,43 @@ 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 {
InstrRegister::B B | C | D | E | H | L | A => {
| InstrRegister::C let right = cpu.register(rhs.to_register());
| InstrRegister::D
| InstrRegister::E
| InstrRegister::H
| InstrRegister::L
| InstrRegister::A => cpu.register(rhs.to_register()),
InstrRegister::IndirectHL => {
let addr = cpu.register_pair(RegisterPair::HL);
cpu.read_byte(addr)
}
}
};
match lhs { match lhs {
InstrRegister::B B | C | D | E | H | L | A => {
| InstrRegister::C cpu.set_register(lhs.to_register(), right);
| InstrRegister::D
| InstrRegister::E
| InstrRegister::H
| InstrRegister::L
| InstrRegister::A => {
cpu.set_register(lhs.to_register(), rhs_value);
Cycles::new(4) Cycles::new(4)
} }
InstrRegister::IndirectHL => { IndirectHL => {
let addr = cpu.register_pair(RegisterPair::HL); let addr = cpu.register_pair(RegisterPair::HL);
cpu.write_byte(addr, rhs_value); cpu.write_byte(addr, right);
Cycles::new(8) Cycles::new(8)
} }
} }
} }
IndirectHL => {
let addr = cpu.register_pair(RegisterPair::HL);
let right = cpu.read_byte(addr);
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
)
}
}
}
}
}
(LDTarget::ByteAtAddressWithOffset(n), LDTarget::Register(InstrRegister::A)) => { (LDTarget::ByteAtAddressWithOffset(n), LDTarget::Register(InstrRegister::A)) => {
// LD (0xFF00 + n), A | Store register A at address (0xFF00 + n) // LD (0xFF00 + n), A | Store register A at address (0xFF00 + n)
cpu.write_byte(0xFF00 + (n as u16), cpu.register(Register::A)); cpu.write_byte(0xFF00 + (n as u16), cpu.register(Register::A));
@ -300,46 +301,50 @@ 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)
} }
} }
} }
}
Instruction::ADD(lhs, rhs) => match (lhs, rhs) { Instruction::ADD(lhs, rhs) => match (lhs, rhs) {
(MATHTarget::RegisterPair(RegisterPair::HL), MATHTarget::RegisterPair(pair)) => { (MATHTarget::RegisterPair(RegisterPair::HL), MATHTarget::RegisterPair(pair)) => {
// ADD HL, rp[p] | add register pair to HL. // ADD HL, rp[p] | add register pair to HL.
@ -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,46 +452,48 @@ 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 => {
let value = cpu.register_pair(pair);
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 // DEC r[y] | Decrement 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::dec_register(value, &mut flags)); cpu.set_register(reg, Self::dec_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 = cpu.read_byte(addr); let byte = cpu.read_byte(addr);
cpu.write_byte(addr, Self::dec_register(byte, &mut flags)); cpu.write_byte(addr, Self::dec_register(byte, &mut flags));
cycles = Cycles::new(12); Cycles::new(12)
}
} }
};
cpu.set_flags(flags); cpu.set_flags(flags);
cycles cycles
} }
Registers::Word(pair) => {
// DEC rp[p] | Decrement Register Pair
use RegisterPair::*;
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)
}
}
}
Instruction::RLCA => { Instruction::RLCA => {
// Rotate Register A left // Rotate Register A left
let mut flags: Flags = *cpu.flags(); let mut flags: Flags = *cpu.flags();
@ -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,31 +957,35 @@ 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);
Cycles::new(16) Cycles::new(16)
@ -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 {