use crate::compiler::instr::builder::{InstrBuilder, MicrocodeReadable, MicrocodeWritable};
use crate::microcode::args::Reg16;
use crate::microcode::Microcode;
pub struct Mem;
impl MicrocodeReadable for Mem {
fn to_read(self) -> InstrBuilder {
InstrBuilder::r#yield().then(Microcode::ReadMem)
}
}
impl MicrocodeWritable for Mem {
fn to_write(self) -> InstrBuilder {
InstrBuilder::r#yield().then(Microcode::WriteMem)
}
}
pub struct Immediate8;
impl MicrocodeReadable for Immediate8 {
fn to_read(self) -> InstrBuilder {
InstrBuilder::read(Reg16::Pc)
.then(Microcode::Dup16)
.then(Microcode::Inc16)
.then_write(Reg16::Pc)
.then_yield()
.then(Microcode::ReadMem)
}
}
pub struct Immediate16;
impl MicrocodeReadable for Immediate16 {
fn to_read(self) -> InstrBuilder {
InstrBuilder::read(Immediate8).then_read(Immediate8)
}
}
pub struct SpInc;
impl MicrocodeReadable for SpInc {
fn to_read(self) -> InstrBuilder {
InstrBuilder::read(Reg16::Sp)
.then(Microcode::Dup16)
.then(Microcode::Inc16)
.then_write(Reg16::Sp)
}
}
pub struct DecSp;
impl MicrocodeReadable for DecSp {
fn to_read(self) -> InstrBuilder {
InstrBuilder::read(Reg16::Sp)
.then(Microcode::Dec16)
.then(Microcode::Dup16)
.then_write(Reg16::Sp)
}
}
pub struct GbStack16;
impl MicrocodeReadable for GbStack16 {
fn to_read(self) -> InstrBuilder {
InstrBuilder::read(SpInc)
.then_read(Mem)
.then_read(SpInc)
.then_read(Mem)
}
}
impl MicrocodeWritable for GbStack16 {
fn to_write(self) -> InstrBuilder {
InstrBuilder::read(DecSp)
.then_write(Mem)
.then_read(DecSp)
.then_write(Mem)
}
}
pub struct HlInc;
impl MicrocodeReadable for HlInc {
fn to_read(self) -> InstrBuilder {
InstrBuilder::read(Reg16::HL)
.then(Microcode::Dup16)
.then(Microcode::Inc16)
.then_write(Reg16::HL)
}
}
pub struct HlDec;
impl MicrocodeReadable for HlDec {
fn to_read(self) -> InstrBuilder {
InstrBuilder::read(Reg16::HL)
.then(Microcode::Dup16)
.then(Microcode::Dec16)
.then_write(Reg16::HL)
}
}
pub struct HandleHalt;
impl From<HandleHalt> for InstrBuilder {
fn from(_: HandleHalt) -> Self {
InstrBuilder::first(Microcode::CheckHalt)
.then_if_true(
InstrBuilder::first(Microcode::GetActiveInterrupts)
.then_cond(
Microcode::ClearHalt,
InstrBuilder::r#yield()
.then(Microcode::FetchNextInstruction),
),
)
}
}
pub struct ServiceInterrupt;
impl From<ServiceInterrupt> for InstrBuilder {
fn from(_: ServiceInterrupt) -> Self {
InstrBuilder::first(Microcode::CheckIme)
.then_if_true(
InstrBuilder::first(Microcode::GetActiveInterrupts)
.then_if_true(
InstrBuilder::first(Microcode::PopInterrupt)
.then(Microcode::DisableInterrupts)
.then_read(Reg16::Pc)
.then(Microcode::PopHaltBug)
.then_if_true(Microcode::Dec16)
.then_yield()
.then_yield()
.then_write(GbStack16)
.then_yield()
.then_write(Reg16::Pc)
.then(Microcode::FetchNextInstruction),
),
)
}
}
pub struct LoadAndExecute;
impl From<LoadAndExecute> for InstrBuilder {
fn from(_: LoadAndExecute) -> Self {
InstrBuilder::read(Immediate8)
.then(Microcode::TickImeOnEnd)
.then(Microcode::PopHaltBug)
.then_if_true(
InstrBuilder::read(Reg16::Pc)
.then(Microcode::Dec16)
.then_write(Reg16::Pc),
)
.then(Microcode::ParseOpcode)
}
}