1use rug::float::Round;
4
5#[derive(Default, Clone, Copy)]
7pub struct CPURegister(pub u64);
8impl CPURegister {
9 pub const fn get_x64(self) -> u64 {
11 self.0
12 }
13 pub fn set_x64(&mut self, val: u64) {
15 self.0 = val;
16 }
17
18 pub const fn get_x32(self) -> u32 {
20 self.0 as u32
21 }
22 pub fn set_x32(&mut self, val: u32) {
24 self.0 = val as u64;
25 }
26
27 pub const fn get_x16(self) -> u16 {
29 self.0 as u16
30 }
31 pub fn set_x16(&mut self, val: u16) {
33 self.0 = (self.0 & 0xffffffffffff0000) | (val as u64);
34 }
35
36 pub const fn get_x8(self) -> u8 {
38 self.0 as u8
39 }
40 pub fn set_x8(&mut self, val: u8) {
42 self.0 = (self.0 & 0xffffffffffffff00) | (val as u64);
43 }
44
45 pub const fn get_x8h(self) -> u8 {
47 (self.0 >> 8) as u8
48 }
49 pub fn set_x8h(&mut self, val: u8) {
51 self.0 = (self.0 & 0xffffffffffff00ff) | ((val as u64) << 8);
52 }
53
54 pub(super) fn get_raw(self, sizecode: u8) -> u64 {
57 match sizecode {
58 0 => self.get_x8() as u64,
59 1 => self.get_x16() as u64,
60 2 => self.get_x32() as u64,
61 3 => self.get_x64(),
62 _ => panic!(),
63 }
64 }
65 pub(super) fn set_raw(&mut self, sizecode: u8, value: u64) {
68 match sizecode {
69 0 => self.set_x8(value as u8),
70 1 => self.set_x16(value as u16),
71 2 => self.set_x32(value as u32),
72 3 => self.set_x64(value),
73 _ => panic!(),
74 }
75 }
76}
77
78#[test]
79fn test_cpu_register() {
80 let mut r = CPURegister::default();
81 assert_eq!(r.get_x64(), 0);
82
83 r.set_x64(0x2049381758392734);
84 assert_eq!(r.get_x64(), 0x2049381758392734);
85 assert_eq!(r.get_x32(), 0x58392734);
86 assert_eq!(r.get_x16(), 0x2734);
87 assert_eq!(r.get_x8(), 0x34);
88 assert_eq!(r.get_x8h(), 0x27);
89
90 r.set_x16(0x8692);
91 assert_eq!(r.get_x64(), 0x2049381758398692);
92 assert_eq!(r.get_x32(), 0x58398692);
93 assert_eq!(r.get_x16(), 0x8692);
94 assert_eq!(r.get_x8(), 0x92);
95 assert_eq!(r.get_x8h(), 0x86);
96
97 r.set_x8(0xf5);
98 assert_eq!(r.get_x64(), 0x20493817583986f5);
99 assert_eq!(r.get_x32(), 0x583986f5);
100 assert_eq!(r.get_x16(), 0x86f5);
101 assert_eq!(r.get_x8(), 0xf5);
102 assert_eq!(r.get_x8h(), 0x86);
103
104 r.set_x8h(0x12);
105 assert_eq!(r.get_x64(), 0x20493817583912f5);
106 assert_eq!(r.get_x32(), 0x583912f5);
107 assert_eq!(r.get_x16(), 0x12f5);
108 assert_eq!(r.get_x8(), 0xf5);
109 assert_eq!(r.get_x8h(), 0x12);
110
111 r.set_x32(0x59288643);
112 assert_eq!(r.get_x64(), 0x59288643);
113 assert_eq!(r.get_x32(), 0x59288643);
114 assert_eq!(r.get_x16(), 0x8643);
115 assert_eq!(r.get_x8(), 0x43);
116 assert_eq!(r.get_x8h(), 0x86);
117}
118
119#[derive(Clone, Copy)]
125#[repr(align(64))]
126pub struct ZMMRegister(pub [u8; 64]);
127impl Default for ZMMRegister {
128 fn default() -> Self {
129 Self([0; 64]) }
131}
132macro_rules! zmm_impl {
133 ($get:ident : $set:ident => $t:ident) => {
134 pub fn $get(&self, index: usize) -> $t {
135 $t::from_le(bytemuck::cast_slice(&self.0)[index])
136 }
137 pub fn $set(&mut self, index: usize, value: $t) {
138 bytemuck::cast_slice_mut(&mut self.0)[index] = value.to_le()
139 }
140 };
141 (signed $get:ident : $set:ident => $i:ident : $u:ident : $get_raw:ident : $set_raw:ident) => {
142 pub fn $get(&self, index: usize) -> $i {
143 self.$get_raw(index) as $i
144 }
145 pub fn $set(&mut self, index: usize, value: $i) {
146 self.$set_raw(index, value as $u)
147 }
148 };
149 (float $get:ident : $set:ident => $t:ident : $get_raw:ident : $set_raw:ident) => {
150 pub fn $get(&self, index: usize) -> $t {
151 $t::from_bits(self.$get_raw(index))
152 }
153 pub fn $set(&mut self, index: usize, value: $t) {
154 self.$set_raw(index, value.to_bits())
155 }
156 };
157}
158impl ZMMRegister {
159 pub fn get_u8(&self, index: usize) -> u8 {
160 self.0[index]
161 }
162 pub fn set_u8(&mut self, index: usize, value: u8) {
163 self.0[index] = value
164 }
165
166 zmm_impl! { get_u16 : set_u16 => u16 }
167 zmm_impl! { get_u32 : set_u32 => u32 }
168 zmm_impl! { get_u64 : set_u64 => u64 }
169
170 zmm_impl! { signed get_i64 : set_i64 => i64 : u64 : get_u64 : set_u64 }
171 zmm_impl! { signed get_i32 : set_i32 => i32 : u32 : get_u32 : set_u32 }
172 zmm_impl! { signed get_i16 : set_i16 => i16 : u16 : get_u16 : set_u16 }
173 zmm_impl! { signed get_i8 : set_i8 => i8 : u8 : get_u8 : set_u8 }
174
175 zmm_impl! { float get_f64 : set_f64 => f64 : get_u64 : set_u64 }
176 zmm_impl! { float get_f32 : set_f32 => f32 : get_u32 : set_u32 }
177
178 pub(crate) fn get(&self, index: usize, size: u8) -> u64 {
179 match size {
180 0 => self.get_u8(index) as u64,
181 1 => self.get_u16(index) as u64,
182 2 => self.get_u32(index) as u64,
183 3 => self.get_u64(index),
184 _ => panic!(),
185 }
186 }
187 pub(crate) fn set(&mut self, index: usize, size: u8, value: u64) {
188 match size {
189 0 => self.set_u8(index, value as u8),
190 1 => self.set_u16(index, value as u16),
191 2 => self.set_u32(index, value as u32),
192 3 => self.set_u64(index, value),
193 _ => panic!(),
194 }
195 }
196}
197
198#[test]
199fn test_zmm_register() {
200 assert_eq!(std::mem::align_of::<ZMMRegister>(), 64);
201 assert_eq!(std::mem::size_of::<ZMMRegister>(), 64);
202
203 let mut r = ZMMRegister::default();
204
205 for i in 0..64 {
206 r.set_u8(i, i as u8);
207 }
208 for i in 0..32 {
209 assert_eq!(r.get_u16(i), u16::from_le_bytes([i as u8 * 2, i as u8 * 2 + 1]));
210 }
211}
212
213macro_rules! impl_flag {
214 ($mask_name:ident, $set:ident, $clear:ident, $flip:ident, $get:ident, $assign:ident => $from:ty [ $mask:literal ]) => {
215 pub const $mask_name: $from = $mask;
216 pub fn $set(&mut self) { self.0 |= $mask }
217 pub fn $clear(&mut self) { self.0 &= !$mask }
218 pub fn $flip(&mut self) { self.0 ^= $mask }
219 pub const fn $get(self) -> bool { (self.0 & $mask) != 0 }
220 pub fn $assign(&mut self, value: bool) {
221 if value { self.$set() } else { self.$clear() }
222 }
223 }
224}
225macro_rules! impl_field {
226 ($mask_name:ident, $get:ident, $assign:ident => $from:ty [ $shift:literal => $mask:literal ] $to:ty) => {
227 pub const $mask_name: $from = $mask << $shift;
228 pub const fn $get(self) -> $to {
229 ((self.0 >> $shift) & $mask) as $to
230 }
231 pub fn $assign(&mut self, val: $to) {
232 assert_eq!(val, val & $mask);
233 self.0 = (self.0 & !($mask << $shift)) | ((val as $from) << $shift);
234 }
235 }
236}
237
238#[derive(Default, Clone, Copy)]
240pub struct Flags(pub u64);
241impl Flags {
242 impl_flag! { MASK_CF, set_cf, clear_cf, flip_cf, get_cf, assign_cf => u64 [0x0000000000000001] }
243 impl_flag! { MASK_PF, set_pf, clear_pf, flip_pf, get_pf, assign_pf => u64 [0x0000000000000004] }
244 impl_flag! { MASK_AF, set_af, clear_af, flip_af, get_af, assign_af => u64 [0x0000000000000010] }
245 impl_flag! { MASK_ZF, set_zf, clear_zf, flip_zf, get_zf, assign_zf => u64 [0x0000000000000040] }
246 impl_flag! { MASK_SF, set_sf, clear_sf, flip_sf, get_sf, assign_sf => u64 [0x0000000000000080] }
247 impl_flag! { MASK_TF, set_tf, clear_tf, flip_tf, get_tf, assign_tf => u64 [0x0000000000000100] }
248 impl_flag! { MASK_IF, set_if, clear_if, flip_if, get_if, assign_if => u64 [0x0000000000000200] }
249 impl_flag! { MASK_DF, set_df, clear_df, flip_df, get_df, assign_df => u64 [0x0000000000000400] }
250 impl_flag! { MASK_OF, set_of, clear_of, flip_of, get_of, assign_of => u64 [0x0000000000000800] }
251 impl_flag! { MASK_NT, set_nt, clear_nt, flip_nt, get_nt, assign_nt => u64 [0x0000000000004000] }
252 impl_flag! { MASK_RF, set_rf, clear_rf, flip_rf, get_rf, assign_rf => u64 [0x0000000000010000] }
253 impl_flag! { MASK_VM, set_vm, clear_vm, flip_vm, get_vm, assign_vm => u64 [0x0000000000020000] }
254 impl_flag! { MASK_AC, set_ac, clear_ac, flip_ac, get_ac, assign_ac => u64 [0x0000000000040000] }
255 impl_flag! { MASK_VIF, set_vif, clear_vif, flip_vif, get_vif, assign_vif => u64 [0x0000000000080000] }
256 impl_flag! { MASK_VIP, set_vip, clear_vip, flip_vip, get_vip, assign_vip => u64 [0x0000000000100000] }
257 impl_flag! { MASK_ID, set_id, clear_id, flip_id, get_id, assign_id => u64 [0x0000000000200000] }
258
259 impl_field! { MASK_IOPL, get_iopl, assign_iopl => u64 [ 12 => 0b11 ] u8 }
260
261 impl_flag! { MASK_OTS, set_ots, clear_ots, flip_ots, get_ots, assign_ots => u64 [0x0000000100000000] }
264
265 pub const fn condition_b(self) -> bool { self.get_cf() }
269 pub const fn condition_be(self) -> bool { self.get_cf() || self.get_zf() }
271 pub const fn condition_a(self) -> bool { !self.condition_be() }
273 pub const fn condition_ae(self) -> bool { !self.condition_b() }
275
276 pub const fn condition_l(self) -> bool { self.get_sf() != self.get_of() }
280 pub const fn condition_le(self) -> bool { self.get_zf() || (self.get_sf() != self.get_of()) }
282 pub const fn condition_g(self) -> bool { !self.condition_le() }
284 pub const fn condition_ge(self) -> bool { !self.condition_l() }
286}
287
288#[derive(Default, Clone, Copy)]
290pub struct MXCSR(pub u16);
291impl MXCSR {
292
293}
294
295#[derive(Clone, Copy)]
297pub struct Control(pub u16);
298impl Control {
299 impl_flag! { MASK_IM, set_im, clear_im, flip_im, get_im, assign_im => u16 [0x0001] }
300 impl_flag! { MASK_DM, set_dm, clear_dm, flip_dm, get_dm, assign_dm => u16 [0x0002] }
301 impl_flag! { MASK_ZM, set_zm, clear_zm, flip_zm, get_zm, assign_zm => u16 [0x0004] }
302 impl_flag! { MASK_OM, set_om, clear_om, flip_om, get_om, assign_om => u16 [0x0008] }
303 impl_flag! { MASK_UM, set_um, clear_um, flip_um, get_um, assign_um => u16 [0x0010] }
304 impl_flag! { MASK_PM, set_pm, clear_pm, flip_pm, get_pm, assign_pm => u16 [0x0020] }
305 impl_flag! { MASK_IEM, set_iem, clear_iem, flip_iem, get_iem, assign_iem => u16 [0x0080] }
306 impl_flag! { MASK_IC, set_ic, clear_ic, flip_ic, get_ic, assign_ic => u16 [0x1000] }
307
308 impl_field! { MASK_PC, get_pc, assign_pc => u16 [ 8 => 0b11 ] u8 }
309 impl_field! { MASK_RC, get_rc, assign_rc => u16 [ 10 => 0b11 ] u8 }
310
311 pub fn get_rc_enum(self) -> Round {
313 match self.get_rc() {
314 0 => Round::Nearest,
315 1 => Round::Down,
316 2 => Round::Up,
317 3 => Round::Zero,
318 _ => unreachable!(),
319 }
320 }
321 pub fn get_pc_val(self) -> Result<u32, ()> {
324 match self.get_pc() {
325 0 => Ok(24),
326 1 => Err(()),
327 2 => Ok(53),
328 3 => Ok(64),
329 _ => unreachable!(),
330 }
331 }
332}
333
334#[derive(Clone, Copy)]
336pub struct Status(pub u16);
337impl Status {
338 impl_flag! { MASK_I, set_i, clear_i, flip_i, get_i, assign_i => u16 [0x0001] }
339 impl_flag! { MASK_D, set_d, clear_d, flip_d, get_d, assign_d => u16 [0x0002] }
340 impl_flag! { MASK_Z, set_z, clear_z, flip_z, get_z, assign_z => u16 [0x0004] }
341 impl_flag! { MASK_O, set_o, clear_o, flip_o, get_o, assign_o => u16 [0x0008] }
342 impl_flag! { MASK_U, set_u, clear_u, flip_u, get_u, assign_u => u16 [0x0010] }
343 impl_flag! { MASK_P, set_p, clear_p, flip_p, get_p, assign_p => u16 [0x0020] }
344 impl_flag! { MASK_SF, set_sf, clear_sf, flip_sf, get_sf, assign_sf => u16 [0x0040] }
345 impl_flag! { MASK_IR, set_ir, clear_ir, flip_ir, get_ir, assign_ir => u16 [0x0080] }
346 impl_flag! { MASK_C0, set_c0, clear_c0, flip_c0, get_c0, assign_c0 => u16 [0x0100] }
347 impl_flag! { MASK_C1, set_c1, clear_c1, flip_c1, get_c1, assign_c1 => u16 [0x0200] }
348 impl_flag! { MASK_C2, set_c2, clear_c2, flip_c2, get_c2, assign_c2 => u16 [0x0400] }
349 impl_flag! { MASK_C3, set_c3, clear_c3, flip_c3, get_c3, assign_c3 => u16 [0x4000] }
350 impl_flag! { MASK_B, set_b, clear_b, flip_b, get_b, assign_b => u16 [0x8000] }
351
352 impl_field! { MASK_TOP, get_top, assign_top => u16 [ 11 => 0b111 ] u8 }
353}
354
355#[derive(Clone, Copy)]
357pub struct Tag(pub u16);
358impl Tag {
359 pub fn get_physical(self, index: u8) -> u8 {
360 ((self.0 >> (2 * index)) & 3) as u8
361 }
362 pub fn set_physical(&mut self, index: u8, value: TagValue) {
363 assert!(index < 8);
364 let s = 2 * index;
365 self.0 = (self.0 & !(3 << s)) | ((value as u16) << s);
366 }
367}
368
369#[repr(u8)]
371pub enum TagValue {
372 NonZero = 0,
373 Zero = 1,
374 Special = 2,
375 Empty = 3,
376}