asmkit/core/
arch_traits.rs1use crate::x86::arch_traits::{X64_ARCH_TRAITS, X86_ARCH_TRAITS};
2
3use super::operand::{OperandSignature, RegGroup, RegType};
4use super::types::TypeId;
5
6pub struct ArchTraits {
7    pub sp_reg_id: u8,
8    pub fp_reg_id: u8,
9    pub link_reg_id: u8,
10    pub ip_reg_id: u8,
11    pub hw_stack_alignment: u8,
12    pub min_stack_offset: u32,
13    pub max_stack_offset: u32,
14    pub regs_signature: [OperandSignature; RegType::MaxValue as usize + 1],
15    pub reg_type_to_type_id: [TypeId; RegType::MaxValue as usize + 1],
16    pub type_id_to_reg_type: [RegType; 32],
17}
18
19pub const ARCH_X86: usize = if cfg!(any(target_arch = "x86", target_arch = "x86_64")) {
20    size_of::<usize>() * 8
21} else {
22    0
23};
24
25pub const ARCH_ARM: usize = if cfg!(any(target_arch = "aarch64", target_arch = "arm")) {
26    size_of::<usize>() * 8
27} else {
28    0
29};
30pub const ARCH_RISCV: usize = if cfg!(any(target_arch = "riscv64", target_arch = "riscv32")) {
31    size_of::<usize>() * 8
32} else {
33    0
34};
35
36#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
38pub enum Arch {
39    Unknown = 0,
41
42    X86 = 1,
44    X64 = 2,
46
47    RISCV32 = 3,
49    RISCV64 = 4,
51
52    ARM = 5,
54    AArch64 = 6,
56    Thumb = 7,
58
59    MIPS32LE = 9,
62    MIPS64LE = 10,
64
65    ARMBE = 11,
67    AArch64BE = 12,
69    ThumbBE = 13,
71
72    MIPS32BE = 15,
75    MIPS64BE = 16,
77
78    Max,
79}
80
81impl Arch {
82    pub const HOST: Arch = {
83        if ARCH_X86 == 32 {
84            Arch::X86
85        } else if ARCH_X86 == 64 {
86            Arch::X64
87        } else if ARCH_RISCV == 32 {
88            Arch::RISCV32
89        } else if ARCH_RISCV == 64 {
90            Arch::RISCV64
91        } else if ARCH_ARM == 32 && cfg!(target_endian = "little") {
92            Arch::ARM
93        } else if ARCH_ARM == 32 && cfg!(target_endian = "big") {
94            Arch::ARMBE
95        } else if ARCH_ARM == 64 && cfg!(target_endian = "little") {
96            Arch::AArch64
97        } else if ARCH_ARM == 64 && cfg!(target_endian = "big") {
98            Arch::AArch64BE
99        } else {
100            Arch::Unknown
101        }
102    };
103}
104
105impl Default for Arch {
106    fn default() -> Self {
107        Self::HOST
108    }
109}
110
111const NO_ARCH_TRAITS: ArchTraits = ArchTraits {
112    fp_reg_id: 0xff,
113    sp_reg_id: 0xff,
114    link_reg_id: 0xff,
115    ip_reg_id: 0xff,
116    hw_stack_alignment: 0,
117    min_stack_offset: 0,
118    max_stack_offset: 0,
119    regs_signature: [OperandSignature::new(0); 32],
120    reg_type_to_type_id: [TypeId::Void; 32],
121    type_id_to_reg_type: [RegType::None; 32],
122};
123
124#[rustfmt::skip]
125const ARCH_TRAITS: [ArchTraits; Arch::Max as usize] =[
126    NO_ARCH_TRAITS,
127    X86_ARCH_TRAITS,
128    X64_ARCH_TRAITS,
129    NO_ARCH_TRAITS,
130    NO_ARCH_TRAITS,
131    NO_ARCH_TRAITS,
132    NO_ARCH_TRAITS,
133    NO_ARCH_TRAITS,
134    NO_ARCH_TRAITS,
135    NO_ARCH_TRAITS,
136    NO_ARCH_TRAITS,
137    NO_ARCH_TRAITS,
138    NO_ARCH_TRAITS,
139    NO_ARCH_TRAITS,
140    NO_ARCH_TRAITS,
141    NO_ARCH_TRAITS,
142    NO_ARCH_TRAITS,
143];
144
145impl ArchTraits {
146    pub const fn sp_reg_id(&self) -> u32 {
148        self.sp_reg_id as _
149    }
150
151    pub const fn fp_reg_id(&self) -> u32 {
153        self.fp_reg_id as _
154    }
155
156    pub const fn link_reg_id(&self) -> u32 {
158        self.link_reg_id as _
159    }
160
161    pub const fn ip_reg_id(&self) -> u32 {
163        self.ip_reg_id as _
164    }
165    pub const fn hw_stack_alignment(&self) -> u32 {
171        self.hw_stack_alignment as _
172    }
173
174    pub const fn has_link_reg(&self) -> bool {
177        self.link_reg_id != 0xff
178    }
179
180    pub const fn min_stack_offset(&self) -> u32 {
182        self.min_stack_offset
183    }
184
185    pub const fn max_stack_offset(&self) -> u32 {
187        self.max_stack_offset
188    }
189
190    pub const fn has_reg_type(&self, typ: RegType) -> bool {
191        (typ as u32) <= RegType::MaxValue as u32 && self.regs_signature[typ as usize].is_valid()
192    }
193
194    pub const fn reg_type_to_signature(&self, typ: RegType) -> OperandSignature {
195        self.regs_signature[typ as usize]
196    }
197
198    pub fn reg_type_to_group(&self, typ: RegType) -> RegGroup {
199        self.reg_type_to_signature(typ).reg_group()
200    }
201
202    pub fn reg_type_to_size(&self, typ: RegType) -> u32 {
203        self.reg_type_to_signature(typ).size()
204    }
205
206    pub const fn reg_type_to_type_id(&self, typ: RegType) -> TypeId {
207        self.reg_type_to_type_id[typ as usize]
208    }
209
210    pub const fn by_arch(arch: Arch) -> &'static Self {
211        &ARCH_TRAITS[arch as usize]
212    }
213}