Skip to main content

asmkit/aarch64/
operands.rs

1//! AArch64 operands definition.
2use crate::{
3    core::{operand::*, types::TypeId},
4    define_abstract_reg, define_operand_cast,
5};
6
7use core::fmt;
8use derive_more::derive::{Deref, DerefMut};
9
10pub struct A64Gpw;
11impl RegTraits for A64Gpw {
12    const TYPE: RegType = RegType::Gp32;
13    const GROUP: RegGroup = RegGroup::Gp;
14    const SIZE: u32 = 4;
15    const TYPE_ID: TypeId = TypeId::Int32;
16}
17
18pub struct A64Gpx;
19impl RegTraits for A64Gpx {
20    const TYPE: RegType = RegType::Gp64;
21    const GROUP: RegGroup = RegGroup::Gp;
22    const SIZE: u32 = 8;
23    const TYPE_ID: TypeId = TypeId::Int64;
24}
25
26pub struct A64VecB;
27impl RegTraits for A64VecB {
28    const TYPE: RegType = RegType::Vec8;
29    const GROUP: RegGroup = RegGroup::Vec;
30    const SIZE: u32 = 1;
31    const TYPE_ID: TypeId = TypeId::Int8;
32}
33
34pub struct A64VecH;
35impl RegTraits for A64VecH {
36    const TYPE: RegType = RegType::Vec16;
37    const GROUP: RegGroup = RegGroup::Vec;
38    const SIZE: u32 = 2;
39    const TYPE_ID: TypeId = TypeId::Int16;
40}
41
42pub struct A64VecS;
43impl RegTraits for A64VecS {
44    const TYPE: RegType = RegType::Vec32;
45    const GROUP: RegGroup = RegGroup::Vec;
46    const SIZE: u32 = 4;
47    const TYPE_ID: TypeId = TypeId::Int32;
48}
49
50pub struct A64VecD;
51impl RegTraits for A64VecD {
52    const TYPE: RegType = RegType::Vec64;
53    const GROUP: RegGroup = RegGroup::Vec;
54    const SIZE: u32 = 8;
55    const TYPE_ID: TypeId = TypeId::Int64;
56}
57
58pub struct A64VecQ;
59impl RegTraits for A64VecQ {
60    const TYPE: RegType = RegType::Vec128;
61    const GROUP: RegGroup = RegGroup::Vec;
62    const SIZE: u32 = 16;
63    const TYPE_ID: TypeId = TypeId::Int32x4;
64}
65
66#[derive(Deref, DerefMut, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
67pub struct Reg(pub BaseReg);
68
69define_abstract_reg!(Reg, BaseReg);
70
71impl Reg {
72    pub const fn signature_of(typ: RegType) -> OperandSignature {
73        match typ {
74            RegType::Gp32 => OperandSignature::new(A64Gpw::SIGNATURE),
75            RegType::Gp64 => OperandSignature::new(A64Gpx::SIGNATURE),
76            RegType::Vec8 => OperandSignature::new(A64VecB::SIGNATURE),
77            RegType::Vec16 => OperandSignature::new(A64VecH::SIGNATURE),
78            RegType::Vec32 => OperandSignature::new(A64VecS::SIGNATURE),
79            RegType::Vec64 => OperandSignature::new(A64VecD::SIGNATURE),
80            RegType::Vec128 => OperandSignature::new(A64VecQ::SIGNATURE),
81            _ => OperandSignature::new(0),
82        }
83    }
84
85    pub fn is_gp(&self) -> bool {
86        self.is_group(RegGroup::Gp)
87    }
88
89    pub fn is_gp32(&self) -> bool {
90        self.has_base_signature(A64Gpw::SIGNATURE)
91    }
92
93    pub fn is_gp64(&self) -> bool {
94        self.has_base_signature(A64Gpx::SIGNATURE)
95    }
96
97    pub fn is_vec(&self) -> bool {
98        self.is_group(RegGroup::Vec)
99    }
100
101    pub fn is_vec8(&self) -> bool {
102        self.has_base_signature(A64VecB::SIGNATURE)
103    }
104
105    pub fn is_vec16(&self) -> bool {
106        self.has_base_signature(A64VecH::SIGNATURE)
107    }
108
109    pub fn is_vec32(&self) -> bool {
110        self.has_base_signature(A64VecS::SIGNATURE)
111    }
112
113    pub fn is_vec64(&self) -> bool {
114        self.has_base_signature(A64VecD::SIGNATURE)
115    }
116
117    pub fn is_vec128(&self) -> bool {
118        self.has_base_signature(A64VecQ::SIGNATURE)
119    }
120
121    pub fn set_reg_t<T: RegTraits>(&mut self, rid: u32) {
122        self.set_signature(T::SIGNATURE.into());
123        self.set_id(rid);
124    }
125
126    pub fn set_type_and_id(&mut self, typ: RegType, id: u32) {
127        self.set_signature(Self::signature_of(typ));
128        self.set_id(id);
129    }
130
131    pub const fn group_of_t<T: RegTraits>() -> RegGroup {
132        T::GROUP
133    }
134
135    pub const fn type_id_of_t<T: RegTraits>() -> TypeId {
136        T::TYPE_ID
137    }
138
139    pub const SIGNATURE: u32 = BaseReg::SIGNATURE;
140}
141
142#[derive(Deref, DerefMut, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
143pub struct Gp(pub Reg);
144
145define_abstract_reg!(Gp, Reg);
146
147impl Gp {
148    pub const ID_OS: u32 = 18;
149    pub const ID_FP: u32 = 29;
150    pub const ID_LR: u32 = 30;
151    pub const ID_SP: u32 = 31;
152    pub const ID_ZR: u32 = 63;
153
154    pub const fn signature_of(typ: RegType) -> OperandSignature {
155        Reg::signature_of(typ)
156    }
157
158    pub const fn make_r32(reg_id: u32) -> Self {
159        Self(Reg::from_signature_and_id(
160            OperandSignature::new(A64Gpw::SIGNATURE),
161            reg_id,
162        ))
163    }
164
165    pub const fn make_r64(reg_id: u32) -> Self {
166        Self(Reg::from_signature_and_id(
167            OperandSignature::new(A64Gpx::SIGNATURE),
168            reg_id,
169        ))
170    }
171
172    pub const fn make_w(reg_id: u32) -> Self {
173        Self::make_r32(reg_id)
174    }
175
176    pub const fn make_x(reg_id: u32) -> Self {
177        Self::make_r64(reg_id)
178    }
179
180    pub fn is_zr(&self) -> bool {
181        self.id() == Self::ID_ZR
182    }
183
184    pub fn is_sp(&self) -> bool {
185        self.id() == Self::ID_SP
186    }
187
188    pub fn r32(&self) -> Self {
189        Self::make_r32(self.id())
190    }
191
192    pub fn r64(&self) -> Self {
193        Self::make_r64(self.id())
194    }
195
196    pub fn w(&self) -> Self {
197        self.r32()
198    }
199
200    pub fn x(&self) -> Self {
201        self.r64()
202    }
203
204    pub const SIGNATURE: u32 = Reg::SIGNATURE;
205}
206
207#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
208#[repr(u32)]
209pub enum VecElementType {
210    None = 0,
211    B = 1,
212    H = 2,
213    S = 3,
214    D = 4,
215    B4 = 5,
216    H2 = 6,
217}
218
219#[derive(Deref, DerefMut, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
220pub struct Vec(pub Reg);
221
222define_abstract_reg!(Vec, Reg);
223
224impl Vec {
225    pub const SIGNATURE_REG_ELEMENT_TYPE_SHIFT: u32 = 12;
226    pub const SIGNATURE_REG_ELEMENT_TYPE_MASK: u32 = 0x07 << Self::SIGNATURE_REG_ELEMENT_TYPE_SHIFT;
227
228    pub const SIGNATURE_REG_ELEMENT_FLAG_SHIFT: u32 = 15;
229    pub const SIGNATURE_REG_ELEMENT_FLAG_MASK: u32 = 0x01 << Self::SIGNATURE_REG_ELEMENT_FLAG_SHIFT;
230
231    pub const SIGNATURE_REG_ELEMENT_INDEX_SHIFT: u32 = 16;
232    pub const SIGNATURE_REG_ELEMENT_INDEX_MASK: u32 =
233        0x0F << Self::SIGNATURE_REG_ELEMENT_INDEX_SHIFT;
234
235    pub const SIGNATURE_ELEMENT_B: u32 =
236        (VecElementType::B as u32) << Self::SIGNATURE_REG_ELEMENT_TYPE_SHIFT;
237    pub const SIGNATURE_ELEMENT_H: u32 =
238        (VecElementType::H as u32) << Self::SIGNATURE_REG_ELEMENT_TYPE_SHIFT;
239    pub const SIGNATURE_ELEMENT_S: u32 =
240        (VecElementType::S as u32) << Self::SIGNATURE_REG_ELEMENT_TYPE_SHIFT;
241    pub const SIGNATURE_ELEMENT_D: u32 =
242        (VecElementType::D as u32) << Self::SIGNATURE_REG_ELEMENT_TYPE_SHIFT;
243    pub const SIGNATURE_ELEMENT_B4: u32 =
244        (VecElementType::B4 as u32) << Self::SIGNATURE_REG_ELEMENT_TYPE_SHIFT;
245    pub const SIGNATURE_ELEMENT_H2: u32 =
246        (VecElementType::H2 as u32) << Self::SIGNATURE_REG_ELEMENT_TYPE_SHIFT;
247
248    const fn make_element_access_signature(
249        element_type: VecElementType,
250        element_index: u32,
251    ) -> OperandSignature {
252        OperandSignature::new(
253            A64VecQ::SIGNATURE
254                | Self::SIGNATURE_REG_ELEMENT_FLAG_MASK
255                | ((element_type as u32) << Self::SIGNATURE_REG_ELEMENT_TYPE_SHIFT)
256                | (element_index << Self::SIGNATURE_REG_ELEMENT_INDEX_SHIFT),
257        )
258    }
259
260    pub const fn signature_of(typ: RegType) -> OperandSignature {
261        Reg::signature_of(typ)
262    }
263
264    pub const fn make_v8(reg_id: u32) -> Self {
265        Self(Reg::from_signature_and_id(
266            OperandSignature::new(A64VecB::SIGNATURE),
267            reg_id,
268        ))
269    }
270
271    pub const fn make_v16(reg_id: u32) -> Self {
272        Self(Reg::from_signature_and_id(
273            OperandSignature::new(A64VecH::SIGNATURE),
274            reg_id,
275        ))
276    }
277
278    pub const fn make_v32(reg_id: u32) -> Self {
279        Self(Reg::from_signature_and_id(
280            OperandSignature::new(A64VecS::SIGNATURE),
281            reg_id,
282        ))
283    }
284
285    pub const fn make_v64(reg_id: u32) -> Self {
286        Self(Reg::from_signature_and_id(
287            OperandSignature::new(A64VecD::SIGNATURE),
288            reg_id,
289        ))
290    }
291
292    pub const fn make_v128(reg_id: u32) -> Self {
293        Self(Reg::from_signature_and_id(
294            OperandSignature::new(A64VecQ::SIGNATURE),
295            reg_id,
296        ))
297    }
298
299    pub const fn make_b(reg_id: u32) -> Self {
300        Self::make_v8(reg_id)
301    }
302
303    pub const fn make_h(reg_id: u32) -> Self {
304        Self::make_v16(reg_id)
305    }
306
307    pub const fn make_s(reg_id: u32) -> Self {
308        Self::make_v32(reg_id)
309    }
310
311    pub const fn make_d(reg_id: u32) -> Self {
312        Self::make_v64(reg_id)
313    }
314
315    pub const fn make_q(reg_id: u32) -> Self {
316        Self::make_v128(reg_id)
317    }
318
319    pub const fn make_v32_with_element_type(element_type: VecElementType, reg_id: u32) -> Self {
320        Self(Reg::from_signature_and_id(
321            OperandSignature::new(
322                A64VecS::SIGNATURE
323                    | ((element_type as u32) << Self::SIGNATURE_REG_ELEMENT_TYPE_SHIFT),
324            ),
325            reg_id,
326        ))
327    }
328
329    pub const fn make_v64_with_element_type(element_type: VecElementType, reg_id: u32) -> Self {
330        Self(Reg::from_signature_and_id(
331            OperandSignature::new(
332                A64VecD::SIGNATURE
333                    | ((element_type as u32) << Self::SIGNATURE_REG_ELEMENT_TYPE_SHIFT),
334            ),
335            reg_id,
336        ))
337    }
338
339    pub const fn make_v128_with_element_type(element_type: VecElementType, reg_id: u32) -> Self {
340        Self(Reg::from_signature_and_id(
341            OperandSignature::new(
342                A64VecQ::SIGNATURE
343                    | ((element_type as u32) << Self::SIGNATURE_REG_ELEMENT_TYPE_SHIFT),
344            ),
345            reg_id,
346        ))
347    }
348
349    pub const fn make_v128_with_element_index(
350        element_type: VecElementType,
351        element_index: u32,
352        reg_id: u32,
353    ) -> Self {
354        Self(Reg::from_signature_and_id(
355            Self::make_element_access_signature(element_type, element_index),
356            reg_id,
357        ))
358    }
359
360    pub fn has_element_type_or_index(&self) -> bool {
361        self.0
362			.0
363			.0
364			.signature
365			.has_field::<{ Self::SIGNATURE_REG_ELEMENT_TYPE_MASK | Self::SIGNATURE_REG_ELEMENT_FLAG_MASK }>()
366    }
367
368    pub fn is_vec_b8(&self) -> bool {
369        self.0
370             .0
371             .0
372            .signature
373            .subset(REG_BASE_SIGNATURE_MASK | Self::SIGNATURE_REG_ELEMENT_TYPE_MASK)
374            == OperandSignature::new(A64VecD::SIGNATURE | Self::SIGNATURE_ELEMENT_B)
375    }
376
377    pub fn is_vec_h4(&self) -> bool {
378        self.0
379             .0
380             .0
381            .signature
382            .subset(REG_BASE_SIGNATURE_MASK | Self::SIGNATURE_REG_ELEMENT_TYPE_MASK)
383            == OperandSignature::new(A64VecD::SIGNATURE | Self::SIGNATURE_ELEMENT_H)
384    }
385
386    pub fn is_vec_s2(&self) -> bool {
387        self.0
388             .0
389             .0
390            .signature
391            .subset(REG_BASE_SIGNATURE_MASK | Self::SIGNATURE_REG_ELEMENT_TYPE_MASK)
392            == OperandSignature::new(A64VecD::SIGNATURE | Self::SIGNATURE_ELEMENT_S)
393    }
394
395    pub fn is_vec_d1(&self) -> bool {
396        self.0
397             .0
398             .0
399            .signature
400            .subset(REG_BASE_SIGNATURE_MASK | Self::SIGNATURE_REG_ELEMENT_TYPE_MASK)
401            == OperandSignature::new(A64VecD::SIGNATURE)
402    }
403
404    pub fn is_vec_b16(&self) -> bool {
405        self.0
406             .0
407             .0
408            .signature
409            .subset(REG_BASE_SIGNATURE_MASK | Self::SIGNATURE_REG_ELEMENT_TYPE_MASK)
410            == OperandSignature::new(A64VecQ::SIGNATURE | Self::SIGNATURE_ELEMENT_B)
411    }
412
413    pub fn is_vec_h8(&self) -> bool {
414        self.0
415             .0
416             .0
417            .signature
418            .subset(REG_BASE_SIGNATURE_MASK | Self::SIGNATURE_REG_ELEMENT_TYPE_MASK)
419            == OperandSignature::new(A64VecQ::SIGNATURE | Self::SIGNATURE_ELEMENT_H)
420    }
421
422    pub fn is_vec_s4(&self) -> bool {
423        self.0
424             .0
425             .0
426            .signature
427            .subset(REG_BASE_SIGNATURE_MASK | Self::SIGNATURE_REG_ELEMENT_TYPE_MASK)
428            == OperandSignature::new(A64VecQ::SIGNATURE | Self::SIGNATURE_ELEMENT_S)
429    }
430
431    pub fn is_vec_d2(&self) -> bool {
432        self.0
433             .0
434             .0
435            .signature
436            .subset(REG_BASE_SIGNATURE_MASK | Self::SIGNATURE_REG_ELEMENT_TYPE_MASK)
437            == OperandSignature::new(A64VecQ::SIGNATURE | Self::SIGNATURE_ELEMENT_D)
438    }
439
440    pub fn is_vec_b4x4(&self) -> bool {
441        self.0
442             .0
443             .0
444            .signature
445            .subset(REG_BASE_SIGNATURE_MASK | Self::SIGNATURE_REG_ELEMENT_TYPE_MASK)
446            == OperandSignature::new(A64VecQ::SIGNATURE | Self::SIGNATURE_ELEMENT_B4)
447    }
448
449    pub fn is_vec_h2x4(&self) -> bool {
450        self.0
451             .0
452             .0
453            .signature
454            .subset(REG_BASE_SIGNATURE_MASK | Self::SIGNATURE_REG_ELEMENT_TYPE_MASK)
455            == OperandSignature::new(A64VecQ::SIGNATURE | Self::SIGNATURE_ELEMENT_H2)
456    }
457
458    pub fn v8(&self) -> Self {
459        Self::make_v8(self.id())
460    }
461
462    pub fn v16(&self) -> Self {
463        Self::make_v16(self.id())
464    }
465
466    pub fn v32(&self) -> Self {
467        Self::make_v32(self.id())
468    }
469
470    pub fn v64(&self) -> Self {
471        Self::make_v64(self.id())
472    }
473
474    pub fn v128(&self) -> Self {
475        Self::make_v128(self.id())
476    }
477
478    pub fn b(&self) -> Self {
479        self.v8()
480    }
481
482    pub fn h(&self) -> Self {
483        self.v16()
484    }
485
486    pub fn s(&self) -> Self {
487        self.v32()
488    }
489
490    pub fn d(&self) -> Self {
491        self.v64()
492    }
493
494    pub fn q(&self) -> Self {
495        self.v128()
496    }
497
498    pub fn b_at(&self, element_index: u32) -> Self {
499        Self::make_v128_with_element_index(VecElementType::B, element_index, self.id())
500    }
501
502    pub fn h_at(&self, element_index: u32) -> Self {
503        Self::make_v128_with_element_index(VecElementType::H, element_index, self.id())
504    }
505
506    pub fn s_at(&self, element_index: u32) -> Self {
507        Self::make_v128_with_element_index(VecElementType::S, element_index, self.id())
508    }
509
510    pub fn d_at(&self, element_index: u32) -> Self {
511        Self::make_v128_with_element_index(VecElementType::D, element_index, self.id())
512    }
513
514    pub fn h2_at(&self, element_index: u32) -> Self {
515        Self::make_v128_with_element_index(VecElementType::H2, element_index, self.id())
516    }
517
518    pub fn b4_at(&self, element_index: u32) -> Self {
519        Self::make_v128_with_element_index(VecElementType::B4, element_index, self.id())
520    }
521
522    pub fn b8(&self) -> Self {
523        Self::make_v64_with_element_type(VecElementType::B, self.id())
524    }
525
526    pub fn b16(&self) -> Self {
527        Self::make_v128_with_element_type(VecElementType::B, self.id())
528    }
529
530    pub fn h2(&self) -> Self {
531        Self::make_v32_with_element_type(VecElementType::H, self.id())
532    }
533
534    pub fn h4(&self) -> Self {
535        Self::make_v64_with_element_type(VecElementType::H, self.id())
536    }
537
538    pub fn h8(&self) -> Self {
539        Self::make_v128_with_element_type(VecElementType::H, self.id())
540    }
541
542    pub fn s2(&self) -> Self {
543        Self::make_v64_with_element_type(VecElementType::S, self.id())
544    }
545
546    pub fn s4(&self) -> Self {
547        Self::make_v128_with_element_type(VecElementType::S, self.id())
548    }
549
550    pub fn d2(&self) -> Self {
551        Self::make_v128_with_element_type(VecElementType::D, self.id())
552    }
553
554    pub fn has_element_type(&self) -> bool {
555        self.0
556             .0
557             .0
558            .signature
559            .has_field::<{ Self::SIGNATURE_REG_ELEMENT_TYPE_MASK }>()
560    }
561
562    pub fn element_type(&self) -> VecElementType {
563        match self
564            .0
565             .0
566             .0
567            .signature
568            .get_field::<{ Self::SIGNATURE_REG_ELEMENT_TYPE_MASK }>()
569        {
570            1 => VecElementType::B,
571            2 => VecElementType::H,
572            3 => VecElementType::S,
573            4 => VecElementType::D,
574            5 => VecElementType::B4,
575            6 => VecElementType::H2,
576            _ => VecElementType::None,
577        }
578    }
579
580    pub fn set_element_type(&mut self, element_type: VecElementType) {
581        self.0
582             .0
583             .0
584            .signature
585            .set_field::<{ Self::SIGNATURE_REG_ELEMENT_TYPE_MASK }>(element_type as u32);
586    }
587
588    pub fn reset_element_type(&mut self) {
589        self.0
590             .0
591             .0
592            .signature
593            .set_field::<{ Self::SIGNATURE_REG_ELEMENT_TYPE_MASK }>(0);
594    }
595
596    pub fn has_element_index(&self) -> bool {
597        self.0
598             .0
599             .0
600            .signature
601            .has_field::<{ Self::SIGNATURE_REG_ELEMENT_FLAG_MASK }>()
602    }
603
604    pub fn element_index(&self) -> u32 {
605        self.0
606             .0
607             .0
608            .signature
609            .get_field::<{ Self::SIGNATURE_REG_ELEMENT_INDEX_MASK }>()
610    }
611
612    pub fn set_element_index(&mut self, element_index: u32) {
613        self.0 .0 .0.signature.bits |= Self::SIGNATURE_REG_ELEMENT_FLAG_MASK;
614        self.0
615             .0
616             .0
617            .signature
618            .set_field::<{ Self::SIGNATURE_REG_ELEMENT_INDEX_MASK }>(element_index);
619    }
620
621    pub fn reset_element_index(&mut self) {
622        self.0 .0 .0.signature.bits &=
623            !(Self::SIGNATURE_REG_ELEMENT_FLAG_MASK | Self::SIGNATURE_REG_ELEMENT_INDEX_MASK);
624    }
625
626    pub fn at(&self, element_index: u32) -> Self {
627        Self(Reg::from_signature_and_id(
628            OperandSignature::new(
629                (self.0 .0 .0.signature.bits & !Self::SIGNATURE_REG_ELEMENT_INDEX_MASK)
630                    | (element_index << Self::SIGNATURE_REG_ELEMENT_INDEX_SHIFT)
631                    | Self::SIGNATURE_REG_ELEMENT_FLAG_MASK,
632            ),
633            self.id(),
634        ))
635    }
636
637    pub const SIGNATURE: u32 = Reg::SIGNATURE;
638}
639
640#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
641#[repr(u32)]
642pub enum ShiftOp {
643    LSL = 0,
644    LSR = 1,
645    ASR = 2,
646    ROR = 3,
647    RRX = 4,
648    MSL = 5,
649    UXTB = 6,
650    UXTH = 7,
651    UXTW = 8,
652    UXTX = 9,
653    SXTB = 10,
654    SXTH = 11,
655    SXTW = 12,
656    SXTX = 13,
657}
658
659#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
660pub struct Shift {
661    op: ShiftOp,
662    value: u32,
663}
664
665impl Shift {
666    pub const fn new(op: ShiftOp, value: u32) -> Self {
667        Self { op, value }
668    }
669
670    pub const fn op(&self) -> ShiftOp {
671        self.op
672    }
673
674    pub const fn value(&self) -> u32 {
675        self.value
676    }
677}
678
679impl From<u32> for Shift {
680    fn from(value: u32) -> Self {
681        Self::new(ShiftOp::LSL, value)
682    }
683}
684
685#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
686#[repr(u32)]
687pub enum OffsetMode {
688    Fixed = 0,
689    PreIndex = 1,
690    PostIndex = 2,
691}
692
693#[derive(Deref, DerefMut, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
694pub struct Mem(pub BaseMem);
695
696define_operand_cast!(Mem, BaseMem);
697
698type Signature = OperandSignature;
699
700impl Mem {
701    pub const SIGNATURE_MEM_SHIFT_VALUE_SHIFT: u32 = 14;
702    pub const SIGNATURE_MEM_SHIFT_VALUE_MASK: u32 = 0x1F << Self::SIGNATURE_MEM_SHIFT_VALUE_SHIFT;
703
704    pub const SIGNATURE_MEM_SHIFT_OP_SHIFT: u32 = 20;
705    pub const SIGNATURE_MEM_SHIFT_OP_MASK: u32 = 0x0F << Self::SIGNATURE_MEM_SHIFT_OP_SHIFT;
706
707    pub const SIGNATURE_MEM_OFFSET_MODE_SHIFT: u32 = 24;
708    pub const SIGNATURE_MEM_OFFSET_MODE_MASK: u32 = 0x03 << Self::SIGNATURE_MEM_OFFSET_MODE_SHIFT;
709
710    pub const fn new() -> Self {
711        Self(BaseMem::new())
712    }
713
714    pub fn from_signature_base_and_index_id_disp(
715        signature: OperandSignature,
716        base_id: u32,
717        index_id: u32,
718        offset: i32,
719    ) -> Self {
720        Self(BaseMem::from_base_and_index_disp(
721            signature, base_id, index_id, offset,
722        ))
723    }
724
725    pub fn from_label_and_disp(base: &Label, off: i32, signature: OperandSignature) -> Self {
726        Self(BaseMem::from_base_and_index_disp(
727            Signature::from_op_type(OperandType::Mem)
728                | Signature::from_mem_base_type(RegType::LabelTag)
729                | signature,
730            base.id(),
731            0,
732            off,
733        ))
734    }
735
736    pub fn from_base_and_disp(base: &Reg, off: i32, signature: OperandSignature) -> Self {
737        Self(BaseMem::from_base_and_index_disp(
738            Signature::from_op_type(OperandType::Mem)
739                | Signature::from_mem_base_type(base.typ())
740                | signature,
741            base.id(),
742            0,
743            off,
744        ))
745    }
746
747    pub fn from_base_and_index(base: &Reg, index: &Reg, signature: OperandSignature) -> Self {
748        Self(BaseMem::from_base_and_index_disp(
749            Signature::from_op_type(OperandType::Mem)
750                | Signature::from_mem_base_type(base.typ())
751                | Signature::from_mem_index_type(index.typ())
752                | signature,
753            base.id(),
754            index.id(),
755            0,
756        ))
757    }
758
759    pub fn from_base_and_index_shift(
760        base: &Reg,
761        index: &Reg,
762        shift: impl Into<Shift>,
763        signature: OperandSignature,
764    ) -> Self {
765        let shift = shift.into();
766        Self(BaseMem::from_base_and_index_disp(
767            Signature::from_op_type(OperandType::Mem)
768                | Signature::from_mem_base_type(base.typ())
769                | Signature::from_mem_index_type(index.typ())
770                | Signature::from_value::<{ Self::SIGNATURE_MEM_SHIFT_OP_MASK }>(shift.op() as u32)
771                | Signature::from_value::<{ Self::SIGNATURE_MEM_SHIFT_VALUE_MASK }>(shift.value())
772                | signature,
773            base.id(),
774            index.id(),
775            0,
776        ))
777    }
778
779    pub fn from_u64(base: u64, signature: OperandSignature) -> Self {
780        Self(BaseMem::from_base_and_index_disp(
781            Signature::from_op_type(OperandType::Mem) | signature,
782            (base >> 32) as u32,
783            0,
784            (base & 0xFFFF_FFFF) as u32 as i32,
785        ))
786    }
787
788    pub fn clone_adjusted(&self, off: i64) -> Self {
789        let mut result = *self;
790        result.add_offset(off);
791        result
792    }
793
794    pub fn pre(&self) -> Self {
795        let mut result = *self;
796        result.set_offset_mode(OffsetMode::PreIndex);
797        result
798    }
799
800    pub fn pre_offset(&self, off: i64) -> Self {
801        let mut result = *self;
802        result.set_offset_mode(OffsetMode::PreIndex);
803        result.add_offset(off);
804        result
805    }
806
807    pub fn post(&self) -> Self {
808        let mut result = *self;
809        result.set_offset_mode(OffsetMode::PostIndex);
810        result
811    }
812
813    pub fn post_offset(&self, off: i64) -> Self {
814        let mut result = *self;
815        result.set_offset_mode(OffsetMode::PostIndex);
816        result.add_offset(off);
817        result
818    }
819
820    pub fn base_reg(&self) -> Reg {
821        Reg::from_type_and_id(self.base_type(), self.base_id())
822    }
823
824    pub fn index_reg(&self) -> Reg {
825        Reg::from_type_and_id(self.index_type(), self.index_id())
826    }
827
828    pub fn set_index(&mut self, index: Reg, shift: impl Into<Shift>) {
829        self.0.set_index(&index.0);
830        self.set_shift(shift);
831    }
832
833    pub fn offset_mode(&self) -> OffsetMode {
834        match self
835            .0
836            .signature
837            .get_field::<{ Self::SIGNATURE_MEM_OFFSET_MODE_MASK }>()
838        {
839            1 => OffsetMode::PreIndex,
840            2 => OffsetMode::PostIndex,
841            _ => OffsetMode::Fixed,
842        }
843    }
844
845    pub fn set_offset_mode(&mut self, mode: OffsetMode) {
846        self.0
847            .signature
848            .set_field::<{ Self::SIGNATURE_MEM_OFFSET_MODE_MASK }>(mode as u32);
849    }
850
851    pub fn reset_offset_mode(&mut self) {
852        self.set_offset_mode(OffsetMode::Fixed);
853    }
854
855    pub fn is_fixed_offset(&self) -> bool {
856        self.offset_mode() == OffsetMode::Fixed
857    }
858
859    pub fn is_pre_or_post(&self) -> bool {
860        self.offset_mode() != OffsetMode::Fixed
861    }
862
863    pub fn is_pre_index(&self) -> bool {
864        self.offset_mode() == OffsetMode::PreIndex
865    }
866
867    pub fn is_post_index(&self) -> bool {
868        self.offset_mode() == OffsetMode::PostIndex
869    }
870
871    pub fn make_pre_index(&mut self) {
872        self.set_offset_mode(OffsetMode::PreIndex);
873    }
874
875    pub fn make_post_index(&mut self) {
876        self.set_offset_mode(OffsetMode::PostIndex);
877    }
878
879    pub fn shift_op(&self) -> ShiftOp {
880        match self
881            .0
882            .signature
883            .get_field::<{ Self::SIGNATURE_MEM_SHIFT_OP_MASK }>()
884        {
885            1 => ShiftOp::LSR,
886            2 => ShiftOp::ASR,
887            3 => ShiftOp::ROR,
888            4 => ShiftOp::RRX,
889            5 => ShiftOp::MSL,
890            6 => ShiftOp::UXTB,
891            7 => ShiftOp::UXTH,
892            8 => ShiftOp::UXTW,
893            9 => ShiftOp::UXTX,
894            10 => ShiftOp::SXTB,
895            11 => ShiftOp::SXTH,
896            12 => ShiftOp::SXTW,
897            13 => ShiftOp::SXTX,
898            _ => ShiftOp::LSL,
899        }
900    }
901
902    pub fn set_shift_op(&mut self, op: ShiftOp) {
903        self.0
904            .signature
905            .set_field::<{ Self::SIGNATURE_MEM_SHIFT_OP_MASK }>(op as u32);
906    }
907
908    pub fn reset_shift_op(&mut self) {
909        self.set_shift_op(ShiftOp::LSL);
910    }
911
912    pub fn has_shift(&self) -> bool {
913        self.0
914            .signature
915            .has_field::<{ Self::SIGNATURE_MEM_SHIFT_VALUE_MASK }>()
916    }
917
918    pub fn shift(&self) -> u32 {
919        self.0
920            .signature
921            .get_field::<{ Self::SIGNATURE_MEM_SHIFT_VALUE_MASK }>()
922    }
923
924    pub fn set_shift(&mut self, shift: impl Into<Shift>) {
925        let shift = shift.into();
926        self.set_shift_op(shift.op());
927        self.0
928            .signature
929            .set_field::<{ Self::SIGNATURE_MEM_SHIFT_VALUE_MASK }>(shift.value());
930    }
931
932    pub fn reset_shift(&mut self) {
933        self.0
934            .signature
935            .set_field::<{ Self::SIGNATURE_MEM_SHIFT_VALUE_MASK }>(0);
936    }
937}
938
939pub mod regs {
940    use super::*;
941
942    pub const fn w(id: u32) -> Gp {
943        Gp::make_r32(id)
944    }
945
946    pub const fn gp32(id: u32) -> Gp {
947        Gp::make_r32(id)
948    }
949
950    pub const fn x(id: u32) -> Gp {
951        Gp::make_r64(id)
952    }
953
954    pub const fn gp64(id: u32) -> Gp {
955        Gp::make_r64(id)
956    }
957
958    pub const fn b(id: u32) -> Vec {
959        Vec::make_v8(id)
960    }
961
962    pub const fn h(id: u32) -> Vec {
963        Vec::make_v16(id)
964    }
965
966    pub const fn s(id: u32) -> Vec {
967        Vec::make_v32(id)
968    }
969
970    pub const fn d(id: u32) -> Vec {
971        Vec::make_v64(id)
972    }
973
974    pub const fn q(id: u32) -> Vec {
975        Vec::make_v128(id)
976    }
977
978    pub const fn v(id: u32) -> Vec {
979        Vec::make_v128(id)
980    }
981
982    macro_rules! define_reg_consts {
983		($ctor:ident, $ty:ty, { $($name:ident = $id:expr),* $(,)? }) => {
984			$(pub const $name: $ty = $ctor($id);)*
985		};
986	}
987
988    define_reg_consts!(w, Gp, {
989        w0 = 0, w1 = 1, w2 = 2, w3 = 3, w4 = 4, w5 = 5, w6 = 6, w7 = 7,
990        w8 = 8, w9 = 9, w10 = 10, w11 = 11, w12 = 12, w13 = 13, w14 = 14, w15 = 15,
991        w16 = 16, w17 = 17, w18 = 18, w19 = 19, w20 = 20, w21 = 21, w22 = 22, w23 = 23,
992        w24 = 24, w25 = 25, w26 = 26, w27 = 27, w28 = 28, w29 = 29, w30 = 30,
993        wzr = Gp::ID_ZR, wsp = Gp::ID_SP
994    });
995
996    define_reg_consts!(x, Gp, {
997        x0 = 0, x1 = 1, x2 = 2, x3 = 3, x4 = 4, x5 = 5, x6 = 6, x7 = 7,
998        x8 = 8, x9 = 9, x10 = 10, x11 = 11, x12 = 12, x13 = 13, x14 = 14, x15 = 15,
999        x16 = 16, x17 = 17, x18 = 18, x19 = 19, x20 = 20, x21 = 21, x22 = 22, x23 = 23,
1000        x24 = 24, x25 = 25, x26 = 26, x27 = 27, x28 = 28, x29 = 29, x30 = 30,
1001        xzr = Gp::ID_ZR, sp = Gp::ID_SP
1002    });
1003
1004    pub const wos: Gp = w(Gp::ID_OS);
1005    pub const wfp: Gp = w(Gp::ID_FP);
1006    pub const wlr: Gp = w(Gp::ID_LR);
1007    pub const os: Gp = x(Gp::ID_OS);
1008    pub const fp: Gp = x(Gp::ID_FP);
1009    pub const lr: Gp = x(Gp::ID_LR);
1010    pub const zr: Gp = x(Gp::ID_ZR);
1011
1012    define_reg_consts!(b, Vec, {
1013        b0 = 0, b1 = 1, b2 = 2, b3 = 3, b4 = 4, b5 = 5, b6 = 6, b7 = 7,
1014        b8 = 8, b9 = 9, b10 = 10, b11 = 11, b12 = 12, b13 = 13, b14 = 14, b15 = 15,
1015        b16 = 16, b17 = 17, b18 = 18, b19 = 19, b20 = 20, b21 = 21, b22 = 22, b23 = 23,
1016        b24 = 24, b25 = 25, b26 = 26, b27 = 27, b28 = 28, b29 = 29, b30 = 30, b31 = 31
1017    });
1018
1019    define_reg_consts!(h, Vec, {
1020        h0 = 0, h1 = 1, h2 = 2, h3 = 3, h4 = 4, h5 = 5, h6 = 6, h7 = 7,
1021        h8 = 8, h9 = 9, h10 = 10, h11 = 11, h12 = 12, h13 = 13, h14 = 14, h15 = 15,
1022        h16 = 16, h17 = 17, h18 = 18, h19 = 19, h20 = 20, h21 = 21, h22 = 22, h23 = 23,
1023        h24 = 24, h25 = 25, h26 = 26, h27 = 27, h28 = 28, h29 = 29, h30 = 30, h31 = 31
1024    });
1025
1026    define_reg_consts!(s, Vec, {
1027        s0 = 0, s1 = 1, s2 = 2, s3 = 3, s4 = 4, s5 = 5, s6 = 6, s7 = 7,
1028        s8 = 8, s9 = 9, s10 = 10, s11 = 11, s12 = 12, s13 = 13, s14 = 14, s15 = 15,
1029        s16 = 16, s17 = 17, s18 = 18, s19 = 19, s20 = 20, s21 = 21, s22 = 22, s23 = 23,
1030        s24 = 24, s25 = 25, s26 = 26, s27 = 27, s28 = 28, s29 = 29, s30 = 30, s31 = 31
1031    });
1032
1033    define_reg_consts!(d, Vec, {
1034        d0 = 0, d1 = 1, d2 = 2, d3 = 3, d4 = 4, d5 = 5, d6 = 6, d7 = 7,
1035        d8 = 8, d9 = 9, d10 = 10, d11 = 11, d12 = 12, d13 = 13, d14 = 14, d15 = 15,
1036        d16 = 16, d17 = 17, d18 = 18, d19 = 19, d20 = 20, d21 = 21, d22 = 22, d23 = 23,
1037        d24 = 24, d25 = 25, d26 = 26, d27 = 27, d28 = 28, d29 = 29, d30 = 30, d31 = 31
1038    });
1039
1040    define_reg_consts!(q, Vec, {
1041        q0 = 0, q1 = 1, q2 = 2, q3 = 3, q4 = 4, q5 = 5, q6 = 6, q7 = 7,
1042        q8 = 8, q9 = 9, q10 = 10, q11 = 11, q12 = 12, q13 = 13, q14 = 14, q15 = 15,
1043        q16 = 16, q17 = 17, q18 = 18, q19 = 19, q20 = 20, q21 = 21, q22 = 22, q23 = 23,
1044        q24 = 24, q25 = 25, q26 = 26, q27 = 27, q28 = 28, q29 = 29, q30 = 30, q31 = 31
1045    });
1046
1047    define_reg_consts!(v, Vec, {
1048        v0 = 0, v1 = 1, v2 = 2, v3 = 3, v4 = 4, v5 = 5, v6 = 6, v7 = 7,
1049        v8 = 8, v9 = 9, v10 = 10, v11 = 11, v12 = 12, v13 = 13, v14 = 14, v15 = 15,
1050        v16 = 16, v17 = 17, v18 = 18, v19 = 19, v20 = 20, v21 = 21, v22 = 22, v23 = 23,
1051        v24 = 24, v25 = 25, v26 = 26, v27 = 27, v28 = 28, v29 = 29, v30 = 30, v31 = 31
1052    });
1053}
1054
1055pub use regs::*;
1056
1057pub const fn lsl(value: u32) -> Shift {
1058    Shift::new(ShiftOp::LSL, value)
1059}
1060
1061pub const fn lsr(value: u32) -> Shift {
1062    Shift::new(ShiftOp::LSR, value)
1063}
1064
1065pub const fn asr(value: u32) -> Shift {
1066    Shift::new(ShiftOp::ASR, value)
1067}
1068
1069pub const fn ror(value: u32) -> Shift {
1070    Shift::new(ShiftOp::ROR, value)
1071}
1072
1073pub const fn rrx() -> Shift {
1074    Shift::new(ShiftOp::RRX, 0)
1075}
1076
1077pub const fn msl(value: u32) -> Shift {
1078    Shift::new(ShiftOp::MSL, value)
1079}
1080
1081pub const fn uxtb(value: u32) -> Shift {
1082    Shift::new(ShiftOp::UXTB, value)
1083}
1084
1085pub const fn uxth(value: u32) -> Shift {
1086    Shift::new(ShiftOp::UXTH, value)
1087}
1088
1089pub const fn uxtw(value: u32) -> Shift {
1090    Shift::new(ShiftOp::UXTW, value)
1091}
1092
1093pub const fn uxtx(value: u32) -> Shift {
1094    Shift::new(ShiftOp::UXTX, value)
1095}
1096
1097pub const fn sxtb(value: u32) -> Shift {
1098    Shift::new(ShiftOp::SXTB, value)
1099}
1100
1101pub const fn sxth(value: u32) -> Shift {
1102    Shift::new(ShiftOp::SXTH, value)
1103}
1104
1105pub const fn sxtw(value: u32) -> Shift {
1106    Shift::new(ShiftOp::SXTW, value)
1107}
1108
1109pub const fn sxtx(value: u32) -> Shift {
1110    Shift::new(ShiftOp::SXTX, value)
1111}
1112
1113pub fn ptr(base: Gp, offset: i32) -> Mem {
1114    Mem::from_base_and_disp(&base.0, offset, OperandSignature::new(0))
1115}
1116
1117pub fn ptr_pre(base: Gp, offset: i32) -> Mem {
1118    Mem::from_base_and_disp(
1119        &base.0,
1120        offset,
1121        OperandSignature::from_value::<{ Mem::SIGNATURE_MEM_OFFSET_MODE_MASK }>(
1122            OffsetMode::PreIndex as u32,
1123        ),
1124    )
1125}
1126
1127pub fn ptr_post(base: Gp, offset: i32) -> Mem {
1128    Mem::from_base_and_disp(
1129        &base.0,
1130        offset,
1131        OperandSignature::from_value::<{ Mem::SIGNATURE_MEM_OFFSET_MODE_MASK }>(
1132            OffsetMode::PostIndex as u32,
1133        ),
1134    )
1135}
1136
1137pub fn ptr_reg(base: Gp, index: Gp) -> Mem {
1138    Mem::from_base_and_index(&base.0, &index.0, OperandSignature::new(0))
1139}
1140
1141pub fn ptr_reg_pre(base: Gp, index: Gp) -> Mem {
1142    Mem::from_base_and_index(
1143        &base.0,
1144        &index.0,
1145        OperandSignature::from_value::<{ Mem::SIGNATURE_MEM_OFFSET_MODE_MASK }>(
1146            OffsetMode::PreIndex as u32,
1147        ),
1148    )
1149}
1150
1151pub fn ptr_reg_post(base: Gp, index: Gp) -> Mem {
1152    Mem::from_base_and_index(
1153        &base.0,
1154        &index.0,
1155        OperandSignature::from_value::<{ Mem::SIGNATURE_MEM_OFFSET_MODE_MASK }>(
1156            OffsetMode::PostIndex as u32,
1157        ),
1158    )
1159}
1160
1161pub fn ptr_shift(base: Gp, index: Gp, shift: impl Into<Shift>) -> Mem {
1162    Mem::from_base_and_index_shift(&base.0, &index.0, shift, OperandSignature::new(0))
1163}
1164
1165pub fn label_ptr(base: Label, offset: i32) -> Mem {
1166    Mem::from_label_and_disp(&base, offset, OperandSignature::new(0))
1167}
1168
1169pub fn abs_ptr(base: u64) -> Mem {
1170    Mem::from_u64(base, OperandSignature::new(0))
1171}
1172
1173impl fmt::Display for Reg {
1174    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1175        if !self.is_valid() {
1176            return write!(f, "reg_invalid");
1177        }
1178
1179        if self.is_gp32() || self.is_gp64() {
1180            write!(f, "{}", Gp::from_type_and_id(self.typ(), self.id()))
1181        } else if self.is_vec() {
1182            write!(f, "{}", Vec::from_type_and_id(self.typ(), self.id()))
1183        } else {
1184            write!(f, "reg{}", self.id())
1185        }
1186    }
1187}
1188
1189impl fmt::Display for Gp {
1190    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1191        if !self.is_valid() {
1192            return write!(f, "gp_invalid");
1193        }
1194
1195        if self.is_gp32() {
1196            match self.id() {
1197                Self::ID_SP => write!(f, "wsp"),
1198                Self::ID_ZR => write!(f, "wzr"),
1199                id => write!(f, "w{}", id),
1200            }
1201        } else {
1202            match self.id() {
1203                Self::ID_SP => write!(f, "sp"),
1204                Self::ID_ZR => write!(f, "xzr"),
1205                id => write!(f, "x{}", id),
1206            }
1207        }
1208    }
1209}
1210
1211impl fmt::Display for Vec {
1212    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1213        if !self.is_valid() {
1214            return write!(f, "vec_invalid");
1215        }
1216
1217        if self.has_element_index() {
1218            let suffix = match self.element_type() {
1219                VecElementType::B => "b",
1220                VecElementType::H => "h",
1221                VecElementType::S => "s",
1222                VecElementType::D => "d",
1223                VecElementType::B4 => "b4",
1224                VecElementType::H2 => "h2",
1225                VecElementType::None => "",
1226            };
1227            if suffix.is_empty() {
1228                write!(f, "v{}[{}]", self.id(), self.element_index())
1229            } else {
1230                write!(f, "v{}.{}[{}]", self.id(), suffix, self.element_index())
1231            }
1232        } else if self.has_element_type() {
1233            let suffix = match (self.typ(), self.element_type()) {
1234                (RegType::Vec32, VecElementType::H) => "2h",
1235                (RegType::Vec64, VecElementType::B) => "8b",
1236                (RegType::Vec64, VecElementType::H) => "4h",
1237                (RegType::Vec64, VecElementType::S) => "2s",
1238                (RegType::Vec64, VecElementType::D) | (RegType::Vec64, VecElementType::None) => {
1239                    "1d"
1240                }
1241                (RegType::Vec128, VecElementType::B) => "16b",
1242                (RegType::Vec128, VecElementType::H) => "8h",
1243                (RegType::Vec128, VecElementType::S) => "4s",
1244                (RegType::Vec128, VecElementType::D) => "2d",
1245                (RegType::Vec128, VecElementType::B4) => "4b",
1246                (RegType::Vec128, VecElementType::H2) => "2h",
1247                _ => "",
1248            };
1249
1250            if suffix.is_empty() {
1251                write!(f, "v{}", self.id())
1252            } else {
1253                write!(f, "v{}.{}", self.id(), suffix)
1254            }
1255        } else {
1256            match self.typ() {
1257                RegType::Vec8 => write!(f, "b{}", self.id()),
1258                RegType::Vec16 => write!(f, "h{}", self.id()),
1259                RegType::Vec32 => write!(f, "s{}", self.id()),
1260                RegType::Vec64 => write!(f, "d{}", self.id()),
1261                RegType::Vec128 => write!(f, "v{}", self.id()),
1262                _ => write!(f, "vec{}", self.id()),
1263            }
1264        }
1265    }
1266}
1267
1268impl fmt::Display for Shift {
1269    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1270        let op = match self.op() {
1271            ShiftOp::LSL => "lsl",
1272            ShiftOp::LSR => "lsr",
1273            ShiftOp::ASR => "asr",
1274            ShiftOp::ROR => "ror",
1275            ShiftOp::RRX => "rrx",
1276            ShiftOp::MSL => "msl",
1277            ShiftOp::UXTB => "uxtb",
1278            ShiftOp::UXTH => "uxth",
1279            ShiftOp::UXTW => "uxtw",
1280            ShiftOp::UXTX => "uxtx",
1281            ShiftOp::SXTB => "sxtb",
1282            ShiftOp::SXTH => "sxth",
1283            ShiftOp::SXTW => "sxtw",
1284            ShiftOp::SXTX => "sxtx",
1285        };
1286
1287        if matches!(self.op(), ShiftOp::RRX) {
1288            write!(f, "{}", op)
1289        } else {
1290            write!(f, "{} #{}", op, self.value())
1291        }
1292    }
1293}
1294
1295impl fmt::Display for OffsetMode {
1296    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1297        match self {
1298            OffsetMode::Fixed => write!(f, "fixed"),
1299            OffsetMode::PreIndex => write!(f, "pre-index"),
1300            OffsetMode::PostIndex => write!(f, "post-index"),
1301        }
1302    }
1303}
1304
1305impl fmt::Display for Mem {
1306    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1307        if !self.has_base() && !self.has_index() {
1308            let addr = ((self.base_id() as u64) << 32) | (self.offset() as u32 as u64);
1309            return write!(f, "[0x{addr:x}]");
1310        }
1311
1312        let has_offset = self.has_offset() && self.offset() != 0;
1313        let has_index = self.has_index() && self.has_index_reg();
1314
1315        match self.offset_mode() {
1316            OffsetMode::PostIndex => {
1317                write!(f, "[")?;
1318                if self.has_base_label() {
1319                    write!(f, "label{}", self.base_id())?;
1320                } else {
1321                    write!(f, "{}", self.base_reg())?;
1322                }
1323                write!(f, "]")?;
1324
1325                if has_index {
1326                    write!(f, ", {}", self.index_reg())?;
1327                    if self.has_shift() {
1328                        write!(f, ", {}", Shift::new(self.shift_op(), self.shift()))?;
1329                    }
1330                } else if has_offset {
1331                    write!(f, ", #{}", self.offset())?;
1332                }
1333
1334                Ok(())
1335            }
1336            OffsetMode::Fixed | OffsetMode::PreIndex => {
1337                write!(f, "[")?;
1338                if self.has_base_label() {
1339                    write!(f, "label{}", self.base_id())?;
1340                } else {
1341                    write!(f, "{}", self.base_reg())?;
1342                }
1343
1344                if has_index {
1345                    write!(f, ", {}", self.index_reg())?;
1346                    if self.has_shift() {
1347                        write!(f, ", {}", Shift::new(self.shift_op(), self.shift()))?;
1348                    }
1349                } else if has_offset {
1350                    write!(f, ", #{}", self.offset())?;
1351                }
1352
1353                write!(f, "]")?;
1354
1355                if self.is_pre_index() {
1356                    write!(f, "!")?;
1357                }
1358
1359                Ok(())
1360            }
1361        }
1362    }
1363}