Utilize pattern matching more

This commit is contained in:
Rekai Nyangadzayi Musuka 2020-09-02 19:35:48 -05:00
parent cb365fd932
commit 49dac85470
2 changed files with 153 additions and 166 deletions

View File

@ -1,5 +1,7 @@
use super::bus::Bus;
use super::instruction::Instruction;
#[derive(Debug, Copy, Clone)]
pub struct Cpu {
bus: Bus,
reg: Registers,
@ -41,6 +43,7 @@ impl Cpu {
}
}
#[derive(Debug, Copy, Clone)]
enum State {
Execute,
Halt,
@ -112,6 +115,7 @@ impl Cpu {
}
}
#[derive(Debug, Copy, Clone)]
pub enum Register {
A,
B,
@ -123,6 +127,7 @@ pub enum Register {
Flag,
}
#[derive(Debug, Copy, Clone)]
pub enum RegisterPair {
AF,
BC,
@ -132,6 +137,7 @@ pub enum RegisterPair {
PC,
}
#[derive(Debug, Copy, Clone)]
struct Registers {
a: u8,
b: u8,

View File

@ -1,4 +1,6 @@
use super::cpu::{Cpu, Flags, Register, RegisterPair};
use std::convert::TryFrom;
#[derive(Debug, Copy, Clone)]
pub enum Instruction {
NOP,
LD(LDTarget, LDTarget),
@ -35,6 +37,7 @@ pub enum Instruction {
RST(u8),
}
#[derive(Debug, Copy, Clone)]
pub struct Cycles(u8);
impl Instruction {
@ -47,29 +50,26 @@ impl Instruction {
cpu.write_word(nn, cpu.register_pair(RegisterPair::SP));
Cycles(20)
}
(LDTarget::RegisterPair(pairs), LDTarget::ImmediateWord(nn)) => {
(LDTarget::RegisterPair(pair), LDTarget::ImmediateWord(nn)) => {
// LD rp[p], nn | Put value nn into register pair
match pairs {
RegisterPair::BC => cpu.set_register_pair(RegisterPair::BC, nn),
RegisterPair::DE => cpu.set_register_pair(RegisterPair::DE, nn),
RegisterPair::HL => cpu.set_register_pair(RegisterPair::HL, nn),
RegisterPair::SP => cpu.set_register_pair(RegisterPair::SP, nn),
match pair {
RegisterPair::BC
| RegisterPair::DE
| RegisterPair::HL
| RegisterPair::SP => {
cpu.set_register_pair(RegisterPair::try_from(pair).unwrap(), nn)
}
_ => unreachable!(),
}
Cycles(12)
}
(LDTarget::IndirectRegister(pair), LDTarget::Register(InstrRegister::A)) => {
let a = cpu.register(Register::A);
match pair {
InstrRegisterPair::BC => {
InstrRegisterPair::BC | InstrRegisterPair::DE => {
// LD (BC), A | Put A into memory address BC
let addr = cpu.register_pair(RegisterPair::BC);
cpu.write_byte(addr, a);
}
InstrRegisterPair::DE => {
// LD (DE), A | Put A into memory address DE
let addr = cpu.register_pair(RegisterPair::DE);
let addr = cpu.register_pair(RegisterPair::try_from(pair).unwrap());
cpu.write_byte(addr, a);
}
InstrRegisterPair::IncrementHL => {
@ -92,14 +92,10 @@ impl Instruction {
}
(LDTarget::Register(InstrRegister::A), LDTarget::IndirectRegister(pair)) => {
match pair {
InstrRegisterPair::BC => {
InstrRegisterPair::BC | InstrRegisterPair::DE => {
// LD A, (BC) | Put value at address BC into A
let addr = cpu.register_pair(RegisterPair::BC);
cpu.set_register(Register::A, cpu.read_byte(addr));
}
InstrRegisterPair::DE => {
// LD A, (DE) | Put value at address DE into A
let addr = cpu.register_pair(RegisterPair::DE);
let addr = cpu.register_pair(RegisterPair::try_from(pair).unwrap());
cpu.set_register(Register::A, cpu.read_byte(addr));
}
InstrRegisterPair::IncrementHL => {
@ -122,46 +118,26 @@ impl Instruction {
}
(LDTarget::Register(reg), LDTarget::ImmediateByte(n)) => {
// LD r[y], n | Store n in Register
let cycles: Cycles;
match reg {
InstrRegister::B => {
cpu.set_register(Register::B, n);
cycles = Cycles(8);
}
InstrRegister::C => {
cpu.set_register(Register::C, n);
cycles = Cycles(8);
}
InstrRegister::D => {
cpu.set_register(Register::D, n);
cycles = Cycles(8);
}
InstrRegister::E => {
cpu.set_register(Register::E, n);
cycles = Cycles(8);
}
InstrRegister::H => {
cpu.set_register(Register::H, n);
cycles = Cycles(8);
}
InstrRegister::L => {
cpu.set_register(Register::L, n);
cycles = Cycles(8);
}
InstrRegister::IndirectHL => {
let addr = cpu.register_pair(RegisterPair::HL);
cpu.write_byte(addr, n);
cycles = Cycles(12);
Cycles(12)
}
InstrRegister::A => {
cpu.set_register(Register::A, n);
cycles = Cycles(8);
InstrRegister::A
| InstrRegister::B
| InstrRegister::C
| InstrRegister::D
| InstrRegister::E
| InstrRegister::H
| InstrRegister::L => {
cpu.set_register(Register::try_from(reg).unwrap(), n);
Cycles(8)
}
InstrRegister::IndirectC => unreachable!(),
}
cycles
}
(LDTarget::Register(lhs), LDTarget::Register(rhs)) => unimplemented!(),
_ => unimplemented!(),
},
Instruction::STOP => Cycles(4),
@ -211,30 +187,22 @@ impl Instruction {
Instruction::ADD(lhs, rhs) => match (lhs, rhs) {
(MATHTarget::RegisterPair(RegisterPair::HL), MATHTarget::RegisterPair(pair)) => {
// ADD HL, rp[p] | add register pair to HL.
let hl = cpu.register_pair(RegisterPair::HL);
let mut flags: Flags = cpu.register(Register::Flag).into();
let sum;
match pair {
RegisterPair::BC => {
let bc = cpu.register_pair(RegisterPair::BC);
sum = Self::add_u16s(hl, bc, &mut flags);
}
RegisterPair::DE => {
let de = cpu.register_pair(RegisterPair::DE);
sum = Self::add_u16s(hl, de, &mut flags);
}
RegisterPair::HL => {
sum = Self::add_u16s(hl, hl, &mut flags);
}
RegisterPair::SP => {
let sp = cpu.register_pair(RegisterPair::SP);
sum = Self::add_u16s(hl, sp, &mut flags);
RegisterPair::BC
| RegisterPair::DE
| RegisterPair::HL
| RegisterPair::SP => {
let hl_value = cpu.register_pair(RegisterPair::HL);
let value = cpu.register_pair(RegisterPair::try_from(pair).unwrap());
let sum = Self::add_u16s(hl_value, value, &mut flags);
cpu.set_register_pair(RegisterPair::HL, sum);
}
_ => unreachable!(),
}
cpu.set_register(Register::Flag, flags.into());
cpu.set_register_pair(RegisterPair::HL, sum);
Cycles(8)
}
_ => unimplemented!(),
@ -242,21 +210,9 @@ impl Instruction {
Instruction::INC(Registers::Word(pair)) => {
// INC rp[p] | Increment Register Pair
match pair {
RegisterPair::BC => {
let bc = cpu.register_pair(RegisterPair::BC);
cpu.set_register_pair(RegisterPair::BC, bc + 1);
}
RegisterPair::DE => {
let de = cpu.register_pair(RegisterPair::DE);
cpu.set_register_pair(RegisterPair::DE, de + 1);
}
RegisterPair::HL => {
let hl = cpu.register_pair(RegisterPair::HL);
cpu.set_register_pair(RegisterPair::HL, hl + 1);
}
RegisterPair::SP => {
let sp = cpu.register_pair(RegisterPair::SP);
cpu.set_register_pair(RegisterPair::SP, sp + 1);
RegisterPair::BC | RegisterPair::DE | RegisterPair::HL | RegisterPair::SP => {
let value = cpu.register_pair(pair);
cpu.set_register_pair(pair, value + 1);
}
_ => unreachable!(),
}
@ -268,45 +224,23 @@ impl Instruction {
let cycles: Cycles;
match reg {
InstrRegister::B => {
let b = cpu.register(Register::B);
cpu.set_register(Register::B, Self::inc_register(b, &mut flags));
cycles = Cycles(4);
}
InstrRegister::C => {
let c = cpu.register(Register::C);
cpu.set_register(Register::C, Self::inc_register(c, &mut flags));
cycles = Cycles(4);
}
InstrRegister::D => {
let d = cpu.register(Register::D);
cpu.set_register(Register::D, Self::inc_register(d, &mut flags));
cycles = Cycles(4);
}
InstrRegister::E => {
let e = cpu.register(Register::E);
cpu.set_register(Register::E, Self::inc_register(e, &mut flags));
cycles = Cycles(4);
}
InstrRegister::H => {
let h = cpu.register(Register::H);
cpu.set_register(Register::H, Self::inc_register(h, &mut flags));
cycles = Cycles(4);
}
InstrRegister::L => {
let l = cpu.register(Register::L);
cpu.set_register(Register::L, Self::inc_register(l, &mut flags));
cycles = Cycles(4);
InstrRegister::B
| InstrRegister::C
| InstrRegister::D
| InstrRegister::E
| InstrRegister::H
| InstrRegister::L
| InstrRegister::A => {
let reg = Register::try_from(reg).unwrap();
let value = cpu.register(reg);
cpu.set_register(reg, Self::inc_register(value, &mut flags));
cycles = Cycles(4)
}
InstrRegister::IndirectHL => {
let addr = cpu.register_pair(RegisterPair::HL);
cpu.write_byte(addr, Self::inc_register(cpu.read_byte(addr), &mut flags));
cycles = Cycles(12);
}
InstrRegister::A => {
let a = cpu.register(Register::A);
cpu.set_register(Register::A, Self::inc_register(a, &mut flags));
cycles = Cycles(4);
cycles = Cycles(12)
}
InstrRegister::IndirectC => unreachable!(),
}
@ -314,23 +248,10 @@ impl Instruction {
cycles
}
Instruction::DEC(Registers::Word(pair)) => {
// DEC rp[p] | Decrement Register Pair
match pair {
RegisterPair::BC => {
let bc = cpu.register_pair(RegisterPair::BC);
cpu.set_register_pair(RegisterPair::BC, bc - 1);
}
RegisterPair::DE => {
let de = cpu.register_pair(RegisterPair::DE);
cpu.set_register_pair(RegisterPair::DE, de - 1);
}
RegisterPair::HL => {
let hl = cpu.register_pair(RegisterPair::HL);
cpu.set_register_pair(RegisterPair::HL, hl - 1);
}
RegisterPair::SP => {
let sp = cpu.register_pair(RegisterPair::SP);
cpu.set_register_pair(RegisterPair::SP, sp - 1);
RegisterPair::BC | RegisterPair::DE | RegisterPair::HL | RegisterPair::SP => {
let value = cpu.register_pair(pair);
cpu.set_register_pair(pair, value - 1);
}
_ => unreachable!(),
}
@ -342,34 +263,17 @@ impl Instruction {
let cycles: Cycles;
match reg {
InstrRegister::B => {
let b = cpu.register(Register::B);
cpu.set_register(Register::B, Self::dec_register(b, &mut flags));
cycles = Cycles(4);
}
InstrRegister::C => {
let c = cpu.register(Register::C);
cpu.set_register(Register::C, Self::dec_register(c, &mut flags));
cycles = Cycles(4);
}
InstrRegister::D => {
let d = cpu.register(Register::D);
cpu.set_register(Register::D, Self::dec_register(d, &mut flags));
cycles = Cycles(4);
}
InstrRegister::E => {
let e = cpu.register(Register::E);
cpu.set_register(Register::E, Self::dec_register(e, &mut flags));
cycles = Cycles(4);
}
InstrRegister::H => {
let h = cpu.register(Register::H);
cpu.set_register(Register::H, Self::dec_register(h, &mut flags));
cycles = Cycles(4);
}
InstrRegister::L => {
let l = cpu.register(Register::L);
cpu.set_register(Register::L, Self::dec_register(l, &mut flags));
InstrRegister::B
| InstrRegister::C
| InstrRegister::D
| InstrRegister::E
| InstrRegister::H
| InstrRegister::L
| InstrRegister::A => {
let reg = Register::try_from(reg).unwrap();
let value = cpu.register(reg);
cpu.set_register(reg, Self::dec_register(value, &mut flags));
cycles = Cycles(4);
}
InstrRegister::IndirectHL => {
@ -377,11 +281,6 @@ impl Instruction {
cpu.write_byte(addr, Self::dec_register(cpu.read_byte(addr), &mut flags));
cycles = Cycles(12);
}
InstrRegister::A => {
let a = cpu.register(Register::A);
cpu.set_register(Register::A, Self::dec_register(a, &mut flags));
cycles = Cycles(4);
}
InstrRegister::IndirectC => unreachable!(),
}
cpu.set_register(Register::Flag, flags.into());
@ -732,16 +631,20 @@ impl Instruction {
unimplemented!()
}
}
#[derive(Debug, Copy, Clone)]
pub enum JPTarget {
RegisterPair(RegisterPair),
ImmediateWord(u16),
}
#[derive(Debug, Copy, Clone)]
pub enum Registers {
Byte(InstrRegister),
Word(RegisterPair),
}
#[derive(Debug, Copy, Clone)]
pub enum MATHTarget {
HL,
SP,
@ -750,6 +653,7 @@ pub enum MATHTarget {
ImmediateByte(u8),
}
#[derive(Debug, Copy, Clone)]
pub enum LDTarget {
Register(InstrRegister),
IndirectRegister(InstrRegisterPair),
@ -759,6 +663,7 @@ pub enum LDTarget {
RegisterPair(RegisterPair),
}
#[derive(Debug, Copy, Clone)]
enum InstrRegisterPair {
AF,
BC,
@ -770,6 +675,41 @@ enum InstrRegisterPair {
DecrementHL,
}
impl From<RegisterPair> for InstrRegisterPair {
fn from(pair: RegisterPair) -> Self {
match pair {
RegisterPair::AF => Self::AF,
RegisterPair::BC => Self::BC,
RegisterPair::DE => Self::DE,
RegisterPair::HL => Self::HL,
RegisterPair::SP => Self::SP,
RegisterPair::PC => Self::PC,
}
}
}
impl TryFrom<InstrRegisterPair> for RegisterPair {
type Error = String; // FIXME: Proper error type goes here.
fn try_from(pair: InstrRegisterPair) -> Result<Self, Self::Error> {
match pair {
InstrRegisterPair::AF => Ok(Self::AF),
InstrRegisterPair::BC => Ok(Self::BC),
InstrRegisterPair::DE => Ok(Self::DE),
InstrRegisterPair::HL => Ok(Self::HL),
InstrRegisterPair::SP => Ok(Self::SP),
InstrRegisterPair::PC => Ok(Self::PC),
InstrRegisterPair::IncrementHL => {
Err("Can not convert InstrRegisterPair::IncrementHL to RegisterPair".to_string())
}
InstrRegisterPair::DecrementHL => {
Err("Can not convert InstrRegisterPair::DecrementHL to RegisterPair".to_string())
}
}
}
}
#[derive(Debug, Copy, Clone)]
enum InstrRegister {
A,
B,
@ -782,6 +722,46 @@ enum InstrRegister {
IndirectC, // (0xFF00 + C)
}
impl TryFrom<Register> for InstrRegister {
type Error = String; // FIXME: Proper error type goes here
fn try_from(register: Register) -> Result<Self, Self::Error> {
match register {
Register::A => Ok(Self::A),
Register::B => Ok(Self::B),
Register::C => Ok(Self::C),
Register::D => Ok(Self::D),
Register::E => Ok(Self::E),
Register::H => Ok(Self::H),
Register::L => Ok(Self::L),
Register::Flag => Err("Can not convert Register::Flag to InstrRegister".to_string()),
}
}
}
impl TryFrom<InstrRegister> for Register {
type Error = String; // FIXME: Proper error type goes here.
fn try_from(register: InstrRegister) -> Result<Self, Self::Error> {
match register {
InstrRegister::A => Ok(Self::A),
InstrRegister::B => Ok(Self::B),
InstrRegister::C => Ok(Self::C),
InstrRegister::D => Ok(Self::D),
InstrRegister::E => Ok(Self::E),
InstrRegister::H => Ok(Self::H),
InstrRegister::L => Ok(Self::L),
InstrRegister::IndirectHL => {
Err("Can not convert InstrRegister::IndirectHL to Register".to_string())
}
InstrRegister::IndirectC => {
Err("Can not convert InstrRegister::IndirectC to Register".to_string())
}
}
}
}
#[derive(Debug, Copy, Clone)]
pub enum JumpCondition {
NotZero,
Zero,
@ -790,6 +770,7 @@ pub enum JumpCondition {
Always,
}
#[derive(Debug, Copy, Clone)]
struct Table;
impl Table {