use core::fmt::{Debug, LowerHex, UpperHex};
use ax_memory_addr::AddrRange;
use axvm_types::GuestPhysAddr;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum AccessWidth {
Byte,
Word,
Dword,
Qword,
}
impl TryFrom<usize> for AccessWidth {
type Error = ();
fn try_from(value: usize) -> Result<Self, Self::Error> {
match value {
1 => Ok(Self::Byte),
2 => Ok(Self::Word),
4 => Ok(Self::Dword),
8 => Ok(Self::Qword),
_ => Err(()),
}
}
}
impl From<AccessWidth> for usize {
fn from(width: AccessWidth) -> usize {
match width {
AccessWidth::Byte => 1,
AccessWidth::Word => 2,
AccessWidth::Dword => 4,
AccessWidth::Qword => 8,
}
}
}
impl AccessWidth {
pub fn size(&self) -> usize {
(*self).into()
}
pub fn bits_range(&self) -> core::ops::Range<usize> {
match self {
AccessWidth::Byte => 0..8,
AccessWidth::Word => 0..16,
AccessWidth::Dword => 0..32,
AccessWidth::Qword => 0..64,
}
}
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct Port(pub u16);
impl Port {
pub fn new(port: u16) -> Self {
Self(port)
}
pub fn number(&self) -> u16 {
self.0
}
}
impl LowerHex for Port {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "Port({:#x})", self.0)
}
}
impl UpperHex for Port {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "Port({:#X})", self.0)
}
}
impl Debug for Port {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "Port({})", self.0)
}
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
pub struct SysRegAddr(pub usize);
impl SysRegAddr {
pub const fn new(addr: usize) -> Self {
Self(addr)
}
pub const fn addr(&self) -> usize {
self.0
}
}
impl LowerHex for SysRegAddr {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "SysRegAddr({:#x})", self.0)
}
}
impl UpperHex for SysRegAddr {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "SysRegAddr({:#X})", self.0)
}
}
impl Debug for SysRegAddr {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "SysRegAddr({})", self.0)
}
}
pub trait DeviceAddr: Copy + Eq + Ord + core::fmt::Debug {}
pub trait DeviceAddrRange {
type Addr: DeviceAddr;
fn contains(&self, addr: Self::Addr) -> bool;
}
impl DeviceAddr for GuestPhysAddr {}
impl DeviceAddrRange for AddrRange<GuestPhysAddr> {
type Addr = GuestPhysAddr;
fn contains(&self, addr: Self::Addr) -> bool {
Self::contains(*self, addr)
}
}
impl DeviceAddr for SysRegAddr {}
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub struct SysRegAddrRange {
pub start: SysRegAddr,
pub end: SysRegAddr,
}
impl SysRegAddrRange {
pub fn new(start: SysRegAddr, end: SysRegAddr) -> Self {
Self { start, end }
}
}
impl DeviceAddrRange for SysRegAddrRange {
type Addr = SysRegAddr;
fn contains(&self, addr: Self::Addr) -> bool {
addr.0 >= self.start.0 && addr.0 <= self.end.0
}
}
impl LowerHex for SysRegAddrRange {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:#x}..={:#x}", self.start.0, self.end.0)
}
}
impl DeviceAddr for Port {}
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub struct PortRange {
pub start: Port,
pub end: Port,
}
impl PortRange {
pub fn new(start: Port, end: Port) -> Self {
Self { start, end }
}
}
impl DeviceAddrRange for PortRange {
type Addr = Port;
fn contains(&self, addr: Self::Addr) -> bool {
addr.0 >= self.start.0 && addr.0 <= self.end.0
}
}
impl LowerHex for PortRange {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:#x}..={:#x}", self.start.0, self.end.0)
}
}