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}