1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
//! This module describes ways to identify chunks in registers bank and wraps an integral and a floating-point implementation.

use std::ops::RangeInclusive;
use std::hash::{Hash, Hasher};
use std::fmt::{Debug, Display, Formatter};

use osiris_data::data::identification::Identifier;

/// A wide range.
pub const REGISTERS_IN_BANK: usize = 65536;

/// A type which always represents a valid register in a bank.
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub struct RegisterId(u16);

impl RegisterId {
    /// Identify a register.
    pub const fn new(raw: u16) -> Self { Self(raw) }
    /// Returns the raw `u16` of this identifier.
    pub const fn to_u16(&self) -> u16 { self.0 }
}

impl Hash for RegisterId {
    fn hash<H: Hasher>(&self, state: &mut H) {
        state.write_usize(self.to_usize());
    }
}

impl Identifier for RegisterId {
    fn to_usize(&self) -> usize { self.0 as usize }
}

/// Represents a range of registers in a bank.
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub struct RegisterRange {
    pub start: RegisterId,
    pub end: RegisterId,
}

impl RegisterRange {
    /// Creates a range from a start and an end [RegisterId]s.
    ///
    /// May **panic** if `end < start`.
    pub fn new(start: RegisterId, end: RegisterId) -> Self {
        if end < start {
            panic!("End of a range cannot be lower to its start.")
        }
        Self { start, end }
    }

    /// Creates a range from a raw `u32`.
    pub fn from_u32(data: u32) -> Self {
        Self {
            start: RegisterId((data >> 16) as u16),
            end: RegisterId(data as u16),
        }
    }

    /// Returns a range usable to extract a slice notably.
    pub fn to_usize_range(&self) -> RangeInclusive<usize> { self.start.to_usize()..=self.end.to_usize() }

    /// Returns a raw `u32` representing the range.
    pub fn to_u32(&self) -> u32 { (self.start.to_u16() as u32) << 16 | self.end.to_u16() as u32 }

    /// Returns the number of registers included in the range.
    pub fn count(&self) -> usize { self.end.to_usize() - self.start.to_usize() + 1 }
}

impl Display for RegisterRange {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(f, "[{:04x}:{:04x}]", self.start.to_u16(), self.end.to_u16())
    }
}

pub mod integral;
pub mod floating_point;
pub mod state;