use crate::hw::cop0::{IntSrc, Mode, Status};
use crate::hw::Register;
use crate::CriticalSection;
use core::fmt;
use core::fmt::{Debug, Formatter};
pub const IEC: u32 = 0;
pub const KUC: u32 = 1;
pub const IEP: u32 = 2;
pub const KUP: u32 = 3;
pub const IEO: u32 = 4;
pub const KUO: u32 = 5;
pub const IM_SW0: u32 = 8;
pub const IM_SW1: u32 = 9;
pub const IM_HW: u32 = 10;
pub const ISC: u32 = 16;
pub const SWC: u32 = 17;
pub const BEV: u32 = 22;
pub const CU0: u32 = 28;
pub const CU2: u32 = 30;
impl Status {
pub fn interrupts_enabled(&self) -> bool {
self.all_set(1 << IEC)
}
pub fn interrupts_disabled(&self) -> bool {
self.all_clear(1 << IEC)
}
pub fn get_mode(&self) -> Mode {
if self.all_set(1 << KUC) {
Mode::User
} else {
Mode::Kernel
}
}
pub fn previous_interrupt_enabled(&self) -> bool {
self.all_set(1 << IEP)
}
pub fn previous_interrupt_disabled(&self) -> bool {
self.all_clear(1 << IEP)
}
pub fn previous_mode(&self) -> Mode {
if self.all_set(1 << KUP) {
Mode::User
} else {
Mode::Kernel
}
}
pub fn old_interrupt_enabled(&self) -> bool {
self.all_set(1 << IEO)
}
pub fn old_mode(&self) -> Mode {
if self.all_set(1 << KUO) {
Mode::User
} else {
Mode::Kernel
}
}
pub fn interrupt_unmasked(&self, int_src: IntSrc) -> bool {
self.all_set(1 << (int_src as u32))
}
pub fn interrupt_masked(&self, int_src: IntSrc) -> bool {
!self.interrupt_unmasked(int_src)
}
pub fn using_boot_vectors(&self) -> bool {
self.all_set(1 << BEV)
}
pub fn user_cop0_enabled(&self) -> bool {
self.all_set(1 << CU0)
}
pub fn gte_enabled(&self) -> bool {
self.all_set(1 << CU2)
}
pub fn enable_interrupts(&mut self) -> &mut Self {
self.set_bits(1 << IEC)
}
pub fn disable_interrupts(&mut self) -> &mut Self {
self.clear_bits(1 << IEC)
}
pub fn previous_interrupt_enable(&mut self) -> &mut Self {
self.set_bits(1 << IEP)
}
pub fn previous_interrupt_disable(&mut self) -> &mut Self {
self.clear_bits(1 << IEP)
}
pub fn set_mode(&mut self, mode: Mode) -> &mut Self {
self.clear_bits(1 << KUC).set_bits((mode as u32) << KUC)
}
pub fn mask_interrupt(&mut self, int_src: IntSrc) -> &mut Self {
self.clear_bits(1 << (int_src as u32))
}
pub fn unmask_interrupt(&mut self, int_src: IntSrc) -> &mut Self {
self.set_bits(1 << (int_src as u32))
}
pub fn cache_isolated(&self) -> bool {
self.all_set(1 << ISC)
}
pub fn isolate_cache(&mut self, isolate: bool) -> &mut Self {
if isolate {
self.set_bits(1 << ISC)
} else {
self.clear_bits(1 << ISC)
}
}
pub fn cache_swapped(&self) -> bool {
self.all_set(1 << SWC)
}
pub fn swap_cache(&mut self) -> &mut Self {
self.toggle_bits(1 << SWC)
}
pub fn use_boot_vectors(&mut self, rom: bool) -> &mut Self {
if rom {
self.set_bits(1 << BEV)
} else {
self.clear_bits(1 << BEV)
}
}
pub fn enable_user_cop0(&mut self) -> &mut Self {
self.set_bits(1 << CU0)
}
pub fn disable_user_cop0(&mut self) -> &mut Self {
self.clear_bits(1 << CU0)
}
pub fn enable_gte(&mut self) -> &mut Self {
self.set_bits(1 << CU2)
}
pub fn disable_gte(&mut self) -> &mut Self {
self.clear_bits(1 << CU2)
}
pub fn critical_section<F: FnMut(&mut CriticalSection) -> R, R>(&mut self, mut f: F) -> R {
let in_critical_section =
self.interrupt_masked(IntSrc::Hardware) || self.interrupts_disabled();
if !in_critical_section {
self.mask_interrupt(IntSrc::Hardware)
.disable_interrupts()
.store();
}
let mut cs = unsafe { CriticalSection::new() };
let res = f(&mut cs);
if !in_critical_section {
self.unmask_interrupt(IntSrc::Hardware)
.enable_interrupts()
.store();
}
res
}
}
impl Debug for Status {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_struct("cop0::Status")
.field("bits", &self.to_bits())
.field("interrupts_enabled", &self.interrupts_enabled())
.field("mode", &self.get_mode())
.field(
"hw_interrupt_masked",
&self.interrupt_masked(IntSrc::Hardware),
)
.field(
"sw0_interrupt_masked",
&self.interrupt_masked(IntSrc::Software0),
)
.field(
"sw1_interrupt_masked",
&self.interrupt_masked(IntSrc::Software1),
)
.field("boot_vectors", &self.using_boot_vectors())
.field("user_cop0_enabled", &self.user_cop0_enabled())
.field("gte_enabled", &self.gte_enabled())
.finish()
}
}