tests, but at what cost
This commit is contained in:
+102
-18
@@ -5,33 +5,34 @@ pub struct Reg {
|
||||
width: Width,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
|
||||
#[repr(u8)]
|
||||
pub enum Width {
|
||||
B64,
|
||||
B32,
|
||||
B16,
|
||||
B8,
|
||||
B8 = 0,
|
||||
B16 = 1,
|
||||
B32 = 2,
|
||||
B64 = 3,
|
||||
}
|
||||
|
||||
def_regs! { Reg;
|
||||
def_regs! {
|
||||
0b0000 : rax eax ax al,
|
||||
0b0001 : rcx ecx cx cl,
|
||||
0b0001 : rcx ecx cx cl !_,
|
||||
0b0010 : rdx edx dx dl,
|
||||
0b0011 : rbx ebx bx bl,
|
||||
|
||||
0b0100 : rsp esp sp spl norex=ah,
|
||||
0b0100 : rsp esp sp spl norex=ah !_,
|
||||
0b0101 : rbp ebp bp bpl norex=ch,
|
||||
0b0110 : rsi esi si sil norex=dh,
|
||||
0b0110 : rsi esi si sil norex=dh !_,
|
||||
0b0111 : rdi edi di dil norex=bh,
|
||||
|
||||
0b1000 : r8 r8d r8w r8b,
|
||||
0b1001 : r9 r9d r9w r9b,
|
||||
0b1001 : r9 r9d r9w r9b !_,
|
||||
0b1010 : r10 r10d r10w r10b,
|
||||
0b1011 : r11 r11d r11w r11b,
|
||||
0b1100 : r12 r12d r12w r12b,
|
||||
0b1101 : r13 r13d r13w r13b,
|
||||
0b1110 : r14 r14d r14w r14b,
|
||||
0b1111 : r15 r15d r15w r15b,
|
||||
0b1111 : r15 r15d r15w r15b !_,
|
||||
}
|
||||
|
||||
impl Reg {
|
||||
@@ -49,16 +50,29 @@ impl Reg {
|
||||
self.high
|
||||
}
|
||||
|
||||
pub fn val(&self) -> u8 {
|
||||
self.val
|
||||
}
|
||||
|
||||
pub fn width(&self) -> Width {
|
||||
self.width
|
||||
}
|
||||
|
||||
/// if self has 64 bit width, changes width to 32 bit
|
||||
pub fn lower64(&mut self) {
|
||||
self.width.lower64()
|
||||
}
|
||||
|
||||
pub fn requires_rex(&self) -> bool {
|
||||
self.gt8()
|
||||
|| self.width == Width::B64
|
||||
|| (self.gt4() && self.width == Width::B8 && !self.high)
|
||||
}
|
||||
|
||||
pub fn requires_mem_rex(&self) -> bool {
|
||||
self.gt8() || (self.gt4() && self.width == Width::B8 && !self.high)
|
||||
}
|
||||
|
||||
pub fn incompatible(&self, other: &Reg) -> bool {
|
||||
(self.requires_rex() && other.high) || (self.high && other.requires_rex())
|
||||
}
|
||||
@@ -77,6 +91,13 @@ impl Width {
|
||||
Self::B8 { .. } => u8::MAX as u64,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lower64(&mut self) {
|
||||
if matches!(self, Width::B64) {
|
||||
*self = Width::B32;
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn bytes(&self) -> usize {
|
||||
match self {
|
||||
Self::B64 => 8,
|
||||
@@ -85,29 +106,75 @@ impl Width {
|
||||
Self::B8 { .. } => 1,
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn fit(val: u64) -> Self {
|
||||
const B8: u64 = 1 << 8;
|
||||
const B16: u64 = 1 << 16;
|
||||
const B32: u64 = 1 << 32;
|
||||
match val {
|
||||
..B8 => Self::B8,
|
||||
B8..B16 => Self::B16,
|
||||
B16..B32 => Self::B32,
|
||||
B32.. => Self::B64,
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn fiti(val: u64) -> Self {
|
||||
match val {
|
||||
..0x80 => Self::B8,
|
||||
0x80..0x8000 => Self::B16,
|
||||
0x8000..0x8000_0000 => Self::B32,
|
||||
0x8000_0000.. => Self::B64,
|
||||
}
|
||||
}
|
||||
|
||||
/// greater than 8 bits
|
||||
pub const fn gt8(&self) -> bool {
|
||||
!matches!(self, Self::B8)
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! filter {
|
||||
($($filtered:ident)*; ! $_:tt $($item:ident)*; $($rest:tt)*) => {
|
||||
filter!($($filtered)* $($item)*; $($rest)*)
|
||||
};
|
||||
($($filtered:ident)*; $($item:ident)*; $($rest:tt)*) => {
|
||||
filter!($($filtered)*; $($rest)*)
|
||||
};
|
||||
($($filtered:ident)*;) => {
|
||||
[$($filtered, )*]
|
||||
};
|
||||
}
|
||||
use filter;
|
||||
|
||||
macro_rules! def_regs {
|
||||
($Struct: ident; $($val:literal : $B64:ident $B32:ident $B16:ident $B8:ident $(norex=$B8H:ident)?,)*) => {
|
||||
($($val:literal : $B64:ident $B32:ident $B16:ident $B8:ident $(norex=$B8H:ident)? $(!$imp:tt)?,)*) => {
|
||||
$(
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const $B64: $Struct = $Struct::new($val, Width::B64, false);
|
||||
pub const $B64: Reg = Reg::new($val, Width::B64, false);
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const $B32: $Struct = $Struct::new($val, Width::B32, false);
|
||||
pub const $B32: Reg = Reg::new($val, Width::B32, false);
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const $B16: $Struct = $Struct::new($val, Width::B16, false);
|
||||
pub const $B16: Reg = Reg::new($val, Width::B16, false);
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const $B8 : $Struct = $Struct::new($val, Width::B8 , false);
|
||||
pub const $B8 : Reg = Reg::new($val, Width::B8 , false);
|
||||
$(
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const $B8H: $Struct = $Struct::new($val, Width::B8, true);
|
||||
pub const $B8H: Reg = Reg::new($val, Width::B8, true);
|
||||
)?
|
||||
)*
|
||||
impl $Struct {
|
||||
|
||||
impl Reg {
|
||||
#[cfg(test)]
|
||||
pub const ALL: &[Reg] = &[
|
||||
$( $B64, $B32, $B16, $B8, $($B8H,)? )*
|
||||
];
|
||||
|
||||
#[cfg(test)]
|
||||
pub const IMPORTANT: &[Reg] = &
|
||||
filter!(; $($(!$imp)? $B64 $B32 $B16 $B8 $($B8H)?; )* )
|
||||
;
|
||||
|
||||
pub fn parse(s: &str) -> Option<Self> {
|
||||
Some(match s.to_lowercase().as_str() {
|
||||
$(
|
||||
@@ -123,6 +190,23 @@ macro_rules! def_regs {
|
||||
})
|
||||
}
|
||||
}
|
||||
impl std::fmt::Display for Reg {
|
||||
#[allow(non_upper_case_globals)]
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", match *self {
|
||||
$(
|
||||
$B64 => stringify!($B64),
|
||||
$B32 => stringify!($B32),
|
||||
$B16 => stringify!($B16),
|
||||
$B8 => stringify!($B8),
|
||||
$(
|
||||
$B8H => stringify!($B8H),
|
||||
)?
|
||||
)*
|
||||
_ => "UNKNOWN",
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user