pub use feo3boy_opcodes::gbz80types::Flags;
use crate::gbz80core::executor::ExecutorState;
use crate::interrupts::{InterruptContext, MemInterrupts};
use crate::memdev::{MemContext, MemDevice, RootExtend};
pub mod direct_executor;
pub mod direct_executor_v2;
pub mod executor;
mod externdefs;
pub mod microcode_executor;
pub mod stepping_executor;
#[derive(Default, Debug, Clone, Eq, PartialEq)]
pub struct Regs {
pub flags: Flags,
pub acc: u8,
pub c: u8,
pub b: u8,
pub e: u8,
pub d: u8,
pub l: u8,
pub h: u8,
pub sp: u16,
pub pc: u16,
}
macro_rules! reg_pair_access {
($name:ident, $get:ident, $set:ident, $h:ident, $l:ident) => {
pub fn $get(&self) -> u16 {
u16::from_le_bytes([self.$l, self.$h])
}
pub fn $set(&mut self, val: u16) {
let [low, high] = val.to_le_bytes();
self.$l = low;
self.$h = high;
}
};
}
impl Regs {
pub fn af(&self) -> u16 {
u16::from_le_bytes([self.flags.bits(), self.acc])
}
pub fn set_af(&mut self, val: u16) {
let [f, a] = val.to_le_bytes();
self.flags = Flags::from_bits_truncate(f);
self.acc = a;
}
reg_pair_access!(BC, bc, set_bc, b, c);
reg_pair_access!(DE, de, set_de, d, e);
reg_pair_access!(HL, hl, set_hl, h, l);
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum InterruptMasterState {
Disabled,
Pending,
Enabled,
}
impl InterruptMasterState {
pub fn set(&mut self) {
*self = Self::Enabled;
}
pub fn clear(&mut self) {
*self = Self::Disabled;
}
pub fn set_next_instruction(&mut self) {
if *self != Self::Enabled {
*self = Self::Pending;
}
}
pub fn enabled(self) -> bool {
self == Self::Enabled
}
fn tick(&mut self, previous_state: Self) {
if previous_state == Self::Pending && *self != Self::Disabled {
*self = Self::Enabled;
}
}
}
impl Default for InterruptMasterState {
fn default() -> Self {
Self::Disabled
}
}
#[derive(Default, Debug, Clone, PartialEq, Eq)]
pub struct Gbz80State {
pub regs: Regs,
pub interrupt_master_enable: InterruptMasterState,
pub halted: bool,
pub halt_bug: bool,
}
impl Gbz80State {
pub fn new() -> Gbz80State {
Default::default()
}
}
pub trait ExecutorContext: CpuContext + MemContext + InterruptContext {
type State: ExecutorState;
fn executor(&self) -> &Self::State;
fn executor_mut(&mut self) -> &mut Self::State;
fn yield1m(&mut self);
}
pub trait CpuContext {
fn cpu(&self) -> &Gbz80State;
fn cpu_mut(&mut self) -> &mut Gbz80State;
}
impl<M: MemDevice> ExecutorContext for (Gbz80State, M) {
type State = ();
#[inline]
fn executor(&self) -> &Self::State {
&()
}
#[inline]
fn executor_mut(&mut self) -> &mut Self::State {
assert!(std::mem::size_of::<()>() == 0);
unsafe { std::mem::transmute(self) }
}
#[inline]
fn yield1m(&mut self) {}
}
impl<M> CpuContext for (Gbz80State, M) {
#[inline]
fn cpu(&self) -> &Gbz80State {
&self.0
}
#[inline]
fn cpu_mut(&mut self) -> &mut Gbz80State {
&mut self.0
}
}
impl<M: MemDevice> MemContext for (Gbz80State, M) {
type Mem = RootExtend<M>;
#[inline]
fn mem(&self) -> &Self::Mem {
RootExtend::wrap_ref(&self.1)
}
#[inline]
fn mem_mut(&mut self) -> &mut Self::Mem {
RootExtend::wrap_mut(&mut self.1)
}
}
impl<M: MemDevice> InterruptContext for (Gbz80State, M) {
type Interrupts = MemInterrupts<RootExtend<M>>;
#[inline]
fn interrupts(&self) -> &Self::Interrupts {
MemInterrupts::wrap_ref(self.mem())
}
#[inline]
fn interrupts_mut(&mut self) -> &mut Self::Interrupts {
MemInterrupts::wrap_mut(self.mem_mut())
}
}
impl<M: MemDevice> ExecutorContext for (&mut Gbz80State, &mut M) {
type State = ();
#[inline]
fn executor(&self) -> &Self::State {
&()
}
#[inline]
fn executor_mut(&mut self) -> &mut Self::State {
assert!(std::mem::size_of::<()>() == 0);
unsafe { std::mem::transmute(self) }
}
#[inline]
fn yield1m(&mut self) {}
}
impl<M> CpuContext for (&mut Gbz80State, &mut M) {
#[inline]
fn cpu(&self) -> &Gbz80State {
self.0
}
#[inline]
fn cpu_mut(&mut self) -> &mut Gbz80State {
self.0
}
}
impl<M: MemDevice> MemContext for (&mut Gbz80State, &mut M) {
type Mem = RootExtend<M>;
#[inline]
fn mem(&self) -> &Self::Mem {
RootExtend::wrap_ref(self.1)
}
#[inline]
fn mem_mut(&mut self) -> &mut Self::Mem {
RootExtend::wrap_mut(self.1)
}
}
impl<M: MemDevice> InterruptContext for (&mut Gbz80State, &mut M) {
type Interrupts = MemInterrupts<RootExtend<M>>;
#[inline]
fn interrupts(&self) -> &Self::Interrupts {
MemInterrupts::wrap_ref(self.mem())
}
#[inline]
fn interrupts_mut(&mut self) -> &mut Self::Interrupts {
MemInterrupts::wrap_mut(self.mem_mut())
}
}
impl<M: MemDevice, S: ExecutorState> ExecutorContext for (Gbz80State, M, S) {
type State = S;
#[inline]
fn executor(&self) -> &Self::State {
&self.2
}
#[inline]
fn executor_mut(&mut self) -> &mut Self::State {
&mut self.2
}
#[inline]
fn yield1m(&mut self) {}
}
impl<M, S> CpuContext for (Gbz80State, M, S) {
#[inline]
fn cpu(&self) -> &Gbz80State {
&self.0
}
#[inline]
fn cpu_mut(&mut self) -> &mut Gbz80State {
&mut self.0
}
}
impl<M: MemDevice, S> MemContext for (Gbz80State, M, S) {
type Mem = RootExtend<M>;
#[inline]
fn mem(&self) -> &Self::Mem {
RootExtend::wrap_ref(&self.1)
}
#[inline]
fn mem_mut(&mut self) -> &mut Self::Mem {
RootExtend::wrap_mut(&mut self.1)
}
}
impl<M: MemDevice, S> InterruptContext for (Gbz80State, M, S) {
type Interrupts = MemInterrupts<RootExtend<M>>;
#[inline]
fn interrupts(&self) -> &Self::Interrupts {
MemInterrupts::wrap_ref(self.mem())
}
#[inline]
fn interrupts_mut(&mut self) -> &mut Self::Interrupts {
MemInterrupts::wrap_mut(self.mem_mut())
}
}
impl<M: MemDevice, S: ExecutorState> ExecutorContext for (&mut Gbz80State, &mut M, &mut S) {
type State = S;
#[inline]
fn executor(&self) -> &Self::State {
&self.2
}
#[inline]
fn executor_mut(&mut self) -> &mut Self::State {
&mut self.2
}
#[inline]
fn yield1m(&mut self) {}
}
impl<M: MemDevice, S> CpuContext for (&mut Gbz80State, &mut M, &mut S) {
#[inline]
fn cpu(&self) -> &Gbz80State {
self.0
}
#[inline]
fn cpu_mut(&mut self) -> &mut Gbz80State {
self.0
}
}
impl<M: MemDevice, S> MemContext for (&mut Gbz80State, &mut M, &mut S) {
type Mem = RootExtend<M>;
#[inline]
fn mem(&self) -> &Self::Mem {
RootExtend::wrap_ref(self.1)
}
#[inline]
fn mem_mut(&mut self) -> &mut Self::Mem {
RootExtend::wrap_mut(self.1)
}
}
impl<M: MemDevice, S> InterruptContext for (&mut Gbz80State, &mut M, &mut S) {
type Interrupts = MemInterrupts<RootExtend<M>>;
#[inline]
fn interrupts(&self) -> &Self::Interrupts {
MemInterrupts::wrap_ref(self.mem())
}
#[inline]
fn interrupts_mut(&mut self) -> &mut Self::Interrupts {
MemInterrupts::wrap_mut(self.mem_mut())
}
}