asmkit/core/
arch_traits.rs1#[cfg(feature = "aarch64")]
2use crate::aarch64::arch_traits::AARCH64_ARCH_TRAITS;
3#[cfg(feature = "riscv")]
4use crate::riscv::arch_traits::{RISCV32_ARCH_TRAITS, RISCV64_ARCH_TRAITS};
5#[cfg(feature = "x86")]
6use crate::x86::arch_traits::{X64_ARCH_TRAITS, X86_ARCH_TRAITS};
7
8#[cfg(not(feature = "aarch64"))]
9const AARCH64_ARCH_TRAITS: ArchTraits = NO_ARCH_TRAITS;
10#[cfg(not(feature = "riscv"))]
11const RISCV32_ARCH_TRAITS: ArchTraits = NO_ARCH_TRAITS;
12#[cfg(not(feature = "riscv"))]
13const RISCV64_ARCH_TRAITS: ArchTraits = NO_ARCH_TRAITS;
14#[cfg(not(feature = "x86"))]
15const X86_ARCH_TRAITS: ArchTraits = NO_ARCH_TRAITS;
16#[cfg(not(feature = "x86"))]
17const X64_ARCH_TRAITS: ArchTraits = NO_ARCH_TRAITS;
18
19use super::operand::{OperandSignature, RegGroup, RegType};
20use super::types::TypeId;
21
22pub struct ArchTraits {
23 pub sp_reg_id: u8,
24 pub fp_reg_id: u8,
25 pub link_reg_id: u8,
26 pub ip_reg_id: u8,
27 pub hw_stack_alignment: u8,
28 pub min_stack_offset: u32,
29 pub max_stack_offset: u32,
30 pub regs_signature: [OperandSignature; RegType::MaxValue as usize + 1],
31 pub reg_type_to_type_id: [TypeId; RegType::MaxValue as usize + 1],
32 pub type_id_to_reg_type: [RegType; 32],
33}
34
35pub const ARCH_X86: usize = if cfg!(any(target_arch = "x86", target_arch = "x86_64")) {
36 usize::BITS as usize
37} else {
38 0
39};
40
41pub const ARCH_RISCV: usize = if cfg!(any(target_arch = "riscv64", target_arch = "riscv32")) {
42 usize::BITS as usize
43} else {
44 0
45};
46
47#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
49pub enum Arch {
50 Unknown = 0,
52
53 X86 = 1,
55 X64 = 2,
57
58 RISCV32 = 3,
60 RISCV64 = 4,
62
63 AArch64 = 6,
66
67 Max,
68}
69
70impl Arch {
71 pub const HOST: Arch = {
72 if ARCH_X86 == 32 {
73 Arch::X86
74 } else if ARCH_X86 == 64 {
75 Arch::X64
76 } else if ARCH_RISCV == 32 {
77 Arch::RISCV32
78 } else if ARCH_RISCV == 64 {
79 Arch::RISCV64
80 } else if cfg!(all(target_arch = "aarch64", target_endian = "little")) {
81 Arch::AArch64
82 } else {
83 Arch::Unknown
84 }
85 };
86}
87
88impl Arch {
89 pub const fn is_32bit(self) -> bool {
94 (self as u32) < Arch::Max as u32 && (self as u32) & 1 != 0
95 }
96
97 pub const fn is_64bit(self) -> bool {
99 (self as u32) < Arch::Max as u32 && self as u32 != 0 && (self as u32) & 1 == 0
100 }
101}
102
103impl Default for Arch {
104 fn default() -> Self {
105 Self::HOST
106 }
107}
108
109const NO_ARCH_TRAITS: ArchTraits = ArchTraits {
110 fp_reg_id: 0xff,
111 sp_reg_id: 0xff,
112 link_reg_id: 0xff,
113 ip_reg_id: 0xff,
114 hw_stack_alignment: 0,
115 min_stack_offset: 0,
116 max_stack_offset: 0,
117 regs_signature: [OperandSignature::new(0); 32],
118 reg_type_to_type_id: [TypeId::Void; 32],
119 type_id_to_reg_type: [RegType::None; 32],
120};
121
122#[rustfmt::skip]
123const ARCH_TRAITS: [ArchTraits; Arch::Max as usize] =[
124 NO_ARCH_TRAITS,
125 X86_ARCH_TRAITS,
126 X64_ARCH_TRAITS,
127 RISCV32_ARCH_TRAITS,
128 RISCV64_ARCH_TRAITS,
129 NO_ARCH_TRAITS,
130 AARCH64_ARCH_TRAITS,
131];
132
133impl ArchTraits {
134 pub const fn sp_reg_id(&self) -> u32 {
136 self.sp_reg_id as _
137 }
138
139 pub const fn fp_reg_id(&self) -> u32 {
141 self.fp_reg_id as _
142 }
143
144 pub const fn link_reg_id(&self) -> u32 {
146 self.link_reg_id as _
147 }
148
149 pub const fn ip_reg_id(&self) -> u32 {
151 self.ip_reg_id as _
152 }
153 pub const fn hw_stack_alignment(&self) -> u32 {
159 self.hw_stack_alignment as _
160 }
161
162 pub const fn has_link_reg(&self) -> bool {
165 self.link_reg_id != 0xff
166 }
167
168 pub const fn min_stack_offset(&self) -> u32 {
170 self.min_stack_offset
171 }
172
173 pub const fn max_stack_offset(&self) -> u32 {
175 self.max_stack_offset
176 }
177
178 pub const fn has_reg_type(&self, typ: RegType) -> bool {
179 (typ as u32) <= RegType::MaxValue as u32 && self.regs_signature[typ as usize].is_valid()
180 }
181
182 pub const fn reg_type_to_signature(&self, typ: RegType) -> OperandSignature {
183 self.regs_signature[typ as usize]
184 }
185
186 pub fn reg_type_to_group(&self, typ: RegType) -> RegGroup {
187 self.reg_type_to_signature(typ).reg_group()
188 }
189
190 pub fn reg_type_to_size(&self, typ: RegType) -> u32 {
191 self.reg_type_to_signature(typ).size()
192 }
193
194 pub const fn reg_type_to_type_id(&self, typ: RegType) -> TypeId {
195 self.reg_type_to_type_id[typ as usize]
196 }
197
198 pub const fn by_arch(arch: Arch) -> &'static Self {
199 &ARCH_TRAITS[arch as usize]
200 }
201}