use crate::trap::TrapDispatcher;
pub(crate) const SPIN_FASTFWD_MAX_TICKS: u32 = 1_000_000;
pub(crate) enum AdvanceResult {
Advanced,
CapHit,
Interrupted,
TooFar,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub(crate) struct CpuArchitecturalSnapshot {
pub(crate) dar: [u32; 16],
pub(crate) dar_save: [u32; 16],
pub(crate) sr_save: u16,
pub(crate) ppc: u32,
pub(crate) stack_pointers: [u32; 8],
pub(crate) pc: u32,
pub(crate) sr: u16,
pub(crate) vbr: u32,
pub(crate) sfc: u32,
pub(crate) dfc: u32,
pub(crate) cacr: u32,
pub(crate) caar: u32,
pub(crate) cacr_pending_ops: u32,
pub(crate) itt: [u32; 2],
pub(crate) dtt: [u32; 2],
pub(crate) ir: u32,
pub(crate) fpr: [m68k::fpu::FloatX80; 8],
pub(crate) fpiar: u32,
pub(crate) fpsr: u32,
pub(crate) fpcr: u32,
pub(crate) mmu: [u32; 14],
pub(crate) pmmu_enabled: bool,
pub(crate) int_level: u32,
pub(crate) stopped: u32,
pub(crate) change_of_flow: bool,
pub(crate) loop_mode: bool,
pub(crate) loop_body_word: u16,
pub(crate) loop_dbcc_word: u16,
pub(crate) prefetch: [u16; 2],
pub(crate) prefetch_count: u8,
pub(crate) consume_without_prefetch: bool,
pub(crate) pending_sync_clocks: u32,
pub(crate) run_mode: u32,
pub(crate) fpu_just_reset: bool,
pub(crate) reset_cycles: u32,
pub(crate) virq_state: u32,
pub(crate) nmi_pending: u32,
pub(crate) exception_processing: bool,
}
impl CpuArchitecturalSnapshot {
pub(crate) fn capture(cpu: &m68k::CpuCore) -> Self {
Self {
dar: cpu.dar,
dar_save: cpu.dar_save,
sr_save: cpu.sr_save,
ppc: cpu.ppc,
stack_pointers: cpu.sp,
pc: cpu.pc,
sr: cpu.get_sr(),
vbr: cpu.vbr,
sfc: cpu.sfc,
dfc: cpu.dfc,
cacr: cpu.cacr,
caar: cpu.caar,
cacr_pending_ops: cpu.cacr_pending_ops,
itt: [cpu.itt0, cpu.itt1],
dtt: [cpu.dtt0, cpu.dtt1],
ir: cpu.ir,
fpr: cpu.fpr,
fpiar: cpu.fpiar,
fpsr: cpu.fpsr,
fpcr: cpu.fpcr,
mmu: [
cpu.mmu_crp_aptr,
cpu.mmu_crp_limit,
cpu.mmu_srp_aptr,
cpu.mmu_srp_limit,
cpu.mmu_tc,
cpu.mmu_sr,
cpu.mmu_tt0,
cpu.mmu_tt1,
cpu.dacr0,
cpu.dacr1,
cpu.iacr0,
cpu.iacr1,
cpu.pcr,
cpu.buscr,
],
pmmu_enabled: cpu.pmmu_enabled,
int_level: cpu.int_level,
stopped: cpu.stopped,
change_of_flow: false,
loop_mode: cpu.loop_mode,
loop_body_word: cpu.loop_body_word,
loop_dbcc_word: cpu.loop_dbcc_word,
prefetch: cpu.prefetch_queue,
prefetch_count: cpu.prefetch_count,
consume_without_prefetch: cpu.consume_without_prefetch,
pending_sync_clocks: cpu.pending_sync_clocks,
run_mode: cpu.run_mode,
fpu_just_reset: cpu.fpu_just_reset,
reset_cycles: cpu.reset_cycles,
virq_state: cpu.virq_state,
nmi_pending: cpu.nmi_pending,
exception_processing: cpu.exception_processing,
}
}
}
pub(crate) struct IdleCycleProbe {
pub(crate) trap_pc: u32,
pub(crate) tick: u32,
pub(crate) cpu: CpuArchitecturalSnapshot,
pub(crate) arrivals: u8,
}
pub(crate) const IDLE_CYCLE_MAX_PERIOD: u8 = 4;
pub(crate) const IDLE_CYCLE_MAX_PROBES_PER_TICK: u8 = 2;
#[derive(Clone, Debug, Eq, PartialEq)]
pub(crate) struct IdleCycleHostSnapshot {
pub(crate) mouse_pos: (i16, i16),
pub(crate) mouse_button: bool,
pub(crate) key_map: [u8; 16],
pub(crate) caps_lock_physically_pressed: bool,
pub(crate) window_list: Vec<u32>,
pub(crate) pending_native_menu_selection: Option<(i16, i16)>,
}
impl IdleCycleHostSnapshot {
pub(crate) fn capture(dispatcher: &TrapDispatcher) -> Self {
Self {
mouse_pos: dispatcher.input_state.mouse_pos,
mouse_button: dispatcher.input_state.mouse_button,
key_map: *dispatcher.key_map_bytes(),
caps_lock_physically_pressed: dispatcher.input_state.caps_lock_physically_pressed,
window_list: dispatcher.window_list.to_vec(),
pending_native_menu_selection: dispatcher.pending_native_menu_selection.snapshot(),
}
}
}
pub(crate) struct ProvenIdleCycleSleep {
pub(crate) trap_pc: u32,
pub(crate) wake_tick: u32,
pub(crate) tick: u32,
pub(crate) cpu: CpuArchitecturalSnapshot,
pub(crate) host: IdleCycleHostSnapshot,
}