better processor modularisation
This commit is contained in:
parent
8413dedb89
commit
3a599b069f
43
src/processor/instructions/instructions.rs
Normal file
43
src/processor/instructions/instructions.rs
Normal file
|
@ -0,0 +1,43 @@
|
|||
use crate::processor::{get_bit, Direction, CPU};
|
||||
|
||||
impl CPU {
|
||||
pub(crate) fn rlc(&mut self, byte: u8) -> u8 {
|
||||
self.rotate_c(byte, Direction::Left)
|
||||
}
|
||||
|
||||
pub(crate) fn rrc(&mut self, byte: u8) -> u8 {
|
||||
self.rotate_c(byte, Direction::Right)
|
||||
}
|
||||
|
||||
pub(crate) fn rl(&mut self, byte: u8) -> u8 {
|
||||
self.rotate(byte, Direction::Left)
|
||||
}
|
||||
|
||||
pub(crate) fn rr(&mut self, byte: u8) -> u8 {
|
||||
self.rotate(byte, Direction::Right)
|
||||
}
|
||||
|
||||
pub(crate) fn sla(&mut self, byte: u8) -> u8 {
|
||||
self.shift(byte, Direction::Left)
|
||||
}
|
||||
|
||||
pub(crate) fn sra(&mut self, byte: u8) -> u8 {
|
||||
let b = get_bit(byte, 7);
|
||||
let val = self.shift(byte, Direction::Right);
|
||||
if b {
|
||||
val + 0b10000000
|
||||
} else {
|
||||
val
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn srl(&mut self, byte: u8) -> u8 {
|
||||
self.shift(byte, Direction::Right)
|
||||
}
|
||||
|
||||
pub(crate) fn rst(&mut self, address: u16) {
|
||||
self.push(self.state.pc);
|
||||
self.state.pc.as_u8s.left = 0x0;
|
||||
self.state.pc.as_u8s.right = self.memory.get(address);
|
||||
}
|
||||
}
|
2
src/processor/instructions/mod.rs
Normal file
2
src/processor/instructions/mod.rs
Normal file
|
@ -0,0 +1,2 @@
|
|||
pub mod instructions;
|
||||
pub mod primitives;
|
180
src/processor/instructions/primitives.rs
Normal file
180
src/processor/instructions/primitives.rs
Normal file
|
@ -0,0 +1,180 @@
|
|||
use std::ops::{BitAnd, BitOr, BitXor};
|
||||
|
||||
use crate::{
|
||||
processor::{get_bit, get_rotation_carry, rotate, Direction, CPU, FLAGS},
|
||||
verbose_println, Inner, Register,
|
||||
};
|
||||
|
||||
impl CPU {
|
||||
pub(crate) fn pop_word(&mut self) -> Register {
|
||||
unsafe {
|
||||
let address = self.state.sp.as_u16;
|
||||
self.state.sp.as_u16 = self.state.sp.as_u16.wrapping_add(0x2);
|
||||
Register {
|
||||
as_u8s: Inner {
|
||||
left: self.memory.get(address),
|
||||
right: self.memory.get(address.wrapping_add(1)),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn store_word(&mut self, address: u16, word: Register) {
|
||||
unsafe {
|
||||
self.memory.set(address, word.as_u8s.left);
|
||||
self.memory.set(address + 1, word.as_u8s.right);
|
||||
};
|
||||
}
|
||||
|
||||
pub(crate) fn push(&mut self, register: Register) {
|
||||
unsafe {
|
||||
let address = self.state.sp.as_u16;
|
||||
self.memory
|
||||
.set(address.wrapping_sub(1), register.as_u8s.right);
|
||||
self.memory
|
||||
.set(address.wrapping_sub(2), register.as_u8s.left);
|
||||
self.state.sp.as_u16 = address.wrapping_sub(2);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn ld_immediate_byte(&mut self) -> u8 {
|
||||
self.next_opcode()
|
||||
}
|
||||
|
||||
pub(crate) fn ld_immediate_word(&mut self) -> Register {
|
||||
Register {
|
||||
as_u8s: Inner {
|
||||
left: self.next_opcode(),
|
||||
right: self.next_opcode(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn rotate_c(&mut self, byte: u8, direction: Direction) -> u8 {
|
||||
let (mut rotated, carry) = rotate(byte, &direction);
|
||||
if carry {
|
||||
rotated += get_rotation_carry(&direction);
|
||||
self.set_flag(FLAGS::Carry);
|
||||
}
|
||||
return rotated;
|
||||
}
|
||||
|
||||
pub(crate) fn rotate(&mut self, byte: u8, direction: Direction) -> u8 {
|
||||
let old_carry = self.get_flag(FLAGS::Carry);
|
||||
let (mut rotated, carry) = rotate(byte, &direction);
|
||||
if old_carry > 0 {
|
||||
rotated += get_rotation_carry(&direction);
|
||||
}
|
||||
if carry {
|
||||
self.set_flag(FLAGS::Carry);
|
||||
}
|
||||
return rotated;
|
||||
}
|
||||
|
||||
pub(crate) fn shift(&mut self, byte: u8, direction: Direction) -> u8 {
|
||||
let (rotated, carry) = rotate(byte, &direction);
|
||||
if carry {
|
||||
self.set_flag(FLAGS::Carry);
|
||||
}
|
||||
return rotated;
|
||||
}
|
||||
|
||||
pub(crate) fn bit(&mut self, byte: u8, bit: u8) {
|
||||
self.set_or_clear_flag(FLAGS::Zero, !get_bit(byte, bit));
|
||||
}
|
||||
|
||||
pub(crate) fn get_flag(&mut self, flag: FLAGS) -> u8 {
|
||||
unsafe {
|
||||
if get_bit(self.state.af.as_u8s.right, flag as u8) {
|
||||
0x1
|
||||
} else {
|
||||
0x0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn set_flag(&mut self, flag: FLAGS) {
|
||||
if flag == FLAGS::Zero {
|
||||
verbose_println!("setting z flag");
|
||||
}
|
||||
unsafe {
|
||||
verbose_println!(
|
||||
"setting flag: currently {0:#b} / {0:#X}",
|
||||
self.state.af.as_u8s.right
|
||||
);
|
||||
self.state.af.as_u8s.right = self.state.af.as_u8s.right.bitor(1 << flag as u8);
|
||||
verbose_println!(
|
||||
" now {0:#b} / {0:#X}",
|
||||
self.state.af.as_u8s.right
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
pub(crate) fn clear_flag(&mut self, flag: FLAGS) {
|
||||
unsafe {
|
||||
self.state.af.as_u8s.right = self.state.af.as_u8s.right.bitand(!(1 << flag as u8));
|
||||
};
|
||||
}
|
||||
|
||||
pub(crate) fn toggle_flag(&mut self, flag: FLAGS) {
|
||||
unsafe {
|
||||
self.state.af.as_u8s.right = self.state.af.as_u8s.right.bitxor(1 << flag as u8);
|
||||
};
|
||||
}
|
||||
|
||||
pub(crate) fn set_or_clear_flag(&mut self, flag: FLAGS, state: bool) {
|
||||
if state {
|
||||
self.set_flag(flag)
|
||||
} else {
|
||||
self.clear_flag(flag)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn add_u8s(&mut self, first: u8, second: u8) -> u8 {
|
||||
let (result, carry) = first.overflowing_add(second);
|
||||
self.clear_flag(FLAGS::NSubtract);
|
||||
self.set_or_clear_flag(FLAGS::Carry, carry);
|
||||
self.set_or_clear_flag(FLAGS::Zero, result == 0x0);
|
||||
self.set_or_clear_flag(
|
||||
FLAGS::HalfCarry,
|
||||
(((first & 0xF).wrapping_add(second & 0xF)) & 0x10) == 0x10,
|
||||
);
|
||||
return result;
|
||||
}
|
||||
|
||||
pub(crate) fn add_u16s(&mut self, first: u16, second: u16) -> u16 {
|
||||
let (result, carry) = first.overflowing_add(second);
|
||||
self.clear_flag(FLAGS::NSubtract);
|
||||
self.set_or_clear_flag(FLAGS::Carry, carry);
|
||||
self.set_or_clear_flag(FLAGS::Zero, result == 0x0);
|
||||
self.set_or_clear_flag(
|
||||
FLAGS::HalfCarry,
|
||||
(((first & 0xFFF).wrapping_add(second & 0xFFF)) & 0x1000) == 0x1000,
|
||||
);
|
||||
return result;
|
||||
}
|
||||
|
||||
pub(crate) fn sub_u8s(&mut self, first: u8, second: u8) -> u8 {
|
||||
let (result, carry) = first.overflowing_sub(second);
|
||||
self.set_flag(FLAGS::NSubtract);
|
||||
self.set_or_clear_flag(FLAGS::Carry, carry);
|
||||
self.set_or_clear_flag(FLAGS::Zero, result == 0x0);
|
||||
self.set_or_clear_flag(
|
||||
FLAGS::HalfCarry,
|
||||
(((first & 0xF).wrapping_sub(second & 0xF)) & 0x10) == 0x10,
|
||||
);
|
||||
return result;
|
||||
}
|
||||
|
||||
pub(crate) fn sub_u16s(&mut self, first: u16, second: u16) -> u16 {
|
||||
let (result, carry) = first.overflowing_sub(second);
|
||||
self.set_flag(FLAGS::NSubtract);
|
||||
self.set_or_clear_flag(FLAGS::Carry, carry);
|
||||
self.set_or_clear_flag(FLAGS::Zero, result == 0x0);
|
||||
self.set_or_clear_flag(
|
||||
FLAGS::HalfCarry,
|
||||
(((first & 0xFFF).wrapping_sub(second & 0xFFF)) & 0x1000) == 0x1000,
|
||||
);
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -1,21 +1,19 @@
|
|||
use std::{
|
||||
mem::transmute,
|
||||
ops::{BitAnd, BitOr, BitXor},
|
||||
};
|
||||
use std::mem::transmute;
|
||||
|
||||
use crate::{verbose_println, Inner, Memory, Register, State};
|
||||
use crate::{verbose_println, Memory, State};
|
||||
|
||||
mod instructions;
|
||||
mod opcodes;
|
||||
|
||||
#[derive(PartialEq)]
|
||||
enum FLAGS {
|
||||
pub(crate) enum FLAGS {
|
||||
Zero = 7,
|
||||
NSubtract = 6,
|
||||
HalfCarry = 5,
|
||||
Carry = 4,
|
||||
}
|
||||
|
||||
enum Direction {
|
||||
pub(crate) enum Direction {
|
||||
Left,
|
||||
Right,
|
||||
}
|
||||
|
@ -47,218 +45,6 @@ impl CPU {
|
|||
return opcode;
|
||||
};
|
||||
}
|
||||
|
||||
fn rlc(&mut self, byte: u8) -> u8 {
|
||||
self.rotate_c(byte, Direction::Left)
|
||||
}
|
||||
|
||||
fn rrc(&mut self, byte: u8) -> u8 {
|
||||
self.rotate_c(byte, Direction::Right)
|
||||
}
|
||||
|
||||
fn rl(&mut self, byte: u8) -> u8 {
|
||||
self.rotate(byte, Direction::Left)
|
||||
}
|
||||
|
||||
fn rr(&mut self, byte: u8) -> u8 {
|
||||
self.rotate(byte, Direction::Right)
|
||||
}
|
||||
|
||||
fn rotate_c(&mut self, byte: u8, direction: Direction) -> u8 {
|
||||
let (mut rotated, carry) = rotate(byte, &direction);
|
||||
if carry {
|
||||
rotated += get_rotation_carry(&direction);
|
||||
self.set_flag(FLAGS::Carry);
|
||||
}
|
||||
return rotated;
|
||||
}
|
||||
|
||||
fn rotate(&mut self, byte: u8, direction: Direction) -> u8 {
|
||||
let old_carry = self.get_flag(FLAGS::Carry);
|
||||
let (mut rotated, carry) = rotate(byte, &direction);
|
||||
if old_carry > 0 {
|
||||
rotated += get_rotation_carry(&direction);
|
||||
}
|
||||
if carry {
|
||||
self.set_flag(FLAGS::Carry);
|
||||
}
|
||||
return rotated;
|
||||
}
|
||||
|
||||
fn sla(&mut self, byte: u8) -> u8 {
|
||||
self.shift(byte, Direction::Left)
|
||||
}
|
||||
|
||||
fn sra(&mut self, byte: u8) -> u8 {
|
||||
let b = get_bit(byte, 7);
|
||||
let val = self.shift(byte, Direction::Right);
|
||||
if b {
|
||||
val + 0b10000000
|
||||
} else {
|
||||
val
|
||||
}
|
||||
}
|
||||
|
||||
fn srl(&mut self, byte: u8) -> u8 {
|
||||
self.shift(byte, Direction::Right)
|
||||
}
|
||||
|
||||
fn shift(&mut self, byte: u8, direction: Direction) -> u8 {
|
||||
let (rotated, carry) = rotate(byte, &direction);
|
||||
if carry {
|
||||
self.set_flag(FLAGS::Carry);
|
||||
}
|
||||
return rotated;
|
||||
}
|
||||
|
||||
fn bit(&mut self, byte: u8, bit: u8) {
|
||||
self.set_or_clear_flag(FLAGS::Zero, !get_bit(byte, bit));
|
||||
}
|
||||
|
||||
fn rst(&mut self, address: u16) {
|
||||
self.push(self.state.pc);
|
||||
self.state.pc.as_u8s.left = 0x0;
|
||||
self.state.pc.as_u8s.right = self.memory.get(address);
|
||||
}
|
||||
|
||||
fn push(&mut self, register: Register) {
|
||||
unsafe {
|
||||
let address = self.state.sp.as_u16;
|
||||
self.memory
|
||||
.set(address.wrapping_sub(1), register.as_u8s.right);
|
||||
self.memory
|
||||
.set(address.wrapping_sub(2), register.as_u8s.left);
|
||||
self.state.sp.as_u16 = address.wrapping_sub(2);
|
||||
}
|
||||
}
|
||||
|
||||
fn pop_word(&mut self) -> Register {
|
||||
unsafe {
|
||||
let address = self.state.sp.as_u16;
|
||||
self.state.sp.as_u16 = self.state.sp.as_u16.wrapping_add(0x2);
|
||||
Register {
|
||||
as_u8s: Inner {
|
||||
left: self.memory.get(address),
|
||||
right: self.memory.get(address.wrapping_add(1)),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn store_word(&mut self, address: u16, word: Register) {
|
||||
unsafe {
|
||||
self.memory.set(address, word.as_u8s.left);
|
||||
self.memory.set(address + 1, word.as_u8s.right);
|
||||
};
|
||||
}
|
||||
|
||||
fn ld_immediate_word(&mut self) -> Register {
|
||||
Register {
|
||||
as_u8s: Inner {
|
||||
left: self.next_opcode(),
|
||||
right: self.next_opcode(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn ld_immediate_byte(&mut self) -> u8 {
|
||||
self.next_opcode()
|
||||
}
|
||||
|
||||
fn get_flag(&mut self, flag: FLAGS) -> u8 {
|
||||
unsafe {
|
||||
if get_bit(self.state.af.as_u8s.right, flag as u8) {
|
||||
0x1
|
||||
} else {
|
||||
0x0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn set_flag(&mut self, flag: FLAGS) {
|
||||
if flag == FLAGS::Zero {
|
||||
verbose_println!("setting z flag");
|
||||
}
|
||||
unsafe {
|
||||
verbose_println!(
|
||||
"setting flag: currently {0:#b} / {0:#X}",
|
||||
self.state.af.as_u8s.right
|
||||
);
|
||||
self.state.af.as_u8s.right = self.state.af.as_u8s.right.bitor(1 << flag as u8);
|
||||
verbose_println!(
|
||||
" now {0:#b} / {0:#X}",
|
||||
self.state.af.as_u8s.right
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
fn clear_flag(&mut self, flag: FLAGS) {
|
||||
unsafe {
|
||||
self.state.af.as_u8s.right = self.state.af.as_u8s.right.bitand(!(1 << flag as u8));
|
||||
};
|
||||
}
|
||||
|
||||
fn toggle_flag(&mut self, flag: FLAGS) {
|
||||
unsafe {
|
||||
self.state.af.as_u8s.right = self.state.af.as_u8s.right.bitxor(1 << flag as u8);
|
||||
};
|
||||
}
|
||||
|
||||
fn set_or_clear_flag(&mut self, flag: FLAGS, state: bool) {
|
||||
if state {
|
||||
self.set_flag(flag)
|
||||
} else {
|
||||
self.clear_flag(flag)
|
||||
}
|
||||
}
|
||||
|
||||
fn add_u8s(&mut self, first: u8, second: u8) -> u8 {
|
||||
let (result, carry) = first.overflowing_add(second);
|
||||
self.clear_flag(FLAGS::NSubtract);
|
||||
self.set_or_clear_flag(FLAGS::Carry, carry);
|
||||
self.set_or_clear_flag(FLAGS::Zero, result == 0x0);
|
||||
self.set_or_clear_flag(
|
||||
FLAGS::HalfCarry,
|
||||
(((first & 0xF).wrapping_add(second & 0xF)) & 0x10) == 0x10,
|
||||
);
|
||||
return result;
|
||||
}
|
||||
|
||||
fn add_u16s(&mut self, first: u16, second: u16) -> u16 {
|
||||
let (result, carry) = first.overflowing_add(second);
|
||||
self.clear_flag(FLAGS::NSubtract);
|
||||
self.set_or_clear_flag(FLAGS::Carry, carry);
|
||||
self.set_or_clear_flag(FLAGS::Zero, result == 0x0);
|
||||
self.set_or_clear_flag(
|
||||
FLAGS::HalfCarry,
|
||||
(((first & 0xFFF).wrapping_add(second & 0xFFF)) & 0x1000) == 0x1000,
|
||||
);
|
||||
return result;
|
||||
}
|
||||
|
||||
fn sub_u8s(&mut self, first: u8, second: u8) -> u8 {
|
||||
let (result, carry) = first.overflowing_sub(second);
|
||||
self.set_flag(FLAGS::NSubtract);
|
||||
self.set_or_clear_flag(FLAGS::Carry, carry);
|
||||
self.set_or_clear_flag(FLAGS::Zero, result == 0x0);
|
||||
self.set_or_clear_flag(
|
||||
FLAGS::HalfCarry,
|
||||
(((first & 0xF).wrapping_sub(second & 0xF)) & 0x10) == 0x10,
|
||||
);
|
||||
return result;
|
||||
}
|
||||
|
||||
fn sub_u16s(&mut self, first: u16, second: u16) -> u16 {
|
||||
let (result, carry) = first.overflowing_sub(second);
|
||||
self.set_flag(FLAGS::NSubtract);
|
||||
self.set_or_clear_flag(FLAGS::Carry, carry);
|
||||
self.set_or_clear_flag(FLAGS::Zero, result == 0x0);
|
||||
self.set_or_clear_flag(
|
||||
FLAGS::HalfCarry,
|
||||
(((first & 0xFFF).wrapping_sub(second & 0xFFF)) & 0x1000) == 0x1000,
|
||||
);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
fn as_signed(unsigned: u8) -> i8 {
|
||||
|
|
Loading…
Reference in a new issue