2021-10-11 17:58:09 +00:00
|
|
|
use crate::utils::{BitIndex, get_bit, set_bit};
|
|
|
|
|
2021-10-11 15:53:02 +00:00
|
|
|
pub enum Register {
|
2021-10-11 16:39:13 +00:00
|
|
|
A(u8), // Accumulator
|
|
|
|
F(u8), // Flags
|
|
|
|
B(u8),
|
2021-10-11 15:53:02 +00:00
|
|
|
C(u8),
|
|
|
|
D(u8),
|
|
|
|
E(u8),
|
|
|
|
H(u8),
|
|
|
|
L(u8),
|
2021-10-11 16:39:13 +00:00
|
|
|
// This registers are just the same as above but combined to get a 16 bits register
|
|
|
|
BC(u16),
|
|
|
|
DE(u16),
|
|
|
|
HL(u16),
|
|
|
|
|
2021-10-11 15:53:02 +00:00
|
|
|
SP(u16),
|
|
|
|
PC(u16),
|
|
|
|
}
|
|
|
|
|
2021-10-11 17:58:09 +00:00
|
|
|
pub enum FlagRegister {
|
|
|
|
Zero(bool), // Set when the result of a math operation is zero or if two values matches using the CP instruction
|
|
|
|
Substract(bool), // Set if a substraction was performed in the last math instruction
|
|
|
|
HalfCarry(bool), // Set if a carry ocurred from the lower nibble in the last math operation
|
|
|
|
Carry(bool), // Set if a carry was ocurrend from the last math operation or if register A is the smaller value when executing the CP instruction
|
|
|
|
}
|
|
|
|
|
2021-10-11 15:53:02 +00:00
|
|
|
pub struct Registers {
|
2021-10-11 16:39:13 +00:00
|
|
|
a: u8,
|
|
|
|
f: u8,
|
|
|
|
b: u8,
|
|
|
|
c: u8,
|
|
|
|
d: u8,
|
|
|
|
e: u8,
|
|
|
|
h: u8,
|
|
|
|
l: u8,
|
|
|
|
sp: u16,
|
|
|
|
pc: u16,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Registers {
|
2021-10-11 17:58:09 +00:00
|
|
|
pub fn new() -> Self {
|
|
|
|
Self {
|
|
|
|
a: 0,
|
|
|
|
f: 0b11110000, // The first 4 lower bits are always set to 0
|
|
|
|
b: 0,
|
|
|
|
c: 0,
|
|
|
|
d: 0,
|
|
|
|
e: 0,
|
|
|
|
h: 0,
|
|
|
|
l: 0,
|
|
|
|
sp: 0,
|
|
|
|
pc: 0,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-11 16:39:13 +00:00
|
|
|
pub fn get(&self, register: Register) -> u16 {
|
|
|
|
match register {
|
|
|
|
Register::A(_) => self.a as u16,
|
|
|
|
Register::B(_) => self.b as u16,
|
|
|
|
Register::C(_) => self.c as u16,
|
|
|
|
Register::D(_) => self.d as u16,
|
|
|
|
Register::E(_) => self.e as u16,
|
|
|
|
Register::F(_) => self.f as u16,
|
|
|
|
Register::H(_) => self.h as u16,
|
|
|
|
Register::L(_) => self.l as u16,
|
|
|
|
Register::BC(_) => self.get_bc(),
|
|
|
|
Register::DE(_) => self.get_de(),
|
|
|
|
Register::HL(_) => self.get_hl(),
|
|
|
|
Register::SP(_) => self.sp,
|
|
|
|
Register::PC(_) => self.pc,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set(&mut self, register: Register) {
|
|
|
|
match register {
|
2021-10-11 17:58:09 +00:00
|
|
|
Register::A(val) => self.a = val,
|
|
|
|
Register::B(val) => self.b = val,
|
|
|
|
Register::C(val) => self.c = val,
|
|
|
|
Register::D(val) => self.d = val,
|
|
|
|
Register::E(val) => self.e = val,
|
|
|
|
Register::F(val) => self.f = val,
|
|
|
|
Register::H(val) => self.h = val,
|
|
|
|
Register::L(val) => self.l = val,
|
2021-10-11 16:39:13 +00:00
|
|
|
Register::BC(val) => self.set_bc(val),
|
|
|
|
Register::DE(val) => self.set_de(val),
|
|
|
|
Register::HL(val) => self.set_hl(val),
|
|
|
|
Register::SP(val) => self.sp = val,
|
|
|
|
Register::PC(val) => self.pc = val,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-11 17:58:09 +00:00
|
|
|
pub fn get_flag(&self, flag: FlagRegister) -> bool {
|
|
|
|
match flag {
|
|
|
|
FlagRegister::Zero(_) => get_bit(self.f, BitIndex::I7),
|
|
|
|
FlagRegister::Substract(_) => get_bit(self.f, BitIndex::I6),
|
|
|
|
FlagRegister::HalfCarry(_) => get_bit(self.f, BitIndex::I5),
|
|
|
|
FlagRegister::Carry(_) => get_bit(self.f, BitIndex::I4),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set_flag(&mut self, flag: FlagRegister) {
|
|
|
|
match flag {
|
|
|
|
FlagRegister::Zero(val) => self.f = set_bit(self.f, val, BitIndex::I7),
|
|
|
|
FlagRegister::Substract(val) => self.f = set_bit(self.f, val, BitIndex::I6),
|
|
|
|
FlagRegister::HalfCarry(val) => self.f = set_bit(self.f, val, BitIndex::I5),
|
|
|
|
FlagRegister::Carry(val) => self.f = set_bit(self.f, val, BitIndex::I4),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-11 16:39:13 +00:00
|
|
|
fn get_bc(&self) -> u16 {
|
|
|
|
((self.b as u16) << 8) | (self.c as u16)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_de(&self) -> u16 {
|
|
|
|
((self.d as u16) << 8) | (self.e as u16)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_hl(&self) -> u16 {
|
|
|
|
((self.h as u16) << 8) | (self.l as u16)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn set_bc(&mut self, val: u16) {
|
|
|
|
let bytes = val.to_be_bytes();
|
|
|
|
self.b = bytes[0];
|
|
|
|
self.c = bytes[1];
|
|
|
|
}
|
|
|
|
|
|
|
|
fn set_de(&mut self, val: u16) {
|
|
|
|
let bytes = val.to_be_bytes();
|
|
|
|
self.d = bytes[0];
|
|
|
|
self.e = bytes[1];
|
|
|
|
}
|
|
|
|
|
|
|
|
fn set_hl(&mut self, val: u16) {
|
|
|
|
let bytes = val.to_be_bytes();
|
|
|
|
self.h = bytes[0];
|
|
|
|
self.l = bytes[1];
|
|
|
|
}
|
2021-10-11 15:53:02 +00:00
|
|
|
}
|
|
|
|
|
2021-10-12 01:38:37 +00:00
|
|
|
pub enum CpuOpcode {
|
|
|
|
LD,
|
|
|
|
LDD,
|
|
|
|
LDI,
|
|
|
|
LDHL,
|
|
|
|
PUSH,
|
|
|
|
POP,
|
|
|
|
ADC,
|
|
|
|
SUB,
|
|
|
|
SBC,
|
|
|
|
AND,
|
|
|
|
OR,
|
|
|
|
XOR,
|
|
|
|
CP,
|
|
|
|
ADD,
|
|
|
|
INC,
|
|
|
|
DEC,
|
|
|
|
SWAP,
|
|
|
|
DAA,
|
|
|
|
CPL,
|
|
|
|
CCF,
|
|
|
|
SCF,
|
|
|
|
NOP,
|
|
|
|
HALT,
|
|
|
|
STOP,
|
|
|
|
DI,
|
|
|
|
EI,
|
|
|
|
RLCA,
|
|
|
|
RLA,
|
|
|
|
RRCA,
|
|
|
|
RRA,
|
|
|
|
RLC,
|
|
|
|
RL,
|
|
|
|
RRC,
|
|
|
|
RR,
|
|
|
|
SLA,
|
|
|
|
SRA,
|
|
|
|
SRL,
|
|
|
|
BIT,
|
|
|
|
SET,
|
|
|
|
RES,
|
|
|
|
JP,
|
|
|
|
JR,
|
|
|
|
CALL,
|
|
|
|
RST,
|
|
|
|
RET,
|
|
|
|
RETI,
|
2021-10-12 17:52:04 +00:00
|
|
|
IllegalInstruction,
|
2021-10-12 01:38:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-10-11 15:53:02 +00:00
|
|
|
pub struct CPU {
|
|
|
|
registers: Registers,
|
|
|
|
}
|
2021-10-11 18:14:08 +00:00
|
|
|
|
2021-10-12 01:38:37 +00:00
|
|
|
impl CPU {
|
|
|
|
pub fn parse_opcode(opcode: u8) -> CpuOpcode {
|
|
|
|
match opcode {
|
|
|
|
0x06 => CpuOpcode::LD,
|
|
|
|
0x0E => CpuOpcode::LD,
|
|
|
|
0x16 => CpuOpcode::LD,
|
|
|
|
0x1E => CpuOpcode::LD,
|
|
|
|
0x26 => CpuOpcode::LD,
|
|
|
|
0x2E => CpuOpcode::LD,
|
|
|
|
0x7F => CpuOpcode::LD,
|
|
|
|
0x78 => CpuOpcode::LD,
|
|
|
|
0x79 => CpuOpcode::LD,
|
|
|
|
0x7A => CpuOpcode::LD,
|
|
|
|
0x7B => CpuOpcode::LD,
|
|
|
|
0x7C => CpuOpcode::LD,
|
|
|
|
0x7D => CpuOpcode::LD,
|
|
|
|
0x7E => CpuOpcode::LD,
|
|
|
|
0x40 => CpuOpcode::LD,
|
|
|
|
0x41 => CpuOpcode::LD,
|
|
|
|
0x42 => CpuOpcode::LD,
|
|
|
|
0x43 => CpuOpcode::LD,
|
|
|
|
0x44 => CpuOpcode::LD,
|
|
|
|
0x45 => CpuOpcode::LD,
|
|
|
|
0x46 => CpuOpcode::LD,
|
|
|
|
0x48 => CpuOpcode::LD,
|
|
|
|
0x49 => CpuOpcode::LD,
|
|
|
|
0x4A => CpuOpcode::LD,
|
|
|
|
0x4B => CpuOpcode::LD,
|
|
|
|
0x4C => CpuOpcode::LD,
|
|
|
|
0x4D => CpuOpcode::LD,
|
|
|
|
0x4E => CpuOpcode::LD,
|
|
|
|
0x50 => CpuOpcode::LD,
|
|
|
|
0x51 => CpuOpcode::LD,
|
|
|
|
0x52 => CpuOpcode::LD,
|
|
|
|
0x53 => CpuOpcode::LD,
|
|
|
|
0x54 => CpuOpcode::LD,
|
|
|
|
0x55 => CpuOpcode::LD,
|
|
|
|
0x56 => CpuOpcode::LD,
|
|
|
|
0x58 => CpuOpcode::LD,
|
|
|
|
0x59 => CpuOpcode::LD,
|
|
|
|
0x5A => CpuOpcode::LD,
|
|
|
|
0x5B => CpuOpcode::LD,
|
|
|
|
0x5C => CpuOpcode::LD,
|
|
|
|
0x5D => CpuOpcode::LD,
|
|
|
|
0x5E => CpuOpcode::LD,
|
|
|
|
0x60 => CpuOpcode::LD,
|
|
|
|
0x61 => CpuOpcode::LD,
|
|
|
|
0x62 => CpuOpcode::LD,
|
|
|
|
0x63 => CpuOpcode::LD,
|
|
|
|
0x64 => CpuOpcode::LD,
|
|
|
|
0x65 => CpuOpcode::LD,
|
|
|
|
0x66 => CpuOpcode::LD,
|
|
|
|
0x68 => CpuOpcode::LD,
|
|
|
|
0x69 => CpuOpcode::LD,
|
|
|
|
0x6A => CpuOpcode::LD,
|
|
|
|
0x6B => CpuOpcode::LD,
|
|
|
|
0x6C => CpuOpcode::LD,
|
|
|
|
0x6D => CpuOpcode::LD,
|
|
|
|
0x6E => CpuOpcode::LD,
|
|
|
|
0x70 => CpuOpcode::LD,
|
|
|
|
0x71 => CpuOpcode::LD,
|
|
|
|
0x72 => CpuOpcode::LD,
|
|
|
|
0x73 => CpuOpcode::LD,
|
|
|
|
0x74 => CpuOpcode::LD,
|
|
|
|
0x75 => CpuOpcode::LD,
|
|
|
|
0x36 => CpuOpcode::LD,
|
|
|
|
0x0A => CpuOpcode::LD,
|
|
|
|
0x1A => CpuOpcode::LD,
|
|
|
|
0xFA => CpuOpcode::LD,
|
|
|
|
0x3E => CpuOpcode::LD,
|
|
|
|
0x47 => CpuOpcode::LD,
|
|
|
|
0x4F => CpuOpcode::LD,
|
|
|
|
0x57 => CpuOpcode::LD,
|
|
|
|
0x5F => CpuOpcode::LD,
|
|
|
|
0x67 => CpuOpcode::LD,
|
|
|
|
0x6F => CpuOpcode::LD,
|
|
|
|
0x02 => CpuOpcode::LD,
|
|
|
|
0x12 => CpuOpcode::LD,
|
|
|
|
0x77 => CpuOpcode::LD,
|
|
|
|
0xEA => CpuOpcode::LD,
|
|
|
|
0xF2 => CpuOpcode::LD,
|
|
|
|
0xE2 => CpuOpcode::LD,
|
|
|
|
0x3A => CpuOpcode::LD,
|
|
|
|
0x32 => CpuOpcode::LDD,
|
|
|
|
0x2A => CpuOpcode::LDI,
|
|
|
|
0x22 => CpuOpcode::LDI,
|
|
|
|
0xE0 => CpuOpcode::LD,
|
|
|
|
0xF0 => CpuOpcode::LD,
|
|
|
|
0x01 => CpuOpcode::LD,
|
|
|
|
0x11 => CpuOpcode::LD,
|
|
|
|
0x21 => CpuOpcode::LD,
|
|
|
|
0x31 => CpuOpcode::LD,
|
|
|
|
0xF9 => CpuOpcode::LD,
|
|
|
|
0xF8 => CpuOpcode::LDHL,
|
|
|
|
0x08 => CpuOpcode::LD,
|
|
|
|
0xF5 => CpuOpcode::PUSH,
|
|
|
|
0xC5 => CpuOpcode::PUSH,
|
|
|
|
0xD5 => CpuOpcode::PUSH,
|
|
|
|
0xE5 => CpuOpcode::PUSH,
|
|
|
|
0xF1 => CpuOpcode::POP,
|
|
|
|
0xC1 => CpuOpcode::POP,
|
|
|
|
0xD1 => CpuOpcode::POP,
|
|
|
|
0xE1 => CpuOpcode::POP,
|
|
|
|
0x87 => CpuOpcode::ADD,
|
|
|
|
0x80 => CpuOpcode::ADD,
|
|
|
|
0x81 => CpuOpcode::ADD,
|
|
|
|
0x82 => CpuOpcode::ADD,
|
|
|
|
0x83 => CpuOpcode::ADD,
|
|
|
|
0x84 => CpuOpcode::ADD,
|
|
|
|
0x85 => CpuOpcode::ADD,
|
|
|
|
0x86 => CpuOpcode::ADD,
|
|
|
|
0xC6 => CpuOpcode::ADD,
|
|
|
|
0x8F => CpuOpcode::ADC,
|
|
|
|
0x88 => CpuOpcode::ADC,
|
|
|
|
0x89 => CpuOpcode::ADC,
|
|
|
|
0x8A => CpuOpcode::ADC,
|
|
|
|
0x8B => CpuOpcode::ADC,
|
|
|
|
0x8C => CpuOpcode::ADC,
|
|
|
|
0x8D => CpuOpcode::ADC,
|
|
|
|
0x8E => CpuOpcode::ADC,
|
|
|
|
0xCE => CpuOpcode::ADC,
|
|
|
|
0x97 => CpuOpcode::SUB,
|
|
|
|
0x90 => CpuOpcode::SUB,
|
|
|
|
0x91 => CpuOpcode::SUB,
|
|
|
|
0x92 => CpuOpcode::SUB,
|
|
|
|
0x93 => CpuOpcode::SUB,
|
|
|
|
0x94 => CpuOpcode::SUB,
|
|
|
|
0x95 => CpuOpcode::SUB,
|
|
|
|
0x96 => CpuOpcode::SUB,
|
|
|
|
0xD6 => CpuOpcode::SUB,
|
|
|
|
0x9F => CpuOpcode::SBC,
|
|
|
|
0x98 => CpuOpcode::SBC,
|
|
|
|
0x99 => CpuOpcode::SBC,
|
|
|
|
0x9A => CpuOpcode::SBC,
|
|
|
|
0x9B => CpuOpcode::SBC,
|
|
|
|
0x9C => CpuOpcode::SBC,
|
|
|
|
0x9D => CpuOpcode::SBC,
|
|
|
|
0x9E => CpuOpcode::SBC,
|
|
|
|
0xA7 => CpuOpcode::AND,
|
|
|
|
0xA0 => CpuOpcode::AND,
|
|
|
|
0xA1 => CpuOpcode::AND,
|
|
|
|
0xA2 => CpuOpcode::AND,
|
|
|
|
0xA3 => CpuOpcode::AND,
|
|
|
|
0xA4 => CpuOpcode::AND,
|
|
|
|
0xA5 => CpuOpcode::AND,
|
|
|
|
0xA6 => CpuOpcode::AND,
|
|
|
|
0xE6 => CpuOpcode::AND,
|
|
|
|
0xB7 => CpuOpcode::OR,
|
|
|
|
0xB0 => CpuOpcode::OR,
|
|
|
|
0xB1 => CpuOpcode::OR,
|
|
|
|
0xB2 => CpuOpcode::OR,
|
|
|
|
0xB3 => CpuOpcode::OR,
|
|
|
|
0xB4 => CpuOpcode::OR,
|
|
|
|
0xB5 => CpuOpcode::OR,
|
|
|
|
0xB6 => CpuOpcode::OR,
|
|
|
|
0xF6 => CpuOpcode::OR,
|
|
|
|
0xAF => CpuOpcode::XOR,
|
|
|
|
0xA8 => CpuOpcode::XOR,
|
|
|
|
0xA9 => CpuOpcode::XOR,
|
|
|
|
0xAA => CpuOpcode::XOR,
|
|
|
|
0xAB => CpuOpcode::XOR,
|
|
|
|
0xAC => CpuOpcode::XOR,
|
|
|
|
0xAD => CpuOpcode::XOR,
|
|
|
|
0xAE => CpuOpcode::XOR,
|
|
|
|
0xEE => CpuOpcode::XOR,
|
|
|
|
0xBF => CpuOpcode::CP,
|
|
|
|
0xB8 => CpuOpcode::CP,
|
|
|
|
0xB9 => CpuOpcode::CP,
|
|
|
|
0xBA => CpuOpcode::CP,
|
|
|
|
0xBB => CpuOpcode::CP,
|
|
|
|
0xBC => CpuOpcode::CP,
|
|
|
|
0xBD => CpuOpcode::CP,
|
|
|
|
0xBE => CpuOpcode::CP,
|
|
|
|
0xFE => CpuOpcode::CP,
|
|
|
|
0x3C => CpuOpcode::INC,
|
|
|
|
0x04 => CpuOpcode::INC,
|
|
|
|
0x0C => CpuOpcode::INC,
|
|
|
|
0x14 => CpuOpcode::INC,
|
|
|
|
0x1C => CpuOpcode::INC,
|
|
|
|
0x24 => CpuOpcode::INC,
|
|
|
|
0x2C => CpuOpcode::INC,
|
|
|
|
0x34 => CpuOpcode::INC,
|
|
|
|
0x3D => CpuOpcode::DEC,
|
|
|
|
0x05 => CpuOpcode::DEC,
|
|
|
|
0x0D => CpuOpcode::DEC,
|
|
|
|
0x15 => CpuOpcode::DEC,
|
|
|
|
0x1D => CpuOpcode::DEC,
|
|
|
|
0x25 => CpuOpcode::DEC,
|
|
|
|
0x2D => CpuOpcode::DEC,
|
|
|
|
0x35 => CpuOpcode::DEC,
|
|
|
|
0x09 => CpuOpcode::ADD,
|
|
|
|
0x19 => CpuOpcode::ADD,
|
|
|
|
0x29 => CpuOpcode::ADD,
|
|
|
|
0x39 => CpuOpcode::ADD,
|
|
|
|
0xE8 => CpuOpcode::ADD,
|
|
|
|
0x03 => CpuOpcode::INC,
|
|
|
|
0x13 => CpuOpcode::INC,
|
|
|
|
0x23 => CpuOpcode::INC,
|
|
|
|
0x33 => CpuOpcode::INC,
|
|
|
|
0x0B => CpuOpcode::DEC,
|
|
|
|
0x1B => CpuOpcode::DEC,
|
|
|
|
0x2B => CpuOpcode::DEC,
|
|
|
|
0x3B => CpuOpcode::DEC,
|
|
|
|
0xCB => CpuOpcode::SWAP,
|
|
|
|
0x27 => CpuOpcode::DAA,
|
|
|
|
0x2F => CpuOpcode::CPL,
|
|
|
|
0x3F => CpuOpcode::CCF,
|
|
|
|
0x37 => CpuOpcode::SCF,
|
|
|
|
0x17 => CpuOpcode::RLA,
|
|
|
|
0x07 => CpuOpcode::RLCA,
|
|
|
|
0x0F => CpuOpcode::RRCA,
|
|
|
|
0x1F => CpuOpcode::RRA,
|
|
|
|
//0xCB => CpuOpcode::RLC,
|
|
|
|
//0xCB => CpuOpcode::RL,
|
|
|
|
//0xCB => CpuOpcode::RRC,
|
|
|
|
//0xCB => CpuOpcode::RR,
|
|
|
|
//0xCB => CpuOpcode::SLA,
|
|
|
|
//0xCB => CpuOpcode::SRA,
|
|
|
|
//0xCB => CpuOpcode::SRL,
|
|
|
|
//0xCB => CpuOpcode::BIT,
|
|
|
|
//0xCB => CpuOpcode::SET,
|
|
|
|
//0xCB => CpuOpcode::RES,
|
|
|
|
0xC3 => CpuOpcode::JP,
|
|
|
|
0xC2 => CpuOpcode::JP,
|
|
|
|
0xCA => CpuOpcode::JP,
|
|
|
|
0xD2 => CpuOpcode::JP,
|
|
|
|
0xDA => CpuOpcode::JP,
|
|
|
|
0xE9 => CpuOpcode::JP,
|
|
|
|
0x18 => CpuOpcode::JR,
|
|
|
|
0x20 => CpuOpcode::JR,
|
|
|
|
0x28 => CpuOpcode::JR,
|
|
|
|
0x30 => CpuOpcode::JR,
|
|
|
|
0x38 => CpuOpcode::JR,
|
|
|
|
0xCD => CpuOpcode::CALL,
|
|
|
|
0xC4 => CpuOpcode::CALL,
|
|
|
|
0xCC => CpuOpcode::CALL,
|
|
|
|
0xD4 => CpuOpcode::CALL,
|
|
|
|
0xDC => CpuOpcode::CALL,
|
|
|
|
0xC7 => CpuOpcode::RST,
|
|
|
|
0xCF => CpuOpcode::RST,
|
|
|
|
0xD7 => CpuOpcode::RST,
|
|
|
|
0xDF => CpuOpcode::RST,
|
|
|
|
0xE7 => CpuOpcode::RST,
|
|
|
|
0xEF => CpuOpcode::RST,
|
|
|
|
0xF7 => CpuOpcode::RST,
|
|
|
|
0xFF => CpuOpcode::RST,
|
|
|
|
0xC9 => CpuOpcode::RET,
|
|
|
|
0xC0 => CpuOpcode::RET,
|
|
|
|
0xC8 => CpuOpcode::RET,
|
|
|
|
0xD0 => CpuOpcode::RET,
|
|
|
|
0xD8 => CpuOpcode::RET,
|
|
|
|
0xD9 => CpuOpcode::RETI,
|
|
|
|
0xF3 => CpuOpcode::DI,
|
|
|
|
0xFB => CpuOpcode::EI,
|
|
|
|
0x76 => CpuOpcode::HALT,
|
|
|
|
0x10 => CpuOpcode::STOP,
|
|
|
|
0x00 => CpuOpcode::NOP,
|
2021-10-12 17:52:04 +00:00
|
|
|
_ => CpuOpcode::IllegalInstruction,
|
2021-10-12 01:38:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-10-11 18:14:08 +00:00
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_registers_setters_getters() {
|
|
|
|
// Test 8 bit setters and getters
|
|
|
|
let mut registers = Registers::new();
|
|
|
|
registers.set(Register::A(0b01010101));
|
|
|
|
assert_eq!(registers.get(Register::A(0)), 0b01010101);
|
|
|
|
registers.set(Register::F(0b01010101));
|
|
|
|
assert_eq!(registers.get(Register::F(0)), 0b01010101);
|
|
|
|
registers.set(Register::B(0b01010101));
|
|
|
|
assert_eq!(registers.get(Register::B(0)), 0b01010101);
|
|
|
|
registers.set(Register::C(0b01010101));
|
|
|
|
assert_eq!(registers.get(Register::C(0)), 0b01010101);
|
|
|
|
registers.set(Register::D(0b01010101));
|
|
|
|
assert_eq!(registers.get(Register::D(0)), 0b01010101);
|
|
|
|
registers.set(Register::E(0b01010101));
|
|
|
|
assert_eq!(registers.get(Register::E(0)), 0b01010101);
|
|
|
|
registers.set(Register::H(0b01010101));
|
|
|
|
assert_eq!(registers.get(Register::H(0)), 0b01010101);
|
|
|
|
registers.set(Register::L(0b01010101));
|
|
|
|
assert_eq!(registers.get(Register::L(0)), 0b01010101);
|
|
|
|
|
|
|
|
// Test 16 bit setters and getters
|
|
|
|
let mut registers = Registers::new();
|
|
|
|
registers.set(Register::B(0b01010101));
|
|
|
|
registers.set(Register::C(0b11111111));
|
|
|
|
assert_eq!(registers.get(Register::BC(0)), 0b0101010111111111);
|
|
|
|
|
|
|
|
registers.set(Register::D(0b01010101));
|
|
|
|
registers.set(Register::E(0b11111111));
|
|
|
|
assert_eq!(registers.get(Register::DE(0)), 0b0101010111111111);
|
|
|
|
|
|
|
|
registers.set(Register::H(0b01010101));
|
|
|
|
registers.set(Register::L(0b11111111));
|
|
|
|
assert_eq!(registers.get(Register::HL(0)), 0b0101010111111111);
|
|
|
|
|
|
|
|
registers.set(Register::SP(0b0101010111111111));
|
|
|
|
assert_eq!(registers.get(Register::SP(0)), 0b0101010111111111);
|
|
|
|
|
|
|
|
registers.set(Register::PC(0b0101010111111111));
|
|
|
|
assert_eq!(registers.get(Register::PC(0)), 0b0101010111111111);
|
|
|
|
}
|
|
|
|
}
|