asmkit/x86/
operands.rs

1use core::ops::{Add, Deref, Mul};
2
3use derive_more::derive::{Deref, DerefMut};
4
5use crate::{
6    core::{
7        arch_traits::{Arch, ArchTraits},
8        operand::*,
9        types::TypeId,
10    },
11    define_abstract_reg, define_final_reg, define_operand_cast, define_reg_traits,
12};
13
14define_reg_traits!(X86Rip, RegGroup::X86Rip, 0, TypeId::Void);
15define_reg_traits!(X86GpbLo, RegGroup::Gp, 1, TypeId::Int8);
16define_reg_traits!(X86GpbHi, RegGroup::Gp, 1, TypeId::Int8);
17define_reg_traits!(X86Gpw, RegGroup::Gp, 2, TypeId::Int16);
18define_reg_traits!(X86Gpd, RegGroup::Gp, 4, TypeId::Int32);
19define_reg_traits!(X86Gpq, RegGroup::Gp, 8, TypeId::Int64);
20define_reg_traits!(X86Xmm, RegGroup::Vec, 16, TypeId::Int32x4);
21define_reg_traits!(X86Ymm, RegGroup::Vec, 32, TypeId::Int32x8);
22define_reg_traits!(X86Zmm, RegGroup::Vec, 64, TypeId::Int32x16);
23define_reg_traits!(X86KReg, RegGroup::X86K, 0, TypeId::Void);
24define_reg_traits!(X86Mm, RegGroup::X86MM, 8, TypeId::Mmx64);
25define_reg_traits!(X86SReg, RegGroup::X86SReg, 2, TypeId::Void);
26define_reg_traits!(X86CReg, RegGroup::X86CReg, 0, TypeId::Void);
27define_reg_traits!(X86DReg, RegGroup::X86DReg, 0, TypeId::Void);
28define_reg_traits!(X86St, RegGroup::X86St, 10, TypeId::Float80);
29define_reg_traits!(X86Bnd, RegGroup::X86Bnd, 16, TypeId::Void);
30define_reg_traits!(X86Tmm, RegGroup::X86Tmm, 0, TypeId::Void);
31
32#[derive(Deref, DerefMut, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
33pub struct Reg(pub BaseReg);
34
35define_abstract_reg!(Reg, BaseReg);
36
37impl Reg {
38    pub const fn signature_of(typ: RegType) -> OperandSignature {
39        ArchTraits::by_arch(Arch::X86).reg_type_to_signature(typ)
40    }
41
42    pub fn is_gpb(&self) -> bool {
43        self.size() == 1
44    }
45
46    pub fn is_gpb_lo(&self) -> bool {
47        self.has_base_signature(X86GpbLo::SIGNATURE)
48    }
49
50    pub fn is_gpb_hi(&self) -> bool {
51        self.has_base_signature(X86GpbHi::SIGNATURE)
52    }
53
54    pub fn is_gpw(&self) -> bool {
55        self.has_base_signature(X86Gpw::SIGNATURE)
56    }
57
58    pub fn is_gpd(&self) -> bool {
59        self.has_base_signature(X86Gpd::SIGNATURE)
60    }
61
62    pub fn is_gpq(&self) -> bool {
63        self.has_base_signature(X86Gpq::SIGNATURE)
64    }
65
66    pub fn is_gp32(&self) -> bool {
67        self.has_base_signature(X86Gpd::SIGNATURE)
68    }
69
70    pub fn is_gp64(&self) -> bool {
71        self.has_base_signature(X86Gpq::SIGNATURE)
72    }
73
74    pub fn is_xmm(&self) -> bool {
75        self.has_base_signature(X86Xmm::SIGNATURE)
76    }
77
78    pub fn is_ymm(&self) -> bool {
79        self.has_base_signature(X86Ymm::SIGNATURE)
80    }
81
82    pub fn is_zmm(&self) -> bool {
83        self.has_base_signature(X86Zmm::SIGNATURE)
84    }
85
86    pub fn is_vec128(&self) -> bool {
87        self.has_base_signature(X86Xmm::SIGNATURE)
88    }
89
90    pub fn is_vec256(&self) -> bool {
91        self.has_base_signature(X86Ymm::SIGNATURE)
92    }
93
94    pub fn is_vec512(&self) -> bool {
95        self.has_base_signature(X86Zmm::SIGNATURE)
96    }
97
98    pub fn is_mm(&self) -> bool {
99        self.has_base_signature(X86Mm::SIGNATURE)
100    }
101
102    pub fn is_k_reg(&self) -> bool {
103        self.has_base_signature(X86KReg::SIGNATURE)
104    }
105
106    pub fn is_s_reg(&self) -> bool {
107        self.has_base_signature(X86SReg::SIGNATURE)
108    }
109
110    pub fn is_c_reg(&self) -> bool {
111        self.has_base_signature(X86CReg::SIGNATURE)
112    }
113
114    pub fn is_d_reg(&self) -> bool {
115        self.has_base_signature(X86DReg::SIGNATURE)
116    }
117
118    pub fn is_st(&self) -> bool {
119        self.has_base_signature(X86St::SIGNATURE)
120    }
121
122    pub fn is_bnd(&self) -> bool {
123        self.has_base_signature(X86Bnd::SIGNATURE)
124    }
125
126    pub fn is_tmm(&self) -> bool {
127        self.has_base_signature(X86Tmm::SIGNATURE)
128    }
129
130    pub fn is_rip(&self) -> bool {
131        self.has_base_signature(X86Rip::SIGNATURE)
132    }
133
134    pub fn set_reg_t<T: RegTraits>(&mut self, rid: u32) {
135        self.set_signature(T::SIGNATURE.into());
136        self.set_id(rid);
137    }
138
139    pub fn set_type_and_id(&mut self, typ: RegType, id: u32) {
140        self.set_signature(Self::signature_of(typ));
141        self.set_id(id);
142    }
143
144    pub fn group_of(typ: RegType) -> RegGroup {
145        ArchTraits::by_arch(Arch::X86).reg_type_to_group(typ)
146    }
147
148    pub const fn type_id_of(typ: RegType) -> TypeId {
149        ArchTraits::by_arch(Arch::X86).reg_type_to_type_id(typ)
150    }
151
152    pub const fn group_of_t<T: RegTraits>() -> RegGroup {
153        T::GROUP
154    }
155
156    pub const fn type_id_of_t<T: RegTraits>() -> TypeId {
157        T::TYPE_ID
158    }
159
160    pub const fn signature_of_vec_by_type(typ: TypeId) -> OperandSignature {
161        let typ = typ as u32;
162
163        if typ <= TypeId::VEC128_END {
164            OperandSignature::new(X86Xmm::SIGNATURE)
165        } else if typ <= TypeId::VEC256_END {
166            OperandSignature::new(X86Ymm::SIGNATURE)
167        } else {
168            OperandSignature::new(X86Zmm::SIGNATURE)
169        }
170    }
171
172    pub const fn signature_of_vec_by_size(size: u32) -> OperandSignature {
173        if size <= 16 {
174            OperandSignature::new(X86Xmm::SIGNATURE)
175        } else if size <= 32 {
176            OperandSignature::new(X86Ymm::SIGNATURE)
177        } else {
178            OperandSignature::new(X86Zmm::SIGNATURE)
179        }
180    }
181
182    pub fn operand_is_gpb(op: &Operand) -> bool {
183        op.signature.subset(
184            OperandSignature::OP_TYPE_MASK
185                | OperandSignature::REG_GROUP_MASK
186                | OperandSignature::SIZE_MASK,
187        ) == (OperandSignature::from_op_type(OperandType::Reg)
188            | OperandSignature::from_reg_group(RegGroup::Gp)
189            | OperandSignature::from_size(1))
190    }
191
192    pub fn operand_is_gpb_lo(op: &Operand) -> bool {
193        op.as_::<Self>().is_gpb_lo()
194    }
195    pub fn operand_is_gpb_hi(op: &Operand) -> bool {
196        op.as_::<Self>().is_gpb_hi()
197    }
198    pub fn operand_is_gpw(op: &Operand) -> bool {
199        op.as_::<Self>().is_gpw()
200    }
201    pub fn operand_is_gpd(op: &Operand) -> bool {
202        op.as_::<Self>().is_gpd()
203    }
204    pub fn operand_is_gpq(op: &Operand) -> bool {
205        op.as_::<Self>().is_gpq()
206    }
207    pub fn operand_is_xmm(op: &Operand) -> bool {
208        op.as_::<Self>().is_xmm()
209    }
210    pub fn operand_is_ymm(op: &Operand) -> bool {
211        op.as_::<Self>().is_ymm()
212    }
213    pub fn operand_is_zmm(op: &Operand) -> bool {
214        op.as_::<Self>().is_zmm()
215    }
216    pub fn operand_is_mm(op: &Operand) -> bool {
217        op.as_::<Self>().is_mm()
218    }
219    pub fn operand_is_k_reg(op: &Operand) -> bool {
220        op.as_::<Self>().is_k_reg()
221    }
222    pub fn operand_is_s_reg(op: &Operand) -> bool {
223        op.as_::<Self>().is_s_reg()
224    }
225    pub fn operand_is_c_reg(op: &Operand) -> bool {
226        op.as_::<Self>().is_c_reg()
227    }
228    pub fn operand_is_d_reg(op: &Operand) -> bool {
229        op.as_::<Self>().is_d_reg()
230    }
231    pub fn operand_is_st(op: &Operand) -> bool {
232        op.as_::<Self>().is_st()
233    }
234    pub fn operand_is_bnd(op: &Operand) -> bool {
235        op.as_::<Self>().is_bnd()
236    }
237    pub fn operand_is_tmm(op: &Operand) -> bool {
238        op.as_::<Self>().is_tmm()
239    }
240    pub fn operand_is_rip(op: &Operand) -> bool {
241        op.as_::<Self>().is_rip()
242    }
243
244    pub fn operand_is_gpb_with_id(op: &Operand, rid: u32) -> bool {
245        (Self::operand_is_gpb(op) as u32 & (op.id() == rid) as u32) != 0
246    }
247    pub fn operand_is_gpb_lo_with_id(op: &Operand, rid: u32) -> bool {
248        (Self::operand_is_gpb_lo(op) as u32 & (op.id() == rid) as u32) != 0
249    }
250    pub fn operand_is_gpb_hi_with_id(op: &Operand, rid: u32) -> bool {
251        (Self::operand_is_gpb_hi(op) as u32 & (op.id() == rid) as u32) != 0
252    }
253    pub fn operand_is_gpw_with_id(op: &Operand, rid: u32) -> bool {
254        (Self::operand_is_gpw(op) as u32 & (op.id() == rid) as u32) != 0
255    }
256    pub fn operand_is_gpd_with_id(op: &Operand, rid: u32) -> bool {
257        (Self::operand_is_gpd(op) as u32 & (op.id() == rid) as u32) != 0
258    }
259    pub fn operand_is_gpq_with_id(op: &Operand, rid: u32) -> bool {
260        (Self::operand_is_gpq(op) as u32 & (op.id() == rid) as u32) != 0
261    }
262    pub fn operand_is_xmm_with_id(op: &Operand, rid: u32) -> bool {
263        (Self::operand_is_xmm(op) as u32 & (op.id() == rid) as u32) != 0
264    }
265    pub fn operand_is_ymm_with_id(op: &Operand, rid: u32) -> bool {
266        (Self::operand_is_ymm(op) as u32 & (op.id() == rid) as u32) != 0
267    }
268    pub fn operand_is_zmm_with_id(op: &Operand, rid: u32) -> bool {
269        (Self::operand_is_zmm(op) as u32 & (op.id() == rid) as u32) != 0
270    }
271    pub fn operand_is_mm_with_id(op: &Operand, rid: u32) -> bool {
272        (Self::operand_is_mm(op) as u32 & (op.id() == rid) as u32) != 0
273    }
274    pub fn operand_is_k_reg_with_id(op: &Operand, rid: u32) -> bool {
275        (Self::operand_is_k_reg(op) as u32 & (op.id() == rid) as u32) != 0
276    }
277    pub fn operand_is_s_reg_with_id(op: &Operand, rid: u32) -> bool {
278        (Self::operand_is_s_reg(op) as u32 & (op.id() == rid) as u32) != 0
279    }
280    pub fn operand_is_c_reg_with_id(op: &Operand, rid: u32) -> bool {
281        (Self::operand_is_c_reg(op) as u32 & (op.id() == rid) as u32) != 0
282    }
283    pub fn operand_is_d_reg_with_id(op: &Operand, rid: u32) -> bool {
284        (Self::operand_is_d_reg(op) as u32 & (op.id() == rid) as u32) != 0
285    }
286    pub fn operand_is_st_with_id(op: &Operand, rid: u32) -> bool {
287        (Self::operand_is_st(op) as u32 & (op.id() == rid) as u32) != 0
288    }
289    pub fn operand_is_bnd_with_id(op: &Operand, rid: u32) -> bool {
290        (Self::operand_is_bnd(op) as u32 & (op.id() == rid) as u32) != 0
291    }
292    pub fn operand_is_tmm_with_id(op: &Operand, rid: u32) -> bool {
293        (Self::operand_is_tmm(op) as u32 & (op.id() == rid) as u32) != 0
294    }
295    pub fn operand_is_rip_with_id(op: &Operand, rid: u32) -> bool {
296        (Self::operand_is_rip(op) as u32 & (op.id() == rid) as u32) != 0
297    }
298
299    pub const SIGNATURE: u32 = BaseReg::SIGNATURE;
300}
301
302#[derive(Deref, DerefMut, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
303pub struct Gp(pub Reg);
304
305define_abstract_reg!(Gp, Reg);
306
307impl Gp {
308    pub const fn signature_of(typ: RegType) -> OperandSignature {
309        ArchTraits::by_arch(Arch::X86).reg_type_to_signature(typ)
310    }
311
312    pub const AX: u32 = 0;
313    pub const CX: u32 = 1;
314    pub const DX: u32 = 2;
315    pub const BX: u32 = 3;
316    pub const SP: u32 = 4;
317    pub const BP: u32 = 5;
318    pub const SI: u32 = 6;
319    pub const DI: u32 = 7;
320    pub const R8: u32 = 8;
321    pub const R9: u32 = 9;
322    pub const R10: u32 = 10;
323    pub const R11: u32 = 11;
324    pub const R12: u32 = 12;
325    pub const R13: u32 = 13;
326    pub const R14: u32 = 14;
327    pub const R15: u32 = 15;
328
329    pub const SIGNATURE: u32 = Reg::SIGNATURE;
330}
331
332#[derive(Deref, DerefMut, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
333pub struct Vec(pub Reg);
334
335define_abstract_reg!(Vec, Reg);
336
337impl Vec {
338    pub const fn signature_of(typ: RegType) -> OperandSignature {
339        ArchTraits::by_arch(Arch::X86).reg_type_to_signature(typ)
340    }
341
342    pub const SIGNATURE: u32 = Reg::SIGNATURE;
343}
344
345#[derive(Deref, DerefMut, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
346pub struct SReg(pub Reg);
347
348impl SReg {
349    pub const fn signature_of(typ: RegType) -> OperandSignature {
350        ArchTraits::by_arch(Arch::X86).reg_type_to_signature(typ)
351    }
352
353    pub const ES: u32 = 1;
354    pub const CS: u32 = 2;
355    pub const SS: u32 = 3;
356    pub const DS: u32 = 4;
357    pub const FS: u32 = 5;
358    pub const GS: u32 = 6;
359}
360
361define_final_reg!(SReg, Reg, X86SReg);
362
363#[derive(Deref, DerefMut, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
364pub struct Gpb(pub Gp);
365
366define_abstract_reg!(Gpb, Gp);
367
368impl Gpb {
369    pub const fn signature_of(typ: RegType) -> OperandSignature {
370        ArchTraits::by_arch(Arch::X86).reg_type_to_signature(typ)
371    }
372
373    pub const SIGNATURE: u32 = Gp::SIGNATURE;
374}
375
376#[derive(Deref, DerefMut, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
377pub struct GpbLo(pub Gpb);
378
379impl GpbLo {
380    pub const fn signature_of(typ: RegType) -> OperandSignature {
381        ArchTraits::by_arch(Arch::X86).reg_type_to_signature(typ)
382    }
383}
384
385define_final_reg!(GpbLo, Gpb, X86GpbLo);
386
387#[derive(Deref, DerefMut, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
388pub struct GpbHi(pub Gpb);
389
390impl GpbHi {
391    pub const fn signature_of(typ: RegType) -> OperandSignature {
392        ArchTraits::by_arch(Arch::X86).reg_type_to_signature(typ)
393    }
394}
395
396define_final_reg!(GpbHi, Gpb, X86GpbHi);
397
398#[derive(Deref, DerefMut, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
399pub struct Gpw(pub Gp);
400
401impl Gpw {
402    pub const fn signature_of(typ: RegType) -> OperandSignature {
403        ArchTraits::by_arch(Arch::X86).reg_type_to_signature(typ)
404    }
405}
406
407define_final_reg!(Gpw, Gp, X86Gpw);
408
409#[derive(Deref, DerefMut, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
410pub struct Gpd(pub Gp);
411
412impl Gpd {
413    pub const fn signature_of(typ: RegType) -> OperandSignature {
414        ArchTraits::by_arch(Arch::X86).reg_type_to_signature(typ)
415    }
416}
417
418define_final_reg!(Gpd, Gp, X86Gpd);
419
420#[derive(Deref, DerefMut, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
421pub struct Gpq(pub Gp);
422
423impl Gpq {
424    pub const fn signature_of(typ: RegType) -> OperandSignature {
425        ArchTraits::by_arch(Arch::X86).reg_type_to_signature(typ)
426    }
427}
428
429define_final_reg!(Gpq, Gp, X86Gpq);
430
431#[derive(Deref, DerefMut, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
432pub struct Xmm(pub Vec);
433
434impl Xmm {
435    pub const fn signature_of(typ: RegType) -> OperandSignature {
436        ArchTraits::by_arch(Arch::X86).reg_type_to_signature(typ)
437    }
438
439    pub fn half(&self) -> Xmm {
440        Xmm::from_id(self.id())
441    }
442}
443
444define_final_reg!(Xmm, Vec, X86Xmm);
445
446#[derive(Deref, DerefMut, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
447pub struct Ymm(pub Vec);
448
449impl Ymm {
450    pub const fn signature_of(typ: RegType) -> OperandSignature {
451        ArchTraits::by_arch(Arch::X86).reg_type_to_signature(typ)
452    }
453
454    pub fn half(&self) -> Xmm {
455        Xmm::from_id(self.id())
456    }
457}
458
459define_final_reg!(Ymm, Vec, X86Ymm);
460
461#[derive(Deref, DerefMut, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
462pub struct Zmm(pub Vec);
463
464impl Zmm {
465    pub const fn signature_of(typ: RegType) -> OperandSignature {
466        ArchTraits::by_arch(Arch::X86).reg_type_to_signature(typ)
467    }
468
469    pub fn half(&self) -> Ymm {
470        Ymm::from_id(self.id())
471    }
472}
473
474define_final_reg!(Zmm, Vec, X86Zmm);
475
476#[derive(Deref, DerefMut, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
477pub struct Mm(pub Reg);
478
479impl Mm {
480    pub const fn signature_of(typ: RegType) -> OperandSignature {
481        ArchTraits::by_arch(Arch::X86).reg_type_to_signature(typ)
482    }
483}
484
485define_final_reg!(Mm, Reg, X86Mm);
486
487#[derive(Deref, DerefMut, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
488pub struct KReg(pub Reg);
489
490impl KReg {
491    pub const fn signature_of(typ: RegType) -> OperandSignature {
492        ArchTraits::by_arch(Arch::X86).reg_type_to_signature(typ)
493    }
494}
495
496define_final_reg!(KReg, Reg, X86KReg);
497
498#[derive(Deref, DerefMut, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
499pub struct CReg(pub Reg);
500
501impl CReg {
502    pub const fn signature_of(typ: RegType) -> OperandSignature {
503        ArchTraits::by_arch(Arch::X86).reg_type_to_signature(typ)
504    }
505}
506
507define_final_reg!(CReg, Reg, X86CReg);
508
509#[derive(Deref, DerefMut, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
510pub struct DReg(pub Reg);
511
512impl DReg {
513    pub const fn signature_of(typ: RegType) -> OperandSignature {
514        ArchTraits::by_arch(Arch::X86).reg_type_to_signature(typ)
515    }
516}
517
518define_final_reg!(DReg, Reg, X86DReg);
519
520#[derive(Deref, DerefMut, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
521pub struct St(pub Reg);
522
523impl St {
524    pub const fn signature_of(typ: RegType) -> OperandSignature {
525        ArchTraits::by_arch(Arch::X86).reg_type_to_signature(typ)
526    }
527}
528
529define_final_reg!(St, Reg, X86St);
530
531#[derive(Deref, DerefMut, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
532pub struct Bnd(pub Reg);
533
534impl Bnd {
535    pub const fn signature_of(typ: RegType) -> OperandSignature {
536        ArchTraits::by_arch(Arch::X86).reg_type_to_signature(typ)
537    }
538}
539
540define_final_reg!(Bnd, Reg, X86Bnd);
541
542#[derive(Deref, DerefMut, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
543pub struct Tmm(pub Reg);
544
545impl Tmm {
546    pub const fn signature_of(typ: RegType) -> OperandSignature {
547        ArchTraits::by_arch(Arch::X86).reg_type_to_signature(typ)
548    }
549}
550
551define_final_reg!(Tmm, Reg, X86Tmm);
552
553#[derive(Deref, DerefMut, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
554pub struct Rip(pub Reg);
555
556impl Rip {
557    pub const fn signature_of(typ: RegType) -> OperandSignature {
558        ArchTraits::by_arch(Arch::X86).reg_type_to_signature(typ)
559    }
560}
561
562define_final_reg!(Rip, Reg, X86Rip);
563
564impl Gp {
565    pub fn r8(&self) -> GpbLo {
566        GpbLo::from_id(self.id())
567    }
568
569    pub fn r8lo(&self) -> GpbLo {
570        GpbLo::from_id(self.id())
571    }
572
573    pub fn r8hi(&self) -> GpbHi {
574        GpbHi::from_id(self.id())
575    }
576
577    pub fn r16(&self) -> Gpw {
578        Gpw::from_id(self.id())
579    }
580
581    pub fn r32(&self) -> Gpd {
582        Gpd::from_id(self.id())
583    }
584
585    pub fn r64(&self) -> Gpq {
586        Gpq::from_id(self.id())
587    }
588}
589impl Vec {
590    pub fn xmm(&self) -> Xmm {
591        Xmm::from_id(self.id())
592    }
593
594    pub fn ymm(&self) -> Ymm {
595        Ymm::from_id(self.id())
596    }
597
598    pub fn zmm(&self) -> Zmm {
599        Zmm::from_id(self.id())
600    }
601
602    pub fn v128(&self) -> Xmm {
603        Xmm::from_id(self.id())
604    }
605
606    pub fn v256(&self) -> Ymm {
607        Ymm::from_id(self.id())
608    }
609
610    pub fn v512(&self) -> Zmm {
611        Zmm::from_id(self.id())
612    }
613}
614
615pub mod regs {
616    use super::*;
617    pub const fn gpb(id: u32) -> GpbLo {
618        GpbLo::from_id(id)
619    }
620
621    pub const fn gpb_lo(id: u32) -> GpbLo {
622        GpbLo::from_id(id)
623    }
624
625    pub const fn gpb_hi(id: u32) -> GpbHi {
626        GpbHi::from_id(id)
627    }
628
629    pub const fn gpw(id: u32) -> Gpw {
630        Gpw::from_id(id)
631    }
632
633    pub const fn gpd(id: u32) -> Gpd {
634        Gpd::from_id(id)
635    }
636
637    pub const fn gpq(id: u32) -> Gpq {
638        Gpq::from_id(id)
639    }
640
641    pub const fn xmm(id: u32) -> Xmm {
642        Xmm::from_id(id)
643    }
644
645    pub const fn ymm(id: u32) -> Ymm {
646        Ymm::from_id(id)
647    }
648
649    pub const fn zmm(id: u32) -> Zmm {
650        Zmm::from_id(id)
651    }
652
653    pub const fn mm(id: u32) -> Mm {
654        Mm::from_id(id)
655    }
656
657    pub const fn k(id: u32) -> KReg {
658        KReg::from_id(id)
659    }
660
661    pub const fn cr(id: u32) -> CReg {
662        CReg::from_id(id)
663    }
664
665    pub const fn dr(id: u32) -> DReg {
666        DReg::from_id(id)
667    }
668
669    pub const fn st(id: u32) -> St {
670        St::from_id(id)
671    }
672
673    pub const fn bnd(id: u32) -> Bnd {
674        Bnd::from_id(id)
675    }
676
677    pub const fn tmm(id: u32) -> Tmm {
678        Tmm::from_id(id)
679    }
680
681    pub const fn rip() -> Rip {
682        Rip::from_id(0x120)
683    }
684
685    pub const fn sreg(id: u32) -> SReg {
686        SReg::from_id(id)
687    }
688
689    pub const AL: GpbLo = gpb_lo(Gp::AX);
690    pub const CL: GpbLo = gpb_lo(Gp::CX);
691    pub const DL: GpbLo = gpb_lo(Gp::DX);
692    pub const BL: GpbLo = gpb_lo(Gp::BX);
693    pub const SPL: GpbLo = gpb_lo(Gp::SP);
694    pub const BPL: GpbLo = gpb_lo(Gp::BP);
695    pub const SIL: GpbLo = gpb_lo(Gp::SI);
696    pub const DIL: GpbLo = gpb_lo(Gp::DI);
697    pub const R8B: GpbLo = gpb_lo(Gp::R8);
698    pub const R9B: GpbLo = gpb_lo(Gp::R9);
699    pub const R10B: GpbLo = gpb_lo(Gp::R10);
700    pub const R11B: GpbLo = gpb_lo(Gp::R11);
701    pub const R12B: GpbLo = gpb_lo(Gp::R12);
702    pub const R13B: GpbLo = gpb_lo(Gp::R13);
703    pub const R14B: GpbLo = gpb_lo(Gp::R14);
704    pub const R15B: GpbLo = gpb_lo(Gp::R15);
705
706    pub const AH: GpbHi = gpb_hi(Gp::AX);
707    pub const CH: GpbHi = gpb_hi(Gp::CX);
708    pub const DH: GpbHi = gpb_hi(Gp::DX);
709    pub const BH: GpbHi = gpb_hi(Gp::BX);
710
711    pub const AX: Gpw = gpw(Gp::AX);
712    pub const CX: Gpw = gpw(Gp::CX);
713    pub const DX: Gpw = gpw(Gp::DX);
714    pub const BX: Gpw = gpw(Gp::BX);
715    pub const SP: Gpw = gpw(Gp::SP);
716    pub const BP: Gpw = gpw(Gp::BP);
717    pub const SI: Gpw = gpw(Gp::SI);
718    pub const DI: Gpw = gpw(Gp::DI);
719    pub const R8W: Gpw = gpw(Gp::R8);
720    pub const R9W: Gpw = gpw(Gp::R9);
721    pub const R10W: Gpw = gpw(Gp::R10);
722    pub const R11W: Gpw = gpw(Gp::R11);
723    pub const R12W: Gpw = gpw(Gp::R12);
724    pub const R13W: Gpw = gpw(Gp::R13);
725    pub const R14W: Gpw = gpw(Gp::R14);
726    pub const R15W: Gpw = gpw(Gp::R15);
727
728    pub const EAX: Gpd = gpd(Gp::AX);
729    pub const ECX: Gpd = gpd(Gp::CX);
730    pub const EDX: Gpd = gpd(Gp::DX);
731    pub const EBX: Gpd = gpd(Gp::BX);
732    pub const ESP: Gpd = gpd(Gp::SP);
733    pub const EBP: Gpd = gpd(Gp::BP);
734    pub const ESI: Gpd = gpd(Gp::SI);
735    pub const EDI: Gpd = gpd(Gp::DI);
736    pub const R8D: Gpd = gpd(Gp::R8);
737    pub const R9D: Gpd = gpd(Gp::R9);
738    pub const R10D: Gpd = gpd(Gp::R10);
739    pub const R11D: Gpd = gpd(Gp::R11);
740    pub const R12D: Gpd = gpd(Gp::R12);
741    pub const R13D: Gpd = gpd(Gp::R13);
742    pub const R14D: Gpd = gpd(Gp::R14);
743    pub const R15D: Gpd = gpd(Gp::R15);
744
745    pub const RAX: Gpq = gpq(Gp::AX);
746    pub const RCX: Gpq = gpq(Gp::CX);
747    pub const RDX: Gpq = gpq(Gp::DX);
748    pub const RBX: Gpq = gpq(Gp::BX);
749    pub const RSP: Gpq = gpq(Gp::SP);
750    pub const RBP: Gpq = gpq(Gp::BP);
751    pub const RSI: Gpq = gpq(Gp::SI);
752    pub const RDI: Gpq = gpq(Gp::DI);
753    pub const R8: Gpq = gpq(Gp::R8);
754    pub const R9: Gpq = gpq(Gp::R9);
755    pub const R10: Gpq = gpq(Gp::R10);
756    pub const R11: Gpq = gpq(Gp::R11);
757    pub const R12: Gpq = gpq(Gp::R12);
758    pub const R13: Gpq = gpq(Gp::R13);
759    pub const R14: Gpq = gpq(Gp::R14);
760    pub const R15: Gpq = gpq(Gp::R15);
761
762    pub const XMM0: Xmm = xmm(0);
763    pub const XMM1: Xmm = xmm(1);
764    pub const XMM2: Xmm = xmm(2);
765    pub const XMM3: Xmm = xmm(3);
766    pub const XMM4: Xmm = xmm(4);
767    pub const XMM5: Xmm = xmm(5);
768    pub const XMM6: Xmm = xmm(6);
769    pub const XMM7: Xmm = xmm(7);
770    pub const XMM8: Xmm = xmm(8);
771    pub const XMM9: Xmm = xmm(9);
772    pub const XMM10: Xmm = xmm(10);
773    pub const XMM11: Xmm = xmm(11);
774    pub const XMM12: Xmm = xmm(12);
775    pub const XMM13: Xmm = xmm(13);
776    pub const XMM14: Xmm = xmm(14);
777    pub const XMM15: Xmm = xmm(15);
778    pub const XMM16: Xmm = xmm(16);
779    pub const XMM17: Xmm = xmm(17);
780    pub const XMM18: Xmm = xmm(18);
781    pub const XMM19: Xmm = xmm(19);
782    pub const XMM20: Xmm = xmm(20);
783    pub const XMM21: Xmm = xmm(21);
784    pub const XMM22: Xmm = xmm(22);
785    pub const XMM23: Xmm = xmm(23);
786    pub const XMM24: Xmm = xmm(24);
787    pub const XMM25: Xmm = xmm(25);
788    pub const XMM26: Xmm = xmm(26);
789    pub const XMM27: Xmm = xmm(27);
790    pub const XMM28: Xmm = xmm(28);
791    pub const XMM29: Xmm = xmm(29);
792    pub const XMM30: Xmm = xmm(30);
793    pub const XMM31: Xmm = xmm(31);
794
795    pub const YMM0: Ymm = ymm(0);
796    pub const YMM1: Ymm = ymm(1);
797    pub const YMM2: Ymm = ymm(2);
798    pub const YMM3: Ymm = ymm(3);
799    pub const YMM4: Ymm = ymm(4);
800    pub const YMM5: Ymm = ymm(5);
801    pub const YMM6: Ymm = ymm(6);
802    pub const YMM7: Ymm = ymm(7);
803    pub const YMM8: Ymm = ymm(8);
804    pub const YMM9: Ymm = ymm(9);
805    pub const YMM10: Ymm = ymm(10);
806    pub const YMM11: Ymm = ymm(11);
807    pub const YMM12: Ymm = ymm(12);
808    pub const YMM13: Ymm = ymm(13);
809    pub const YMM14: Ymm = ymm(14);
810    pub const YMM15: Ymm = ymm(15);
811    pub const YMM16: Ymm = ymm(16);
812    pub const YMM17: Ymm = ymm(17);
813    pub const YMM18: Ymm = ymm(18);
814    pub const YMM19: Ymm = ymm(19);
815    pub const YMM20: Ymm = ymm(20);
816    pub const YMM21: Ymm = ymm(21);
817    pub const YMM22: Ymm = ymm(22);
818    pub const YMM23: Ymm = ymm(23);
819    pub const YMM24: Ymm = ymm(24);
820    pub const YMM25: Ymm = ymm(25);
821    pub const YMM26: Ymm = ymm(26);
822    pub const YMM27: Ymm = ymm(27);
823    pub const YMM28: Ymm = ymm(28);
824    pub const YMM29: Ymm = ymm(29);
825    pub const YMM30: Ymm = ymm(30);
826    pub const YMM31: Ymm = ymm(31);
827
828    pub const ZMM0: Zmm = zmm(0);
829    pub const ZMM1: Zmm = zmm(1);
830    pub const ZMM2: Zmm = zmm(2);
831    pub const ZMM3: Zmm = zmm(3);
832    pub const ZMM4: Zmm = zmm(4);
833    pub const ZMM5: Zmm = zmm(5);
834    pub const ZMM6: Zmm = zmm(6);
835    pub const ZMM7: Zmm = zmm(7);
836    pub const ZMM8: Zmm = zmm(8);
837    pub const ZMM9: Zmm = zmm(9);
838    pub const ZMM10: Zmm = zmm(10);
839    pub const ZMM11: Zmm = zmm(11);
840    pub const ZMM12: Zmm = zmm(12);
841    pub const ZMM13: Zmm = zmm(13);
842    pub const ZMM14: Zmm = zmm(14);
843    pub const ZMM15: Zmm = zmm(15);
844    pub const ZMM16: Zmm = zmm(16);
845    pub const ZMM17: Zmm = zmm(17);
846    pub const ZMM18: Zmm = zmm(18);
847    pub const ZMM19: Zmm = zmm(19);
848    pub const ZMM20: Zmm = zmm(20);
849    pub const ZMM21: Zmm = zmm(21);
850    pub const ZMM22: Zmm = zmm(22);
851    pub const ZMM23: Zmm = zmm(23);
852    pub const ZMM24: Zmm = zmm(24);
853    pub const ZMM25: Zmm = zmm(25);
854    pub const ZMM26: Zmm = zmm(26);
855    pub const ZMM27: Zmm = zmm(27);
856    pub const ZMM28: Zmm = zmm(28);
857    pub const ZMM29: Zmm = zmm(29);
858    pub const ZMM30: Zmm = zmm(30);
859    pub const ZMM31: Zmm = zmm(31);
860
861    pub const MM0: Mm = mm(0);
862    pub const MM1: Mm = mm(1);
863    pub const MM2: Mm = mm(2);
864    pub const MM3: Mm = mm(3);
865    pub const MM4: Mm = mm(4);
866    pub const MM5: Mm = mm(5);
867    pub const MM6: Mm = mm(6);
868    pub const MM7: Mm = mm(7);
869
870    pub const K0: KReg = k(0);
871    pub const K1: KReg = k(1);
872    pub const K2: KReg = k(2);
873    pub const K3: KReg = k(3);
874    pub const K4: KReg = k(4);
875    pub const K5: KReg = k(5);
876    pub const K6: KReg = k(6);
877    pub const K7: KReg = k(7);
878
879    pub const CR0: CReg = cr(0);
880    pub const CR2: CReg = cr(2);
881    pub const CR3: CReg = cr(3);
882    pub const CR4: CReg = cr(4);
883    pub const CR8: CReg = cr(8);
884
885    pub const DR0: DReg = dr(0);
886    pub const DR1: DReg = dr(1);
887    pub const DR2: DReg = dr(2);
888    pub const DR3: DReg = dr(3);
889    pub const DR6: DReg = dr(6);
890    pub const DR7: DReg = dr(7);
891
892    pub const ST0: St = st(0);
893    pub const ST1: St = st(1);
894    pub const ST2: St = st(2);
895    pub const ST3: St = st(3);
896    pub const ST4: St = st(4);
897    pub const ST5: St = st(5);
898    pub const ST6: St = st(6);
899    pub const ST7: St = st(7);
900
901    pub const BND0: Bnd = bnd(0);
902    pub const BND1: Bnd = bnd(1);
903    pub const BND2: Bnd = bnd(2);
904    pub const BND3: Bnd = bnd(3);
905
906    pub const TMM0: Tmm = tmm(0);
907    pub const TMM1: Tmm = tmm(1);
908    pub const TMM2: Tmm = tmm(2);
909    pub const TMM3: Tmm = tmm(3);
910    pub const TMM4: Tmm = tmm(4);
911    pub const TMM5: Tmm = tmm(5);
912    pub const TMM6: Tmm = tmm(6);
913    pub const TMM7: Tmm = tmm(7);
914
915    pub const RIP: Rip = rip();
916
917    pub const ES: SReg = sreg(SReg::ES);
918    pub const CS: SReg = sreg(SReg::CS);
919    pub const SS: SReg = sreg(SReg::SS);
920    pub const DS: SReg = sreg(SReg::DS);
921    pub const FS: SReg = sreg(SReg::FS);
922    pub const GS: SReg = sreg(SReg::GS);
923}
924pub use regs::*;
925
926#[derive(Deref, DerefMut, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
927pub struct Mem(pub BaseMem);
928
929define_operand_cast!(Mem, BaseMem);
930
931#[derive(Clone, Copy, PartialEq, Eq)]
932#[repr(u32)]
933pub enum AddrType {
934    Default = 0,
935    Abs = 1,
936    Rel = 2,
937}
938
939#[derive(Clone, Copy, PartialEq, Eq)]
940#[repr(u32)]
941pub enum Broadcast {
942    None = 0,
943    B1To2 = 1,
944    B1To4 = 2,
945    B1To8 = 3,
946    B1To16 = 4,
947    B1To32 = 5,
948    B1To64 = 6,
949}
950type Signature = OperandSignature;
951
952impl Mem {
953    pub const SIGNATURE_MEM_ADDR_TYPE_SHIFT: u32 = 14;
954    pub const SIGNATURE_MEM_ADDR_TYPE_MASK: u32 = 0x03 << Self::SIGNATURE_MEM_ADDR_TYPE_SHIFT;
955
956    pub const SIGNATURE_MEM_SHIFT_VALUE_SHIFT: u32 = 16;
957    pub const SIGNATURE_MEM_SHIFT_VALUE_MASK: u32 = 0x03 << Self::SIGNATURE_MEM_SHIFT_VALUE_SHIFT;
958
959    pub const SIGNATURE_MEM_SEGMENT_SHIFT: u32 = 18;
960    pub const SIGNATURE_MEM_SEGMENT_MASK: u32 = 0x07 << Self::SIGNATURE_MEM_SEGMENT_SHIFT;
961
962    pub const SIGNATURE_MEM_BROADCAST_SHIFT: u32 = 21;
963    pub const SIGNATURE_MEM_BROADCAST_MASK: u32 = 0x7 << Self::SIGNATURE_MEM_BROADCAST_SHIFT;
964
965    pub const fn new() -> Self {
966        Self(BaseMem::new())
967    }
968
969    pub fn base_reg(&self) -> Reg {
970        Reg::from_type_and_id(self.base_type(), self.base_id())
971    }
972
973    pub fn index_reg(&self) -> Reg {
974        Reg::from_type_and_id(self.index_type(), self.index_id())
975    }
976
977    pub fn set_index(&mut self, index: &BaseReg, shift: u32) {
978        self.0.set_index(index);
979        self.set_shift(shift);
980    }
981
982    pub fn has_size(&self) -> bool {
983        self.0.signature.has_field::<{ Signature::SIZE_MASK }>()
984    }
985
986    pub fn has_size_of(&self, s: u32) -> bool {
987        self.size() == s
988    }
989
990    pub fn size(&self) -> u32 {
991        self.0.signature.get_field::<{ Signature::SIZE_MASK }>()
992    }
993
994    pub fn set_size(&mut self, size: u32) {
995        self.0.signature.set_field::<{ Signature::SIZE_MASK }>(size);
996    }
997
998    pub fn addr_type(&self) -> AddrType {
999        unsafe {
1000            core::mem::transmute(
1001                self.0
1002                    .signature
1003                    .get_field::<{ Self::SIGNATURE_MEM_ADDR_TYPE_MASK }>(),
1004            )
1005        }
1006    }
1007
1008    pub fn set_addr_type(&mut self, addr_type: AddrType) {
1009        self.0
1010            .signature
1011            .set_field::<{ Self::SIGNATURE_MEM_ADDR_TYPE_MASK }>(addr_type as u32);
1012    }
1013
1014    pub fn reset_addr_type(&mut self) {
1015        self.set_addr_type(AddrType::Default);
1016    }
1017
1018    pub fn is_abs(&self) -> bool {
1019        self.addr_type() == AddrType::Abs
1020    }
1021
1022    pub fn set_abs(&mut self) {
1023        self.set_addr_type(AddrType::Abs);
1024    }
1025
1026    pub fn is_rel(&self) -> bool {
1027        self.addr_type() == AddrType::Rel
1028    }
1029
1030    pub fn set_rel(&mut self) {
1031        self.set_addr_type(AddrType::Rel);
1032    }
1033
1034    pub fn has_segment(&self) -> bool {
1035        self.0
1036            .signature
1037            .has_field::<{ Self::SIGNATURE_MEM_SEGMENT_MASK }>()
1038    }
1039
1040    pub fn segment(&self) -> SReg {
1041        SReg::from_id(self.segment_id())
1042    }
1043
1044    pub fn segment_id(&self) -> u32 {
1045        self.0
1046            .signature
1047            .get_field::<{ Self::SIGNATURE_MEM_SEGMENT_MASK }>()
1048    }
1049
1050    pub fn set_segment(&mut self, seg: SReg) {
1051        self.set_segment_id(seg.id());
1052    }
1053
1054    pub fn set_segment_id(&mut self, r_id: u32) {
1055        self.0
1056            .signature
1057            .set_field::<{ Self::SIGNATURE_MEM_SEGMENT_MASK }>(r_id);
1058    }
1059
1060    pub fn reset_segment(&mut self) {
1061        self.set_segment_id(0);
1062    }
1063
1064    pub fn has_shift(&self) -> bool {
1065        self.0
1066            .signature
1067            .has_field::<{ Self::SIGNATURE_MEM_SHIFT_VALUE_MASK }>()
1068    }
1069
1070    pub fn shift(&self) -> u32 {
1071        self.0
1072            .signature
1073            .get_field::<{ Self::SIGNATURE_MEM_SHIFT_VALUE_MASK }>()
1074    }
1075
1076    pub fn set_shift(&mut self, shift: u32) {
1077        self.0
1078            .signature
1079            .set_field::<{ Self::SIGNATURE_MEM_SHIFT_VALUE_MASK }>(shift);
1080    }
1081
1082    pub fn reset_shift(&mut self) {
1083        self.set_shift(0);
1084    }
1085
1086    pub fn has_broadcast(&self) -> bool {
1087        self.0
1088            .signature
1089            .has_field::<{ Self::SIGNATURE_MEM_BROADCAST_MASK }>()
1090    }
1091
1092    pub fn get_broadcast(&self) -> Broadcast {
1093        unsafe {
1094            core::mem::transmute(
1095                self.0
1096                    .signature
1097                    .get_field::<{ Self::SIGNATURE_MEM_BROADCAST_MASK }>(),
1098            )
1099        }
1100    }
1101
1102    pub fn set_broadcast(&mut self, b: Broadcast) {
1103        self.0
1104            .signature
1105            .set_field::<{ Self::SIGNATURE_MEM_BROADCAST_MASK }>(b as u32);
1106    }
1107
1108    pub fn reset_broadcast(&mut self) {
1109        self.set_broadcast(Broadcast::None);
1110    }
1111
1112    pub fn _1to1(&self) -> Self {
1113        self.clone_broadcasted(Broadcast::None)
1114    }
1115
1116    pub fn _1to2(&self) -> Self {
1117        self.clone_broadcasted(Broadcast::B1To2)
1118    }
1119
1120    pub fn _1to4(&self) -> Self {
1121        self.clone_broadcasted(Broadcast::B1To4)
1122    }
1123
1124    pub fn _1to8(&self) -> Self {
1125        self.clone_broadcasted(Broadcast::B1To8)
1126    }
1127
1128    pub fn _1to16(&self) -> Self {
1129        self.clone_broadcasted(Broadcast::B1To16)
1130    }
1131
1132    pub fn _1to32(&self) -> Self {
1133        self.clone_broadcasted(Broadcast::B1To32)
1134    }
1135
1136    pub fn _1to64(&self) -> Self {
1137        self.clone_broadcasted(Broadcast::B1To64)
1138    }
1139
1140    pub fn base_and_index_types(&self) -> u32 {
1141        self.signature
1142            .get_field::<{ OperandSignature::MEM_BASE_INDEX_MASK }>()
1143    }
1144
1145    pub fn clone_broadcasted(&self, bcst: Broadcast) -> Self {
1146        Self(BaseMem::from_base_and_index_disp(
1147            OperandSignature::new(
1148                self.0.signature.bits() & !Self::SIGNATURE_MEM_BROADCAST_MASK as u32,
1149            ) | OperandSignature::new((bcst as u32) << Self::SIGNATURE_MEM_BROADCAST_SHIFT),
1150            self.0.base_id(),
1151            self.0.data[0],
1152            self.0.data[1] as _,
1153        ))
1154    }
1155
1156    pub fn from_signature_base_and_index_id_disp(
1157        signature: OperandSignature,
1158        base_id: u32,
1159        index_id: u32,
1160        offset: i32,
1161    ) -> Self {
1162        Self(BaseMem::from_base_and_index_disp(
1163            signature, base_id, index_id, offset,
1164        ))
1165    }
1166
1167    pub fn from_sym_and_index_shift_disp(
1168        base: &Sym,
1169        index: &BaseReg,
1170        shift: u32,
1171        off: i32,
1172        size: u32,
1173        signature: OperandSignature,
1174    ) -> Self {
1175        Self(BaseMem::from_base_and_index_disp(
1176            Signature::from_op_type(OperandType::Mem)
1177                | Signature::from_mem_base_type(RegType::SymTag)
1178                | Signature::from_mem_index_type(index.typ())
1179                | Signature::from_value::<{ Self::SIGNATURE_MEM_SHIFT_VALUE_MASK }>(shift)
1180                | Signature::from_size(size)
1181                | signature,
1182            base.id(),
1183            index.id(),
1184            off,
1185        ))
1186    }
1187    pub fn from_label_and_index_shift_disp(
1188        base: &Label,
1189        index: &BaseReg,
1190        shift: u32,
1191        off: i32,
1192        size: u32,
1193        signature: OperandSignature,
1194    ) -> Self {
1195        Self(BaseMem::from_base_and_index_disp(
1196            Signature::from_op_type(OperandType::Mem)
1197                | Signature::from_mem_base_type(RegType::LabelTag)
1198                | Signature::from_mem_index_type(index.typ())
1199                | Signature::from_value::<{ Self::SIGNATURE_MEM_SHIFT_VALUE_MASK }>(shift)
1200                | Signature::from_size(size)
1201                | signature,
1202            base.id(),
1203            index.id(),
1204            off,
1205        ))
1206    }
1207
1208    pub fn from_label_and_disp(
1209        base: &Label,
1210        off: i32,
1211        size: u32,
1212        signature: OperandSignature,
1213    ) -> Self {
1214        Self(BaseMem::from_base_and_index_disp(
1215            Signature::from_op_type(OperandType::Mem)
1216                | Signature::from_mem_base_type(RegType::LabelTag)
1217                | Signature::from_size(size)
1218                | signature,
1219            base.id(),
1220            0,
1221            off,
1222        ))
1223    }
1224
1225    pub fn from_sym_and_disp(base: &Sym, off: i32, size: u32, signature: OperandSignature) -> Self {
1226        Self(BaseMem::from_base_and_index_disp(
1227            Signature::from_op_type(OperandType::Mem)
1228                | Signature::from_mem_base_type(RegType::SymTag)
1229                | Signature::from_size(size)
1230                | signature,
1231            base.id(),
1232            0,
1233            off,
1234        ))
1235    }
1236
1237    pub fn from_base_and_disp(
1238        base: &BaseReg,
1239        off: i32,
1240        size: u32,
1241        signature: OperandSignature,
1242    ) -> Self {
1243        Self(BaseMem::from_base_and_index_disp(
1244            Signature::from_op_type(OperandType::Mem)
1245                | Signature::from_mem_base_type(base.typ())
1246                | Signature::from_size(size)
1247                | signature,
1248            base.id(),
1249            0,
1250            off,
1251        ))
1252    }
1253
1254    pub fn from_base_and_index_shift_disp(
1255        base: &BaseReg,
1256        index: &BaseReg,
1257        shift: u32,
1258        off: i32,
1259        size: u32,
1260        signature: OperandSignature,
1261    ) -> Self {
1262        Self(BaseMem::from_base_and_index_disp(
1263            Signature::from_op_type(OperandType::Mem)
1264                | Signature::from_mem_base_type(base.typ())
1265                | Signature::from_mem_index_type(index.typ())
1266                | Signature::from_value::<{ Self::SIGNATURE_MEM_SHIFT_VALUE_MASK }>(shift)
1267                | Signature::from_size(size)
1268                | signature,
1269            base.id(),
1270            index.id(),
1271            off,
1272        ))
1273    }
1274
1275    pub fn from_u64_and_index_shift_disp(
1276        base: u64,
1277        index: &BaseReg,
1278        shift: u32,
1279        size: u32,
1280        signature: OperandSignature,
1281    ) -> Self {
1282        Self(BaseMem::from_base_and_index_disp(
1283            Signature::from_op_type(OperandType::Mem)
1284                | Signature::from_mem_index_type(index.typ())
1285                | Signature::from_value::<{ Self::SIGNATURE_MEM_SHIFT_VALUE_MASK }>(shift)
1286                | Signature::from_size(size)
1287                | signature,
1288            (base >> 32) as u32,
1289            index.id(),
1290            (base & 0xFFFFFFF) as _,
1291        ))
1292    }
1293
1294    pub fn from_u64(base: u64, size: u32, signature: OperandSignature) -> Self {
1295        Self(BaseMem::from_base_and_index_disp(
1296            Signature::from_op_type(OperandType::Mem) | Signature::from_size(size) | signature,
1297            (base >> 32) as u32,
1298            0,
1299            (base & 0xFFFFFFF) as _,
1300        ))
1301    }
1302}
1303
1304impl Add<i32> for Gpq {
1305    type Output = Mem;
1306    fn add(self, rhs: i32) -> Self::Output {
1307        ptr(self, rhs, 0)
1308    }
1309}
1310
1311impl Mul<i32> for Gpq {
1312    type Output = Mem;
1313
1314    fn mul(self, rhs: i32) -> Self::Output {
1315        let shift = match rhs {
1316            0 | 1 => 0,
1317            2 => 1,
1318            4 => 2,
1319            8 => 3,
1320            16 => 4,
1321            _ => todo!(),
1322        };
1323        ptr_index(RAX, self, shift, 0, 0)
1324    }
1325}
1326
1327impl<T: Deref<Target = Gp>> Mul<T> for Mem {
1328    type Output = Mem;
1329
1330    fn mul(self, rhs: T) -> Self::Output {
1331        let mut this = self;
1332        let reg = rhs.deref();
1333        this.set_index_id(reg.id());
1334        this.set_index_type(reg.typ());
1335
1336        this
1337    }
1338}
1339
1340impl Add<i32> for Label {
1341    type Output = Mem;
1342
1343    fn add(self, rhs: i32) -> Self::Output {
1344        label_ptr(self, rhs, 0)
1345    }
1346}
1347
1348impl Add<Mem> for Gpq {
1349    type Output = Mem;
1350
1351    fn add(self, mut rhs: Mem) -> Self::Output {
1352        rhs.set_base(&self);
1353        rhs
1354    }
1355}
1356
1357impl Add<i32> for Mem {
1358    type Output = Mem;
1359
1360    fn add(self, rhs: i32) -> Self::Output {
1361        let mut this = self;
1362        this.add_offset(rhs as _);
1363        this
1364    }
1365}
1366
1367macro_rules! mem_ptr {
1368    ($name: ident, $size: literal) => {
1369        paste::paste! {
1370            pub fn $name(base: impl Deref<Target = Gp>, offset: i32) -> Mem {
1371                Mem::from_base_and_disp(base.deref(), offset, $size, 0.into())
1372            }
1373
1374            pub fn [<$name _index>](base: impl Deref<Target = Gp>, index: impl Deref<Target = Gp>, shift: u32, offset: i32) -> Mem {
1375                Mem::from_base_and_index_shift_disp(base.deref(), index.deref(), shift, offset, $size, 0.into())
1376            }
1377
1378            pub fn [<$name _label>](base: Label, offset: i32) -> Mem {
1379                Mem::from_label_and_disp(&base, offset, $size, 0.into())
1380            }
1381
1382            pub fn [<$name _label_index>](base: Label, index: impl Deref<Target = Gp>, shift: u32, offset: i32) -> Mem {
1383                Mem::from_label_and_index_shift_disp(&base, index.deref(), shift, offset, $size, 0.into())
1384            }
1385
1386            pub fn [<$name _sym>](base: Sym, offset: i32) -> Mem {
1387                Mem::from_sym_and_disp(&base, offset, $size, 0.into())
1388            }
1389
1390            pub fn [<$name _sym_index>](base: Sym, index: impl Deref<Target = Gp>, shift: u32, offset: i32) -> Mem {
1391                Mem::from_sym_and_index_shift_disp(&base, index.deref(), shift, offset, $size, 0.into())
1392            }
1393
1394
1395            pub fn [<$name _rip>](offset: i32) -> Mem {
1396                Mem::from_base_and_disp(&RIP, offset, $size, 0.into())
1397            }
1398
1399            pub fn [<$name _u64>](base: u64) -> Mem {
1400                Mem::from_u64(base, $size, 0.into())
1401            }
1402
1403            pub fn [<$name _u64_index>](base: u64, index: impl Deref<Target = Gp>, shift: u32) -> Mem {
1404                Mem::from_u64_and_index_shift_disp(base, index.deref(), shift, $size, 0.into())
1405            }
1406
1407            pub fn [<$name _u64_abs>](base: u64) -> Mem {
1408                Mem::from_u64(base, $size, OperandSignature::from_value::<{ Mem::SIGNATURE_MEM_ADDR_TYPE_MASK }>(AddrType::Abs as _))
1409            }
1410
1411            pub fn [<$name _u64_index_abs>](base: u64, index: impl Deref<Target = Gp>, shift: u32) -> Mem {
1412                Mem::from_u64_and_index_shift_disp(base, index.deref(), shift, $size, OperandSignature::from_value::<{ Mem::SIGNATURE_MEM_ADDR_TYPE_MASK }>(AddrType::Abs as _))
1413            }
1414
1415            pub fn [<$name _u64_rel>](base: u64) -> Mem {
1416                Mem::from_u64(base, $size, OperandSignature::from_value::<{ Mem::SIGNATURE_MEM_ADDR_TYPE_MASK }>(AddrType::Rel as _))
1417            }
1418
1419            pub fn [<$name _u64_index_rel>](base: u64, index: impl Deref<Target = Gp>, shift: u32) -> Mem {
1420                Mem::from_u64_and_index_shift_disp(base, index.deref(), shift, $size, OperandSignature::from_value::<{ Mem::SIGNATURE_MEM_ADDR_TYPE_MASK }>(AddrType::Rel as _))
1421            }
1422        }
1423    }
1424}
1425mem_ptr!(ptr8, 1);
1426mem_ptr!(ptr16, 2);
1427mem_ptr!(ptr32, 4);
1428mem_ptr!(ptr48, 6);
1429mem_ptr!(ptr64, 8);
1430mem_ptr!(ptr80, 10);
1431mem_ptr!(ptr128, 16);
1432mem_ptr!(ptr256, 32);
1433mem_ptr!(ptr512, 64);
1434
1435mem_ptr!(byte_ptr, 1);
1436mem_ptr!(word_ptr, 2);
1437mem_ptr!(dword_ptr, 4);
1438mem_ptr!(fword_ptr, 6);
1439mem_ptr!(qword_ptr, 8);
1440mem_ptr!(tbyte_ptr, 10);
1441mem_ptr!(tword_ptr, 10);
1442mem_ptr!(oword_ptr, 16);
1443mem_ptr!(dqword_ptr, 16);
1444mem_ptr!(qqword_ptr, 32);
1445mem_ptr!(xmmword_ptr, 16);
1446mem_ptr!(ymmword_ptr, 32);
1447mem_ptr!(zmmword_ptr, 64);
1448
1449pub fn ptr(base: impl Deref<Target = Gp>, offset: i32, size: u32) -> Mem {
1450    Mem::from_base_and_disp(base.deref(), offset, size, 0.into())
1451}
1452
1453pub fn ptr_index(
1454    base: impl Deref<Target = Gp>,
1455    index: impl Deref<Target = Gp>,
1456    shift: u32,
1457    offset: i32,
1458    size: u32,
1459) -> Mem {
1460    Mem::from_base_and_index_shift_disp(base.deref(), index.deref(), shift, offset, size, 0.into())
1461}
1462
1463pub fn label_ptr(base: Label, offset: i32, size: u32) -> Mem {
1464    Mem::from_label_and_disp(&base, offset, size, 0.into())
1465}
1466pub fn label_ptr_index(
1467    base: Label,
1468    index: impl Deref<Target = Gp>,
1469    shift: u32,
1470    offset: i32,
1471    size: u32,
1472) -> Mem {
1473    Mem::from_label_and_index_shift_disp(&base, index.deref(), shift, offset, size, 0.into())
1474}
1475
1476pub fn sym_ptr(base: Sym, offset: i32, size: u32) -> Mem {
1477    Mem::from_sym_and_disp(&base, offset, size, 0.into())
1478}
1479pub fn sym_ptr_index(
1480    base: Sym,
1481    index: impl Deref<Target = Gp>,
1482    shift: u32,
1483    offset: i32,
1484    size: u32,
1485) -> Mem {
1486    Mem::from_sym_and_index_shift_disp(&base, index.deref(), shift, offset, size, 0.into())
1487}
1488
1489pub fn rip_rel(offset: i32, size: u32) -> Mem {
1490    Mem::from_base_and_disp(&RIP, offset, size, 0.into())
1491}
1492
1493pub fn u64_ptr(base: u64, size: u32) -> Mem {
1494    Mem::from_u64(base, size, 0.into())
1495}
1496
1497pub fn u64_ptr_index(base: u64, index: impl Deref<Target = Gp>, shift: u32, size: u32) -> Mem {
1498    Mem::from_u64_and_index_shift_disp(base, index.deref(), shift, size, 0.into())
1499}
1500
1501pub fn u64_ptr_abs(base: u64, size: u32) -> Mem {
1502    Mem::from_u64(
1503        base,
1504        size,
1505        OperandSignature::from_value::<{ Mem::SIGNATURE_MEM_ADDR_TYPE_MASK }>(AddrType::Abs as _),
1506    )
1507}
1508
1509pub fn u64_ptr_index_abs(base: u64, index: impl Deref<Target = Gp>, shift: u32, size: u32) -> Mem {
1510    Mem::from_u64_and_index_shift_disp(
1511        base,
1512        index.deref(),
1513        shift,
1514        size,
1515        OperandSignature::from_value::<{ Mem::SIGNATURE_MEM_ADDR_TYPE_MASK }>(AddrType::Abs as _),
1516    )
1517}