Skip to main content

osom_encoders_x86_64/models/
gpr_kind.rs

1use core::mem::transmute;
2
3use super::Size;
4
5/// Represents the kind of a general purpose register.
6#[repr(u8)]
7#[derive(Debug, Clone, PartialEq, Eq, Hash, Copy)]
8#[must_use]
9pub enum GPRKind {
10    /// Represents AH, BH, CH and DH registers.
11    Bit8High = 1, // We start from 1 to allow Option<GPRKind> optimization
12
13    /// Represents AL, CL, DL, BL, SPL, BPL, SIL, DIL, R8B, R9B, R10B, R11B, R12B, R13B, R14B and R15B registers.
14    Bit8 = 2,
15
16    /// Represents AX, CX, DX, BX, SP, BP, SI, DI, R8W, R9W, R10W, R11W, R12W, R13W, R14W and R15W registers.
17    Bit16 = 3,
18
19    /// Represents EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI, R8D, R9D, R10D, R11D, R12D, R13D, R14D and R15D registers.
20    Bit32 = 4,
21
22    /// Represents RAX, RCX, RDX, RBX, RSP, RBP, RSI, RDI, R8, R9, R10, R11, R12, R13, R14 and R15 registers.
23    Bit64 = 5,
24}
25
26impl GPRKind {
27    /// Compares two [`GPRKind`] values for equality.
28    #[inline(always)]
29    #[must_use]
30    pub const fn equals(self, other: Self) -> bool {
31        self.as_u8() == other.as_u8()
32    }
33
34    /// Represents the size of the [`GPRKind`].
35    pub const fn size(self) -> Size {
36        match self {
37            Self::Bit8High | Self::Bit8 => Size::Bit8,
38            Self::Bit16 => Size::Bit16,
39            Self::Bit32 => Size::Bit32,
40            Self::Bit64 => Size::Bit64,
41        }
42    }
43
44    #[inline(always)]
45    #[must_use]
46    pub(crate) const fn as_u8(self) -> u8 {
47        unsafe {
48            let result = transmute::<Self, u8>(self);
49            core::hint::assert_unchecked(result > 0);
50            core::hint::assert_unchecked(result <= 5);
51            result
52        }
53    }
54
55    #[inline]
56    #[allow(dead_code)]
57    pub(crate) const fn from_u8(value: u8) -> Self {
58        debug_assert!(value > 0 && value <= 5, "Invalid GPRKind value");
59        unsafe { core::mem::transmute(value) }
60    }
61}