1use derive_more::derive::{BitAnd, BitOr, BitXor, Deref, DerefMut, TryFrom};
16use num_traits::{FromPrimitive, ToPrimitive};
17
18use super::{globals::INVALID_ID, support::bitmask_from_bool, types::TypeId};
19#[macro_export]
20macro_rules! define_operand_cast {
21 ($t: ty, $base: ty) => {
22 impl OperandCast for $t {
23 fn as_operand(&self) -> &Operand {
24 (**self).as_operand()
25 }
26
27 fn from_operand(op: &Operand) -> Self {
28 Self(<$base>::from_operand(op))
29 }
30 }
31 };
32}
33
34#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, derive_more::TryFrom, Debug)]
36#[repr(u32)]
37#[try_from(repr)]
38pub enum OperandType {
39 None = 0,
41 Reg = 1,
43 Mem = 2,
45 RegList = 3,
47 Imm = 4,
49 Label = 5,
51 Sym = 6,
53}
54
55pub type RegMask = u32;
59
60#[derive(TryFrom, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
64#[repr(u32)]
65#[try_from(repr)]
66pub enum RegType {
67 None,
69
70 LabelTag,
72 SymTag,
74 PC,
76
77 Gp8Lo,
79
80 Gp8Hi,
82
83 Gp16,
85
86 Gp32,
88
89 Gp64,
91
92 Vec8,
94
95 Vec16,
97
98 Vec32,
100
101 Vec64,
103
104 Vec128,
106
107 Vec256,
109
110 Vec512,
112
113 VecNLen,
115
116 Mask,
118
119 Extra,
121
122 X86SReg,
123 X86CReg,
124 X86DReg,
125 X86St,
126 X86Bnd,
127 X86Tmm,
128 MaxValue = 31,
129}
130
131#[allow(non_upper_case_globals)]
132impl RegType {
133 pub const X86Mm: Self = Self::Extra;
134 pub const X86Rip: Self = Self::PC;
135 pub const X86GpbLo: Self = Self::Gp8Lo;
136 pub const X86GpbHi: Self = Self::Gp8Hi;
137 pub const X86Gpw: Self = Self::Gp16;
138 pub const X86Gpd: Self = Self::Gp32;
139 pub const X86Gpq: Self = Self::Gp64;
140 pub const X86Xmm: Self = Self::Vec128;
141 pub const X86Ymm: Self = Self::Vec256;
142 pub const X86Zmm: Self = Self::Vec512;
143 pub const X86KReg: Self = Self::Mask;
144
145 pub const RISCVPC: Self = Self::PC;
146 pub const RISCV64Gp: Self = Self::Gp64;
147 pub const RISCV32Gp: Self = Self::Gp32;
148 pub const RISCVFp: Self = Self::Vec64;
149 pub const RISCVVec: Self = Self::VecNLen;
150}
151
152#[derive(TryFrom, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
153#[repr(u32)]
154#[try_from(repr)]
155pub enum RegGroup {
156 Gp = 0,
157 Vec,
158 Mask,
159 ExtraVirt3,
160 PC,
161 X86SReg,
162 X86CReg,
163 X86DReg,
164 X86St,
165 X86Bnd,
166 X86Tmm,
167}
168
169impl RegGroup {
170 pub const X86K: Self = Self::Mask;
171 pub const X86MM: Self = Self::ExtraVirt3;
172}
173
174#[allow(non_upper_case_globals)]
175impl RegGroup {
176 pub const X86Rip: Self = Self::PC;
177}
178
179#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, BitOr, BitAnd, BitXor)]
180pub struct OperandSignature {
181 pub bits: u32,
182}
183
184impl From<u32> for OperandSignature {
185 fn from(value: u32) -> Self {
186 Self { bits: value }
187 }
188}
189
190impl OperandSignature {
191 pub const OP_TYPE_SHIFT: u32 = 0;
193 pub const OP_TYPE_MASK: u32 = 0x07u32 << Self::OP_TYPE_SHIFT;
195
196 pub const REG_TYPE_SHIFT: u32 = 3;
198 pub const REG_TYPE_MASK: u32 = 0x1Fu32 << Self::REG_TYPE_SHIFT;
200
201 pub const REG_GROUP_SHIFT: u32 = 8;
203 pub const REG_GROUP_MASK: u32 = 0x0Fu32 << Self::REG_GROUP_SHIFT;
205
206 pub const MEM_BASE_TYPE_SHIFT: u32 = 3;
208 pub const MEM_BASE_TYPE_MASK: u32 = 0x1Fu32 << Self::MEM_BASE_TYPE_SHIFT;
210
211 pub const MEM_INDEX_TYPE_SHIFT: u32 = 8;
213 pub const MEM_INDEX_TYPE_MASK: u32 = 0x1Fu32 << Self::MEM_INDEX_TYPE_SHIFT;
215
216 pub const MEM_BASE_INDEX_SHIFT: u32 = 3;
218 pub const MEM_BASE_INDEX_MASK: u32 = 0x3FFu32 << Self::MEM_BASE_INDEX_SHIFT;
220
221 pub const MEM_REG_HOME_SHIFT: u32 = 13;
222 pub const MEM_REG_HOME_FLAG: u32 = 0x01 << Self::MEM_REG_HOME_SHIFT;
223
224 pub const PREDICATE_SHIFT: u32 = 20;
226 pub const PREDICATE_MASK: u32 = 0x0Fu32 << Self::PREDICATE_SHIFT;
228
229 pub const SIZE_SHIFT: u32 = 24;
231 pub const SIZE_MASK: u32 = 0xFFu32 << Self::SIZE_SHIFT;
233
234 pub const fn new(bits: u32) -> Self {
235 Self { bits }
236 }
237
238 pub const fn subset(&self, mask: u32) -> Self {
239 Self {
240 bits: self.bits & mask,
241 }
242 }
243}
244
245impl OperandSignature {
246 pub fn reset(&mut self) -> () {
247 self.bits = 0;
248 }
249
250 pub const fn bits(&self) -> u32 {
251 self.bits
252 }
253
254 pub fn set_bits(&mut self, bits: u32) -> () {
255 self.bits = bits;
256 }
257
258 pub const fn has_field<const K_FIELD_MASK: u32>(&self) -> bool {
259 (self.bits & K_FIELD_MASK) != 0
260 }
261
262 pub const fn has_value<const K_FIELD_MASK: u32>(&self, value: u32) -> bool {
263 (self.bits & K_FIELD_MASK) != value << K_FIELD_MASK.trailing_zeros()
264 }
265
266 pub const fn from_bits(bits: u32) -> Self {
267 OperandSignature { bits }
268 }
269
270 pub const fn from_value<const K_FIELD_MASK: u32>(value: u32) -> Self {
271 OperandSignature {
272 bits: value << K_FIELD_MASK.trailing_zeros(),
273 }
274 }
275
276 pub const fn from_op_type(op_type: OperandType) -> Self {
277 OperandSignature {
278 bits: (op_type as u32) << Self::OP_TYPE_SHIFT,
279 }
280 }
281
282 pub const fn from_reg_type(reg_type: RegType) -> Self {
283 OperandSignature {
284 bits: (reg_type as u32) << Self::REG_TYPE_SHIFT,
285 }
286 }
287
288 pub const fn from_reg_group(reg_group: RegGroup) -> Self {
289 OperandSignature {
290 bits: (reg_group as u32) << Self::REG_GROUP_SHIFT,
291 }
292 }
293
294 pub const fn from_mem_base_type(base_type: RegType) -> Self {
295 OperandSignature {
296 bits: (base_type as u32) << Self::MEM_BASE_TYPE_SHIFT,
297 }
298 }
299
300 pub const fn from_mem_index_type(index_type: RegType) -> Self {
301 OperandSignature {
302 bits: (index_type as u32) << Self::MEM_INDEX_TYPE_SHIFT,
303 }
304 }
305
306 pub const fn from_predicate(predicate: u32) -> Self {
307 OperandSignature {
308 bits: predicate << Self::PREDICATE_SHIFT,
309 }
310 }
311
312 pub const fn from_size(size: u32) -> Self {
313 OperandSignature {
314 bits: size << Self::SIZE_SHIFT,
315 }
316 }
317
318 pub fn set_field<const K_FIELD_MASK: u32>(&mut self, value: u32) -> () {
319 self.bits = (self.bits & !K_FIELD_MASK) | (value << K_FIELD_MASK.trailing_zeros());
320 }
321
322 pub const fn get_field<const K_FIELD_MASK: u32>(&self) -> u32 {
323 (self.bits >> K_FIELD_MASK.trailing_zeros())
324 & (K_FIELD_MASK >> K_FIELD_MASK.trailing_zeros())
325 }
326
327 pub const fn is_valid(&self) -> bool {
328 self.bits != 0
329 }
330
331 pub fn op_type(&self) -> OperandType {
332 OperandType::try_from(self.get_field::<{ Self::OP_TYPE_MASK }>()).unwrap()
333 }
334
335 pub fn reg_type(&self) -> RegType {
336 RegType::try_from(self.get_field::<{ Self::REG_TYPE_MASK }>()).unwrap()
337 }
338
339 pub fn reg_group(&self) -> RegGroup {
340 RegGroup::try_from(self.get_field::<{ Self::REG_GROUP_MASK }>()).unwrap()
341 }
342
343 pub fn mem_base_type(&self) -> RegType {
344 RegType::try_from(self.get_field::<{ Self::MEM_BASE_TYPE_MASK }>()).unwrap()
345 }
346
347 pub fn mem_index_type(&self) -> RegType {
348 RegType::try_from(self.get_field::<{ Self::MEM_INDEX_TYPE_MASK }>()).unwrap()
349 }
350
351 pub fn predicate(&self) -> u32 {
352 self.get_field::<{ Self::PREDICATE_MASK }>()
353 }
354
355 pub fn size(&self) -> u32 {
356 self.get_field::<{ Self::SIZE_MASK }>()
357 }
358
359 pub fn set_op_type(&mut self, op_type: OperandType) {
360 self.set_field::<{ Self::OP_TYPE_MASK }>(op_type as _);
361 }
362
363 pub fn set_reg_type(&mut self, reg_type: RegType) {
364 self.set_field::<{ Self::REG_TYPE_MASK }>(reg_type as _);
365 }
366
367 pub fn set_reg_group(&mut self, reg_group: RegGroup) {
368 self.set_field::<{ Self::REG_GROUP_MASK }>(reg_group as _);
369 }
370
371 pub fn set_mem_base_type(&mut self, base_type: RegType) {
372 self.set_field::<{ Self::MEM_BASE_TYPE_MASK }>(base_type as _);
373 }
374
375 pub fn set_mem_index_type(&mut self, index_type: RegType) {
376 self.set_field::<{ Self::MEM_INDEX_TYPE_MASK }>(index_type as _);
377 }
378
379 pub fn set_predicate(&mut self, predicate: u32) {
380 self.set_field::<{ Self::PREDICATE_MASK }>(predicate);
381 }
382
383 pub fn set_size(&mut self, size: u32) {
384 self.set_field::<{ Self::SIZE_MASK }>(size);
385 }
386}
387
388pub const DATA_MEM_INDEX_ID: usize = 0;
389pub const DATA_MEM_OFFSET_LO: usize = 1;
390pub const DATA_IMM_VALUE_LO: usize = if cfg!(target_endian = "little") { 0 } else { 1 };
391pub const DATA_IMM_VALUE_HI: usize = if DATA_IMM_VALUE_LO == 0 { 1 } else { 0 };
392
393pub const VIRT_ID_MIN: u32 = 400;
394pub const VIRT_ID_MAX: u32 = u32::MAX - 1;
395pub const VIRT_ID_COUNT: u32 = VIRT_ID_MAX - VIRT_ID_MIN + 1;
396
397#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash, Debug)]
403pub struct Operand {
404 pub signature: OperandSignature,
405 pub base_id: u32,
406 pub data: [u32; 2],
407}
408
409pub const fn is_virt_id(id: u32) -> bool {
410 id - VIRT_ID_MIN < VIRT_ID_COUNT
411}
412
413pub const fn index_to_virt_id(id: u32) -> u32 {
414 id + VIRT_ID_MIN
415}
416
417pub const fn virt_id_to_index(id: u32) -> u32 {
418 id - VIRT_ID_MIN
419}
420
421impl Operand {
422 pub const fn new() -> Self {
423 Self {
424 base_id: INVALID_ID,
425 signature: OperandSignature::new(0),
426 data: [0; 2],
427 }
428 }
429
430 pub const fn make_reg(sig: OperandSignature, id: u32) -> Self {
431 Self {
432 base_id: id,
433 signature: sig,
434 data: [0; 2],
435 }
436 }
437
438 pub fn reset(&mut self) {
439 self.signature.reset();
440 self.base_id = 0;
441 self.data = [0; 2]
442 }
443
444 pub fn has_signature(&self, other: OperandSignature) -> bool {
445 self.signature == other
446 }
447
448 pub const fn signature(&self) -> OperandSignature {
449 self.signature
450 }
451
452 pub fn set_signature(&mut self, sig: OperandSignature) {
453 self.signature = sig;
454 }
455
456 pub fn set_id(&mut self, id: u32) {
457 self.base_id = id;
458 }
459
460 pub fn op_type(&self) -> OperandType {
461 self.signature.op_type()
462 }
463
464 pub const fn is_none(&self) -> bool {
465 self.signature.bits == 0
466 }
467
468 pub fn is_reg(&self) -> bool {
469 self.op_type() == OperandType::Reg
470 }
471
472 pub fn is_reg_list(&self) -> bool {
473 self.op_type() == OperandType::RegList
474 }
475
476 pub fn is_mem(&self) -> bool {
477 self.op_type() == OperandType::Mem
478 }
479
480 pub fn is_imm(&self) -> bool {
481 self.op_type() == OperandType::Imm
482 }
483
484 pub fn is_label(&self) -> bool {
485 self.op_type() == OperandType::Label
486 }
487
488 pub fn is_sym(&self) -> bool {
489 self.op_type() == OperandType::Sym
490 }
491
492 pub fn is_phys_reg(&self) -> bool {
493 self.is_reg() && self.base_id < 0xff
494 }
495
496 pub fn is_virt_reg(&self) -> bool {
497 self.is_reg() && self.base_id > 0xff
498 }
499
500 pub const fn id(&self) -> u32 {
501 self.base_id
502 }
503
504 pub fn is_reg_type_of(&self, typ: RegType) -> bool {
505 self.signature
506 .subset(OperandSignature::OP_TYPE_MASK | OperandSignature::REG_TYPE_MASK)
507 == OperandSignature::from_reg_type(typ)
508 | OperandSignature::from_op_type(OperandType::Reg)
509 }
510
511 pub fn is_reg_group_of(&self, group: RegGroup) -> bool {
512 self.signature
513 .subset(OperandSignature::OP_TYPE_MASK | OperandSignature::REG_GROUP_MASK)
514 == OperandSignature::from_reg_group(group)
515 | OperandSignature::from_op_type(OperandType::Reg)
516 }
517
518 pub fn is_gp(&self) -> bool {
519 self.is_reg_group_of(RegGroup::Gp)
520 }
521
522 pub fn is_gp32(&self) -> bool {
523 self.is_reg_type_of(RegType::Gp32)
524 }
525
526 pub fn is_gp64(&self) -> bool {
527 self.is_reg_type_of(RegType::Gp64)
528 }
529
530 pub fn is_vec(&self) -> bool {
531 self.is_reg_group_of(RegGroup::Vec)
532 }
533
534 pub fn is_vec8(&self) -> bool {
535 self.is_reg_type_of(RegType::Vec8)
536 }
537
538 pub fn is_vec16(&self) -> bool {
539 self.is_reg_type_of(RegType::Vec16)
540 }
541
542 pub fn is_vec32(&self) -> bool {
543 self.is_reg_type_of(RegType::Vec32)
544 }
545
546 pub fn is_vec64(&self) -> bool {
547 self.is_reg_type_of(RegType::Vec64)
548 }
549
550 pub fn is_vec128(&self) -> bool {
551 self.is_reg_type_of(RegType::Vec128)
552 }
553
554 pub fn is_vec256(&self) -> bool {
555 self.is_reg_type_of(RegType::Vec256)
556 }
557
558 pub fn is_vec512(&self) -> bool {
559 self.is_reg_type_of(RegType::Vec512)
560 }
561
562 pub fn is_mask(&self) -> bool {
563 self.is_reg_group_of(RegGroup::Mask)
564 }
565
566 pub fn is_reg_list_of(&self, typ: RegType) -> bool {
567 self.signature
568 .subset(OperandSignature::OP_TYPE_MASK | OperandSignature::REG_TYPE_MASK)
569 == OperandSignature::from_reg_type(typ)
570 }
571
572 pub fn is_reg_or_mem(&self) -> bool {
573 self.op_type() >= OperandType::Reg && self.op_type() <= OperandType::Mem
574 }
575
576 pub fn is_reg_or_reg_list_or_mem(&self) -> bool {
577 self.op_type() >= OperandType::RegList && self.op_type() <= OperandType::RegList
578 }
579
580 pub fn x86_rm_size(&self) -> u32 {
581 self.signature.size()
582 }
583}
584
585#[derive(Deref, DerefMut, Clone, Copy, PartialEq, Eq, Hash)]
586pub struct Label(pub Operand);
587
588impl core::fmt::Debug for Label {
589 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
590 write!(f, "label{}", self.id())
591 }
592}
593
594impl PartialOrd for Label {
595 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
596 self.id().partial_cmp(&other.id())
597 }
598}
599
600impl Ord for Label {
601 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
602 self.id().cmp(&other.id())
603 }
604}
605
606define_operand_cast!(Label, Operand);
607
608impl Label {
609 pub const fn new() -> Self {
610 Self(Operand {
611 signature: OperandSignature::from_op_type(OperandType::Label),
612 base_id: INVALID_ID,
613 data: [0; 2],
614 })
615 }
616
617 pub const fn from_id(id: u32) -> Self {
618 Self(Operand {
619 signature: OperandSignature::from_op_type(OperandType::Label),
620 base_id: id,
621 data: [0; 2],
622 })
623 }
624
625 pub const fn is_valid(&self) -> bool {
626 self.0.base_id != INVALID_ID
627 }
628
629 pub fn set_id(&mut self, id: u32) {
630 self.base_id = id;
631 }
632}
633
634#[derive(Deref, DerefMut, Clone, Copy, PartialEq, Eq, Hash)]
635pub struct Sym(pub Operand);
636
637impl core::fmt::Debug for Sym {
638 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
639 write!(f, "sym{}", self.id())
640 }
641}
642
643impl PartialOrd for Sym {
644 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
645 self.id().partial_cmp(&other.id())
646 }
647}
648
649impl Ord for Sym {
650 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
651 self.id().cmp(&other.id())
652 }
653}
654
655define_operand_cast!(Sym, Operand);
656
657impl Sym {
658 pub const fn new() -> Self {
659 Self(Operand {
660 signature: OperandSignature::from_op_type(OperandType::Sym),
661 base_id: INVALID_ID,
662 data: [0; 2],
663 })
664 }
665
666 pub const fn from_id(id: u32) -> Self {
667 Self(Operand {
668 signature: OperandSignature::from_op_type(OperandType::Sym),
669 base_id: id,
670 data: [0; 2],
671 })
672 }
673
674 pub const fn is_valid(&self) -> bool {
675 self.0.base_id != INVALID_ID
676 }
677
678 pub fn set_id(&mut self, id: u32) {
679 self.base_id = id;
680 }
681}
682
683#[derive(Deref, DerefMut, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
684pub struct BaseReg(pub Operand);
685
686pub const REG_SIGNATURE: OperandSignature = OperandSignature::from_op_type(OperandType::Reg);
687pub const REG_TYPE_NONE: u32 = RegType::None as u32;
688pub const REG_BASE_SIGNATURE_MASK: u32 = OperandSignature::OP_TYPE_MASK
689 | OperandSignature::REG_TYPE_MASK
690 | OperandSignature::REG_GROUP_MASK
691 | OperandSignature::SIZE_MASK;
692
693impl BaseReg {
694 pub const SIGNATURE: u32 = REG_BASE_SIGNATURE_MASK;
695
696 pub const fn new() -> Self {
697 Self(Operand {
698 signature: OperandSignature::from_op_type(OperandType::Reg),
699 base_id: 0xff,
700 data: [0; 2],
701 })
702 }
703
704 pub const fn from_signature_and_id(signature: OperandSignature, id: u32) -> Self {
705 Self(Operand {
706 signature,
707 base_id: id,
708 data: [0; 2],
709 })
710 }
711
712 pub const fn base_signature(&self) -> OperandSignature {
713 OperandSignature {
714 bits: self.0.signature.bits & REG_BASE_SIGNATURE_MASK,
715 }
716 }
717
718 pub fn has_base_signature(&self, signature: impl Into<OperandSignature>) -> bool {
719 self.base_signature().bits == signature.into().bits
720 }
721
722 pub fn is_valid(&self) -> bool {
723 self.signature().is_valid() && self.base_id != 0xff
724 }
725
726 pub fn is_phys_reg(&self) -> bool {
727 self.base_id < 0xff
728 }
729
730 pub fn is_virt_reg(&self) -> bool {
731 self.base_id > 0xff
732 }
733
734 pub fn is_type(&self, typ: RegType) -> bool {
735 self.signature.subset(OperandSignature::REG_TYPE_MASK)
736 == OperandSignature::from_reg_type(typ)
737 }
738
739 pub fn is_group(&self, group: RegGroup) -> bool {
740 self.signature.subset(OperandSignature::REG_GROUP_MASK)
741 == OperandSignature::from_reg_group(group)
742 }
743
744 pub fn is_gp(&self) -> bool {
745 self.is_group(RegGroup::Gp)
746 }
747
748 pub fn is_vec(&self) -> bool {
749 self.is_group(RegGroup::Vec)
750 }
751
752 pub fn is_mask(&self) -> bool {
753 self.is_group(RegGroup::Mask)
754 }
755
756 pub fn operand_is_gp(op: &Operand) -> bool {
757 op.signature()
758 .subset(OperandSignature::OP_TYPE_MASK | OperandSignature::REG_GROUP_MASK)
759 == (OperandSignature::from_op_type(OperandType::Reg)
760 | OperandSignature::from_reg_group(RegGroup::Gp))
761 }
762
763 pub fn operand_is_vec(op: &Operand) -> bool {
764 op.signature()
765 .subset(OperandSignature::OP_TYPE_MASK | OperandSignature::REG_GROUP_MASK)
766 == (OperandSignature::from_op_type(OperandType::Reg)
767 | OperandSignature::from_reg_group(RegGroup::Vec))
768 }
769
770 pub fn operand_is_gp_with_id(op: &Operand, id: u32) -> bool {
771 Self::operand_is_gp(op) && op.id() == id
772 }
773
774 pub fn is_vec_with_id(op: &Operand, id: u32) -> bool {
775 Self::operand_is_vec(op) && op.id() == id
776 }
777
778 pub fn is_reg_of_type(&self, typ: RegType) -> bool {
779 self.is_type(typ)
780 }
781
782 pub fn is_reg_of_type_and_id(&self, typ: RegType, id: u32) -> bool {
783 self.is_type(typ) && self.base_id == id
784 }
785
786 pub fn typ(&self) -> RegType {
787 self.signature.reg_type()
788 }
789
790 pub fn group(&self) -> RegGroup {
791 self.signature.reg_group()
792 }
793
794 pub fn has_size(&self) -> bool {
795 self.signature
796 .has_field::<{ OperandSignature::SIZE_MASK }>()
797 }
798
799 pub fn size(&self) -> u32 {
800 self.signature.size()
801 }
802
803 pub fn predicate(&self) -> u32 {
804 self.signature.predicate()
805 }
806
807 pub fn set_predicate(&mut self, predicate: u32) {
808 self.signature
809 .set_field::<{ OperandSignature::PREDICATE_MASK }>(predicate);
810 }
811
812 pub fn reset_predicate(&mut self) {
813 self.set_predicate(0);
814 }
815}
816
817pub trait RegTraits {
818 const VALID: u32 = 1;
819 const TYPE: RegType;
820 const GROUP: RegGroup;
821 const SIZE: u32;
822 const TYPE_ID: TypeId;
823
824 const SIGNATURE: u32 = OperandSignature::from_op_type(OperandType::Reg).bits
825 | OperandSignature::from_reg_type(Self::TYPE).bits
826 | OperandSignature::from_reg_group(Self::GROUP).bits
827 | OperandSignature::from_size(Self::SIZE).bits;
828}
829
830#[macro_export]
831macro_rules! define_abstract_reg {
832 ($reg: ty, $base: ty) => {
833 impl $reg {
834 pub const fn new() -> Self {
835 Self(<$base>::from_signature_and_id(
836 OperandSignature {
837 bits: <$base>::SIGNATURE,
838 },
839 0xff,
840 ))
841 }
842
843 pub const fn from_signature_and_id(signature: OperandSignature, id: u32) -> Self {
844 Self(<$base>::from_signature_and_id(signature, id))
845 }
846
847 pub const fn from_type_and_id(typ: RegType, id: u32) -> Self {
848 Self::from_signature_and_id(Self::signature_of(typ), id)
849 }
850 }
851
852 define_operand_cast!($reg, $base);
853 };
854}
855
856#[macro_export]
857macro_rules! define_final_reg {
858 ($reg: ty, $base: ty, $traits: ty) => {
859 define_abstract_reg!($reg, $base);
860 impl $reg {
861 pub const THIS_TYPE: RegType = <$traits>::TYPE;
862 pub const THIS_GROUP: RegGroup = <$traits>::GROUP;
863 pub const THIS_SIZE: u32 = <$traits>::SIZE;
864 pub const SIGNATURE: u32 = <$traits>::SIGNATURE;
865
866 pub const fn from_id(id: u32) -> Self {
867 Self(<$base>::from_signature_and_id(
868 OperandSignature::new(Self::SIGNATURE),
869 id,
870 ))
871 }
872 }
873 };
874}
875
876#[macro_export]
877macro_rules! define_reg_traits {
878 ($reg_type: ident, $group: path, $size: expr, $type_id: path) => {
879 pub struct $reg_type;
880
881 impl RegTraits for $reg_type {
882 const TYPE: RegType = RegType::$reg_type;
883 const GROUP: RegGroup = $group;
884 const SIZE: u32 = $size;
885 const TYPE_ID: TypeId = $type_id;
886 }
887 };
888}
889
890pub trait OperandCast {
893 fn as_operand(&self) -> &Operand;
894 fn from_operand(op: &Operand) -> Self;
895}
896
897impl OperandCast for Operand {
898 fn as_operand(&self) -> &Operand {
899 self
900 }
901
902 fn from_operand(op: &Operand) -> Self {
903 *op
904 }
905}
906
907define_operand_cast!(BaseReg, Operand);
908
909impl Operand {
910 pub fn as_<T>(&self) -> T
911 where
912 T: OperandCast,
913 {
914 T::from_operand(self)
915 }
916}
917
918#[derive(Deref, DerefMut, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash, Debug)]
919pub struct BaseMem(pub Operand);
920
921define_operand_cast!(BaseMem, Operand);
922
923impl BaseMem {
924 pub fn from_base_disp(base_reg: impl AsRef<BaseReg>, offset: i32) -> Self {
925 let base = base_reg.as_ref();
926 Self(Operand {
927 signature: OperandSignature::from_op_type(OperandType::Mem)
928 | OperandSignature::from_mem_base_type(base.typ()),
929 base_id: base.id(),
930 data: [0, offset as _],
931 })
932 }
933
934 pub fn from_base_and_index_disp(
935 u0: OperandSignature,
936 base_id: u32,
937 index_id: u32,
938 offset: i32,
939 ) -> Self {
940 Self(Operand {
941 signature: u0,
942 base_id,
943 data: [index_id, offset as _],
944 })
945 }
946
947 pub fn reset(&mut self) {
948 self.signature = OperandSignature::from_op_type(OperandType::Mem);
949 self.base_id = 0;
950 self.data = [0; 2]
951 }
952
953 pub const fn new() -> Self {
954 Self(Operand {
955 signature: OperandSignature::from_op_type(OperandType::Mem),
956 base_id: 0,
957 data: [0; 2],
958 })
959 }
960
961 pub fn is_reg_home(&self) -> bool {
962 self.signature
963 .has_field::<{ OperandSignature::MEM_REG_HOME_FLAG }>()
964 }
965
966 pub fn set_reg_home(&mut self) {
967 self.signature.bits |= OperandSignature::MEM_REG_HOME_FLAG;
968 }
969
970 pub fn clear_reg_home(&mut self) {
971 self.signature.bits &= !OperandSignature::MEM_REG_HOME_FLAG;
972 }
973
974 pub fn has_base(&self) -> bool {
975 self.signature.bits & OperandSignature::MEM_BASE_TYPE_MASK != 0
976 }
977
978 pub fn has_index(&self) -> bool {
979 self.signature.bits & OperandSignature::MEM_INDEX_TYPE_MASK != 0
980 }
981
982 pub fn has_base_or_index(&self) -> bool {
983 self.has_base() || self.has_index()
984 }
985
986 pub fn has_base_and_index(&self) -> bool {
987 self.has_base() && self.has_index()
988 }
989
990 pub fn has_base_label(&self) -> bool {
991 self.signature.subset(OperandSignature::MEM_BASE_TYPE_MASK)
992 == OperandSignature::from_reg_type(RegType::LabelTag)
993 }
994
995 pub fn has_base_sym(&self) -> bool {
996 self.signature.subset(OperandSignature::MEM_BASE_TYPE_MASK)
997 == OperandSignature::from_reg_type(RegType::SymTag)
998 }
999
1000 pub fn has_base_reg(&self) -> bool {
1001 self.signature.subset(OperandSignature::MEM_BASE_TYPE_MASK)
1002 > OperandSignature::from_reg_type(RegType::SymTag)
1003 }
1004
1005 pub fn has_index_reg(&self) -> bool {
1006 self.signature.subset(OperandSignature::MEM_INDEX_TYPE_MASK)
1007 > OperandSignature::from_reg_type(RegType::SymTag)
1008 }
1009
1010 pub fn base_type(&self) -> RegType {
1011 self.signature.mem_base_type()
1012 }
1013
1014 pub fn index_type(&self) -> RegType {
1015 self.signature.mem_index_type()
1016 }
1017
1018 pub fn base_id(&self) -> u32 {
1019 self.base_id
1020 }
1021
1022 pub fn index_id(&self) -> u32 {
1023 self.data[DATA_MEM_INDEX_ID]
1024 }
1025
1026 pub fn set_base_type(&mut self, base_type: RegType) {
1027 self.signature.set_mem_base_type(base_type);
1028 }
1029
1030 pub fn set_index_type(&mut self, index_type: RegType) {
1031 self.signature.set_mem_index_type(index_type);
1032 }
1033
1034 pub fn set_base_id(&mut self, id: u32) {
1035 self.base_id = id;
1036 }
1037
1038 pub fn set_index_id(&mut self, id: u32) {
1039 self.data[DATA_MEM_INDEX_ID] = id;
1040 }
1041
1042 pub fn set_base(&mut self, base: &BaseReg) {
1043 let base_reg = base;
1044 self.set_base_type(base_reg.typ());
1045 self.set_base_id(base_reg.id());
1046 }
1047
1048 pub fn set_index(&mut self, index: &BaseReg) {
1049 let index_reg = index;
1050 self.set_index_type(index_reg.typ());
1051 self.set_index_id(index_reg.id());
1052 }
1053 pub fn reset_base(&mut self) {
1054 self.signature.bits &= !OperandSignature::MEM_BASE_TYPE_MASK;
1055 self.base_id = 0;
1056 }
1057
1058 pub fn reset_index(&mut self) {
1059 self.signature.bits &= !OperandSignature::MEM_INDEX_TYPE_MASK;
1060 self.data[DATA_MEM_INDEX_ID] = 0;
1061 }
1062
1063 pub fn is_offset_64bit(&self) -> bool {
1064 self.base_type() == RegType::None
1066 }
1067
1068 pub fn has_offset(&self) -> bool {
1069 (self.data[DATA_MEM_OFFSET_LO] | (self.base_id & bitmask_from_bool(self.is_offset_64bit())))
1070 != 0
1071 }
1072
1073 pub fn offset(&self) -> i64 {
1074 if self.is_offset_64bit() {
1075 (self.data[DATA_MEM_OFFSET_LO] as u64 | (self.base_id as u64) << 32) as i64
1076 } else {
1077 self.data[DATA_MEM_OFFSET_LO] as i32 as i64
1078 }
1079 }
1080 pub fn offset_lo32(&self) -> i32 {
1081 self.data[DATA_MEM_OFFSET_LO] as i32
1082 }
1083
1084 pub fn offset_hi32(&self) -> i32 {
1085 if self.is_offset_64bit() {
1086 self.base_id as i32
1087 } else {
1088 0
1089 }
1090 }
1091 pub fn set_offset(&mut self, offset: i64) {
1092 let lo = (offset as u64 & 0xFFFFFFFF) as u32;
1093 let hi = (offset as u64 >> 32) as u32;
1094 let hi_msk = bitmask_from_bool(self.is_offset_64bit());
1095
1096 self.data[DATA_MEM_OFFSET_LO] = lo;
1097 self.base_id = (hi & hi_msk) | (self.base_id & !hi_msk);
1098 }
1099 pub fn set_offset_lo32(&mut self, offset: i32) {
1100 self.data[DATA_MEM_OFFSET_LO] = offset as u32;
1101 }
1102
1103 pub fn add_offset(&mut self, offset: i64) {
1104 if self.is_offset_64bit() {
1105 self.set_offset(self.offset() + offset);
1106 } else {
1107 self.set_offset_lo32(self.offset_lo32() + offset as i32);
1108 }
1109 }
1110
1111 pub fn add_offset_lo32(&mut self, offset: i32) {
1112 self.set_offset_lo32(self.offset_lo32() + offset);
1113 }
1114
1115 pub fn reset_offset(&mut self) {
1116 self.set_offset(0);
1117 }
1118
1119 pub fn reset_offset_lo32(&mut self) {
1120 self.set_offset_lo32(0);
1121 }
1122}
1123#[derive(Clone, Copy, PartialEq, Eq)]
1124pub enum ImmType {
1125 Int = 0,
1126 Double = 1,
1127}
1128
1129#[derive(Deref, DerefMut, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
1130pub struct Imm(pub Operand);
1131
1132define_operand_cast!(Imm, Operand);
1133
1134impl Imm {
1135 pub const fn new() -> Self {
1136 Self(Operand {
1137 signature: OperandSignature::from_op_type(OperandType::Imm),
1138 base_id: 0,
1139 data: [0; 2],
1140 })
1141 }
1142 pub fn from_value<T: Into<i64>>(val: T, predicate: u32) -> Self {
1153 let value = val.into();
1154 Self(Operand {
1155 signature: OperandSignature::from_op_type(OperandType::Imm)
1156 | OperandSignature::from_predicate(predicate),
1157 base_id: 0,
1158 data: [value as u32, (value >> 32) as u32],
1159 })
1160 }
1161
1162 pub fn from_float(val: f32, predicate: u32) -> Self {
1163 let mut imm = Self::new();
1164 imm.set_value_float(val);
1165 imm.set_predicate(predicate);
1166 imm
1167 }
1168
1169 pub fn from_double(val: f64, predicate: u32) -> Self {
1170 let mut imm = Self::new();
1171 imm.set_value_float(val);
1172 imm.set_predicate(predicate);
1173 imm
1174 }
1175
1176 pub fn typ(&self) -> ImmType {
1177 if self
1178 .signature()
1179 .get_field::<{ OperandSignature::PREDICATE_MASK }>()
1180 == 0
1181 {
1182 ImmType::Int
1183 } else {
1184 ImmType::Double
1185 }
1186 }
1187
1188 pub fn set_type(&mut self, typ: ImmType) {
1189 self.signature
1190 .set_field::<{ OperandSignature::PREDICATE_MASK }>(typ as u32);
1191 }
1192
1193 pub fn reset_type(&mut self) {
1194 self.set_type(ImmType::Int);
1195 }
1196
1197 pub fn predicate(&self) -> u32 {
1198 self.signature()
1199 .get_field::<{ OperandSignature::PREDICATE_MASK }>()
1200 }
1201
1202 pub fn set_predicate(&mut self, predicate: u32) {
1203 self.signature
1204 .set_field::<{ OperandSignature::PREDICATE_MASK }>(predicate);
1205 }
1206
1207 pub fn reset_predicate(&mut self) {
1208 self.set_predicate(0);
1209 }
1210
1211 pub fn value(&self) -> i64 {
1212 (((self.data[DATA_IMM_VALUE_HI] as u64) << 32) | (self.data[DATA_IMM_VALUE_LO] as u64))
1213 as i64
1214 }
1215
1216 pub fn value_f32(&self) -> f32 {
1217 f32::from_bits(self.data[DATA_IMM_VALUE_LO])
1218 }
1219
1220 pub fn value_f64(&self) -> f64 {
1221 f64::from_bits(
1222 ((self.data[DATA_IMM_VALUE_HI] as u64) << 32) | (self.data[DATA_IMM_VALUE_LO] as u64),
1223 )
1224 }
1225
1226 pub fn is_int(&self) -> bool {
1227 self.typ() == ImmType::Int
1228 }
1229
1230 pub fn is_double(&self) -> bool {
1231 self.typ() == ImmType::Double
1232 }
1233
1234 pub fn is_int8(&self) -> bool {
1235 self.is_int() && (-128..=127).contains(&self.value())
1236 }
1237
1238 pub fn is_uint8(&self) -> bool {
1239 self.is_int() && (0..=255).contains(&self.value())
1240 }
1241
1242 pub fn is_int16(&self) -> bool {
1243 self.is_int() && (-32768..=32767).contains(&self.value())
1244 }
1245
1246 pub fn is_uint16(&self) -> bool {
1247 self.is_int() && (0..=65535).contains(&self.value())
1248 }
1249
1250 pub fn is_int32(&self) -> bool {
1251 self.is_int() && (-2147483648..=2147483647).contains(&self.value())
1252 }
1253
1254 pub fn is_uint32(&self) -> bool {
1255 self.is_int() && self.data[DATA_IMM_VALUE_HI] == 0
1256 }
1257
1258 pub fn value_as<T: FromPrimitive>(&self) -> T {
1259 T::from_i64(self.value()).unwrap()
1260 }
1261
1262 pub fn int32_lo(&self) -> i32 {
1263 self.data[DATA_IMM_VALUE_LO] as i32
1264 }
1265
1266 pub fn int32_hi(&self) -> i32 {
1267 self.data[DATA_IMM_VALUE_HI] as i32
1268 }
1269
1270 pub fn uint32_lo(&self) -> u32 {
1271 self.data[DATA_IMM_VALUE_LO]
1272 }
1273
1274 pub fn uint32_hi(&self) -> u32 {
1275 self.data[DATA_IMM_VALUE_HI]
1276 }
1277
1278 pub fn set_value<T: ToPrimitive>(&mut self, val: T) {
1279 let value = val.to_i64().unwrap();
1280 self.data[DATA_IMM_VALUE_LO] = value as u32;
1281 self.data[DATA_IMM_VALUE_HI] = (value >> 32) as u32;
1282 self.set_type(ImmType::Int);
1283 }
1284 pub fn set_value_float<T: Into<f64>>(&mut self, val: T) {
1285 let value = f64::to_bits(val.into());
1286 self.data[DATA_IMM_VALUE_LO] = value as u32;
1287 self.data[DATA_IMM_VALUE_HI] = (value >> 32) as u32;
1288 self.set_type(ImmType::Double);
1289 }
1290
1291 pub fn clone(&self) -> Self {
1292 *self
1293 }
1294
1295 pub fn sign_extend_8_bits(&mut self) {
1296 self.set_value(self.value_as::<i8>() as i64);
1297 }
1298
1299 pub fn sign_extend_16_bits(&mut self) {
1300 self.set_value(self.value_as::<i16>() as i64);
1301 }
1302
1303 pub fn sign_extend_32_bits(&mut self) {
1304 self.set_value(self.value_as::<i32>() as i64);
1305 }
1306
1307 pub fn zero_extend_8_bits(&mut self) {
1308 self.set_value(self.value_as::<u8>() as u64);
1309 }
1310
1311 pub fn zero_extend_16_bits(&mut self) {
1312 self.set_value(self.value_as::<u16>() as u64);
1313 }
1314
1315 pub fn zero_extend_32_bits(&mut self) {
1316 self.data[DATA_IMM_VALUE_HI] = 0;
1317 }
1318}
1319
1320pub fn imm<T: Into<i64>>(val: T) -> Imm {
1321 Imm::from_value(val, 0)
1322}
1323
1324use core::fmt;
1328
1329impl fmt::Display for OperandType {
1330 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1331 match self {
1332 OperandType::None => write!(f, "None"),
1333 OperandType::Reg => write!(f, "Reg"),
1334 OperandType::Mem => write!(f, "Mem"),
1335 OperandType::RegList => write!(f, "RegList"),
1336 OperandType::Imm => write!(f, "Imm"),
1337 OperandType::Label => write!(f, "Label"),
1338 OperandType::Sym => write!(f, "Sym"),
1339 }
1340 }
1341}
1342
1343impl fmt::Display for RegType {
1344 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1345 match self {
1346 RegType::None => write!(f, "None"),
1347 RegType::LabelTag => write!(f, "LabelTag"),
1348 RegType::SymTag => write!(f, "SymTag"),
1349 RegType::PC => write!(f, "PC"),
1350 RegType::Gp8Lo => write!(f, "Gp8Lo"),
1351 RegType::Gp8Hi => write!(f, "Gp8Hi"),
1352 RegType::Gp16 => write!(f, "Gp16"),
1353 RegType::Gp32 => write!(f, "Gp32"),
1354 RegType::Gp64 => write!(f, "Gp64"),
1355 RegType::Vec8 => write!(f, "Vec8"),
1356 RegType::Vec16 => write!(f, "Vec16"),
1357 RegType::Vec32 => write!(f, "Vec32"),
1358 RegType::Vec64 => write!(f, "Vec64"),
1359 RegType::Vec128 => write!(f, "Vec128"),
1360 RegType::Vec256 => write!(f, "Vec256"),
1361 RegType::Vec512 => write!(f, "Vec512"),
1362 RegType::VecNLen => write!(f, "VecNLen"),
1363 RegType::Mask => write!(f, "Mask"),
1364 RegType::Extra => write!(f, "Extra"),
1365 RegType::X86SReg => write!(f, "X86SReg"),
1366 RegType::X86CReg => write!(f, "X86CReg"),
1367 RegType::X86DReg => write!(f, "X86DReg"),
1368 RegType::X86St => write!(f, "X86St"),
1369 RegType::X86Bnd => write!(f, "X86Bnd"),
1370 RegType::X86Tmm => write!(f, "X86Tmm"),
1371 RegType::MaxValue => write!(f, "MaxValue"),
1372 }
1373 }
1374}
1375
1376impl fmt::Display for RegGroup {
1377 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1378 match self {
1379 RegGroup::Gp => write!(f, "Gp"),
1380 RegGroup::Vec => write!(f, "Vec"),
1381 RegGroup::Mask => write!(f, "Mask"),
1382 RegGroup::ExtraVirt3 => write!(f, "ExtraVirt3"),
1383 RegGroup::PC => write!(f, "PC"),
1384 RegGroup::X86SReg => write!(f, "sreg"),
1385 RegGroup::X86CReg => write!(f, "creg"),
1386 RegGroup::X86DReg => write!(f, "dreg"),
1387 RegGroup::X86St => write!(f, "st"),
1388 RegGroup::X86Bnd => write!(f, "bnd"),
1389 RegGroup::X86Tmm => write!(f, "tmm"),
1390 }
1391 }
1392}
1393
1394impl fmt::Display for Operand {
1395 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1396 match self.op_type() {
1397 OperandType::None => write!(f, "None"),
1398 OperandType::Reg => {
1399 let reg = self.as_::<BaseReg>();
1401 write!(f, "{}", reg)
1402 }
1403 OperandType::Mem => {
1404 let mem = self.as_::<BaseMem>();
1405 write!(f, "{}", mem)
1406 }
1407 OperandType::RegList => write!(f, "RegList"),
1408 OperandType::Imm => {
1409 let imm = self.as_::<Imm>();
1410 write!(f, "{}", imm)
1411 }
1412 OperandType::Label => {
1413 let label = self.as_::<Label>();
1414 write!(f, "{}", label)
1415 }
1416 OperandType::Sym => {
1417 let sym = self.as_::<Sym>();
1418 write!(f, "{}", sym)
1419 }
1420 }
1421 }
1422}
1423
1424impl fmt::Display for Label {
1425 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1426 if self.is_valid() {
1427 write!(f, "label{}", self.id())
1428 } else {
1429 write!(f, "label_invalid")
1430 }
1431 }
1432}
1433
1434impl fmt::Display for Sym {
1435 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1436 if self.is_valid() {
1437 write!(f, "sym{}", self.id())
1438 } else {
1439 write!(f, "sym_invalid")
1440 }
1441 }
1442}
1443
1444impl fmt::Display for BaseReg {
1445 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1446 if !self.is_valid() {
1447 return write!(f, "reg_invalid");
1448 }
1449
1450 match self.typ() {
1452 RegType::Gp8Lo => write!(f, "gp8lo{}", self.id()),
1453 RegType::Gp8Hi => write!(f, "gp8hi{}", self.id()),
1454 RegType::Gp16 => write!(f, "gp16{}", self.id()),
1455 RegType::Gp32 => write!(f, "gp32{}", self.id()),
1456 RegType::Gp64 => write!(f, "gp64{}", self.id()),
1457 RegType::Vec8 => write!(f, "vec8{}", self.id()),
1458 RegType::Vec16 => write!(f, "vec16{}", self.id()),
1459 RegType::Vec32 => write!(f, "vec32{}", self.id()),
1460 RegType::Vec64 => write!(f, "vec64{}", self.id()),
1461 RegType::Vec128 => write!(f, "vec128{}", self.id()),
1462 RegType::Vec256 => write!(f, "vec256{}", self.id()),
1463 RegType::Vec512 => write!(f, "vec512{}", self.id()),
1464 RegType::VecNLen => write!(f, "vecnlen{}", self.id()),
1465 RegType::Mask => write!(f, "mask{}", self.id()),
1466 RegType::X86SReg => write!(f, "sreg{}", self.id()),
1467 RegType::X86CReg => write!(f, "creg{}", self.id()),
1468 RegType::X86DReg => write!(f, "dreg{}", self.id()),
1469 RegType::X86St => write!(f, "st{}", self.id()),
1470 RegType::X86Bnd => write!(f, "bnd{}", self.id()),
1471 RegType::X86Tmm => write!(f, "tmm{}", self.id()),
1472 RegType::PC => write!(f, "pc{}", self.id()),
1473 RegType::Extra => write!(f, "extra{}", self.id()),
1474 RegType::MaxValue => write!(f, "maxvalue"),
1475 RegType::None | RegType::LabelTag | RegType::SymTag => {
1476 write!(f, "reg{}", self.id())
1477 }
1478 }
1479 }
1480}
1481
1482impl fmt::Display for BaseMem {
1483 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1484 use alloc::format;
1485 let mut parts = alloc::vec::Vec::new();
1486
1487 if self.has_base() {
1489 if self.has_base_label() {
1490 parts.push(format!("label{}", self.base_id()));
1491 } else if self.has_base_sym() {
1492 parts.push(format!("sym{}", self.base_id()));
1493 } else if self.has_base_reg() {
1494 let base_reg = BaseReg::from_signature_and_id(
1496 OperandSignature::from_reg_type(self.base_type()),
1497 self.base_id(),
1498 );
1499 parts.push(format!("{}", base_reg));
1500 }
1501 }
1502
1503 if self.has_index() && self.has_index_reg() {
1505 let index_reg = BaseReg::from_signature_and_id(
1506 OperandSignature::from_reg_type(self.index_type()),
1507 self.index_id(),
1508 );
1509 parts.push(format!("{}", index_reg));
1510 }
1511
1512 if self.has_offset() {
1514 let offset = self.offset();
1515 if offset >= 0 {
1516 parts.push(format!("+{}", offset));
1517 } else {
1518 parts.push(format!("{}", offset));
1519 }
1520 }
1521
1522 if parts.is_empty() {
1523 write!(f, "mem[0]")
1524 } else {
1525 write!(f, "mem[{}]", parts.join(" + "))
1526 }
1527 }
1528}
1529
1530impl fmt::Display for Imm {
1531 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1532 match self.typ() {
1533 ImmType::Int => write!(f, "{}", self.value()),
1534 ImmType::Double => write!(f, "{}", self.value_f64()),
1535 }
1536 }
1537}