better processor modularisation

This commit is contained in:
Alex Janka 2023-01-31 10:05:36 +11:00
parent 8413dedb89
commit 3a599b069f
4 changed files with 230 additions and 219 deletions

View 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);
}
}

View file

@ -0,0 +1,2 @@
pub mod instructions;
pub mod primitives;

View 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;
}
}

View file

@ -1,21 +1,19 @@
use std::{ use std::mem::transmute;
mem::transmute,
ops::{BitAnd, BitOr, BitXor},
};
use crate::{verbose_println, Inner, Memory, Register, State}; use crate::{verbose_println, Memory, State};
mod instructions;
mod opcodes; mod opcodes;
#[derive(PartialEq)] #[derive(PartialEq)]
enum FLAGS { pub(crate) enum FLAGS {
Zero = 7, Zero = 7,
NSubtract = 6, NSubtract = 6,
HalfCarry = 5, HalfCarry = 5,
Carry = 4, Carry = 4,
} }
enum Direction { pub(crate) enum Direction {
Left, Left,
Right, Right,
} }
@ -47,218 +45,6 @@ impl CPU {
return opcode; 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 { fn as_signed(unsigned: u8) -> i8 {