Skip to main content

asmkit/x86/
operands.rs

1/* Copyright (c) 2008-2024 The AsmJit Authors
2
3   This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
4
5   Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
6
7   The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
8   Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
9   This notice may not be removed or altered from any source distribution.
10
11*/
12//! X86 operands definition.
13use crate::core::{
14    arch_traits::{Arch, ArchTraits},
15    operand::{define_abstract_reg, define_final_reg, define_operand_cast, define_reg_traits, *},
16    types::TypeId,
17};
18use core::ops::{Add, Deref, Mul};
19
20macro_rules! impl_deref_for_wrapper {
21    ($wrapper:ty, $target:ty) => {
22        impl core::ops::Deref for $wrapper {
23            type Target = $target;
24
25            fn deref(&self) -> &Self::Target {
26                &self.0
27            }
28        }
29
30        impl core::ops::DerefMut for $wrapper {
31            fn deref_mut(&mut self) -> &mut Self::Target {
32                &mut self.0
33            }
34        }
35    };
36}
37
38define_reg_traits!(X86Rip, RegGroup::X86Rip, 0, TypeId::Void);
39define_reg_traits!(X86GpbLo, RegGroup::Gp, 1, TypeId::Int8);
40define_reg_traits!(X86GpbHi, RegGroup::Gp, 1, TypeId::Int8);
41define_reg_traits!(X86Gpw, RegGroup::Gp, 2, TypeId::Int16);
42define_reg_traits!(X86Gpd, RegGroup::Gp, 4, TypeId::Int32);
43define_reg_traits!(X86Gpq, RegGroup::Gp, 8, TypeId::Int64);
44define_reg_traits!(X86Xmm, RegGroup::Vec, 16, TypeId::Int32x4);
45define_reg_traits!(X86Ymm, RegGroup::Vec, 32, TypeId::Int32x8);
46define_reg_traits!(X86Zmm, RegGroup::Vec, 64, TypeId::Int32x16);
47define_reg_traits!(X86KReg, RegGroup::X86K, 0, TypeId::Mask64);
48define_reg_traits!(X86Mm, RegGroup::X86MM, 8, TypeId::Mmx64);
49define_reg_traits!(X86SReg, RegGroup::X86SReg, 2, TypeId::Void);
50define_reg_traits!(X86CReg, RegGroup::X86CReg, 0, TypeId::Void);
51define_reg_traits!(X86DReg, RegGroup::X86DReg, 0, TypeId::Void);
52define_reg_traits!(X86St, RegGroup::X86St, 10, TypeId::Float80);
53define_reg_traits!(X86Bnd, RegGroup::X86Bnd, 16, TypeId::Void);
54define_reg_traits!(X86Tmm, RegGroup::X86Tmm, 0, TypeId::Void);
55
56#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
57pub struct Reg(pub BaseReg);
58
59impl_deref_for_wrapper!(Reg, BaseReg);
60
61define_abstract_reg!(Reg, BaseReg);
62
63impl Reg {
64    pub const fn signature_of(typ: RegType) -> OperandSignature {
65        ArchTraits::by_arch(Arch::X86).reg_type_to_signature(typ)
66    }
67
68    pub fn is_gpb(&self) -> bool {
69        self.size() == 1
70    }
71
72    pub fn is_gpb_lo(&self) -> bool {
73        self.has_base_signature(X86GpbLo::SIGNATURE)
74    }
75
76    pub fn is_gpb_hi(&self) -> bool {
77        self.has_base_signature(X86GpbHi::SIGNATURE)
78    }
79
80    pub fn is_gpw(&self) -> bool {
81        self.has_base_signature(X86Gpw::SIGNATURE)
82    }
83
84    pub fn is_gpd(&self) -> bool {
85        self.has_base_signature(X86Gpd::SIGNATURE)
86    }
87
88    pub fn is_gpq(&self) -> bool {
89        self.has_base_signature(X86Gpq::SIGNATURE)
90    }
91
92    pub fn is_gp32(&self) -> bool {
93        self.has_base_signature(X86Gpd::SIGNATURE)
94    }
95
96    pub fn is_gp64(&self) -> bool {
97        self.has_base_signature(X86Gpq::SIGNATURE)
98    }
99
100    pub fn is_xmm(&self) -> bool {
101        self.has_base_signature(X86Xmm::SIGNATURE)
102    }
103
104    pub fn is_ymm(&self) -> bool {
105        self.has_base_signature(X86Ymm::SIGNATURE)
106    }
107
108    pub fn is_zmm(&self) -> bool {
109        self.has_base_signature(X86Zmm::SIGNATURE)
110    }
111
112    pub fn is_vec128(&self) -> bool {
113        self.has_base_signature(X86Xmm::SIGNATURE)
114    }
115
116    pub fn is_vec256(&self) -> bool {
117        self.has_base_signature(X86Ymm::SIGNATURE)
118    }
119
120    pub fn is_vec512(&self) -> bool {
121        self.has_base_signature(X86Zmm::SIGNATURE)
122    }
123
124    pub fn is_mm(&self) -> bool {
125        self.has_base_signature(X86Mm::SIGNATURE)
126    }
127
128    pub fn is_k_reg(&self) -> bool {
129        self.has_base_signature(X86KReg::SIGNATURE)
130    }
131
132    pub fn is_s_reg(&self) -> bool {
133        self.has_base_signature(X86SReg::SIGNATURE)
134    }
135
136    pub fn is_c_reg(&self) -> bool {
137        self.has_base_signature(X86CReg::SIGNATURE)
138    }
139
140    pub fn is_d_reg(&self) -> bool {
141        self.has_base_signature(X86DReg::SIGNATURE)
142    }
143
144    pub fn is_st(&self) -> bool {
145        self.has_base_signature(X86St::SIGNATURE)
146    }
147
148    pub fn is_bnd(&self) -> bool {
149        self.has_base_signature(X86Bnd::SIGNATURE)
150    }
151
152    pub fn is_tmm(&self) -> bool {
153        self.has_base_signature(X86Tmm::SIGNATURE)
154    }
155
156    pub fn is_rip(&self) -> bool {
157        self.has_base_signature(X86Rip::SIGNATURE)
158    }
159
160    pub fn set_reg_t<T: RegTraits>(&mut self, rid: u32) {
161        self.set_signature(T::SIGNATURE.into());
162        self.set_id(rid);
163    }
164
165    pub fn set_type_and_id(&mut self, typ: RegType, id: u32) {
166        self.set_signature(Self::signature_of(typ));
167        self.set_id(id);
168    }
169
170    pub fn group_of(typ: RegType) -> RegGroup {
171        ArchTraits::by_arch(Arch::X86).reg_type_to_group(typ)
172    }
173
174    pub const fn type_id_of(typ: RegType) -> TypeId {
175        ArchTraits::by_arch(Arch::X86).reg_type_to_type_id(typ)
176    }
177
178    pub const fn group_of_t<T: RegTraits>() -> RegGroup {
179        T::GROUP
180    }
181
182    pub const fn type_id_of_t<T: RegTraits>() -> TypeId {
183        T::TYPE_ID
184    }
185
186    pub const fn signature_of_vec_by_type(typ: TypeId) -> OperandSignature {
187        let typ = typ as u32;
188
189        if typ <= TypeId::VEC128_END {
190            OperandSignature::new(X86Xmm::SIGNATURE)
191        } else if typ <= TypeId::VEC256_END {
192            OperandSignature::new(X86Ymm::SIGNATURE)
193        } else {
194            OperandSignature::new(X86Zmm::SIGNATURE)
195        }
196    }
197
198    pub const fn signature_of_vec_by_size(size: u32) -> OperandSignature {
199        if size <= 16 {
200            OperandSignature::new(X86Xmm::SIGNATURE)
201        } else if size <= 32 {
202            OperandSignature::new(X86Ymm::SIGNATURE)
203        } else {
204            OperandSignature::new(X86Zmm::SIGNATURE)
205        }
206    }
207
208    pub fn operand_is_gpb(op: &Operand) -> bool {
209        op.signature.subset(
210            OperandSignature::OP_TYPE_MASK
211                | OperandSignature::REG_GROUP_MASK
212                | OperandSignature::SIZE_MASK,
213        ) == (OperandSignature::from_op_type(OperandType::Reg)
214            | OperandSignature::from_reg_group(RegGroup::Gp)
215            | OperandSignature::from_size(1))
216    }
217
218    pub fn operand_is_gpb_lo(op: &Operand) -> bool {
219        op.as_::<Self>().is_gpb_lo()
220    }
221    pub fn operand_is_gpb_hi(op: &Operand) -> bool {
222        op.as_::<Self>().is_gpb_hi()
223    }
224    pub fn operand_is_gpw(op: &Operand) -> bool {
225        op.as_::<Self>().is_gpw()
226    }
227    pub fn operand_is_gpd(op: &Operand) -> bool {
228        op.as_::<Self>().is_gpd()
229    }
230    pub fn operand_is_gpq(op: &Operand) -> bool {
231        op.as_::<Self>().is_gpq()
232    }
233    pub fn operand_is_xmm(op: &Operand) -> bool {
234        op.as_::<Self>().is_xmm()
235    }
236    pub fn operand_is_ymm(op: &Operand) -> bool {
237        op.as_::<Self>().is_ymm()
238    }
239    pub fn operand_is_zmm(op: &Operand) -> bool {
240        op.as_::<Self>().is_zmm()
241    }
242    pub fn operand_is_mm(op: &Operand) -> bool {
243        op.as_::<Self>().is_mm()
244    }
245    pub fn operand_is_k_reg(op: &Operand) -> bool {
246        op.as_::<Self>().is_k_reg()
247    }
248    pub fn operand_is_s_reg(op: &Operand) -> bool {
249        op.as_::<Self>().is_s_reg()
250    }
251    pub fn operand_is_c_reg(op: &Operand) -> bool {
252        op.as_::<Self>().is_c_reg()
253    }
254    pub fn operand_is_d_reg(op: &Operand) -> bool {
255        op.as_::<Self>().is_d_reg()
256    }
257    pub fn operand_is_st(op: &Operand) -> bool {
258        op.as_::<Self>().is_st()
259    }
260    pub fn operand_is_bnd(op: &Operand) -> bool {
261        op.as_::<Self>().is_bnd()
262    }
263    pub fn operand_is_tmm(op: &Operand) -> bool {
264        op.as_::<Self>().is_tmm()
265    }
266    pub fn operand_is_rip(op: &Operand) -> bool {
267        op.as_::<Self>().is_rip()
268    }
269
270    pub fn operand_is_gpb_with_id(op: &Operand, rid: u32) -> bool {
271        (Self::operand_is_gpb(op) as u32 & (op.id() == rid) as u32) != 0
272    }
273    pub fn operand_is_gpb_lo_with_id(op: &Operand, rid: u32) -> bool {
274        (Self::operand_is_gpb_lo(op) as u32 & (op.id() == rid) as u32) != 0
275    }
276    pub fn operand_is_gpb_hi_with_id(op: &Operand, rid: u32) -> bool {
277        (Self::operand_is_gpb_hi(op) as u32 & (op.id() == rid) as u32) != 0
278    }
279    pub fn operand_is_gpw_with_id(op: &Operand, rid: u32) -> bool {
280        (Self::operand_is_gpw(op) as u32 & (op.id() == rid) as u32) != 0
281    }
282    pub fn operand_is_gpd_with_id(op: &Operand, rid: u32) -> bool {
283        (Self::operand_is_gpd(op) as u32 & (op.id() == rid) as u32) != 0
284    }
285    pub fn operand_is_gpq_with_id(op: &Operand, rid: u32) -> bool {
286        (Self::operand_is_gpq(op) as u32 & (op.id() == rid) as u32) != 0
287    }
288    pub fn operand_is_xmm_with_id(op: &Operand, rid: u32) -> bool {
289        (Self::operand_is_xmm(op) as u32 & (op.id() == rid) as u32) != 0
290    }
291    pub fn operand_is_ymm_with_id(op: &Operand, rid: u32) -> bool {
292        (Self::operand_is_ymm(op) as u32 & (op.id() == rid) as u32) != 0
293    }
294    pub fn operand_is_zmm_with_id(op: &Operand, rid: u32) -> bool {
295        (Self::operand_is_zmm(op) as u32 & (op.id() == rid) as u32) != 0
296    }
297    pub fn operand_is_mm_with_id(op: &Operand, rid: u32) -> bool {
298        (Self::operand_is_mm(op) as u32 & (op.id() == rid) as u32) != 0
299    }
300    pub fn operand_is_k_reg_with_id(op: &Operand, rid: u32) -> bool {
301        (Self::operand_is_k_reg(op) as u32 & (op.id() == rid) as u32) != 0
302    }
303    pub fn operand_is_s_reg_with_id(op: &Operand, rid: u32) -> bool {
304        (Self::operand_is_s_reg(op) as u32 & (op.id() == rid) as u32) != 0
305    }
306    pub fn operand_is_c_reg_with_id(op: &Operand, rid: u32) -> bool {
307        (Self::operand_is_c_reg(op) as u32 & (op.id() == rid) as u32) != 0
308    }
309    pub fn operand_is_d_reg_with_id(op: &Operand, rid: u32) -> bool {
310        (Self::operand_is_d_reg(op) as u32 & (op.id() == rid) as u32) != 0
311    }
312    pub fn operand_is_st_with_id(op: &Operand, rid: u32) -> bool {
313        (Self::operand_is_st(op) as u32 & (op.id() == rid) as u32) != 0
314    }
315    pub fn operand_is_bnd_with_id(op: &Operand, rid: u32) -> bool {
316        (Self::operand_is_bnd(op) as u32 & (op.id() == rid) as u32) != 0
317    }
318    pub fn operand_is_tmm_with_id(op: &Operand, rid: u32) -> bool {
319        (Self::operand_is_tmm(op) as u32 & (op.id() == rid) as u32) != 0
320    }
321    pub fn operand_is_rip_with_id(op: &Operand, rid: u32) -> bool {
322        (Self::operand_is_rip(op) as u32 & (op.id() == rid) as u32) != 0
323    }
324
325    pub const SIGNATURE: u32 = BaseReg::SIGNATURE;
326}
327
328#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
329pub struct Gp(pub Reg);
330
331impl_deref_for_wrapper!(Gp, Reg);
332
333define_abstract_reg!(Gp, Reg);
334
335impl Gp {
336    pub const fn signature_of(typ: RegType) -> OperandSignature {
337        ArchTraits::by_arch(Arch::X86).reg_type_to_signature(typ)
338    }
339
340    pub const AX: u32 = 0;
341    pub const CX: u32 = 1;
342    pub const DX: u32 = 2;
343    pub const BX: u32 = 3;
344    pub const SP: u32 = 4;
345    pub const BP: u32 = 5;
346    pub const SI: u32 = 6;
347    pub const DI: u32 = 7;
348    pub const R8: u32 = 8;
349    pub const R9: u32 = 9;
350    pub const R10: u32 = 10;
351    pub const R11: u32 = 11;
352    pub const R12: u32 = 12;
353    pub const R13: u32 = 13;
354    pub const R14: u32 = 14;
355    pub const R15: u32 = 15;
356
357    pub const SIGNATURE: u32 = Reg::SIGNATURE;
358}
359
360#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
361pub struct Vec(pub Reg);
362
363impl_deref_for_wrapper!(Vec, Reg);
364
365define_abstract_reg!(Vec, Reg);
366
367impl Vec {
368    pub const fn signature_of(typ: RegType) -> OperandSignature {
369        ArchTraits::by_arch(Arch::X86).reg_type_to_signature(typ)
370    }
371
372    pub const SIGNATURE: u32 = Reg::SIGNATURE;
373}
374
375#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
376pub struct SReg(pub Reg);
377
378impl_deref_for_wrapper!(SReg, Reg);
379
380impl SReg {
381    pub const fn signature_of(typ: RegType) -> OperandSignature {
382        ArchTraits::by_arch(Arch::X86).reg_type_to_signature(typ)
383    }
384
385    pub const ES: u32 = 1;
386    pub const CS: u32 = 2;
387    pub const SS: u32 = 3;
388    pub const DS: u32 = 4;
389    pub const FS: u32 = 5;
390    pub const GS: u32 = 6;
391}
392
393define_final_reg!(SReg, Reg, X86SReg);
394
395#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
396pub struct Gpb(pub Gp);
397
398impl_deref_for_wrapper!(Gpb, Gp);
399
400define_abstract_reg!(Gpb, Gp);
401
402impl Gpb {
403    pub const fn signature_of(typ: RegType) -> OperandSignature {
404        ArchTraits::by_arch(Arch::X86).reg_type_to_signature(typ)
405    }
406
407    pub const SIGNATURE: u32 = Gp::SIGNATURE;
408}
409
410#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
411pub struct GpbLo(pub Gpb);
412
413impl_deref_for_wrapper!(GpbLo, Gpb);
414
415impl GpbLo {
416    pub const fn signature_of(typ: RegType) -> OperandSignature {
417        ArchTraits::by_arch(Arch::X86).reg_type_to_signature(typ)
418    }
419}
420
421define_final_reg!(GpbLo, Gpb, X86GpbLo);
422
423#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
424pub struct GpbHi(pub Gpb);
425
426impl_deref_for_wrapper!(GpbHi, Gpb);
427
428impl GpbHi {
429    pub const fn signature_of(typ: RegType) -> OperandSignature {
430        ArchTraits::by_arch(Arch::X86).reg_type_to_signature(typ)
431    }
432}
433
434define_final_reg!(GpbHi, Gpb, X86GpbHi);
435
436#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
437pub struct Gpw(pub Gp);
438
439impl_deref_for_wrapper!(Gpw, Gp);
440
441impl Gpw {
442    pub const fn signature_of(typ: RegType) -> OperandSignature {
443        ArchTraits::by_arch(Arch::X86).reg_type_to_signature(typ)
444    }
445}
446
447define_final_reg!(Gpw, Gp, X86Gpw);
448
449#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
450pub struct Gpd(pub Gp);
451
452impl_deref_for_wrapper!(Gpd, Gp);
453
454impl Gpd {
455    pub const fn signature_of(typ: RegType) -> OperandSignature {
456        ArchTraits::by_arch(Arch::X86).reg_type_to_signature(typ)
457    }
458}
459
460define_final_reg!(Gpd, Gp, X86Gpd);
461
462#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
463pub struct Gpq(pub Gp);
464
465impl_deref_for_wrapper!(Gpq, Gp);
466
467impl AsRef<BaseReg> for Gpq {
468    fn as_ref(&self) -> &BaseReg {
469        &self.0.0.0
470    }
471}
472
473impl Gpq {
474    pub const fn signature_of(typ: RegType) -> OperandSignature {
475        ArchTraits::by_arch(Arch::X86).reg_type_to_signature(typ)
476    }
477}
478
479define_final_reg!(Gpq, Gp, X86Gpq);
480
481#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
482pub struct Xmm(pub Vec);
483
484impl_deref_for_wrapper!(Xmm, Vec);
485
486impl Xmm {
487    pub const fn signature_of(typ: RegType) -> OperandSignature {
488        ArchTraits::by_arch(Arch::X86).reg_type_to_signature(typ)
489    }
490
491    pub fn half(&self) -> Xmm {
492        Xmm::from_id(self.id())
493    }
494}
495
496define_final_reg!(Xmm, Vec, X86Xmm);
497
498#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
499pub struct Ymm(pub Vec);
500
501impl_deref_for_wrapper!(Ymm, Vec);
502
503impl Ymm {
504    pub const fn signature_of(typ: RegType) -> OperandSignature {
505        ArchTraits::by_arch(Arch::X86).reg_type_to_signature(typ)
506    }
507
508    pub fn half(&self) -> Xmm {
509        Xmm::from_id(self.id())
510    }
511}
512
513define_final_reg!(Ymm, Vec, X86Ymm);
514
515#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
516pub struct Zmm(pub Vec);
517
518impl_deref_for_wrapper!(Zmm, Vec);
519
520impl Zmm {
521    pub const fn signature_of(typ: RegType) -> OperandSignature {
522        ArchTraits::by_arch(Arch::X86).reg_type_to_signature(typ)
523    }
524
525    pub fn half(&self) -> Ymm {
526        Ymm::from_id(self.id())
527    }
528}
529
530define_final_reg!(Zmm, Vec, X86Zmm);
531
532#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
533pub struct Mm(pub Reg);
534
535impl_deref_for_wrapper!(Mm, Reg);
536
537impl Mm {
538    pub const fn signature_of(typ: RegType) -> OperandSignature {
539        ArchTraits::by_arch(Arch::X86).reg_type_to_signature(typ)
540    }
541}
542
543define_final_reg!(Mm, Reg, X86Mm);
544
545#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
546pub struct KReg(pub Reg);
547
548impl_deref_for_wrapper!(KReg, Reg);
549
550impl KReg {
551    pub const fn signature_of(typ: RegType) -> OperandSignature {
552        ArchTraits::by_arch(Arch::X86).reg_type_to_signature(typ)
553    }
554}
555
556define_final_reg!(KReg, Reg, X86KReg);
557
558#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
559pub struct CReg(pub Reg);
560
561impl_deref_for_wrapper!(CReg, Reg);
562
563impl CReg {
564    pub const fn signature_of(typ: RegType) -> OperandSignature {
565        ArchTraits::by_arch(Arch::X86).reg_type_to_signature(typ)
566    }
567}
568
569define_final_reg!(CReg, Reg, X86CReg);
570
571#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
572pub struct DReg(pub Reg);
573
574impl_deref_for_wrapper!(DReg, Reg);
575
576impl DReg {
577    pub const fn signature_of(typ: RegType) -> OperandSignature {
578        ArchTraits::by_arch(Arch::X86).reg_type_to_signature(typ)
579    }
580}
581
582define_final_reg!(DReg, Reg, X86DReg);
583
584#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
585pub struct St(pub Reg);
586
587impl_deref_for_wrapper!(St, Reg);
588
589impl St {
590    pub const fn signature_of(typ: RegType) -> OperandSignature {
591        ArchTraits::by_arch(Arch::X86).reg_type_to_signature(typ)
592    }
593}
594
595define_final_reg!(St, Reg, X86St);
596
597#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
598pub struct Bnd(pub Reg);
599
600impl_deref_for_wrapper!(Bnd, Reg);
601
602impl Bnd {
603    pub const fn signature_of(typ: RegType) -> OperandSignature {
604        ArchTraits::by_arch(Arch::X86).reg_type_to_signature(typ)
605    }
606}
607
608define_final_reg!(Bnd, Reg, X86Bnd);
609
610#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
611pub struct Tmm(pub Reg);
612
613impl_deref_for_wrapper!(Tmm, Reg);
614
615impl Tmm {
616    pub const fn signature_of(typ: RegType) -> OperandSignature {
617        ArchTraits::by_arch(Arch::X86).reg_type_to_signature(typ)
618    }
619}
620
621define_final_reg!(Tmm, Reg, X86Tmm);
622
623#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
624pub struct Rip(pub Reg);
625
626impl_deref_for_wrapper!(Rip, Reg);
627
628impl Rip {
629    pub const fn signature_of(typ: RegType) -> OperandSignature {
630        ArchTraits::by_arch(Arch::X86).reg_type_to_signature(typ)
631    }
632}
633
634define_final_reg!(Rip, Reg, X86Rip);
635
636impl Gp {
637    pub fn r8(&self) -> GpbLo {
638        GpbLo::from_id(self.id())
639    }
640
641    pub fn r8lo(&self) -> GpbLo {
642        GpbLo::from_id(self.id())
643    }
644
645    pub fn r8hi(&self) -> GpbHi {
646        GpbHi::from_id(self.id())
647    }
648
649    pub fn r16(&self) -> Gpw {
650        Gpw::from_id(self.id())
651    }
652
653    pub fn r32(&self) -> Gpd {
654        Gpd::from_id(self.id())
655    }
656
657    pub fn r64(&self) -> Gpq {
658        Gpq::from_id(self.id())
659    }
660}
661impl Vec {
662    pub fn xmm(&self) -> Xmm {
663        Xmm::from_id(self.id())
664    }
665
666    pub fn ymm(&self) -> Ymm {
667        Ymm::from_id(self.id())
668    }
669
670    pub fn zmm(&self) -> Zmm {
671        Zmm::from_id(self.id())
672    }
673
674    pub fn v128(&self) -> Xmm {
675        Xmm::from_id(self.id())
676    }
677
678    pub fn v256(&self) -> Ymm {
679        Ymm::from_id(self.id())
680    }
681
682    pub fn v512(&self) -> Zmm {
683        Zmm::from_id(self.id())
684    }
685}
686
687pub mod regs {
688    use super::*;
689    pub const fn gpb(id: u32) -> GpbLo {
690        GpbLo::from_id(id)
691    }
692
693    pub const fn gpb_lo(id: u32) -> GpbLo {
694        GpbLo::from_id(id)
695    }
696
697    pub const fn gpb_hi(id: u32) -> GpbHi {
698        GpbHi::from_id(id)
699    }
700
701    pub const fn gpw(id: u32) -> Gpw {
702        Gpw::from_id(id)
703    }
704
705    pub const fn gpd(id: u32) -> Gpd {
706        Gpd::from_id(id)
707    }
708
709    pub const fn gpq(id: u32) -> Gpq {
710        Gpq::from_id(id)
711    }
712
713    pub const fn xmm(id: u32) -> Xmm {
714        Xmm::from_id(id)
715    }
716
717    pub const fn ymm(id: u32) -> Ymm {
718        Ymm::from_id(id)
719    }
720
721    pub const fn zmm(id: u32) -> Zmm {
722        Zmm::from_id(id)
723    }
724
725    pub const fn mm(id: u32) -> Mm {
726        Mm::from_id(id)
727    }
728
729    pub const fn k(id: u32) -> KReg {
730        KReg::from_id(id)
731    }
732
733    pub const fn cr(id: u32) -> CReg {
734        CReg::from_id(id)
735    }
736
737    pub const fn dr(id: u32) -> DReg {
738        DReg::from_id(id)
739    }
740
741    pub const fn st(id: u32) -> St {
742        St::from_id(id)
743    }
744
745    pub const fn bnd(id: u32) -> Bnd {
746        Bnd::from_id(id)
747    }
748
749    pub const fn tmm(id: u32) -> Tmm {
750        Tmm::from_id(id)
751    }
752
753    pub const fn rip() -> Rip {
754        Rip::from_id(0)
755    }
756
757    pub const fn sreg(id: u32) -> SReg {
758        SReg::from_id(id)
759    }
760
761    pub const AL: GpbLo = gpb_lo(Gp::AX);
762    pub const CL: GpbLo = gpb_lo(Gp::CX);
763    pub const DL: GpbLo = gpb_lo(Gp::DX);
764    pub const BL: GpbLo = gpb_lo(Gp::BX);
765    pub const SPL: GpbLo = gpb_lo(Gp::SP);
766    pub const BPL: GpbLo = gpb_lo(Gp::BP);
767    pub const SIL: GpbLo = gpb_lo(Gp::SI);
768    pub const DIL: GpbLo = gpb_lo(Gp::DI);
769    pub const R8B: GpbLo = gpb_lo(Gp::R8);
770    pub const R9B: GpbLo = gpb_lo(Gp::R9);
771    pub const R10B: GpbLo = gpb_lo(Gp::R10);
772    pub const R11B: GpbLo = gpb_lo(Gp::R11);
773    pub const R12B: GpbLo = gpb_lo(Gp::R12);
774    pub const R13B: GpbLo = gpb_lo(Gp::R13);
775    pub const R14B: GpbLo = gpb_lo(Gp::R14);
776    pub const R15B: GpbLo = gpb_lo(Gp::R15);
777
778    pub const AH: GpbHi = gpb_hi(Gp::AX);
779    pub const CH: GpbHi = gpb_hi(Gp::CX);
780    pub const DH: GpbHi = gpb_hi(Gp::DX);
781    pub const BH: GpbHi = gpb_hi(Gp::BX);
782
783    pub const AX: Gpw = gpw(Gp::AX);
784    pub const CX: Gpw = gpw(Gp::CX);
785    pub const DX: Gpw = gpw(Gp::DX);
786    pub const BX: Gpw = gpw(Gp::BX);
787    pub const SP: Gpw = gpw(Gp::SP);
788    pub const BP: Gpw = gpw(Gp::BP);
789    pub const SI: Gpw = gpw(Gp::SI);
790    pub const DI: Gpw = gpw(Gp::DI);
791    pub const R8W: Gpw = gpw(Gp::R8);
792    pub const R9W: Gpw = gpw(Gp::R9);
793    pub const R10W: Gpw = gpw(Gp::R10);
794    pub const R11W: Gpw = gpw(Gp::R11);
795    pub const R12W: Gpw = gpw(Gp::R12);
796    pub const R13W: Gpw = gpw(Gp::R13);
797    pub const R14W: Gpw = gpw(Gp::R14);
798    pub const R15W: Gpw = gpw(Gp::R15);
799
800    pub const EAX: Gpd = gpd(Gp::AX);
801    pub const ECX: Gpd = gpd(Gp::CX);
802    pub const EDX: Gpd = gpd(Gp::DX);
803    pub const EBX: Gpd = gpd(Gp::BX);
804    pub const ESP: Gpd = gpd(Gp::SP);
805    pub const EBP: Gpd = gpd(Gp::BP);
806    pub const ESI: Gpd = gpd(Gp::SI);
807    pub const EDI: Gpd = gpd(Gp::DI);
808    pub const R8D: Gpd = gpd(Gp::R8);
809    pub const R9D: Gpd = gpd(Gp::R9);
810    pub const R10D: Gpd = gpd(Gp::R10);
811    pub const R11D: Gpd = gpd(Gp::R11);
812    pub const R12D: Gpd = gpd(Gp::R12);
813    pub const R13D: Gpd = gpd(Gp::R13);
814    pub const R14D: Gpd = gpd(Gp::R14);
815    pub const R15D: Gpd = gpd(Gp::R15);
816
817    pub const RAX: Gpq = gpq(Gp::AX);
818    pub const RCX: Gpq = gpq(Gp::CX);
819    pub const RDX: Gpq = gpq(Gp::DX);
820    pub const RBX: Gpq = gpq(Gp::BX);
821    pub const RSP: Gpq = gpq(Gp::SP);
822    pub const RBP: Gpq = gpq(Gp::BP);
823    pub const RSI: Gpq = gpq(Gp::SI);
824    pub const RDI: Gpq = gpq(Gp::DI);
825    pub const R8: Gpq = gpq(Gp::R8);
826    pub const R9: Gpq = gpq(Gp::R9);
827    pub const R10: Gpq = gpq(Gp::R10);
828    pub const R11: Gpq = gpq(Gp::R11);
829    pub const R12: Gpq = gpq(Gp::R12);
830    pub const R13: Gpq = gpq(Gp::R13);
831    pub const R14: Gpq = gpq(Gp::R14);
832    pub const R15: Gpq = gpq(Gp::R15);
833
834    pub const XMM0: Xmm = xmm(0);
835    pub const XMM1: Xmm = xmm(1);
836    pub const XMM2: Xmm = xmm(2);
837    pub const XMM3: Xmm = xmm(3);
838    pub const XMM4: Xmm = xmm(4);
839    pub const XMM5: Xmm = xmm(5);
840    pub const XMM6: Xmm = xmm(6);
841    pub const XMM7: Xmm = xmm(7);
842    pub const XMM8: Xmm = xmm(8);
843    pub const XMM9: Xmm = xmm(9);
844    pub const XMM10: Xmm = xmm(10);
845    pub const XMM11: Xmm = xmm(11);
846    pub const XMM12: Xmm = xmm(12);
847    pub const XMM13: Xmm = xmm(13);
848    pub const XMM14: Xmm = xmm(14);
849    pub const XMM15: Xmm = xmm(15);
850    pub const XMM16: Xmm = xmm(16);
851    pub const XMM17: Xmm = xmm(17);
852    pub const XMM18: Xmm = xmm(18);
853    pub const XMM19: Xmm = xmm(19);
854    pub const XMM20: Xmm = xmm(20);
855    pub const XMM21: Xmm = xmm(21);
856    pub const XMM22: Xmm = xmm(22);
857    pub const XMM23: Xmm = xmm(23);
858    pub const XMM24: Xmm = xmm(24);
859    pub const XMM25: Xmm = xmm(25);
860    pub const XMM26: Xmm = xmm(26);
861    pub const XMM27: Xmm = xmm(27);
862    pub const XMM28: Xmm = xmm(28);
863    pub const XMM29: Xmm = xmm(29);
864    pub const XMM30: Xmm = xmm(30);
865    pub const XMM31: Xmm = xmm(31);
866
867    pub const YMM0: Ymm = ymm(0);
868    pub const YMM1: Ymm = ymm(1);
869    pub const YMM2: Ymm = ymm(2);
870    pub const YMM3: Ymm = ymm(3);
871    pub const YMM4: Ymm = ymm(4);
872    pub const YMM5: Ymm = ymm(5);
873    pub const YMM6: Ymm = ymm(6);
874    pub const YMM7: Ymm = ymm(7);
875    pub const YMM8: Ymm = ymm(8);
876    pub const YMM9: Ymm = ymm(9);
877    pub const YMM10: Ymm = ymm(10);
878    pub const YMM11: Ymm = ymm(11);
879    pub const YMM12: Ymm = ymm(12);
880    pub const YMM13: Ymm = ymm(13);
881    pub const YMM14: Ymm = ymm(14);
882    pub const YMM15: Ymm = ymm(15);
883    pub const YMM16: Ymm = ymm(16);
884    pub const YMM17: Ymm = ymm(17);
885    pub const YMM18: Ymm = ymm(18);
886    pub const YMM19: Ymm = ymm(19);
887    pub const YMM20: Ymm = ymm(20);
888    pub const YMM21: Ymm = ymm(21);
889    pub const YMM22: Ymm = ymm(22);
890    pub const YMM23: Ymm = ymm(23);
891    pub const YMM24: Ymm = ymm(24);
892    pub const YMM25: Ymm = ymm(25);
893    pub const YMM26: Ymm = ymm(26);
894    pub const YMM27: Ymm = ymm(27);
895    pub const YMM28: Ymm = ymm(28);
896    pub const YMM29: Ymm = ymm(29);
897    pub const YMM30: Ymm = ymm(30);
898    pub const YMM31: Ymm = ymm(31);
899
900    pub const ZMM0: Zmm = zmm(0);
901    pub const ZMM1: Zmm = zmm(1);
902    pub const ZMM2: Zmm = zmm(2);
903    pub const ZMM3: Zmm = zmm(3);
904    pub const ZMM4: Zmm = zmm(4);
905    pub const ZMM5: Zmm = zmm(5);
906    pub const ZMM6: Zmm = zmm(6);
907    pub const ZMM7: Zmm = zmm(7);
908    pub const ZMM8: Zmm = zmm(8);
909    pub const ZMM9: Zmm = zmm(9);
910    pub const ZMM10: Zmm = zmm(10);
911    pub const ZMM11: Zmm = zmm(11);
912    pub const ZMM12: Zmm = zmm(12);
913    pub const ZMM13: Zmm = zmm(13);
914    pub const ZMM14: Zmm = zmm(14);
915    pub const ZMM15: Zmm = zmm(15);
916    pub const ZMM16: Zmm = zmm(16);
917    pub const ZMM17: Zmm = zmm(17);
918    pub const ZMM18: Zmm = zmm(18);
919    pub const ZMM19: Zmm = zmm(19);
920    pub const ZMM20: Zmm = zmm(20);
921    pub const ZMM21: Zmm = zmm(21);
922    pub const ZMM22: Zmm = zmm(22);
923    pub const ZMM23: Zmm = zmm(23);
924    pub const ZMM24: Zmm = zmm(24);
925    pub const ZMM25: Zmm = zmm(25);
926    pub const ZMM26: Zmm = zmm(26);
927    pub const ZMM27: Zmm = zmm(27);
928    pub const ZMM28: Zmm = zmm(28);
929    pub const ZMM29: Zmm = zmm(29);
930    pub const ZMM30: Zmm = zmm(30);
931    pub const ZMM31: Zmm = zmm(31);
932
933    pub const MM0: Mm = mm(0);
934    pub const MM1: Mm = mm(1);
935    pub const MM2: Mm = mm(2);
936    pub const MM3: Mm = mm(3);
937    pub const MM4: Mm = mm(4);
938    pub const MM5: Mm = mm(5);
939    pub const MM6: Mm = mm(6);
940    pub const MM7: Mm = mm(7);
941
942    pub const K0: KReg = k(0);
943    pub const K1: KReg = k(1);
944    pub const K2: KReg = k(2);
945    pub const K3: KReg = k(3);
946    pub const K4: KReg = k(4);
947    pub const K5: KReg = k(5);
948    pub const K6: KReg = k(6);
949    pub const K7: KReg = k(7);
950
951    pub const CR0: CReg = cr(0);
952    pub const CR2: CReg = cr(2);
953    pub const CR3: CReg = cr(3);
954    pub const CR4: CReg = cr(4);
955    pub const CR8: CReg = cr(8);
956
957    pub const DR0: DReg = dr(0);
958    pub const DR1: DReg = dr(1);
959    pub const DR2: DReg = dr(2);
960    pub const DR3: DReg = dr(3);
961    pub const DR6: DReg = dr(6);
962    pub const DR7: DReg = dr(7);
963
964    pub const ST0: St = st(0);
965    pub const ST1: St = st(1);
966    pub const ST2: St = st(2);
967    pub const ST3: St = st(3);
968    pub const ST4: St = st(4);
969    pub const ST5: St = st(5);
970    pub const ST6: St = st(6);
971    pub const ST7: St = st(7);
972
973    pub const BND0: Bnd = bnd(0);
974    pub const BND1: Bnd = bnd(1);
975    pub const BND2: Bnd = bnd(2);
976    pub const BND3: Bnd = bnd(3);
977
978    pub const TMM0: Tmm = tmm(0);
979    pub const TMM1: Tmm = tmm(1);
980    pub const TMM2: Tmm = tmm(2);
981    pub const TMM3: Tmm = tmm(3);
982    pub const TMM4: Tmm = tmm(4);
983    pub const TMM5: Tmm = tmm(5);
984    pub const TMM6: Tmm = tmm(6);
985    pub const TMM7: Tmm = tmm(7);
986
987    pub const RIP: Rip = rip();
988
989    pub const ES: SReg = sreg(SReg::ES);
990    pub const CS: SReg = sreg(SReg::CS);
991    pub const SS: SReg = sreg(SReg::SS);
992    pub const DS: SReg = sreg(SReg::DS);
993    pub const FS: SReg = sreg(SReg::FS);
994    pub const GS: SReg = sreg(SReg::GS);
995}
996pub use regs::*;
997
998#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash, Debug)]
999pub struct Mem(pub BaseMem);
1000
1001impl_deref_for_wrapper!(Mem, BaseMem);
1002
1003define_operand_cast!(Mem, BaseMem);
1004
1005#[derive(Clone, Copy, PartialEq, Eq)]
1006#[repr(u32)]
1007pub enum AddrType {
1008    Default = 0,
1009    Abs = 1,
1010    Rel = 2,
1011}
1012
1013impl TryFrom<u32> for AddrType {
1014    type Error = ();
1015
1016    fn try_from(value: u32) -> Result<Self, Self::Error> {
1017        match value {
1018            0 => Ok(Self::Default),
1019            1 => Ok(Self::Abs),
1020            2 => Ok(Self::Rel),
1021            _ => Err(()),
1022        }
1023    }
1024}
1025
1026#[derive(Clone, Copy, PartialEq, Eq)]
1027#[repr(u32)]
1028pub enum Broadcast {
1029    None = 0,
1030    B1To2 = 1,
1031    B1To4 = 2,
1032    B1To8 = 3,
1033    B1To16 = 4,
1034    B1To32 = 5,
1035    B1To64 = 6,
1036}
1037
1038impl TryFrom<u32> for Broadcast {
1039    type Error = ();
1040
1041    fn try_from(value: u32) -> Result<Self, Self::Error> {
1042        match value {
1043            0 => Ok(Self::None),
1044            1 => Ok(Self::B1To2),
1045            2 => Ok(Self::B1To4),
1046            3 => Ok(Self::B1To8),
1047            4 => Ok(Self::B1To16),
1048            5 => Ok(Self::B1To32),
1049            6 => Ok(Self::B1To64),
1050            _ => Err(()),
1051        }
1052    }
1053}
1054type Signature = OperandSignature;
1055
1056impl Default for Mem {
1057    fn default() -> Self {
1058        Self::new()
1059    }
1060}
1061
1062impl Mem {
1063    pub const SIGNATURE_MEM_ADDR_TYPE_SHIFT: u32 = 14;
1064    pub const SIGNATURE_MEM_ADDR_TYPE_MASK: u32 = 0x03 << Self::SIGNATURE_MEM_ADDR_TYPE_SHIFT;
1065
1066    pub const SIGNATURE_MEM_SHIFT_VALUE_SHIFT: u32 = 16;
1067    pub const SIGNATURE_MEM_SHIFT_VALUE_MASK: u32 = 0x03 << Self::SIGNATURE_MEM_SHIFT_VALUE_SHIFT;
1068
1069    pub const SIGNATURE_MEM_SEGMENT_SHIFT: u32 = 18;
1070    pub const SIGNATURE_MEM_SEGMENT_MASK: u32 = 0x07 << Self::SIGNATURE_MEM_SEGMENT_SHIFT;
1071
1072    pub const SIGNATURE_MEM_BROADCAST_SHIFT: u32 = 21;
1073    pub const SIGNATURE_MEM_BROADCAST_MASK: u32 = 0x7 << Self::SIGNATURE_MEM_BROADCAST_SHIFT;
1074
1075    const INVALID_FIELD: u32 = 3;
1076
1077    fn shift_signature(shift: u32) -> OperandSignature {
1078        if shift <= 3 {
1079            Signature::from_value::<{ Self::SIGNATURE_MEM_SHIFT_VALUE_MASK }>(shift)
1080        } else {
1081            Signature::from_value::<{ Self::SIGNATURE_MEM_ADDR_TYPE_MASK }>(Self::INVALID_FIELD)
1082        }
1083    }
1084
1085    fn size_signature(size: u32) -> OperandSignature {
1086        if matches!(size, 0 | 1 | 2 | 4 | 6 | 8 | 10 | 16 | 32 | 64) {
1087            Signature::from_size(size)
1088        } else {
1089            Signature::from_size(u8::MAX as u32)
1090        }
1091    }
1092
1093    pub const fn new() -> Self {
1094        Self(BaseMem::new())
1095    }
1096
1097    pub fn base_reg(&self) -> Reg {
1098        Reg::from_type_and_id(self.base_type(), self.base_id())
1099    }
1100
1101    pub fn index_reg(&self) -> Reg {
1102        Reg::from_type_and_id(self.index_type(), self.index_id())
1103    }
1104
1105    pub fn set_index(&mut self, index: &BaseReg, shift: u32) {
1106        self.0.set_index(index);
1107        self.set_shift(shift);
1108    }
1109
1110    pub fn has_size(&self) -> bool {
1111        self.0.signature.has_field::<{ Signature::SIZE_MASK }>()
1112    }
1113
1114    pub fn has_size_of(&self, s: u32) -> bool {
1115        self.size() == s
1116    }
1117
1118    pub fn size(&self) -> u32 {
1119        self.0.signature.get_field::<{ Signature::SIZE_MASK }>()
1120    }
1121
1122    pub fn set_size(&mut self, size: u32) {
1123        self.0
1124            .signature
1125            .set_field::<{ Signature::SIZE_MASK }>(Self::size_signature(size).size());
1126    }
1127
1128    pub fn addr_type(&self) -> AddrType {
1129        self.try_addr_type().unwrap_or(AddrType::Default)
1130    }
1131
1132    pub fn try_addr_type(&self) -> Option<AddrType> {
1133        AddrType::try_from(
1134            self.0
1135                .signature
1136                .get_field::<{ Self::SIGNATURE_MEM_ADDR_TYPE_MASK }>(),
1137        )
1138        .ok()
1139    }
1140
1141    pub fn set_addr_type(&mut self, addr_type: AddrType) {
1142        self.0
1143            .signature
1144            .set_field::<{ Self::SIGNATURE_MEM_ADDR_TYPE_MASK }>(addr_type as u32);
1145    }
1146
1147    pub fn reset_addr_type(&mut self) {
1148        self.set_addr_type(AddrType::Default);
1149    }
1150
1151    pub fn is_abs(&self) -> bool {
1152        self.addr_type() == AddrType::Abs
1153    }
1154
1155    pub fn set_abs(&mut self) {
1156        self.set_addr_type(AddrType::Abs);
1157    }
1158
1159    pub fn is_rel(&self) -> bool {
1160        self.addr_type() == AddrType::Rel
1161    }
1162
1163    pub fn set_rel(&mut self) {
1164        self.set_addr_type(AddrType::Rel);
1165    }
1166
1167    pub fn has_segment(&self) -> bool {
1168        self.0
1169            .signature
1170            .has_field::<{ Self::SIGNATURE_MEM_SEGMENT_MASK }>()
1171    }
1172
1173    pub fn segment(&self) -> SReg {
1174        SReg::from_id(self.segment_id())
1175    }
1176
1177    pub fn segment_id(&self) -> u32 {
1178        self.0
1179            .signature
1180            .get_field::<{ Self::SIGNATURE_MEM_SEGMENT_MASK }>()
1181    }
1182
1183    pub fn set_segment(&mut self, seg: SReg) {
1184        self.set_segment_id(seg.id());
1185    }
1186
1187    pub fn set_segment_id(&mut self, r_id: u32) {
1188        if r_id <= SReg::GS {
1189            self.0
1190                .signature
1191                .set_field::<{ Self::SIGNATURE_MEM_SEGMENT_MASK }>(r_id);
1192        } else {
1193            self.0
1194                .signature
1195                .set_field::<{ Self::SIGNATURE_MEM_ADDR_TYPE_MASK }>(Self::INVALID_FIELD);
1196        }
1197    }
1198
1199    pub fn reset_segment(&mut self) {
1200        self.set_segment_id(0);
1201    }
1202
1203    pub fn has_shift(&self) -> bool {
1204        self.0
1205            .signature
1206            .has_field::<{ Self::SIGNATURE_MEM_SHIFT_VALUE_MASK }>()
1207    }
1208
1209    pub fn shift(&self) -> u32 {
1210        self.0
1211            .signature
1212            .get_field::<{ Self::SIGNATURE_MEM_SHIFT_VALUE_MASK }>()
1213    }
1214
1215    pub fn set_shift(&mut self, shift: u32) {
1216        if shift <= 3 {
1217            self.0
1218                .signature
1219                .set_field::<{ Self::SIGNATURE_MEM_SHIFT_VALUE_MASK }>(shift);
1220        } else {
1221            self.0
1222                .signature
1223                .set_field::<{ Self::SIGNATURE_MEM_ADDR_TYPE_MASK }>(Self::INVALID_FIELD);
1224        }
1225    }
1226
1227    pub fn reset_shift(&mut self) {
1228        self.set_shift(0);
1229    }
1230
1231    pub fn has_broadcast(&self) -> bool {
1232        self.0
1233            .signature
1234            .has_field::<{ Self::SIGNATURE_MEM_BROADCAST_MASK }>()
1235    }
1236
1237    pub fn get_broadcast(&self) -> Broadcast {
1238        self.try_broadcast().unwrap_or(Broadcast::None)
1239    }
1240
1241    pub fn try_broadcast(&self) -> Option<Broadcast> {
1242        Broadcast::try_from(
1243            self.0
1244                .signature
1245                .get_field::<{ Self::SIGNATURE_MEM_BROADCAST_MASK }>(),
1246        )
1247        .ok()
1248    }
1249
1250    pub fn set_broadcast(&mut self, b: Broadcast) {
1251        self.0
1252            .signature
1253            .set_field::<{ Self::SIGNATURE_MEM_BROADCAST_MASK }>(b as u32);
1254    }
1255
1256    pub fn reset_broadcast(&mut self) {
1257        self.set_broadcast(Broadcast::None);
1258    }
1259
1260    pub fn _1to1(&self) -> Self {
1261        self.clone_broadcasted(Broadcast::None)
1262    }
1263
1264    pub fn _1to2(&self) -> Self {
1265        self.clone_broadcasted(Broadcast::B1To2)
1266    }
1267
1268    pub fn _1to4(&self) -> Self {
1269        self.clone_broadcasted(Broadcast::B1To4)
1270    }
1271
1272    pub fn _1to8(&self) -> Self {
1273        self.clone_broadcasted(Broadcast::B1To8)
1274    }
1275
1276    pub fn _1to16(&self) -> Self {
1277        self.clone_broadcasted(Broadcast::B1To16)
1278    }
1279
1280    pub fn _1to32(&self) -> Self {
1281        self.clone_broadcasted(Broadcast::B1To32)
1282    }
1283
1284    pub fn _1to64(&self) -> Self {
1285        self.clone_broadcasted(Broadcast::B1To64)
1286    }
1287
1288    pub fn base_and_index_types(&self) -> u32 {
1289        self.signature
1290            .get_field::<{ OperandSignature::MEM_BASE_INDEX_MASK }>()
1291    }
1292
1293    pub fn clone_broadcasted(&self, bcst: Broadcast) -> Self {
1294        Self(BaseMem::from_base_and_index_disp(
1295            OperandSignature::new(self.0.signature.bits() & !Self::SIGNATURE_MEM_BROADCAST_MASK)
1296                | OperandSignature::new((bcst as u32) << Self::SIGNATURE_MEM_BROADCAST_SHIFT),
1297            self.0.base_id(),
1298            self.0.data[0],
1299            self.0.data[1] as _,
1300        ))
1301    }
1302
1303    pub fn from_signature_base_and_index_id_disp(
1304        signature: OperandSignature,
1305        base_id: u32,
1306        index_id: u32,
1307        offset: i32,
1308    ) -> Self {
1309        Self(BaseMem::from_base_and_index_disp(
1310            signature, base_id, index_id, offset,
1311        ))
1312    }
1313
1314    pub fn from_sym_and_index_shift_disp(
1315        base: &Sym,
1316        index: &BaseReg,
1317        shift: u32,
1318        off: i32,
1319        size: u32,
1320        signature: OperandSignature,
1321    ) -> Self {
1322        Self(BaseMem::from_base_and_index_disp(
1323            Signature::from_op_type(OperandType::Mem)
1324                | Signature::from_mem_base_type(RegType::SymTag)
1325                | Signature::from_mem_index_type(index.typ())
1326                | Self::shift_signature(shift)
1327                | Self::size_signature(size)
1328                | signature,
1329            base.id(),
1330            index.id(),
1331            off,
1332        ))
1333    }
1334    pub fn from_label_and_index_shift_disp(
1335        base: &Label,
1336        index: &BaseReg,
1337        shift: u32,
1338        off: i32,
1339        size: u32,
1340        signature: OperandSignature,
1341    ) -> Self {
1342        Self(BaseMem::from_base_and_index_disp(
1343            Signature::from_op_type(OperandType::Mem)
1344                | Signature::from_mem_base_type(RegType::LabelTag)
1345                | Signature::from_mem_index_type(index.typ())
1346                | Self::shift_signature(shift)
1347                | Self::size_signature(size)
1348                | signature,
1349            base.id(),
1350            index.id(),
1351            off,
1352        ))
1353    }
1354
1355    pub fn from_label_and_disp(
1356        base: &Label,
1357        off: i32,
1358        size: u32,
1359        signature: OperandSignature,
1360    ) -> Self {
1361        Self(BaseMem::from_base_and_index_disp(
1362            Signature::from_op_type(OperandType::Mem)
1363                | Signature::from_mem_base_type(RegType::LabelTag)
1364                | Self::size_signature(size)
1365                | signature,
1366            base.id(),
1367            0,
1368            off,
1369        ))
1370    }
1371
1372    pub fn from_sym_and_disp(base: &Sym, off: i32, size: u32, signature: OperandSignature) -> Self {
1373        Self(BaseMem::from_base_and_index_disp(
1374            Signature::from_op_type(OperandType::Mem)
1375                | Signature::from_mem_base_type(RegType::SymTag)
1376                | Self::size_signature(size)
1377                | signature,
1378            base.id(),
1379            0,
1380            off,
1381        ))
1382    }
1383
1384    pub fn from_base_and_disp(
1385        base: &BaseReg,
1386        off: i32,
1387        size: u32,
1388        signature: OperandSignature,
1389    ) -> Self {
1390        Self(BaseMem::from_base_and_index_disp(
1391            Signature::from_op_type(OperandType::Mem)
1392                | Signature::from_mem_base_type(base.typ())
1393                | Self::size_signature(size)
1394                | signature,
1395            base.id(),
1396            0,
1397            off,
1398        ))
1399    }
1400
1401    pub fn from_base_and_index_shift_disp(
1402        base: &BaseReg,
1403        index: &BaseReg,
1404        shift: u32,
1405        off: i32,
1406        size: u32,
1407        signature: OperandSignature,
1408    ) -> Self {
1409        Self(BaseMem::from_base_and_index_disp(
1410            Signature::from_op_type(OperandType::Mem)
1411                | Signature::from_mem_base_type(base.typ())
1412                | Signature::from_mem_index_type(index.typ())
1413                | Self::shift_signature(shift)
1414                | Self::size_signature(size)
1415                | signature,
1416            base.id(),
1417            index.id(),
1418            off,
1419        ))
1420    }
1421
1422    pub fn from_u64_and_index_shift_disp(
1423        base: u64,
1424        index: &BaseReg,
1425        shift: u32,
1426        size: u32,
1427        signature: OperandSignature,
1428    ) -> Self {
1429        Self(BaseMem::from_base_and_index_disp(
1430            Signature::from_op_type(OperandType::Mem)
1431                | Signature::from_mem_index_type(index.typ())
1432                | Self::shift_signature(shift)
1433                | Self::size_signature(size)
1434                | signature,
1435            (base >> 32) as u32,
1436            index.id(),
1437            (base & 0xFFFF_FFFF) as _,
1438        ))
1439    }
1440
1441    pub fn from_u64(base: u64, size: u32, signature: OperandSignature) -> Self {
1442        Self(BaseMem::from_base_and_index_disp(
1443            Signature::from_op_type(OperandType::Mem) | Self::size_signature(size) | signature,
1444            (base >> 32) as u32,
1445            0,
1446            (base & 0xFFFF_FFFF) as _,
1447        ))
1448    }
1449
1450    pub fn absolute_address(self) -> u64 {
1451        ((self.base_id() as u64) << 32) | (self.data[1] as u64)
1452    }
1453}
1454
1455impl Add<i32> for Gpq {
1456    type Output = Mem;
1457    fn add(self, rhs: i32) -> Self::Output {
1458        ptr(self, rhs, 0)
1459    }
1460}
1461
1462impl Mul<i32> for Gpq {
1463    type Output = Mem;
1464
1465    fn mul(self, rhs: i32) -> Self::Output {
1466        let shift = match rhs {
1467            1 => 0,
1468            2 => 1,
1469            4 => 2,
1470            8 => 3,
1471            _ => u32::MAX,
1472        };
1473        ptr_index(RAX, self, shift, 0, 0)
1474    }
1475}
1476
1477impl<T: Deref<Target = Gp>> Mul<T> for Mem {
1478    type Output = Mem;
1479
1480    fn mul(self, rhs: T) -> Self::Output {
1481        let mut this = self;
1482        let reg = rhs.deref();
1483        this.set_index_id(reg.id());
1484        this.set_index_type(reg.typ());
1485
1486        this
1487    }
1488}
1489
1490impl Add<i32> for Label {
1491    type Output = Mem;
1492
1493    fn add(self, rhs: i32) -> Self::Output {
1494        label_ptr(self, rhs, 0)
1495    }
1496}
1497
1498impl Add<Mem> for Gpq {
1499    type Output = Mem;
1500
1501    fn add(self, mut rhs: Mem) -> Self::Output {
1502        rhs.set_base(&self);
1503        rhs
1504    }
1505}
1506
1507impl Add<i32> for Mem {
1508    type Output = Mem;
1509
1510    fn add(self, rhs: i32) -> Self::Output {
1511        let mut this = self;
1512        this.add_offset(rhs as _);
1513        this
1514    }
1515}
1516
1517macro_rules! mem_ptr {
1518    ($name: ident, $size: literal) => {
1519        paste::paste! {
1520            pub fn $name(base: impl Deref<Target = Gp>, offset: i32) -> Mem {
1521                Mem::from_base_and_disp(base.deref(), offset, $size, 0.into())
1522            }
1523
1524            pub fn [<$name _index>](base: impl Deref<Target = Gp>, index: impl Deref<Target = Gp>, shift: u32, offset: i32) -> Mem {
1525                Mem::from_base_and_index_shift_disp(base.deref(), index.deref(), shift, offset, $size, 0.into())
1526            }
1527
1528            pub fn [<$name _label>](base: Label, offset: i32) -> Mem {
1529                Mem::from_label_and_disp(&base, offset, $size, 0.into())
1530            }
1531
1532            pub fn [<$name _label_index>](base: Label, index: impl Deref<Target = Gp>, shift: u32, offset: i32) -> Mem {
1533                Mem::from_label_and_index_shift_disp(&base, index.deref(), shift, offset, $size, 0.into())
1534            }
1535
1536            pub fn [<$name _sym>](base: Sym, offset: i32) -> Mem {
1537                Mem::from_sym_and_disp(&base, offset, $size, 0.into())
1538            }
1539
1540            pub fn [<$name _sym_index>](base: Sym, index: impl Deref<Target = Gp>, shift: u32, offset: i32) -> Mem {
1541                Mem::from_sym_and_index_shift_disp(&base, index.deref(), shift, offset, $size, 0.into())
1542            }
1543
1544
1545            pub fn [<$name _rip>](offset: i32) -> Mem {
1546                Mem::from_base_and_disp(&RIP, offset, $size, 0.into())
1547            }
1548
1549            pub fn [<$name _u64>](base: u64) -> Mem {
1550                Mem::from_u64(base, $size, 0.into())
1551            }
1552
1553            pub fn [<$name _u64_index>](base: u64, index: impl Deref<Target = Gp>, shift: u32) -> Mem {
1554                Mem::from_u64_and_index_shift_disp(base, index.deref(), shift, $size, 0.into())
1555            }
1556
1557            pub fn [<$name _u64_abs>](base: u64) -> AbsoluteAddress {
1558                AbsoluteAddress(Mem::from_u64(base, $size, OperandSignature::from_value::<{ Mem::SIGNATURE_MEM_ADDR_TYPE_MASK }>(AddrType::Abs as _)))
1559            }
1560
1561            pub fn [<$name _u64_index_abs>](base: u64, index: impl Deref<Target = Gp>, shift: u32) -> AbsoluteAddress {
1562                AbsoluteAddress(Mem::from_u64_and_index_shift_disp(base, index.deref(), shift, $size, OperandSignature::from_value::<{ Mem::SIGNATURE_MEM_ADDR_TYPE_MASK }>(AddrType::Abs as _)))
1563            }
1564
1565            pub fn [<$name _u64_rel>](base: u64) -> Mem {
1566                Mem::from_u64(base, $size, OperandSignature::from_value::<{ Mem::SIGNATURE_MEM_ADDR_TYPE_MASK }>(AddrType::Rel as _))
1567            }
1568
1569            pub fn [<$name _u64_index_rel>](base: u64, index: impl Deref<Target = Gp>, shift: u32) -> Mem {
1570                Mem::from_u64_and_index_shift_disp(base, index.deref(), shift, $size, OperandSignature::from_value::<{ Mem::SIGNATURE_MEM_ADDR_TYPE_MASK }>(AddrType::Rel as _))
1571            }
1572        }
1573    }
1574}
1575mem_ptr!(ptr8, 1);
1576mem_ptr!(ptr16, 2);
1577mem_ptr!(ptr32, 4);
1578mem_ptr!(ptr48, 6);
1579mem_ptr!(ptr64, 8);
1580mem_ptr!(ptr80, 10);
1581mem_ptr!(ptr128, 16);
1582mem_ptr!(ptr256, 32);
1583mem_ptr!(ptr512, 64);
1584
1585mem_ptr!(byte_ptr, 1);
1586mem_ptr!(word_ptr, 2);
1587mem_ptr!(dword_ptr, 4);
1588mem_ptr!(fword_ptr, 6);
1589mem_ptr!(qword_ptr, 8);
1590mem_ptr!(tbyte_ptr, 10);
1591mem_ptr!(tword_ptr, 10);
1592mem_ptr!(oword_ptr, 16);
1593mem_ptr!(dqword_ptr, 16);
1594mem_ptr!(qqword_ptr, 32);
1595mem_ptr!(xmmword_ptr, 16);
1596mem_ptr!(ymmword_ptr, 32);
1597mem_ptr!(zmmword_ptr, 64);
1598
1599pub fn ptr(base: impl Deref<Target = Gp>, offset: i32, size: u32) -> Mem {
1600    Mem::from_base_and_disp(base.deref(), offset, size, 0.into())
1601}
1602
1603pub fn ptr_index(
1604    base: impl Deref<Target = Gp>,
1605    index: impl Deref<Target = Gp>,
1606    shift: u32,
1607    offset: i32,
1608    size: u32,
1609) -> Mem {
1610    Mem::from_base_and_index_shift_disp(base.deref(), index.deref(), shift, offset, size, 0.into())
1611}
1612
1613pub fn label_ptr(base: Label, offset: i32, size: u32) -> Mem {
1614    Mem::from_label_and_disp(&base, offset, size, 0.into())
1615}
1616pub fn label_ptr_index(
1617    base: Label,
1618    index: impl Deref<Target = Gp>,
1619    shift: u32,
1620    offset: i32,
1621    size: u32,
1622) -> Mem {
1623    Mem::from_label_and_index_shift_disp(&base, index.deref(), shift, offset, size, 0.into())
1624}
1625
1626pub fn sym_ptr(base: Sym, offset: i32, size: u32) -> Mem {
1627    Mem::from_sym_and_disp(&base, offset, size, 0.into())
1628}
1629pub fn sym_ptr_index(
1630    base: Sym,
1631    index: impl Deref<Target = Gp>,
1632    shift: u32,
1633    offset: i32,
1634    size: u32,
1635) -> Mem {
1636    Mem::from_sym_and_index_shift_disp(&base, index.deref(), shift, offset, size, 0.into())
1637}
1638
1639pub fn rip_rel(offset: i32, size: u32) -> Mem {
1640    Mem::from_base_and_disp(&RIP, offset, size, 0.into())
1641}
1642
1643pub fn u64_ptr(base: u64, size: u32) -> Mem {
1644    Mem::from_u64(base, size, 0.into())
1645}
1646
1647pub fn u64_ptr_index(base: u64, index: impl Deref<Target = Gp>, shift: u32, size: u32) -> Mem {
1648    Mem::from_u64_and_index_shift_disp(base, index.deref(), shift, size, 0.into())
1649}
1650
1651pub fn u64_ptr_abs(base: u64, size: u32) -> Mem {
1652    Mem::from_u64(
1653        base,
1654        size,
1655        OperandSignature::from_value::<{ Mem::SIGNATURE_MEM_ADDR_TYPE_MASK }>(AddrType::Abs as _),
1656    )
1657}
1658
1659pub fn u64_ptr_index_abs(base: u64, index: impl Deref<Target = Gp>, shift: u32, size: u32) -> Mem {
1660    Mem::from_u64_and_index_shift_disp(
1661        base,
1662        index.deref(),
1663        shift,
1664        size,
1665        OperandSignature::from_value::<{ Mem::SIGNATURE_MEM_ADDR_TYPE_MASK }>(AddrType::Abs as _),
1666    )
1667}
1668
1669use core::fmt;
1670
1671impl fmt::Display for Reg {
1672    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1673        if !self.is_valid() {
1674            return write!(f, "reg_invalid");
1675        }
1676
1677        // Display based on specific register type
1678        if self.is_gpb_lo() {
1679            write!(f, "{}", GpbLo::from_type_and_id(RegType::Gp8Lo, self.id()))
1680        } else if self.is_gpb_hi() {
1681            write!(f, "{}", GpbHi::from_type_and_id(RegType::Gp8Hi, self.id()))
1682        } else if self.is_gpw() {
1683            write!(f, "{}", Gpw::from_type_and_id(RegType::Gp16, self.id()))
1684        } else if self.is_gpd() {
1685            write!(f, "{}", Gpd::from_type_and_id(RegType::Gp32, self.id()))
1686        } else if self.is_gpq() {
1687            write!(f, "{}", Gpq::from_type_and_id(RegType::Gp64, self.id()))
1688        } else if self.is_xmm() {
1689            write!(f, "{}", Xmm::from_type_and_id(RegType::Vec128, self.id()))
1690        } else if self.is_ymm() {
1691            write!(f, "{}", Ymm::from_type_and_id(RegType::Vec256, self.id()))
1692        } else if self.is_zmm() {
1693            write!(f, "{}", Zmm::from_type_and_id(RegType::Vec512, self.id()))
1694        } else if self.is_type(RegType::X86Mm) {
1695            write!(f, "{}", Mm::from_type_and_id(RegType::X86Mm, self.id()))
1696        } else if self.is_type(RegType::X86KReg) {
1697            write!(f, "{}", KReg::from_type_and_id(RegType::X86KReg, self.id()))
1698        } else if self.is_type(RegType::X86SReg) {
1699            write!(f, "{}", SReg::from_type_and_id(RegType::X86SReg, self.id()))
1700        } else if self.is_type(RegType::X86CReg) {
1701            write!(f, "{}", CReg::from_type_and_id(RegType::X86CReg, self.id()))
1702        } else if self.is_type(RegType::X86DReg) {
1703            write!(f, "{}", DReg::from_type_and_id(RegType::X86DReg, self.id()))
1704        } else if self.is_type(RegType::X86St) {
1705            write!(f, "{}", St::from_type_and_id(RegType::X86St, self.id()))
1706        } else if self.is_type(RegType::X86Bnd) {
1707            write!(f, "{}", Bnd::from_type_and_id(RegType::X86Bnd, self.id()))
1708        } else if self.is_type(RegType::X86Tmm) {
1709            write!(f, "{}", Tmm::from_type_and_id(RegType::X86Tmm, self.id()))
1710        } else if self.is_type(RegType::X86Rip) {
1711            write!(f, "{}", Rip::from_type_and_id(RegType::X86Rip, self.id()))
1712        } else {
1713            write!(f, "reg{}", self.id())
1714        }
1715    }
1716}
1717
1718impl fmt::Display for Gp {
1719    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1720        if !self.is_valid() {
1721            return write!(f, "gp_invalid");
1722        }
1723
1724        // Use common x86 register names for physical registers
1725        if self.id() < 16 {
1726            match self.size() {
1727                1 => {
1728                    // 8-bit registers
1729                    if self.id() < 4 {
1730                        // Low 8-bit: AL, CL, DL, BL
1731                        let names = ["al", "cl", "dl", "bl"];
1732                        write!(f, "{}", names[self.id() as usize])
1733                    } else if self.id() < 8 {
1734                        // High 8-bit: AH, CH, DH, BH
1735                        let names = ["ah", "ch", "dh", "bh"];
1736                        write!(f, "{}", names[(self.id() - 4) as usize])
1737                    } else {
1738                        // R8B-R15B
1739                        write!(f, "r{}b", self.id() - 8)
1740                    }
1741                }
1742                2 => {
1743                    // 16-bit registers
1744                    if self.id() < 8 {
1745                        let names = ["ax", "cx", "dx", "bx", "sp", "bp", "si", "di"];
1746                        write!(f, "{}", names[self.id() as usize])
1747                    } else {
1748                        write!(f, "r{}w", self.id() - 8)
1749                    }
1750                }
1751                4 => {
1752                    // 32-bit registers
1753                    if self.id() < 8 {
1754                        let names = ["eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"];
1755                        write!(f, "{}", names[self.id() as usize])
1756                    } else {
1757                        write!(f, "r{}d", self.id() - 8)
1758                    }
1759                }
1760                8 => {
1761                    // 64-bit registers
1762                    if self.id() < 8 {
1763                        let names = ["rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi"];
1764                        write!(f, "{}", names[self.id() as usize])
1765                    } else {
1766                        write!(f, "r{}", self.id() - 8)
1767                    }
1768                }
1769                _ => write!(f, "gp{}", self.id()),
1770            }
1771        } else {
1772            write!(f, "gp{}", self.id())
1773        }
1774    }
1775}
1776
1777impl fmt::Display for Vec {
1778    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1779        if !self.is_valid() {
1780            return write!(f, "vec_invalid");
1781        }
1782        write!(f, "vec{}", self.id())
1783    }
1784}
1785
1786impl fmt::Display for SReg {
1787    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1788        if !self.is_valid() {
1789            return write!(f, "sreg_invalid");
1790        }
1791
1792        match self.id() {
1793            SReg::ES => write!(f, "es"),
1794            SReg::CS => write!(f, "cs"),
1795            SReg::SS => write!(f, "ss"),
1796            SReg::DS => write!(f, "ds"),
1797            SReg::FS => write!(f, "fs"),
1798            SReg::GS => write!(f, "gs"),
1799            _ => write!(f, "sreg{}", self.id()),
1800        }
1801    }
1802}
1803
1804impl fmt::Display for Gpb {
1805    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1806        write!(f, "{}", Reg::from_type_and_id(self.typ(), self.id()))
1807    }
1808}
1809
1810impl fmt::Display for GpbLo {
1811    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1812        if !self.is_valid() {
1813            return write!(f, "gpblo_invalid");
1814        }
1815
1816        if self.id() < 4 {
1817            let names = ["al", "cl", "dl", "bl"];
1818            write!(f, "{}", names[self.id() as usize])
1819        } else if self.id() < 8 {
1820            write!(f, "spl")
1821        } else {
1822            write!(f, "r{}b", self.id() - 8)
1823        }
1824    }
1825}
1826
1827impl fmt::Display for GpbHi {
1828    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1829        if !self.is_valid() {
1830            return write!(f, "gpbhi_invalid");
1831        }
1832
1833        let names = ["ah", "ch", "dh", "bh"];
1834        write!(f, "{}", names[self.id() as usize])
1835    }
1836}
1837
1838impl fmt::Display for Gpw {
1839    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1840        if !self.is_valid() {
1841            return write!(f, "gpw_invalid");
1842        }
1843
1844        if self.id() < 8 {
1845            let names = ["ax", "cx", "dx", "bx", "sp", "bp", "si", "di"];
1846            write!(f, "{}", names[self.id() as usize])
1847        } else {
1848            write!(f, "r{}w", self.id() - 8)
1849        }
1850    }
1851}
1852
1853impl fmt::Display for Gpd {
1854    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1855        if !self.is_valid() {
1856            return write!(f, "gpd_invalid");
1857        }
1858
1859        if self.id() < 8 {
1860            let names = ["eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"];
1861            write!(f, "{}", names[self.id() as usize])
1862        } else {
1863            write!(f, "r{}d", self.id() - 8)
1864        }
1865    }
1866}
1867
1868impl fmt::Display for Gpq {
1869    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1870        if !self.is_valid() {
1871            return write!(f, "gpq_invalid");
1872        }
1873
1874        if self.id() < 8 {
1875            let names = ["rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi"];
1876            write!(f, "{}", names[self.id() as usize])
1877        } else {
1878            write!(f, "r{}", self.id() - 8)
1879        }
1880    }
1881}
1882
1883impl fmt::Display for Xmm {
1884    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1885        if !self.is_valid() {
1886            return write!(f, "xmm_invalid");
1887        }
1888        write!(f, "xmm{}", self.id())
1889    }
1890}
1891
1892impl fmt::Display for Ymm {
1893    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1894        if !self.is_valid() {
1895            return write!(f, "ymm_invalid");
1896        }
1897        write!(f, "ymm{}", self.id())
1898    }
1899}
1900
1901impl fmt::Display for Zmm {
1902    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1903        if !self.is_valid() {
1904            return write!(f, "zmm_invalid");
1905        }
1906        write!(f, "zmm{}", self.id())
1907    }
1908}
1909
1910impl fmt::Display for Mm {
1911    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1912        if !self.is_valid() {
1913            return write!(f, "mm_invalid");
1914        }
1915        write!(f, "mm{}", self.id())
1916    }
1917}
1918
1919impl fmt::Display for KReg {
1920    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1921        if !self.is_valid() {
1922            return write!(f, "kreg_invalid");
1923        }
1924        write!(f, "k{}", self.id())
1925    }
1926}
1927
1928impl fmt::Display for CReg {
1929    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1930        if !self.is_valid() {
1931            return write!(f, "creg_invalid");
1932        }
1933        write!(f, "cr{}", self.id())
1934    }
1935}
1936
1937impl fmt::Display for DReg {
1938    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1939        if !self.is_valid() {
1940            return write!(f, "dreg_invalid");
1941        }
1942        write!(f, "dr{}", self.id())
1943    }
1944}
1945
1946impl fmt::Display for St {
1947    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1948        if !self.is_valid() {
1949            return write!(f, "st_invalid");
1950        }
1951        write!(f, "st{}", self.id())
1952    }
1953}
1954
1955impl fmt::Display for Bnd {
1956    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1957        if !self.is_valid() {
1958            return write!(f, "bnd_invalid");
1959        }
1960        write!(f, "bnd{}", self.id())
1961    }
1962}
1963
1964impl fmt::Display for Tmm {
1965    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1966        if !self.is_valid() {
1967            return write!(f, "tmm_invalid");
1968        }
1969        write!(f, "tmm{}", self.id())
1970    }
1971}
1972
1973impl fmt::Display for Rip {
1974    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1975        write!(f, "rip")
1976    }
1977}
1978
1979impl fmt::Display for Mem {
1980    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1981        use alloc::format;
1982        use alloc::string::ToString;
1983        let mut output_parts = alloc::vec::Vec::new();
1984
1985        // Segment override
1986        if self.has_segment() {
1987            output_parts.push(format!("{}:", self.segment()));
1988        }
1989
1990        // Base
1991        if self.has_base() {
1992            if self.has_base_label() {
1993                output_parts.push(format!("label{}", self.base_id()));
1994            } else if self.has_base_sym() {
1995                output_parts.push(format!("sym{}", self.base_id()));
1996            } else if self.has_base_reg() {
1997                let base_reg = self.base_reg();
1998                output_parts.push(format!("{}", base_reg));
1999            }
2000        }
2001
2002        // Index with shift
2003        if self.has_index() && self.has_index_reg() {
2004            let index_reg = self.index_reg();
2005            if self.has_shift() {
2006                output_parts.push(format!("{}*{}", index_reg, self.shift()));
2007            } else {
2008                output_parts.push(format!("{}", index_reg));
2009            }
2010        }
2011
2012        // Offset
2013        if self.has_offset() {
2014            let offset = self.offset();
2015            if offset >= 0 {
2016                if !output_parts.is_empty() {
2017                    output_parts.push(format!("+{}", offset));
2018                } else {
2019                    output_parts.push(format!("{}", offset));
2020                }
2021            } else {
2022                output_parts.push(format!("{}", offset));
2023            }
2024        }
2025
2026        // Broadcast
2027        if self.has_broadcast() {
2028            output_parts.push(format!(" {{{}}}", self.get_broadcast() as u32));
2029        }
2030
2031        // Address type
2032        match self.addr_type() {
2033            AddrType::Abs => output_parts.push(" abs".to_string()),
2034            AddrType::Rel => output_parts.push(" rel".to_string()),
2035            AddrType::Default => {}
2036        }
2037
2038        if output_parts.is_empty() {
2039            write!(f, "byte ptr [0]")
2040        } else {
2041            write!(f, "[{}]", output_parts.join(" "))
2042        }
2043    }
2044}
2045
2046impl fmt::Display for Broadcast {
2047    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2048        match self {
2049            Broadcast::None => write!(f, "none"),
2050            Broadcast::B1To2 => write!(f, "1to2"),
2051            Broadcast::B1To4 => write!(f, "1to4"),
2052            Broadcast::B1To8 => write!(f, "1to8"),
2053            Broadcast::B1To16 => write!(f, "1to16"),
2054            Broadcast::B1To32 => write!(f, "1to32"),
2055            Broadcast::B1To64 => write!(f, "1to64"),
2056        }
2057    }
2058}
2059
2060impl fmt::Display for AddrType {
2061    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2062        match self {
2063            AddrType::Default => write!(f, "default"),
2064            AddrType::Abs => write!(f, "abs"),
2065            AddrType::Rel => write!(f, "rel"),
2066        }
2067    }
2068}
2069
2070pub struct AbsoluteAddress(Mem);
2071
2072impl AbsoluteAddress {
2073    pub fn new(addr: u64, size: u32) -> Self {
2074        Self(Mem::from_u64(
2075            addr,
2076            size,
2077            OperandSignature::from_value::<{ Mem::SIGNATURE_MEM_ADDR_TYPE_MASK }>(
2078                AddrType::Abs as _,
2079            ),
2080        ))
2081    }
2082
2083    pub fn from_mem(mut mem: Mem) -> Self {
2084        mem.set_abs();
2085        Self(mem)
2086    }
2087
2088    pub fn address(&self) -> u64 {
2089        self.0.absolute_address()
2090    }
2091}
2092
2093impl OperandCast for AbsoluteAddress {
2094    fn as_operand(&self) -> &Operand {
2095        self.0.as_operand()
2096    }
2097
2098    fn from_operand(op: &Operand) -> Self {
2099        Self(op.as_::<Mem>())
2100    }
2101}