Skip to main content

asm_rs/
ir.rs

1//! Intermediate representation types for the assembly pipeline.
2//!
3//! These types represent the structured output of the parser and serve
4//! as input to the encoder and linker passes.
5
6use alloc::boxed::Box;
7#[allow(unused_imports)]
8use alloc::format;
9use alloc::string::String;
10use alloc::vec::Vec;
11use core::fmt;
12
13use crate::error::Span;
14
15/// Target architecture.
16#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
17#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
18pub enum Arch {
19    /// 32-bit x86 protected mode.
20    X86,
21    /// 64-bit x86 long mode.
22    X86_64,
23    /// ARM A32 (ARMv7 and below).
24    Arm,
25    /// ARM T32 (Thumb-2).
26    Thumb,
27    /// ARMv8-A 64-bit.
28    Aarch64,
29    /// RISC-V 32-bit.
30    Rv32,
31    /// RISC-V 64-bit.
32    Rv64,
33}
34
35impl fmt::Display for Arch {
36    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37        match self {
38            Arch::X86 => write!(f, "x86"),
39            Arch::X86_64 => write!(f, "x86_64"),
40            Arch::Arm => write!(f, "ARM"),
41            Arch::Thumb => write!(f, "Thumb"),
42            Arch::Aarch64 => write!(f, "AArch64"),
43            Arch::Rv32 => write!(f, "RV32"),
44            Arch::Rv64 => write!(f, "RV64"),
45        }
46    }
47}
48
49impl Arch {
50    /// Convert to the error-side architecture name.
51    #[must_use]
52    pub fn to_arch_name(self) -> crate::error::ArchName {
53        match self {
54            Arch::X86 => crate::error::ArchName::X86,
55            Arch::X86_64 => crate::error::ArchName::X86_64,
56            Arch::Arm => crate::error::ArchName::Arm,
57            Arch::Thumb => crate::error::ArchName::Thumb,
58            Arch::Aarch64 => crate::error::ArchName::Aarch64,
59            Arch::Rv32 => crate::error::ArchName::Rv32,
60            Arch::Rv64 => crate::error::ArchName::Rv64,
61        }
62    }
63}
64
65/// Assembly syntax dialect.
66#[derive(Debug, Clone, Copy, PartialEq, Eq)]
67#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
68pub enum Syntax {
69    /// Intel / NASM style: `mov rax, 1`
70    Intel,
71    /// AT&T / GAS style: `movq $1, %rax`
72    Att,
73    /// ARM Unified Assembly Language.
74    Ual,
75    /// RISC-V standard syntax.
76    RiscV,
77}
78
79/// Optimization level for encoding.
80///
81/// The levels differ in what an optimization is allowed to change, not just in
82/// how hard it tries:
83///
84/// | Level | May shrink encodings | May change architectural state |
85/// |---|---|---|
86/// | [`None`](OptLevel::None) | no | no |
87/// | [`Size`](OptLevel::Size) (default) | yes | no |
88/// | [`Aggressive`](OptLevel::Aggressive) | yes | yes (FLAGS only) |
89///
90/// [`Size`](OptLevel::Size) is the default because every transform it performs
91/// is *observationally equivalent*: the rewritten instruction leaves registers,
92/// memory and FLAGS exactly as the original would.
93///
94/// [`Aggressive`](OptLevel::Aggressive) additionally permits rewrites that
95/// clobber FLAGS — notably
96/// the zero idiom `mov reg, 0` → `xor reg, reg`. That is a real semantic
97/// change: it silently breaks sequences such as
98///
99/// ```text
100/// cmp  eax, ebx
101/// mov  eax, 0     ; must not disturb FLAGS
102/// sete al
103/// ```
104///
105/// so it must be opted into explicitly, and only where FLAGS are known dead.
106#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
107#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
108pub enum OptLevel {
109    /// No optimizations — byte-for-byte predictable output.
110    None,
111    /// Prefer shortest encodings, but only via transforms that preserve all
112    /// architectural state including FLAGS (default).
113    #[default]
114    Size,
115    /// Also allow transforms that clobber FLAGS (e.g. the `mov reg, 0` zero
116    /// idiom). Only safe when FLAGS are dead after the rewritten instruction.
117    Aggressive,
118}
119
120/// x86/x64 register.
121///
122/// Covers all general-purpose, segment, control, and SSE registers
123/// for 16-bit through 64-bit modes.  Each variant encodes its own size
124/// (see [`Register::size_bits`]) and register number
125/// (see [`Register::base_code`]).
126#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
127#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
128pub enum Register {
129    // -- 64-bit general-purpose registers (RAX–R15) --
130    /// RAX — 64-bit accumulator.
131    Rax,
132    /// RCX — 64-bit counter.
133    Rcx,
134    /// RDX — 64-bit data.
135    Rdx,
136    /// RBX — 64-bit base.
137    Rbx,
138    /// RSP — 64-bit stack pointer.
139    Rsp,
140    /// RBP — 64-bit frame pointer.
141    Rbp,
142    /// RSI — 64-bit source index.
143    Rsi,
144    /// RDI — 64-bit destination index.
145    Rdi,
146    /// R8–R15 — extended 64-bit registers (require REX prefix).
147    R8,
148    /// Extended 64-bit register.
149    R9,
150    /// Extended 64-bit register.
151    R10,
152    /// Extended 64-bit register.
153    R11,
154    /// Extended 64-bit register.
155    R12,
156    /// Extended 64-bit register.
157    R13,
158    /// Extended 64-bit register.
159    R14,
160    /// Extended 64-bit register.
161    R15,
162    // -- 32-bit general-purpose registers --
163    /// EAX — 32-bit accumulator.
164    Eax,
165    /// ECX — 32-bit counter.
166    Ecx,
167    /// EDX — 32-bit data.
168    Edx,
169    /// EBX — 32-bit base.
170    Ebx,
171    /// ESP — 32-bit stack pointer.
172    Esp,
173    /// EBP — 32-bit frame pointer.
174    Ebp,
175    /// ESI — 32-bit source index.
176    Esi,
177    /// EDI — 32-bit destination index.
178    Edi,
179    /// R8D–R15D — low 32 bits of extended registers.
180    R8d,
181    /// Low 32 bits of R9.
182    R9d,
183    /// Low 32 bits of R10.
184    R10d,
185    /// Low 32 bits of R11.
186    R11d,
187    /// Low 32 bits of R12.
188    R12d,
189    /// Low 32 bits of R13.
190    R13d,
191    /// Low 32 bits of R14.
192    R14d,
193    /// Low 32 bits of R15.
194    R15d,
195    // -- 16-bit general-purpose registers --
196    /// AX — 16-bit accumulator.
197    Ax,
198    /// CX — 16-bit counter.
199    Cx,
200    /// DX — 16-bit data.
201    Dx,
202    /// BX — 16-bit base.
203    Bx,
204    /// SP — 16-bit stack pointer.
205    Sp,
206    /// BP — 16-bit frame pointer.
207    Bp,
208    /// SI — 16-bit source index.
209    Si,
210    /// DI — 16-bit destination index.
211    Di,
212    /// R8W–R15W — low 16 bits of extended registers.
213    R8w,
214    /// Low 16 bits of R9.
215    R9w,
216    /// Low 16 bits of R10.
217    R10w,
218    /// Low 16 bits of R11.
219    R11w,
220    /// Low 16 bits of R12.
221    R12w,
222    /// Low 16 bits of R13.
223    R13w,
224    /// Low 16 bits of R14.
225    R14w,
226    /// Low 16 bits of R15.
227    R15w,
228    // -- 8-bit general-purpose registers --
229    /// AL — low byte of RAX.
230    Al,
231    /// CL — low byte of RCX.
232    Cl,
233    /// DL — low byte of RDX.
234    Dl,
235    /// BL — low byte of RBX.
236    Bl,
237    /// SPL — low byte of RSP (requires REX).
238    Spl,
239    /// BPL — low byte of RBP (requires REX).
240    Bpl,
241    /// SIL — low byte of RSI (requires REX).
242    Sil,
243    /// DIL — low byte of RDI (requires REX).
244    Dil,
245    /// AH — high byte of AX (incompatible with REX prefix).
246    Ah,
247    /// CH — high byte of CX (incompatible with REX prefix).
248    Ch,
249    /// DH — high byte of DX (incompatible with REX prefix).
250    Dh,
251    /// BH — high byte of BX (incompatible with REX prefix).
252    Bh,
253    /// R8B–R15B — low byte of extended registers.
254    R8b,
255    /// Low byte of R9.
256    R9b,
257    /// Low byte of R10.
258    R10b,
259    /// Low byte of R11.
260    R11b,
261    /// Low byte of R12.
262    R12b,
263    /// Low byte of R13.
264    R13b,
265    /// Low byte of R14.
266    R14b,
267    /// Low byte of R15.
268    R15b,
269    // -- Instruction pointer --
270    /// RIP — 64-bit instruction pointer (for RIP-relative addressing).
271    Rip,
272    /// EIP — 32-bit instruction pointer.
273    Eip,
274    // -- Segment registers --
275    /// CS — code segment.
276    Cs,
277    /// DS — data segment.
278    Ds,
279    /// ES — extra segment.
280    Es,
281    /// FS — additional segment (used for TLS on x86-64 Linux).
282    Fs,
283    /// GS — additional segment (used for TLS on x86-64 Windows/macOS).
284    Gs,
285    /// SS — stack segment.
286    Ss,
287    // -- 128-bit SSE registers --
288    /// XMM0 — SSE register 0.
289    Xmm0,
290    /// SSE register 1.
291    Xmm1,
292    /// SSE register 2.
293    Xmm2,
294    /// SSE register 3.
295    Xmm3,
296    /// SSE register 4.
297    Xmm4,
298    /// SSE register 5.
299    Xmm5,
300    /// SSE register 6.
301    Xmm6,
302    /// SSE register 7.
303    Xmm7,
304    /// XMM8–XMM15 — extended SSE registers (require REX prefix).
305    Xmm8,
306    /// Extended SSE register 9.
307    Xmm9,
308    /// Extended SSE register 10.
309    Xmm10,
310    /// Extended SSE register 11.
311    Xmm11,
312    /// Extended SSE register 12.
313    Xmm12,
314    /// Extended SSE register 13.
315    Xmm13,
316    /// Extended SSE register 14.
317    Xmm14,
318    /// Extended SSE register 15.
319    Xmm15,
320    // -- 256-bit AVX registers --
321    /// YMM0 — AVX register 0.
322    Ymm0,
323    /// AVX register 1.
324    Ymm1,
325    /// AVX register 2.
326    Ymm2,
327    /// AVX register 3.
328    Ymm3,
329    /// AVX register 4.
330    Ymm4,
331    /// AVX register 5.
332    Ymm5,
333    /// AVX register 6.
334    Ymm6,
335    /// AVX register 7.
336    Ymm7,
337    /// YMM8–YMM15 — extended AVX registers.
338    Ymm8,
339    /// Extended AVX register 9.
340    Ymm9,
341    /// Extended AVX register 10.
342    Ymm10,
343    /// Extended AVX register 11.
344    Ymm11,
345    /// Extended AVX register 12.
346    Ymm12,
347    /// Extended AVX register 13.
348    Ymm13,
349    /// Extended AVX register 14.
350    Ymm14,
351    /// Extended AVX register 15.
352    Ymm15,
353    // -- 512-bit AVX-512 registers --
354    /// ZMM0 — AVX-512 register 0.
355    Zmm0,
356    /// AVX-512 register 1.
357    Zmm1,
358    /// AVX-512 register 2.
359    Zmm2,
360    /// AVX-512 register 3.
361    Zmm3,
362    /// AVX-512 register 4.
363    Zmm4,
364    /// AVX-512 register 5.
365    Zmm5,
366    /// AVX-512 register 6.
367    Zmm6,
368    /// AVX-512 register 7.
369    Zmm7,
370    /// ZMM8–ZMM15 — extended by REX/VEX.
371    Zmm8,
372    /// AVX-512 register 9.
373    Zmm9,
374    /// AVX-512 register 10.
375    Zmm10,
376    /// AVX-512 register 11.
377    Zmm11,
378    /// AVX-512 register 12.
379    Zmm12,
380    /// AVX-512 register 13.
381    Zmm13,
382    /// AVX-512 register 14.
383    Zmm14,
384    /// AVX-512 register 15.
385    Zmm15,
386    /// ZMM16–ZMM31 — EVEX-only registers.
387    Zmm16,
388    /// EVEX-only AVX-512 register 17.
389    Zmm17,
390    /// EVEX-only AVX-512 register 18.
391    Zmm18,
392    /// EVEX-only AVX-512 register 19.
393    Zmm19,
394    /// EVEX-only AVX-512 register 20.
395    Zmm20,
396    /// EVEX-only AVX-512 register 21.
397    Zmm21,
398    /// EVEX-only AVX-512 register 22.
399    Zmm22,
400    /// EVEX-only AVX-512 register 23.
401    Zmm23,
402    /// EVEX-only AVX-512 register 24.
403    Zmm24,
404    /// EVEX-only AVX-512 register 25.
405    Zmm25,
406    /// EVEX-only AVX-512 register 26.
407    Zmm26,
408    /// EVEX-only AVX-512 register 27.
409    Zmm27,
410    /// EVEX-only AVX-512 register 28.
411    Zmm28,
412    /// EVEX-only AVX-512 register 29.
413    Zmm29,
414    /// EVEX-only AVX-512 register 30.
415    Zmm30,
416    /// EVEX-only AVX-512 register 31.
417    Zmm31,
418    // -- AVX-512 opmask registers --
419    /// K0 — opmask register 0 (implicit, means "no mask").
420    K0,
421    /// K1 — opmask register 1.
422    K1,
423    /// K2 — opmask register 2.
424    K2,
425    /// K3 — opmask register 3.
426    K3,
427    /// K4 — opmask register 4.
428    K4,
429    /// K5 — opmask register 5.
430    K5,
431    /// K6 — opmask register 6.
432    K6,
433    /// K7 — opmask register 7.
434    K7,
435
436    // ── ARM32 general-purpose registers ─────────────────────
437    /// ARM R0.
438    ArmR0,
439    /// ARM R1.
440    ArmR1,
441    /// ARM R2.
442    ArmR2,
443    /// ARM R3.
444    ArmR3,
445    /// ARM R4.
446    ArmR4,
447    /// ARM R5.
448    ArmR5,
449    /// ARM R6.
450    ArmR6,
451    /// ARM R7.
452    ArmR7,
453    /// ARM R8.
454    ArmR8,
455    /// ARM R9.
456    ArmR9,
457    /// ARM R10.
458    ArmR10,
459    /// ARM R11 (FP by convention).
460    ArmR11,
461    /// ARM R12 (IP — intra-procedure scratch).
462    ArmR12,
463    /// ARM R13 / SP — stack pointer.
464    ArmSp,
465    /// ARM R14 / LR — link register.
466    ArmLr,
467    /// ARM R15 / PC — program counter.
468    ArmPc,
469    /// ARM CPSR — current program status register.
470    ArmCpsr,
471
472    // ── AArch64 64-bit general-purpose registers ────────────
473    /// AArch64 X0.
474    A64X0,
475    /// AArch64 X1.
476    A64X1,
477    /// AArch64 X2.
478    A64X2,
479    /// AArch64 X3.
480    A64X3,
481    /// AArch64 X4.
482    A64X4,
483    /// AArch64 X5.
484    A64X5,
485    /// AArch64 X6.
486    A64X6,
487    /// AArch64 X7.
488    A64X7,
489    /// AArch64 X8.
490    A64X8,
491    /// AArch64 X9.
492    A64X9,
493    /// AArch64 X10.
494    A64X10,
495    /// AArch64 X11.
496    A64X11,
497    /// AArch64 X12.
498    A64X12,
499    /// AArch64 X13.
500    A64X13,
501    /// AArch64 X14.
502    A64X14,
503    /// AArch64 X15.
504    A64X15,
505    /// AArch64 X16.
506    A64X16,
507    /// AArch64 X17.
508    A64X17,
509    /// AArch64 X18.
510    A64X18,
511    /// AArch64 X19.
512    A64X19,
513    /// AArch64 X20.
514    A64X20,
515    /// AArch64 X21.
516    A64X21,
517    /// AArch64 X22.
518    A64X22,
519    /// AArch64 X23.
520    A64X23,
521    /// AArch64 X24.
522    A64X24,
523    /// AArch64 X25.
524    A64X25,
525    /// AArch64 X26.
526    A64X26,
527    /// AArch64 X27.
528    A64X27,
529    /// AArch64 X28.
530    A64X28,
531    /// AArch64 X29 / FP — frame pointer.
532    A64X29,
533    /// AArch64 X30 / LR — link register.
534    A64X30,
535    /// AArch64 SP — stack pointer (64-bit).
536    A64Sp,
537    /// AArch64 XZR — zero register (64-bit).
538    A64Xzr,
539
540    // ── AArch64 32-bit general-purpose registers ────────────
541    /// AArch64 W0.
542    A64W0,
543    /// AArch64 W1.
544    A64W1,
545    /// AArch64 W2.
546    A64W2,
547    /// AArch64 W3.
548    A64W3,
549    /// AArch64 W4.
550    A64W4,
551    /// AArch64 W5.
552    A64W5,
553    /// AArch64 W6.
554    A64W6,
555    /// AArch64 W7.
556    A64W7,
557    /// AArch64 W8.
558    A64W8,
559    /// AArch64 W9.
560    A64W9,
561    /// AArch64 W10.
562    A64W10,
563    /// AArch64 W11.
564    A64W11,
565    /// AArch64 W12.
566    A64W12,
567    /// AArch64 W13.
568    A64W13,
569    /// AArch64 W14.
570    A64W14,
571    /// AArch64 W15.
572    A64W15,
573    /// AArch64 W16.
574    A64W16,
575    /// AArch64 W17.
576    A64W17,
577    /// AArch64 W18.
578    A64W18,
579    /// AArch64 W19.
580    A64W19,
581    /// AArch64 W20.
582    A64W20,
583    /// AArch64 W21.
584    A64W21,
585    /// AArch64 W22.
586    A64W22,
587    /// AArch64 W23.
588    A64W23,
589    /// AArch64 W24.
590    A64W24,
591    /// AArch64 W25.
592    A64W25,
593    /// AArch64 W26.
594    A64W26,
595    /// AArch64 W27.
596    A64W27,
597    /// AArch64 W28.
598    A64W28,
599    /// AArch64 W29.
600    A64W29,
601    /// AArch64 W30.
602    A64W30,
603    /// AArch64 WZR — zero register (32-bit).
604    A64Wzr,
605    /// AArch64 WSP — stack pointer (32-bit view).
606    A64Wsp,
607
608    // ── AArch64 SIMD/FP registers (V0–V31, 128-bit) ────────
609    /// AArch64 128-bit SIMD/FP register V0.
610    A64V0,
611    /// AArch64 128-bit SIMD/FP register V1.
612    A64V1,
613    /// AArch64 128-bit SIMD/FP register V2.
614    A64V2,
615    /// AArch64 128-bit SIMD/FP register V3.
616    A64V3,
617    /// AArch64 128-bit SIMD/FP register V4.
618    A64V4,
619    /// AArch64 128-bit SIMD/FP register V5.
620    A64V5,
621    /// AArch64 128-bit SIMD/FP register V6.
622    A64V6,
623    /// AArch64 128-bit SIMD/FP register V7.
624    A64V7,
625    /// AArch64 128-bit SIMD/FP register V8.
626    A64V8,
627    /// AArch64 128-bit SIMD/FP register V9.
628    A64V9,
629    /// AArch64 128-bit SIMD/FP register V10.
630    A64V10,
631    /// AArch64 128-bit SIMD/FP register V11.
632    A64V11,
633    /// AArch64 128-bit SIMD/FP register V12.
634    A64V12,
635    /// AArch64 128-bit SIMD/FP register V13.
636    A64V13,
637    /// AArch64 128-bit SIMD/FP register V14.
638    A64V14,
639    /// AArch64 128-bit SIMD/FP register V15.
640    A64V15,
641    /// AArch64 128-bit SIMD/FP register V16.
642    A64V16,
643    /// AArch64 128-bit SIMD/FP register V17.
644    A64V17,
645    /// AArch64 128-bit SIMD/FP register V18.
646    A64V18,
647    /// AArch64 128-bit SIMD/FP register V19.
648    A64V19,
649    /// AArch64 128-bit SIMD/FP register V20.
650    A64V20,
651    /// AArch64 128-bit SIMD/FP register V21.
652    A64V21,
653    /// AArch64 128-bit SIMD/FP register V22.
654    A64V22,
655    /// AArch64 128-bit SIMD/FP register V23.
656    A64V23,
657    /// AArch64 128-bit SIMD/FP register V24.
658    A64V24,
659    /// AArch64 128-bit SIMD/FP register V25.
660    A64V25,
661    /// AArch64 128-bit SIMD/FP register V26.
662    A64V26,
663    /// AArch64 128-bit SIMD/FP register V27.
664    A64V27,
665    /// AArch64 128-bit SIMD/FP register V28.
666    A64V28,
667    /// AArch64 128-bit SIMD/FP register V29.
668    A64V29,
669    /// AArch64 128-bit SIMD/FP register V30.
670    A64V30,
671    /// AArch64 128-bit SIMD/FP register V31.
672    A64V31,
673
674    // ── AArch64 SIMD/FP scalar registers (Q, D, S, H, B) ───
675    /// AArch64 128-bit scalar quad register Q0.
676    A64Q0,
677    /// AArch64 128-bit scalar quad register Q1.
678    A64Q1,
679    /// AArch64 128-bit scalar quad register Q2.
680    A64Q2,
681    /// AArch64 128-bit scalar quad register Q3.
682    A64Q3,
683    /// AArch64 128-bit scalar quad register Q4.
684    A64Q4,
685    /// AArch64 128-bit scalar quad register Q5.
686    A64Q5,
687    /// AArch64 128-bit scalar quad register Q6.
688    A64Q6,
689    /// AArch64 128-bit scalar quad register Q7.
690    A64Q7,
691    /// AArch64 128-bit scalar quad register Q8.
692    A64Q8,
693    /// AArch64 128-bit scalar quad register Q9.
694    A64Q9,
695    /// AArch64 128-bit scalar quad register Q10.
696    A64Q10,
697    /// AArch64 128-bit scalar quad register Q11.
698    A64Q11,
699    /// AArch64 128-bit scalar quad register Q12.
700    A64Q12,
701    /// AArch64 128-bit scalar quad register Q13.
702    A64Q13,
703    /// AArch64 128-bit scalar quad register Q14.
704    A64Q14,
705    /// AArch64 128-bit scalar quad register Q15.
706    A64Q15,
707    /// AArch64 128-bit scalar quad register Q16.
708    A64Q16,
709    /// AArch64 128-bit scalar quad register Q17.
710    A64Q17,
711    /// AArch64 128-bit scalar quad register Q18.
712    A64Q18,
713    /// AArch64 128-bit scalar quad register Q19.
714    A64Q19,
715    /// AArch64 128-bit scalar quad register Q20.
716    A64Q20,
717    /// AArch64 128-bit scalar quad register Q21.
718    A64Q21,
719    /// AArch64 128-bit scalar quad register Q22.
720    A64Q22,
721    /// AArch64 128-bit scalar quad register Q23.
722    A64Q23,
723    /// AArch64 128-bit scalar quad register Q24.
724    A64Q24,
725    /// AArch64 128-bit scalar quad register Q25.
726    A64Q25,
727    /// AArch64 128-bit scalar quad register Q26.
728    A64Q26,
729    /// AArch64 128-bit scalar quad register Q27.
730    A64Q27,
731    /// AArch64 128-bit scalar quad register Q28.
732    A64Q28,
733    /// AArch64 128-bit scalar quad register Q29.
734    A64Q29,
735    /// AArch64 128-bit scalar quad register Q30.
736    A64Q30,
737    /// AArch64 128-bit scalar quad register Q31.
738    A64Q31,
739    /// AArch64 64-bit scalar double register D0.
740    A64D0,
741    /// AArch64 64-bit scalar double register D1.
742    A64D1,
743    /// AArch64 64-bit scalar double register D2.
744    A64D2,
745    /// AArch64 64-bit scalar double register D3.
746    A64D3,
747    /// AArch64 64-bit scalar double register D4.
748    A64D4,
749    /// AArch64 64-bit scalar double register D5.
750    A64D5,
751    /// AArch64 64-bit scalar double register D6.
752    A64D6,
753    /// AArch64 64-bit scalar double register D7.
754    A64D7,
755    /// AArch64 64-bit scalar double register D8.
756    A64D8,
757    /// AArch64 64-bit scalar double register D9.
758    A64D9,
759    /// AArch64 64-bit scalar double register D10.
760    A64D10,
761    /// AArch64 64-bit scalar double register D11.
762    A64D11,
763    /// AArch64 64-bit scalar double register D12.
764    A64D12,
765    /// AArch64 64-bit scalar double register D13.
766    A64D13,
767    /// AArch64 64-bit scalar double register D14.
768    A64D14,
769    /// AArch64 64-bit scalar double register D15.
770    A64D15,
771    /// AArch64 64-bit scalar double register D16.
772    A64D16,
773    /// AArch64 64-bit scalar double register D17.
774    A64D17,
775    /// AArch64 64-bit scalar double register D18.
776    A64D18,
777    /// AArch64 64-bit scalar double register D19.
778    A64D19,
779    /// AArch64 64-bit scalar double register D20.
780    A64D20,
781    /// AArch64 64-bit scalar double register D21.
782    A64D21,
783    /// AArch64 64-bit scalar double register D22.
784    A64D22,
785    /// AArch64 64-bit scalar double register D23.
786    A64D23,
787    /// AArch64 64-bit scalar double register D24.
788    A64D24,
789    /// AArch64 64-bit scalar double register D25.
790    A64D25,
791    /// AArch64 64-bit scalar double register D26.
792    A64D26,
793    /// AArch64 64-bit scalar double register D27.
794    A64D27,
795    /// AArch64 64-bit scalar double register D28.
796    A64D28,
797    /// AArch64 64-bit scalar double register D29.
798    A64D29,
799    /// AArch64 64-bit scalar double register D30.
800    A64D30,
801    /// AArch64 64-bit scalar double register D31.
802    A64D31,
803    /// AArch64 32-bit scalar single register S0.
804    A64S0,
805    /// AArch64 32-bit scalar single register S1.
806    A64S1,
807    /// AArch64 32-bit scalar single register S2.
808    A64S2,
809    /// AArch64 32-bit scalar single register S3.
810    A64S3,
811    /// AArch64 32-bit scalar single register S4.
812    A64S4,
813    /// AArch64 32-bit scalar single register S5.
814    A64S5,
815    /// AArch64 32-bit scalar single register S6.
816    A64S6,
817    /// AArch64 32-bit scalar single register S7.
818    A64S7,
819    /// AArch64 32-bit scalar single register S8.
820    A64S8,
821    /// AArch64 32-bit scalar single register S9.
822    A64S9,
823    /// AArch64 32-bit scalar single register S10.
824    A64S10,
825    /// AArch64 32-bit scalar single register S11.
826    A64S11,
827    /// AArch64 32-bit scalar single register S12.
828    A64S12,
829    /// AArch64 32-bit scalar single register S13.
830    A64S13,
831    /// AArch64 32-bit scalar single register S14.
832    A64S14,
833    /// AArch64 32-bit scalar single register S15.
834    A64S15,
835    /// AArch64 32-bit scalar single register S16.
836    A64S16,
837    /// AArch64 32-bit scalar single register S17.
838    A64S17,
839    /// AArch64 32-bit scalar single register S18.
840    A64S18,
841    /// AArch64 32-bit scalar single register S19.
842    A64S19,
843    /// AArch64 32-bit scalar single register S20.
844    A64S20,
845    /// AArch64 32-bit scalar single register S21.
846    A64S21,
847    /// AArch64 32-bit scalar single register S22.
848    A64S22,
849    /// AArch64 32-bit scalar single register S23.
850    A64S23,
851    /// AArch64 32-bit scalar single register S24.
852    A64S24,
853    /// AArch64 32-bit scalar single register S25.
854    A64S25,
855    /// AArch64 32-bit scalar single register S26.
856    A64S26,
857    /// AArch64 32-bit scalar single register S27.
858    A64S27,
859    /// AArch64 32-bit scalar single register S28.
860    A64S28,
861    /// AArch64 32-bit scalar single register S29.
862    A64S29,
863    /// AArch64 32-bit scalar single register S30.
864    A64S30,
865    /// AArch64 32-bit scalar single register S31.
866    A64S31,
867    /// AArch64 16-bit scalar half register H0.
868    A64H0,
869    /// AArch64 16-bit scalar half register H1.
870    A64H1,
871    /// AArch64 16-bit scalar half register H2.
872    A64H2,
873    /// AArch64 16-bit scalar half register H3.
874    A64H3,
875    /// AArch64 16-bit scalar half register H4.
876    A64H4,
877    /// AArch64 16-bit scalar half register H5.
878    A64H5,
879    /// AArch64 16-bit scalar half register H6.
880    A64H6,
881    /// AArch64 16-bit scalar half register H7.
882    A64H7,
883    /// AArch64 16-bit scalar half register H8.
884    A64H8,
885    /// AArch64 16-bit scalar half register H9.
886    A64H9,
887    /// AArch64 16-bit scalar half register H10.
888    A64H10,
889    /// AArch64 16-bit scalar half register H11.
890    A64H11,
891    /// AArch64 16-bit scalar half register H12.
892    A64H12,
893    /// AArch64 16-bit scalar half register H13.
894    A64H13,
895    /// AArch64 16-bit scalar half register H14.
896    A64H14,
897    /// AArch64 16-bit scalar half register H15.
898    A64H15,
899    /// AArch64 16-bit scalar half register H16.
900    A64H16,
901    /// AArch64 16-bit scalar half register H17.
902    A64H17,
903    /// AArch64 16-bit scalar half register H18.
904    A64H18,
905    /// AArch64 16-bit scalar half register H19.
906    A64H19,
907    /// AArch64 16-bit scalar half register H20.
908    A64H20,
909    /// AArch64 16-bit scalar half register H21.
910    A64H21,
911    /// AArch64 16-bit scalar half register H22.
912    A64H22,
913    /// AArch64 16-bit scalar half register H23.
914    A64H23,
915    /// AArch64 16-bit scalar half register H24.
916    A64H24,
917    /// AArch64 16-bit scalar half register H25.
918    A64H25,
919    /// AArch64 16-bit scalar half register H26.
920    A64H26,
921    /// AArch64 16-bit scalar half register H27.
922    A64H27,
923    /// AArch64 16-bit scalar half register H28.
924    A64H28,
925    /// AArch64 16-bit scalar half register H29.
926    A64H29,
927    /// AArch64 16-bit scalar half register H30.
928    A64H30,
929    /// AArch64 16-bit scalar half register H31.
930    A64H31,
931    /// AArch64 8-bit scalar byte register B0.
932    A64B0,
933    /// AArch64 8-bit scalar byte register B1.
934    A64B1,
935    /// AArch64 8-bit scalar byte register B2.
936    A64B2,
937    /// AArch64 8-bit scalar byte register B3.
938    A64B3,
939    /// AArch64 8-bit scalar byte register B4.
940    A64B4,
941    /// AArch64 8-bit scalar byte register B5.
942    A64B5,
943    /// AArch64 8-bit scalar byte register B6.
944    A64B6,
945    /// AArch64 8-bit scalar byte register B7.
946    A64B7,
947    /// AArch64 8-bit scalar byte register B8.
948    A64B8,
949    /// AArch64 8-bit scalar byte register B9.
950    A64B9,
951    /// AArch64 8-bit scalar byte register B10.
952    A64B10,
953    /// AArch64 8-bit scalar byte register B11.
954    A64B11,
955    /// AArch64 8-bit scalar byte register B12.
956    A64B12,
957    /// AArch64 8-bit scalar byte register B13.
958    A64B13,
959    /// AArch64 8-bit scalar byte register B14.
960    A64B14,
961    /// AArch64 8-bit scalar byte register B15.
962    A64B15,
963    /// AArch64 8-bit scalar byte register B16.
964    A64B16,
965    /// AArch64 8-bit scalar byte register B17.
966    A64B17,
967    /// AArch64 8-bit scalar byte register B18.
968    A64B18,
969    /// AArch64 8-bit scalar byte register B19.
970    A64B19,
971    /// AArch64 8-bit scalar byte register B20.
972    A64B20,
973    /// AArch64 8-bit scalar byte register B21.
974    A64B21,
975    /// AArch64 8-bit scalar byte register B22.
976    A64B22,
977    /// AArch64 8-bit scalar byte register B23.
978    A64B23,
979    /// AArch64 8-bit scalar byte register B24.
980    A64B24,
981    /// AArch64 8-bit scalar byte register B25.
982    A64B25,
983    /// AArch64 8-bit scalar byte register B26.
984    A64B26,
985    /// AArch64 8-bit scalar byte register B27.
986    A64B27,
987    /// AArch64 8-bit scalar byte register B28.
988    A64B28,
989    /// AArch64 8-bit scalar byte register B29.
990    A64B29,
991    /// AArch64 8-bit scalar byte register B30.
992    A64B30,
993    /// AArch64 8-bit scalar byte register B31.
994    A64B31,
995
996    // ── AArch64 SVE scalable vector registers (Z0–Z31) ──────
997    /// AArch64 SVE scalable vector register Z0.
998    A64Z0,
999    /// AArch64 SVE scalable vector register Z1.
1000    A64Z1,
1001    /// AArch64 SVE scalable vector register Z2.
1002    A64Z2,
1003    /// AArch64 SVE scalable vector register Z3.
1004    A64Z3,
1005    /// AArch64 SVE scalable vector register Z4.
1006    A64Z4,
1007    /// AArch64 SVE scalable vector register Z5.
1008    A64Z5,
1009    /// AArch64 SVE scalable vector register Z6.
1010    A64Z6,
1011    /// AArch64 SVE scalable vector register Z7.
1012    A64Z7,
1013    /// AArch64 SVE scalable vector register Z8.
1014    A64Z8,
1015    /// AArch64 SVE scalable vector register Z9.
1016    A64Z9,
1017    /// AArch64 SVE scalable vector register Z10.
1018    A64Z10,
1019    /// AArch64 SVE scalable vector register Z11.
1020    A64Z11,
1021    /// AArch64 SVE scalable vector register Z12.
1022    A64Z12,
1023    /// AArch64 SVE scalable vector register Z13.
1024    A64Z13,
1025    /// AArch64 SVE scalable vector register Z14.
1026    A64Z14,
1027    /// AArch64 SVE scalable vector register Z15.
1028    A64Z15,
1029    /// AArch64 SVE scalable vector register Z16.
1030    A64Z16,
1031    /// AArch64 SVE scalable vector register Z17.
1032    A64Z17,
1033    /// AArch64 SVE scalable vector register Z18.
1034    A64Z18,
1035    /// AArch64 SVE scalable vector register Z19.
1036    A64Z19,
1037    /// AArch64 SVE scalable vector register Z20.
1038    A64Z20,
1039    /// AArch64 SVE scalable vector register Z21.
1040    A64Z21,
1041    /// AArch64 SVE scalable vector register Z22.
1042    A64Z22,
1043    /// AArch64 SVE scalable vector register Z23.
1044    A64Z23,
1045    /// AArch64 SVE scalable vector register Z24.
1046    A64Z24,
1047    /// AArch64 SVE scalable vector register Z25.
1048    A64Z25,
1049    /// AArch64 SVE scalable vector register Z26.
1050    A64Z26,
1051    /// AArch64 SVE scalable vector register Z27.
1052    A64Z27,
1053    /// AArch64 SVE scalable vector register Z28.
1054    A64Z28,
1055    /// AArch64 SVE scalable vector register Z29.
1056    A64Z29,
1057    /// AArch64 SVE scalable vector register Z30.
1058    A64Z30,
1059    /// AArch64 SVE scalable vector register Z31.
1060    A64Z31,
1061
1062    // ── AArch64 SVE predicate registers (P0–P15) ────────────
1063    /// AArch64 SVE predicate register P0.
1064    A64P0,
1065    /// AArch64 SVE predicate register P1.
1066    A64P1,
1067    /// AArch64 SVE predicate register P2.
1068    A64P2,
1069    /// AArch64 SVE predicate register P3.
1070    A64P3,
1071    /// AArch64 SVE predicate register P4.
1072    A64P4,
1073    /// AArch64 SVE predicate register P5.
1074    A64P5,
1075    /// AArch64 SVE predicate register P6.
1076    A64P6,
1077    /// AArch64 SVE predicate register P7.
1078    A64P7,
1079    /// AArch64 SVE predicate register P8.
1080    A64P8,
1081    /// AArch64 SVE predicate register P9.
1082    A64P9,
1083    /// AArch64 SVE predicate register P10.
1084    A64P10,
1085    /// AArch64 SVE predicate register P11.
1086    A64P11,
1087    /// AArch64 SVE predicate register P12.
1088    A64P12,
1089    /// AArch64 SVE predicate register P13.
1090    A64P13,
1091    /// AArch64 SVE predicate register P14.
1092    A64P14,
1093    /// AArch64 SVE predicate register P15.
1094    A64P15,
1095
1096    // ── RISC-V integer registers (x0–x31) ───────────────────
1097    /// RISC-V x0 / zero — hardwired zero.
1098    RvX0,
1099    /// RISC-V x1 / ra — return address.
1100    RvX1,
1101    /// RISC-V x2 / sp — stack pointer.
1102    RvX2,
1103    /// RISC-V x3 / gp — global pointer.
1104    RvX3,
1105    /// RISC-V x4 / tp — thread pointer.
1106    RvX4,
1107    /// RISC-V x5 / t0 — temporary.
1108    RvX5,
1109    /// RISC-V x6 / t1 — temporary.
1110    RvX6,
1111    /// RISC-V x7 / t2 — temporary.
1112    RvX7,
1113    /// RISC-V x8 / s0 / fp — saved / frame pointer.
1114    RvX8,
1115    /// RISC-V x9 / s1 — saved register.
1116    RvX9,
1117    /// RISC-V x10 / a0 — argument / return value.
1118    RvX10,
1119    /// RISC-V x11 / a1 — argument / return value.
1120    RvX11,
1121    /// RISC-V x12 / a2 — argument.
1122    RvX12,
1123    /// RISC-V x13 / a3 — argument.
1124    RvX13,
1125    /// RISC-V x14 / a4 — argument.
1126    RvX14,
1127    /// RISC-V x15 / a5 — argument.
1128    RvX15,
1129    /// RISC-V x16 / a6 — argument.
1130    RvX16,
1131    /// RISC-V x17 / a7 — argument.
1132    RvX17,
1133    /// RISC-V x18 / s2 — saved register.
1134    RvX18,
1135    /// RISC-V x19 / s3 — saved register.
1136    RvX19,
1137    /// RISC-V x20 / s4 — saved register.
1138    RvX20,
1139    /// RISC-V x21 / s5 — saved register.
1140    RvX21,
1141    /// RISC-V x22 / s6 — saved register.
1142    RvX22,
1143    /// RISC-V x23 / s7 — saved register.
1144    RvX23,
1145    /// RISC-V x24 / s8 — saved register.
1146    RvX24,
1147    /// RISC-V x25 / s9 — saved register.
1148    RvX25,
1149    /// RISC-V x26 / s10 — saved register.
1150    RvX26,
1151    /// RISC-V x27 / s11 — saved register.
1152    RvX27,
1153    /// RISC-V x28 / t3 — temporary.
1154    RvX28,
1155    /// RISC-V x29 / t4 — temporary.
1156    RvX29,
1157    /// RISC-V x30 / t5 — temporary.
1158    RvX30,
1159    /// RISC-V x31 / t6 — temporary.
1160    RvX31,
1161
1162    // ── RISC-V floating-point registers (f0–f31) ────────────
1163    /// RISC-V f0 / ft0 — FP temporary.
1164    RvF0,
1165    /// RISC-V f1 / ft1 — FP temporary.
1166    RvF1,
1167    /// RISC-V f2 / ft2 — FP temporary.
1168    RvF2,
1169    /// RISC-V f3 / ft3 — FP temporary.
1170    RvF3,
1171    /// RISC-V f4 / ft4 — FP temporary.
1172    RvF4,
1173    /// RISC-V f5 / ft5 — FP temporary.
1174    RvF5,
1175    /// RISC-V f6 / ft6 — FP temporary.
1176    RvF6,
1177    /// RISC-V f7 / ft7 — FP temporary.
1178    RvF7,
1179    /// RISC-V f8 / fs0 — FP saved register.
1180    RvF8,
1181    /// RISC-V f9 / fs1 — FP saved register.
1182    RvF9,
1183    /// RISC-V f10 / fa0 — FP argument/return value.
1184    RvF10,
1185    /// RISC-V f11 / fa1 — FP argument/return value.
1186    RvF11,
1187    /// RISC-V f12 / fa2 — FP argument.
1188    RvF12,
1189    /// RISC-V f13 / fa3 — FP argument.
1190    RvF13,
1191    /// RISC-V f14 / fa4 — FP argument.
1192    RvF14,
1193    /// RISC-V f15 / fa5 — FP argument.
1194    RvF15,
1195    /// RISC-V f16 / fa6 — FP argument.
1196    RvF16,
1197    /// RISC-V f17 / fa7 — FP argument.
1198    RvF17,
1199    /// RISC-V f18 / fs2 — FP saved register.
1200    RvF18,
1201    /// RISC-V f19 / fs3 — FP saved register.
1202    RvF19,
1203    /// RISC-V f20 / fs4 — FP saved register.
1204    RvF20,
1205    /// RISC-V f21 / fs5 — FP saved register.
1206    RvF21,
1207    /// RISC-V f22 / fs6 — FP saved register.
1208    RvF22,
1209    /// RISC-V f23 / fs7 — FP saved register.
1210    RvF23,
1211    /// RISC-V f24 / fs8 — FP saved register.
1212    RvF24,
1213    /// RISC-V f25 / fs9 — FP saved register.
1214    RvF25,
1215    /// RISC-V f26 / fs10 — FP saved register.
1216    RvF26,
1217    /// RISC-V f27 / fs11 — FP saved register.
1218    RvF27,
1219    /// RISC-V f28 / ft8 — FP temporary.
1220    RvF28,
1221    /// RISC-V f29 / ft9 — FP temporary.
1222    RvF29,
1223    /// RISC-V f30 / ft10 — FP temporary.
1224    RvF30,
1225    /// RISC-V f31 / ft11 — FP temporary.
1226    RvF31,
1227
1228    // ── RISC-V vector registers (v0–v31) ────────────────────
1229    /// RISC-V vector register v0 (also used as mask).
1230    RvV0,
1231    /// RISC-V vector register v1.
1232    RvV1,
1233    /// RISC-V vector register v2.
1234    RvV2,
1235    /// RISC-V vector register v3.
1236    RvV3,
1237    /// RISC-V vector register v4.
1238    RvV4,
1239    /// RISC-V vector register v5.
1240    RvV5,
1241    /// RISC-V vector register v6.
1242    RvV6,
1243    /// RISC-V vector register v7.
1244    RvV7,
1245    /// RISC-V vector register v8.
1246    RvV8,
1247    /// RISC-V vector register v9.
1248    RvV9,
1249    /// RISC-V vector register v10.
1250    RvV10,
1251    /// RISC-V vector register v11.
1252    RvV11,
1253    /// RISC-V vector register v12.
1254    RvV12,
1255    /// RISC-V vector register v13.
1256    RvV13,
1257    /// RISC-V vector register v14.
1258    RvV14,
1259    /// RISC-V vector register v15.
1260    RvV15,
1261    /// RISC-V vector register v16.
1262    RvV16,
1263    /// RISC-V vector register v17.
1264    RvV17,
1265    /// RISC-V vector register v18.
1266    RvV18,
1267    /// RISC-V vector register v19.
1268    RvV19,
1269    /// RISC-V vector register v20.
1270    RvV20,
1271    /// RISC-V vector register v21.
1272    RvV21,
1273    /// RISC-V vector register v22.
1274    RvV22,
1275    /// RISC-V vector register v23.
1276    RvV23,
1277    /// RISC-V vector register v24.
1278    RvV24,
1279    /// RISC-V vector register v25.
1280    RvV25,
1281    /// RISC-V vector register v26.
1282    RvV26,
1283    /// RISC-V vector register v27.
1284    RvV27,
1285    /// RISC-V vector register v28.
1286    RvV28,
1287    /// RISC-V vector register v29.
1288    RvV29,
1289    /// RISC-V vector register v30.
1290    RvV30,
1291    /// RISC-V vector register v31.
1292    RvV31,
1293}
1294
1295impl Register {
1296    /// The 3-bit register encoding (bits 0-2 of the register number).
1297    pub fn base_code(self) -> u8 {
1298        use Register::*;
1299        match self {
1300            Rax | Eax | Ax | Al | R8 | R8d | R8w | R8b | Xmm0 | Xmm8 | Ymm0 | Ymm8 | Zmm0
1301            | Zmm8 | Zmm16 | Zmm24 | K0 => 0,
1302            Rcx | Ecx | Cx | Cl | R9 | R9d | R9w | R9b | Xmm1 | Xmm9 | Ymm1 | Ymm9 | Zmm1
1303            | Zmm9 | Zmm17 | Zmm25 | K1 => 1,
1304            Rdx | Edx | Dx | Dl | R10 | R10d | R10w | R10b | Xmm2 | Xmm10 | Ymm2 | Ymm10 | Zmm2
1305            | Zmm10 | Zmm18 | Zmm26 | K2 => 2,
1306            Rbx | Ebx | Bx | Bl | R11 | R11d | R11w | R11b | Xmm3 | Xmm11 | Ymm3 | Ymm11 | Zmm3
1307            | Zmm11 | Zmm19 | Zmm27 | K3 => 3,
1308            Rsp | Esp | Sp | Spl | Ah | R12 | R12d | R12w | R12b | Xmm4 | Xmm12 | Ymm4 | Ymm12
1309            | Zmm4 | Zmm12 | Zmm20 | Zmm28 | K4 => 4,
1310            Rbp | Ebp | Bp | Bpl | Ch | R13 | R13d | R13w | R13b | Xmm5 | Xmm13 | Ymm5 | Ymm13
1311            | Zmm5 | Zmm13 | Zmm21 | Zmm29 | K5 => 5,
1312            Rsi | Esi | Si | Sil | Dh | R14 | R14d | R14w | R14b | Xmm6 | Xmm14 | Ymm6 | Ymm14
1313            | Zmm6 | Zmm14 | Zmm22 | Zmm30 | K6 => 6,
1314            Rdi | Edi | Di | Dil | Bh | R15 | R15d | R15w | R15b | Xmm7 | Xmm15 | Ymm7 | Ymm15
1315            | Zmm7 | Zmm15 | Zmm23 | Zmm31 | K7 => 7,
1316            Rip | Eip => 5, // RIP-relative uses encoding 5 (mod=00, rm=101)
1317            Cs => 1,
1318            Ds => 3,
1319            Es => 0,
1320            Fs => 4,
1321            Gs => 5,
1322            Ss => 2,
1323            // ARM/AArch64 registers don't use x86 base_code — see arm_reg_num / a64_reg_num
1324            _ => 0,
1325        }
1326    }
1327
1328    /// Whether this is an extended register (R8–R15, Xmm8–Xmm15, Ymm8–Ymm15, Zmm8–Zmm15, Zmm24–Zmm31)
1329    /// requiring REX/VEX.R or REX/VEX.B (bit 3 of the register index).
1330    pub fn is_extended(self) -> bool {
1331        use Register::*;
1332        matches!(
1333            self,
1334            R8 | R9
1335                | R10
1336                | R11
1337                | R12
1338                | R13
1339                | R14
1340                | R15
1341                | R8d
1342                | R9d
1343                | R10d
1344                | R11d
1345                | R12d
1346                | R13d
1347                | R14d
1348                | R15d
1349                | R8w
1350                | R9w
1351                | R10w
1352                | R11w
1353                | R12w
1354                | R13w
1355                | R14w
1356                | R15w
1357                | R8b
1358                | R9b
1359                | R10b
1360                | R11b
1361                | R12b
1362                | R13b
1363                | R14b
1364                | R15b
1365                | Xmm8
1366                | Xmm9
1367                | Xmm10
1368                | Xmm11
1369                | Xmm12
1370                | Xmm13
1371                | Xmm14
1372                | Xmm15
1373                | Ymm8
1374                | Ymm9
1375                | Ymm10
1376                | Ymm11
1377                | Ymm12
1378                | Ymm13
1379                | Ymm14
1380                | Ymm15
1381                | Zmm8
1382                | Zmm9
1383                | Zmm10
1384                | Zmm11
1385                | Zmm12
1386                | Zmm13
1387                | Zmm14
1388                | Zmm15
1389                | Zmm24
1390                | Zmm25
1391                | Zmm26
1392                | Zmm27
1393                | Zmm28
1394                | Zmm29
1395                | Zmm30
1396                | Zmm31
1397        )
1398    }
1399
1400    /// Whether this register requires EVEX (ZMM16–ZMM31).
1401    /// These need the EVEX.R' and/or EVEX.V' bits.
1402    pub fn is_evex_extended(self) -> bool {
1403        use Register::*;
1404        matches!(
1405            self,
1406            Zmm16
1407                | Zmm17
1408                | Zmm18
1409                | Zmm19
1410                | Zmm20
1411                | Zmm21
1412                | Zmm22
1413                | Zmm23
1414                | Zmm24
1415                | Zmm25
1416                | Zmm26
1417                | Zmm27
1418                | Zmm28
1419                | Zmm29
1420                | Zmm30
1421                | Zmm31
1422        )
1423    }
1424
1425    /// Size of the register in bits.
1426    pub fn size_bits(self) -> u16 {
1427        use Register::*;
1428        match self {
1429            Rax | Rcx | Rdx | Rbx | Rsp | Rbp | Rsi | Rdi | R8 | R9 | R10 | R11 | R12 | R13
1430            | R14 | R15 | Rip => 64,
1431            Eax | Ecx | Edx | Ebx | Esp | Ebp | Esi | Edi | R8d | R9d | R10d | R11d | R12d
1432            | R13d | R14d | R15d | Eip => 32,
1433            Ax | Cx | Dx | Bx | Sp | Bp | Si | Di | R8w | R9w | R10w | R11w | R12w | R13w
1434            | R14w | R15w => 16,
1435            Al | Cl | Dl | Bl | Spl | Bpl | Sil | Dil | Ah | Ch | Dh | Bh | R8b | R9b | R10b
1436            | R11b | R12b | R13b | R14b | R15b => 8,
1437            Cs | Ds | Es | Fs | Gs | Ss => 16,
1438            Xmm0 | Xmm1 | Xmm2 | Xmm3 | Xmm4 | Xmm5 | Xmm6 | Xmm7 | Xmm8 | Xmm9 | Xmm10 | Xmm11
1439            | Xmm12 | Xmm13 | Xmm14 | Xmm15 => 128,
1440            Ymm0 | Ymm1 | Ymm2 | Ymm3 | Ymm4 | Ymm5 | Ymm6 | Ymm7 | Ymm8 | Ymm9 | Ymm10 | Ymm11
1441            | Ymm12 | Ymm13 | Ymm14 | Ymm15 => 256,
1442            Zmm0 | Zmm1 | Zmm2 | Zmm3 | Zmm4 | Zmm5 | Zmm6 | Zmm7 | Zmm8 | Zmm9 | Zmm10 | Zmm11
1443            | Zmm12 | Zmm13 | Zmm14 | Zmm15 | Zmm16 | Zmm17 | Zmm18 | Zmm19 | Zmm20 | Zmm21
1444            | Zmm22 | Zmm23 | Zmm24 | Zmm25 | Zmm26 | Zmm27 | Zmm28 | Zmm29 | Zmm30 | Zmm31 => 512,
1445            K0 | K1 | K2 | K3 | K4 | K5 | K6 | K7 => 64,
1446            // ARM32 registers
1447            ArmR0 | ArmR1 | ArmR2 | ArmR3 | ArmR4 | ArmR5 | ArmR6 | ArmR7 | ArmR8 | ArmR9
1448            | ArmR10 | ArmR11 | ArmR12 | ArmSp | ArmLr | ArmPc | ArmCpsr => 32,
1449            // AArch64 64-bit registers
1450            A64X0 | A64X1 | A64X2 | A64X3 | A64X4 | A64X5 | A64X6 | A64X7 | A64X8 | A64X9
1451            | A64X10 | A64X11 | A64X12 | A64X13 | A64X14 | A64X15 | A64X16 | A64X17 | A64X18
1452            | A64X19 | A64X20 | A64X21 | A64X22 | A64X23 | A64X24 | A64X25 | A64X26 | A64X27
1453            | A64X28 | A64X29 | A64X30 | A64Sp | A64Xzr => 64,
1454            // AArch64 32-bit registers
1455            A64W0 | A64W1 | A64W2 | A64W3 | A64W4 | A64W5 | A64W6 | A64W7 | A64W8 | A64W9
1456            | A64W10 | A64W11 | A64W12 | A64W13 | A64W14 | A64W15 | A64W16 | A64W17 | A64W18
1457            | A64W19 | A64W20 | A64W21 | A64W22 | A64W23 | A64W24 | A64W25 | A64W26 | A64W27
1458            | A64W28 | A64W29 | A64W30 | A64Wzr | A64Wsp => 32,
1459            // AArch64 SIMD/FP registers — V and Q are 128-bit
1460            A64V0 | A64V1 | A64V2 | A64V3 | A64V4 | A64V5 | A64V6 | A64V7 | A64V8 | A64V9
1461            | A64V10 | A64V11 | A64V12 | A64V13 | A64V14 | A64V15 | A64V16 | A64V17 | A64V18
1462            | A64V19 | A64V20 | A64V21 | A64V22 | A64V23 | A64V24 | A64V25 | A64V26 | A64V27
1463            | A64V28 | A64V29 | A64V30 | A64V31 | A64Q0 | A64Q1 | A64Q2 | A64Q3 | A64Q4 | A64Q5
1464            | A64Q6 | A64Q7 | A64Q8 | A64Q9 | A64Q10 | A64Q11 | A64Q12 | A64Q13 | A64Q14
1465            | A64Q15 | A64Q16 | A64Q17 | A64Q18 | A64Q19 | A64Q20 | A64Q21 | A64Q22 | A64Q23
1466            | A64Q24 | A64Q25 | A64Q26 | A64Q27 | A64Q28 | A64Q29 | A64Q30 | A64Q31 => 128,
1467            // AArch64 SIMD/FP D registers — 64-bit
1468            A64D0 | A64D1 | A64D2 | A64D3 | A64D4 | A64D5 | A64D6 | A64D7 | A64D8 | A64D9
1469            | A64D10 | A64D11 | A64D12 | A64D13 | A64D14 | A64D15 | A64D16 | A64D17 | A64D18
1470            | A64D19 | A64D20 | A64D21 | A64D22 | A64D23 | A64D24 | A64D25 | A64D26 | A64D27
1471            | A64D28 | A64D29 | A64D30 | A64D31 => 64,
1472            // AArch64 SIMD/FP S registers — 32-bit
1473            A64S0 | A64S1 | A64S2 | A64S3 | A64S4 | A64S5 | A64S6 | A64S7 | A64S8 | A64S9
1474            | A64S10 | A64S11 | A64S12 | A64S13 | A64S14 | A64S15 | A64S16 | A64S17 | A64S18
1475            | A64S19 | A64S20 | A64S21 | A64S22 | A64S23 | A64S24 | A64S25 | A64S26 | A64S27
1476            | A64S28 | A64S29 | A64S30 | A64S31 => 32,
1477            // AArch64 SIMD/FP H registers — 16-bit
1478            A64H0 | A64H1 | A64H2 | A64H3 | A64H4 | A64H5 | A64H6 | A64H7 | A64H8 | A64H9
1479            | A64H10 | A64H11 | A64H12 | A64H13 | A64H14 | A64H15 | A64H16 | A64H17 | A64H18
1480            | A64H19 | A64H20 | A64H21 | A64H22 | A64H23 | A64H24 | A64H25 | A64H26 | A64H27
1481            | A64H28 | A64H29 | A64H30 | A64H31 => 16,
1482            // AArch64 SIMD/FP B registers — 8-bit
1483            A64B0 | A64B1 | A64B2 | A64B3 | A64B4 | A64B5 | A64B6 | A64B7 | A64B8 | A64B9
1484            | A64B10 | A64B11 | A64B12 | A64B13 | A64B14 | A64B15 | A64B16 | A64B17 | A64B18
1485            | A64B19 | A64B20 | A64B21 | A64B22 | A64B23 | A64B24 | A64B25 | A64B26 | A64B27
1486            | A64B28 | A64B29 | A64B30 | A64B31 => 8,
1487            // AArch64 SVE Z registers — scalable width, report 0
1488            A64Z0 | A64Z1 | A64Z2 | A64Z3 | A64Z4 | A64Z5 | A64Z6 | A64Z7 | A64Z8 | A64Z9
1489            | A64Z10 | A64Z11 | A64Z12 | A64Z13 | A64Z14 | A64Z15 | A64Z16 | A64Z17 | A64Z18
1490            | A64Z19 | A64Z20 | A64Z21 | A64Z22 | A64Z23 | A64Z24 | A64Z25 | A64Z26 | A64Z27
1491            | A64Z28 | A64Z29 | A64Z30 | A64Z31 => 0,
1492            // AArch64 SVE predicate registers — scalable width, report 0
1493            A64P0 | A64P1 | A64P2 | A64P3 | A64P4 | A64P5 | A64P6 | A64P7 | A64P8 | A64P9
1494            | A64P10 | A64P11 | A64P12 | A64P13 | A64P14 | A64P15 => 0,
1495            // RISC-V registers — size depends on XLEN (32 or 64), we report 0 here
1496            // and let the encoder determine width based on Arch::Rv32 vs Rv64.
1497            RvX0 | RvX1 | RvX2 | RvX3 | RvX4 | RvX5 | RvX6 | RvX7 | RvX8 | RvX9 | RvX10 | RvX11
1498            | RvX12 | RvX13 | RvX14 | RvX15 | RvX16 | RvX17 | RvX18 | RvX19 | RvX20 | RvX21
1499            | RvX22 | RvX23 | RvX24 | RvX25 | RvX26 | RvX27 | RvX28 | RvX29 | RvX30 | RvX31 => 0,
1500            // RISC-V FP registers — size depends on F/D/Q extension; report 0
1501            // and let the encoder determine width from the instruction.
1502            RvF0 | RvF1 | RvF2 | RvF3 | RvF4 | RvF5 | RvF6 | RvF7 | RvF8 | RvF9 | RvF10 | RvF11
1503            | RvF12 | RvF13 | RvF14 | RvF15 | RvF16 | RvF17 | RvF18 | RvF19 | RvF20 | RvF21
1504            | RvF22 | RvF23 | RvF24 | RvF25 | RvF26 | RvF27 | RvF28 | RvF29 | RvF30 | RvF31 => 0,
1505            // RISC-V vector registers — scalable width, report 0
1506            RvV0 | RvV1 | RvV2 | RvV3 | RvV4 | RvV5 | RvV6 | RvV7 | RvV8 | RvV9 | RvV10 | RvV11
1507            | RvV12 | RvV13 | RvV14 | RvV15 | RvV16 | RvV17 | RvV18 | RvV19 | RvV20 | RvV21
1508            | RvV22 | RvV23 | RvV24 | RvV25 | RvV26 | RvV27 | RvV28 | RvV29 | RvV30 | RvV31 => 0,
1509        }
1510    }
1511
1512    /// Whether this register requires a REX prefix to be addressable as an 8-bit register.
1513    /// SPL, BPL, SIL, DIL need REX (even if REX.{W,R,X,B} are all 0).
1514    pub fn requires_rex_for_byte(self) -> bool {
1515        use Register::*;
1516        matches!(self, Spl | Bpl | Sil | Dil)
1517    }
1518
1519    /// Whether this is a high-byte register (AH, CH, DH, BH).
1520    /// These cannot be used with REX prefix.
1521    pub fn is_high_byte(self) -> bool {
1522        use Register::*;
1523        matches!(self, Ah | Ch | Dh | Bh)
1524    }
1525
1526    /// Whether this is an XMM (SSE) register.
1527    #[must_use]
1528    pub fn is_xmm(self) -> bool {
1529        use Register::*;
1530        matches!(
1531            self,
1532            Xmm0 | Xmm1
1533                | Xmm2
1534                | Xmm3
1535                | Xmm4
1536                | Xmm5
1537                | Xmm6
1538                | Xmm7
1539                | Xmm8
1540                | Xmm9
1541                | Xmm10
1542                | Xmm11
1543                | Xmm12
1544                | Xmm13
1545                | Xmm14
1546                | Xmm15
1547        )
1548    }
1549
1550    /// Whether this is a YMM (AVX) register.
1551    #[must_use]
1552    pub fn is_ymm(self) -> bool {
1553        use Register::*;
1554        matches!(
1555            self,
1556            Ymm0 | Ymm1
1557                | Ymm2
1558                | Ymm3
1559                | Ymm4
1560                | Ymm5
1561                | Ymm6
1562                | Ymm7
1563                | Ymm8
1564                | Ymm9
1565                | Ymm10
1566                | Ymm11
1567                | Ymm12
1568                | Ymm13
1569                | Ymm14
1570                | Ymm15
1571        )
1572    }
1573
1574    /// Whether this is a ZMM (AVX-512) register.
1575    #[must_use]
1576    pub fn is_zmm(self) -> bool {
1577        use Register::*;
1578        matches!(
1579            self,
1580            Zmm0 | Zmm1
1581                | Zmm2
1582                | Zmm3
1583                | Zmm4
1584                | Zmm5
1585                | Zmm6
1586                | Zmm7
1587                | Zmm8
1588                | Zmm9
1589                | Zmm10
1590                | Zmm11
1591                | Zmm12
1592                | Zmm13
1593                | Zmm14
1594                | Zmm15
1595                | Zmm16
1596                | Zmm17
1597                | Zmm18
1598                | Zmm19
1599                | Zmm20
1600                | Zmm21
1601                | Zmm22
1602                | Zmm23
1603                | Zmm24
1604                | Zmm25
1605                | Zmm26
1606                | Zmm27
1607                | Zmm28
1608                | Zmm29
1609                | Zmm30
1610                | Zmm31
1611        )
1612    }
1613
1614    /// Whether this is an opmask register (K0–K7).
1615    #[must_use]
1616    pub fn is_opmask(self) -> bool {
1617        use Register::*;
1618        matches!(self, K0 | K1 | K2 | K3 | K4 | K5 | K6 | K7)
1619    }
1620
1621    /// Whether this is any vector register (XMM, YMM, or ZMM).
1622    #[must_use]
1623    pub fn is_vector(self) -> bool {
1624        self.is_xmm() || self.is_ymm() || self.is_zmm()
1625    }
1626
1627    /// Return the 32-bit counterpart of this register, if applicable.
1628    ///
1629    /// For 64-bit GP registers (RAX, RCX, ..., R15), returns the corresponding
1630    /// 32-bit register. For registers that are already 32-bit, returns them
1631    /// unchanged. Returns `None` for 8-bit, 16-bit, segment, and vector registers.
1632    #[must_use]
1633    pub fn to_32bit(self) -> Option<Register> {
1634        use Register::*;
1635        match self {
1636            Rax | Eax => Some(Eax),
1637            Rcx | Ecx => Some(Ecx),
1638            Rdx | Edx => Some(Edx),
1639            Rbx | Ebx => Some(Ebx),
1640            Rsp | Esp => Some(Esp),
1641            Rbp | Ebp => Some(Ebp),
1642            Rsi | Esi => Some(Esi),
1643            Rdi | Edi => Some(Edi),
1644            R8 | R8d => Some(R8d),
1645            R9 | R9d => Some(R9d),
1646            R10 | R10d => Some(R10d),
1647            R11 | R11d => Some(R11d),
1648            R12 | R12d => Some(R12d),
1649            R13 | R13d => Some(R13d),
1650            R14 | R14d => Some(R14d),
1651            R15 | R15d => Some(R15d),
1652            _ => None,
1653        }
1654    }
1655
1656    /// Whether this is an ARM32 register.
1657    #[must_use]
1658    pub fn is_arm(self) -> bool {
1659        use Register::*;
1660        matches!(
1661            self,
1662            ArmR0
1663                | ArmR1
1664                | ArmR2
1665                | ArmR3
1666                | ArmR4
1667                | ArmR5
1668                | ArmR6
1669                | ArmR7
1670                | ArmR8
1671                | ArmR9
1672                | ArmR10
1673                | ArmR11
1674                | ArmR12
1675                | ArmSp
1676                | ArmLr
1677                | ArmPc
1678                | ArmCpsr
1679        )
1680    }
1681
1682    /// ARM32 4-bit register number (0–15).
1683    #[must_use]
1684    pub fn arm_reg_num(self) -> u8 {
1685        use Register::*;
1686        match self {
1687            ArmR0 => 0,
1688            ArmR1 => 1,
1689            ArmR2 => 2,
1690            ArmR3 => 3,
1691            ArmR4 => 4,
1692            ArmR5 => 5,
1693            ArmR6 => 6,
1694            ArmR7 => 7,
1695            ArmR8 => 8,
1696            ArmR9 => 9,
1697            ArmR10 => 10,
1698            ArmR11 => 11,
1699            ArmR12 => 12,
1700            ArmSp => 13,
1701            ArmLr => 14,
1702            ArmPc => 15,
1703            _ => 0,
1704        }
1705    }
1706
1707    /// Whether this is the AArch64 stack pointer (`SP` / `WSP`).
1708    ///
1709    /// Register number 31 is *encoding-dependent* on AArch64: it names the
1710    /// stack pointer in the add/sub immediate, add/sub extended-register and
1711    /// load/store base positions, and the zero register everywhere else.
1712    /// Encoders must therefore distinguish `SP` from `XZR` rather than looking
1713    /// only at [`a64_reg_num`](Self::a64_reg_num), or they will silently emit
1714    /// an instruction that discards its result.
1715    #[must_use]
1716    pub fn is_a64_sp(self) -> bool {
1717        matches!(self, Register::A64Sp | Register::A64Wsp)
1718    }
1719
1720    /// The ARM32 register with the given 4-bit number (0–15).
1721    ///
1722    /// Inverse of [`arm_reg_num`](Self::arm_reg_num); used to expand register
1723    /// ranges such as `{r0-r7}`.
1724    #[must_use]
1725    pub fn from_arm_reg_num(n: u8) -> Option<Self> {
1726        use Register::*;
1727        Some(match n {
1728            0 => ArmR0,
1729            1 => ArmR1,
1730            2 => ArmR2,
1731            3 => ArmR3,
1732            4 => ArmR4,
1733            5 => ArmR5,
1734            6 => ArmR6,
1735            7 => ArmR7,
1736            8 => ArmR8,
1737            9 => ArmR9,
1738            10 => ArmR10,
1739            11 => ArmR11,
1740            12 => ArmR12,
1741            13 => ArmSp,
1742            14 => ArmLr,
1743            15 => ArmPc,
1744            _ => return None,
1745        })
1746    }
1747
1748    /// Whether this is an AArch64 register.
1749    #[must_use]
1750    pub fn is_aarch64(self) -> bool {
1751        use Register::*;
1752        matches!(
1753            self,
1754            A64X0
1755                | A64X1
1756                | A64X2
1757                | A64X3
1758                | A64X4
1759                | A64X5
1760                | A64X6
1761                | A64X7
1762                | A64X8
1763                | A64X9
1764                | A64X10
1765                | A64X11
1766                | A64X12
1767                | A64X13
1768                | A64X14
1769                | A64X15
1770                | A64X16
1771                | A64X17
1772                | A64X18
1773                | A64X19
1774                | A64X20
1775                | A64X21
1776                | A64X22
1777                | A64X23
1778                | A64X24
1779                | A64X25
1780                | A64X26
1781                | A64X27
1782                | A64X28
1783                | A64X29
1784                | A64X30
1785                | A64Sp
1786                | A64Xzr
1787                | A64W0
1788                | A64W1
1789                | A64W2
1790                | A64W3
1791                | A64W4
1792                | A64W5
1793                | A64W6
1794                | A64W7
1795                | A64W8
1796                | A64W9
1797                | A64W10
1798                | A64W11
1799                | A64W12
1800                | A64W13
1801                | A64W14
1802                | A64W15
1803                | A64W16
1804                | A64W17
1805                | A64W18
1806                | A64W19
1807                | A64W20
1808                | A64W21
1809                | A64W22
1810                | A64W23
1811                | A64W24
1812                | A64W25
1813                | A64W26
1814                | A64W27
1815                | A64W28
1816                | A64W29
1817                | A64W30
1818                | A64Wzr
1819                | A64Wsp
1820                | A64V0
1821                | A64V1
1822                | A64V2
1823                | A64V3
1824                | A64V4
1825                | A64V5
1826                | A64V6
1827                | A64V7
1828                | A64V8
1829                | A64V9
1830                | A64V10
1831                | A64V11
1832                | A64V12
1833                | A64V13
1834                | A64V14
1835                | A64V15
1836                | A64V16
1837                | A64V17
1838                | A64V18
1839                | A64V19
1840                | A64V20
1841                | A64V21
1842                | A64V22
1843                | A64V23
1844                | A64V24
1845                | A64V25
1846                | A64V26
1847                | A64V27
1848                | A64V28
1849                | A64V29
1850                | A64V30
1851                | A64V31
1852                | A64Q0
1853                | A64Q1
1854                | A64Q2
1855                | A64Q3
1856                | A64Q4
1857                | A64Q5
1858                | A64Q6
1859                | A64Q7
1860                | A64Q8
1861                | A64Q9
1862                | A64Q10
1863                | A64Q11
1864                | A64Q12
1865                | A64Q13
1866                | A64Q14
1867                | A64Q15
1868                | A64Q16
1869                | A64Q17
1870                | A64Q18
1871                | A64Q19
1872                | A64Q20
1873                | A64Q21
1874                | A64Q22
1875                | A64Q23
1876                | A64Q24
1877                | A64Q25
1878                | A64Q26
1879                | A64Q27
1880                | A64Q28
1881                | A64Q29
1882                | A64Q30
1883                | A64Q31
1884                | A64D0
1885                | A64D1
1886                | A64D2
1887                | A64D3
1888                | A64D4
1889                | A64D5
1890                | A64D6
1891                | A64D7
1892                | A64D8
1893                | A64D9
1894                | A64D10
1895                | A64D11
1896                | A64D12
1897                | A64D13
1898                | A64D14
1899                | A64D15
1900                | A64D16
1901                | A64D17
1902                | A64D18
1903                | A64D19
1904                | A64D20
1905                | A64D21
1906                | A64D22
1907                | A64D23
1908                | A64D24
1909                | A64D25
1910                | A64D26
1911                | A64D27
1912                | A64D28
1913                | A64D29
1914                | A64D30
1915                | A64D31
1916                | A64S0
1917                | A64S1
1918                | A64S2
1919                | A64S3
1920                | A64S4
1921                | A64S5
1922                | A64S6
1923                | A64S7
1924                | A64S8
1925                | A64S9
1926                | A64S10
1927                | A64S11
1928                | A64S12
1929                | A64S13
1930                | A64S14
1931                | A64S15
1932                | A64S16
1933                | A64S17
1934                | A64S18
1935                | A64S19
1936                | A64S20
1937                | A64S21
1938                | A64S22
1939                | A64S23
1940                | A64S24
1941                | A64S25
1942                | A64S26
1943                | A64S27
1944                | A64S28
1945                | A64S29
1946                | A64S30
1947                | A64S31
1948                | A64H0
1949                | A64H1
1950                | A64H2
1951                | A64H3
1952                | A64H4
1953                | A64H5
1954                | A64H6
1955                | A64H7
1956                | A64H8
1957                | A64H9
1958                | A64H10
1959                | A64H11
1960                | A64H12
1961                | A64H13
1962                | A64H14
1963                | A64H15
1964                | A64H16
1965                | A64H17
1966                | A64H18
1967                | A64H19
1968                | A64H20
1969                | A64H21
1970                | A64H22
1971                | A64H23
1972                | A64H24
1973                | A64H25
1974                | A64H26
1975                | A64H27
1976                | A64H28
1977                | A64H29
1978                | A64H30
1979                | A64H31
1980                | A64B0
1981                | A64B1
1982                | A64B2
1983                | A64B3
1984                | A64B4
1985                | A64B5
1986                | A64B6
1987                | A64B7
1988                | A64B8
1989                | A64B9
1990                | A64B10
1991                | A64B11
1992                | A64B12
1993                | A64B13
1994                | A64B14
1995                | A64B15
1996                | A64B16
1997                | A64B17
1998                | A64B18
1999                | A64B19
2000                | A64B20
2001                | A64B21
2002                | A64B22
2003                | A64B23
2004                | A64B24
2005                | A64B25
2006                | A64B26
2007                | A64B27
2008                | A64B28
2009                | A64B29
2010                | A64B30
2011                | A64B31
2012                | A64Z0
2013                | A64Z1
2014                | A64Z2
2015                | A64Z3
2016                | A64Z4
2017                | A64Z5
2018                | A64Z6
2019                | A64Z7
2020                | A64Z8
2021                | A64Z9
2022                | A64Z10
2023                | A64Z11
2024                | A64Z12
2025                | A64Z13
2026                | A64Z14
2027                | A64Z15
2028                | A64Z16
2029                | A64Z17
2030                | A64Z18
2031                | A64Z19
2032                | A64Z20
2033                | A64Z21
2034                | A64Z22
2035                | A64Z23
2036                | A64Z24
2037                | A64Z25
2038                | A64Z26
2039                | A64Z27
2040                | A64Z28
2041                | A64Z29
2042                | A64Z30
2043                | A64Z31
2044                | A64P0
2045                | A64P1
2046                | A64P2
2047                | A64P3
2048                | A64P4
2049                | A64P5
2050                | A64P6
2051                | A64P7
2052                | A64P8
2053                | A64P9
2054                | A64P10
2055                | A64P11
2056                | A64P12
2057                | A64P13
2058                | A64P14
2059                | A64P15
2060        )
2061    }
2062
2063    /// AArch64 5-bit register number (0–31, where 31 = SP or ZR depending on context).
2064    #[must_use]
2065    pub fn a64_reg_num(self) -> u8 {
2066        use Register::*;
2067        match self {
2068            A64X0 | A64W0 => 0,
2069            A64X1 | A64W1 => 1,
2070            A64X2 | A64W2 => 2,
2071            A64X3 | A64W3 => 3,
2072            A64X4 | A64W4 => 4,
2073            A64X5 | A64W5 => 5,
2074            A64X6 | A64W6 => 6,
2075            A64X7 | A64W7 => 7,
2076            A64X8 | A64W8 => 8,
2077            A64X9 | A64W9 => 9,
2078            A64X10 | A64W10 => 10,
2079            A64X11 | A64W11 => 11,
2080            A64X12 | A64W12 => 12,
2081            A64X13 | A64W13 => 13,
2082            A64X14 | A64W14 => 14,
2083            A64X15 | A64W15 => 15,
2084            A64X16 | A64W16 => 16,
2085            A64X17 | A64W17 => 17,
2086            A64X18 | A64W18 => 18,
2087            A64X19 | A64W19 => 19,
2088            A64X20 | A64W20 => 20,
2089            A64X21 | A64W21 => 21,
2090            A64X22 | A64W22 => 22,
2091            A64X23 | A64W23 => 23,
2092            A64X24 | A64W24 => 24,
2093            A64X25 | A64W25 => 25,
2094            A64X26 | A64W26 => 26,
2095            A64X27 | A64W27 => 27,
2096            A64X28 | A64W28 => 28,
2097            A64X29 | A64W29 => 29,
2098            A64X30 | A64W30 => 30,
2099            A64Sp | A64Xzr | A64Wzr | A64Wsp => 31,
2100            // SIMD/FP registers share the same 0–31 numbering
2101            A64V0 | A64Q0 | A64D0 | A64S0 | A64H0 | A64B0 => 0,
2102            A64V1 | A64Q1 | A64D1 | A64S1 | A64H1 | A64B1 => 1,
2103            A64V2 | A64Q2 | A64D2 | A64S2 | A64H2 | A64B2 => 2,
2104            A64V3 | A64Q3 | A64D3 | A64S3 | A64H3 | A64B3 => 3,
2105            A64V4 | A64Q4 | A64D4 | A64S4 | A64H4 | A64B4 => 4,
2106            A64V5 | A64Q5 | A64D5 | A64S5 | A64H5 | A64B5 => 5,
2107            A64V6 | A64Q6 | A64D6 | A64S6 | A64H6 | A64B6 => 6,
2108            A64V7 | A64Q7 | A64D7 | A64S7 | A64H7 | A64B7 => 7,
2109            A64V8 | A64Q8 | A64D8 | A64S8 | A64H8 | A64B8 => 8,
2110            A64V9 | A64Q9 | A64D9 | A64S9 | A64H9 | A64B9 => 9,
2111            A64V10 | A64Q10 | A64D10 | A64S10 | A64H10 | A64B10 => 10,
2112            A64V11 | A64Q11 | A64D11 | A64S11 | A64H11 | A64B11 => 11,
2113            A64V12 | A64Q12 | A64D12 | A64S12 | A64H12 | A64B12 => 12,
2114            A64V13 | A64Q13 | A64D13 | A64S13 | A64H13 | A64B13 => 13,
2115            A64V14 | A64Q14 | A64D14 | A64S14 | A64H14 | A64B14 => 14,
2116            A64V15 | A64Q15 | A64D15 | A64S15 | A64H15 | A64B15 => 15,
2117            A64V16 | A64Q16 | A64D16 | A64S16 | A64H16 | A64B16 => 16,
2118            A64V17 | A64Q17 | A64D17 | A64S17 | A64H17 | A64B17 => 17,
2119            A64V18 | A64Q18 | A64D18 | A64S18 | A64H18 | A64B18 => 18,
2120            A64V19 | A64Q19 | A64D19 | A64S19 | A64H19 | A64B19 => 19,
2121            A64V20 | A64Q20 | A64D20 | A64S20 | A64H20 | A64B20 => 20,
2122            A64V21 | A64Q21 | A64D21 | A64S21 | A64H21 | A64B21 => 21,
2123            A64V22 | A64Q22 | A64D22 | A64S22 | A64H22 | A64B22 => 22,
2124            A64V23 | A64Q23 | A64D23 | A64S23 | A64H23 | A64B23 => 23,
2125            A64V24 | A64Q24 | A64D24 | A64S24 | A64H24 | A64B24 => 24,
2126            A64V25 | A64Q25 | A64D25 | A64S25 | A64H25 | A64B25 => 25,
2127            A64V26 | A64Q26 | A64D26 | A64S26 | A64H26 | A64B26 => 26,
2128            A64V27 | A64Q27 | A64D27 | A64S27 | A64H27 | A64B27 => 27,
2129            A64V28 | A64Q28 | A64D28 | A64S28 | A64H28 | A64B28 => 28,
2130            A64V29 | A64Q29 | A64D29 | A64S29 | A64H29 | A64B29 => 29,
2131            A64V30 | A64Q30 | A64D30 | A64S30 | A64H30 | A64B30 => 30,
2132            A64V31 | A64Q31 | A64D31 | A64S31 | A64H31 | A64B31 => 31,
2133            // SVE Z registers share the same 0–31 numbering
2134            A64Z0 => 0,
2135            A64Z1 => 1,
2136            A64Z2 => 2,
2137            A64Z3 => 3,
2138            A64Z4 => 4,
2139            A64Z5 => 5,
2140            A64Z6 => 6,
2141            A64Z7 => 7,
2142            A64Z8 => 8,
2143            A64Z9 => 9,
2144            A64Z10 => 10,
2145            A64Z11 => 11,
2146            A64Z12 => 12,
2147            A64Z13 => 13,
2148            A64Z14 => 14,
2149            A64Z15 => 15,
2150            A64Z16 => 16,
2151            A64Z17 => 17,
2152            A64Z18 => 18,
2153            A64Z19 => 19,
2154            A64Z20 => 20,
2155            A64Z21 => 21,
2156            A64Z22 => 22,
2157            A64Z23 => 23,
2158            A64Z24 => 24,
2159            A64Z25 => 25,
2160            A64Z26 => 26,
2161            A64Z27 => 27,
2162            A64Z28 => 28,
2163            A64Z29 => 29,
2164            A64Z30 => 30,
2165            A64Z31 => 31,
2166            _ => 0,
2167        }
2168    }
2169
2170    /// Whether this is an AArch64 vector register (V0–V31).
2171    ///
2172    /// Only V registers accept arrangement specifiers (e.g., `V0.4S`).
2173    #[must_use]
2174    pub fn is_a64_vector(self) -> bool {
2175        use Register::*;
2176        matches!(
2177            self,
2178            A64V0
2179                | A64V1
2180                | A64V2
2181                | A64V3
2182                | A64V4
2183                | A64V5
2184                | A64V6
2185                | A64V7
2186                | A64V8
2187                | A64V9
2188                | A64V10
2189                | A64V11
2190                | A64V12
2191                | A64V13
2192                | A64V14
2193                | A64V15
2194                | A64V16
2195                | A64V17
2196                | A64V18
2197                | A64V19
2198                | A64V20
2199                | A64V21
2200                | A64V22
2201                | A64V23
2202                | A64V24
2203                | A64V25
2204                | A64V26
2205                | A64V27
2206                | A64V28
2207                | A64V29
2208                | A64V30
2209                | A64V31
2210        )
2211    }
2212
2213    /// Whether this is an AArch64 SIMD/FP register (V, Q, D, S, H, or B).
2214    #[must_use]
2215    pub fn is_a64_simd_fp(self) -> bool {
2216        use Register::*;
2217        matches!(
2218            self,
2219            A64V0
2220                | A64V1
2221                | A64V2
2222                | A64V3
2223                | A64V4
2224                | A64V5
2225                | A64V6
2226                | A64V7
2227                | A64V8
2228                | A64V9
2229                | A64V10
2230                | A64V11
2231                | A64V12
2232                | A64V13
2233                | A64V14
2234                | A64V15
2235                | A64V16
2236                | A64V17
2237                | A64V18
2238                | A64V19
2239                | A64V20
2240                | A64V21
2241                | A64V22
2242                | A64V23
2243                | A64V24
2244                | A64V25
2245                | A64V26
2246                | A64V27
2247                | A64V28
2248                | A64V29
2249                | A64V30
2250                | A64V31
2251                | A64Q0
2252                | A64Q1
2253                | A64Q2
2254                | A64Q3
2255                | A64Q4
2256                | A64Q5
2257                | A64Q6
2258                | A64Q7
2259                | A64Q8
2260                | A64Q9
2261                | A64Q10
2262                | A64Q11
2263                | A64Q12
2264                | A64Q13
2265                | A64Q14
2266                | A64Q15
2267                | A64Q16
2268                | A64Q17
2269                | A64Q18
2270                | A64Q19
2271                | A64Q20
2272                | A64Q21
2273                | A64Q22
2274                | A64Q23
2275                | A64Q24
2276                | A64Q25
2277                | A64Q26
2278                | A64Q27
2279                | A64Q28
2280                | A64Q29
2281                | A64Q30
2282                | A64Q31
2283                | A64D0
2284                | A64D1
2285                | A64D2
2286                | A64D3
2287                | A64D4
2288                | A64D5
2289                | A64D6
2290                | A64D7
2291                | A64D8
2292                | A64D9
2293                | A64D10
2294                | A64D11
2295                | A64D12
2296                | A64D13
2297                | A64D14
2298                | A64D15
2299                | A64D16
2300                | A64D17
2301                | A64D18
2302                | A64D19
2303                | A64D20
2304                | A64D21
2305                | A64D22
2306                | A64D23
2307                | A64D24
2308                | A64D25
2309                | A64D26
2310                | A64D27
2311                | A64D28
2312                | A64D29
2313                | A64D30
2314                | A64D31
2315                | A64S0
2316                | A64S1
2317                | A64S2
2318                | A64S3
2319                | A64S4
2320                | A64S5
2321                | A64S6
2322                | A64S7
2323                | A64S8
2324                | A64S9
2325                | A64S10
2326                | A64S11
2327                | A64S12
2328                | A64S13
2329                | A64S14
2330                | A64S15
2331                | A64S16
2332                | A64S17
2333                | A64S18
2334                | A64S19
2335                | A64S20
2336                | A64S21
2337                | A64S22
2338                | A64S23
2339                | A64S24
2340                | A64S25
2341                | A64S26
2342                | A64S27
2343                | A64S28
2344                | A64S29
2345                | A64S30
2346                | A64S31
2347                | A64H0
2348                | A64H1
2349                | A64H2
2350                | A64H3
2351                | A64H4
2352                | A64H5
2353                | A64H6
2354                | A64H7
2355                | A64H8
2356                | A64H9
2357                | A64H10
2358                | A64H11
2359                | A64H12
2360                | A64H13
2361                | A64H14
2362                | A64H15
2363                | A64H16
2364                | A64H17
2365                | A64H18
2366                | A64H19
2367                | A64H20
2368                | A64H21
2369                | A64H22
2370                | A64H23
2371                | A64H24
2372                | A64H25
2373                | A64H26
2374                | A64H27
2375                | A64H28
2376                | A64H29
2377                | A64H30
2378                | A64H31
2379                | A64B0
2380                | A64B1
2381                | A64B2
2382                | A64B3
2383                | A64B4
2384                | A64B5
2385                | A64B6
2386                | A64B7
2387                | A64B8
2388                | A64B9
2389                | A64B10
2390                | A64B11
2391                | A64B12
2392                | A64B13
2393                | A64B14
2394                | A64B15
2395                | A64B16
2396                | A64B17
2397                | A64B18
2398                | A64B19
2399                | A64B20
2400                | A64B21
2401                | A64B22
2402                | A64B23
2403                | A64B24
2404                | A64B25
2405                | A64B26
2406                | A64B27
2407                | A64B28
2408                | A64B29
2409                | A64B30
2410                | A64B31
2411        )
2412    }
2413
2414    /// Returns the SIMD/FP register bit width (128 for V/Q, 64 for D, 32 for S, 16 for H, 8 for B).
2415    #[must_use]
2416    pub fn a64_simd_fp_bits(self) -> u32 {
2417        use Register::*;
2418        match self {
2419            A64V0 | A64V1 | A64V2 | A64V3 | A64V4 | A64V5 | A64V6 | A64V7 | A64V8 | A64V9
2420            | A64V10 | A64V11 | A64V12 | A64V13 | A64V14 | A64V15 | A64V16 | A64V17 | A64V18
2421            | A64V19 | A64V20 | A64V21 | A64V22 | A64V23 | A64V24 | A64V25 | A64V26 | A64V27
2422            | A64V28 | A64V29 | A64V30 | A64V31 | A64Q0 | A64Q1 | A64Q2 | A64Q3 | A64Q4 | A64Q5
2423            | A64Q6 | A64Q7 | A64Q8 | A64Q9 | A64Q10 | A64Q11 | A64Q12 | A64Q13 | A64Q14
2424            | A64Q15 | A64Q16 | A64Q17 | A64Q18 | A64Q19 | A64Q20 | A64Q21 | A64Q22 | A64Q23
2425            | A64Q24 | A64Q25 | A64Q26 | A64Q27 | A64Q28 | A64Q29 | A64Q30 | A64Q31 => 128,
2426            A64D0 | A64D1 | A64D2 | A64D3 | A64D4 | A64D5 | A64D6 | A64D7 | A64D8 | A64D9
2427            | A64D10 | A64D11 | A64D12 | A64D13 | A64D14 | A64D15 | A64D16 | A64D17 | A64D18
2428            | A64D19 | A64D20 | A64D21 | A64D22 | A64D23 | A64D24 | A64D25 | A64D26 | A64D27
2429            | A64D28 | A64D29 | A64D30 | A64D31 => 64,
2430            A64S0 | A64S1 | A64S2 | A64S3 | A64S4 | A64S5 | A64S6 | A64S7 | A64S8 | A64S9
2431            | A64S10 | A64S11 | A64S12 | A64S13 | A64S14 | A64S15 | A64S16 | A64S17 | A64S18
2432            | A64S19 | A64S20 | A64S21 | A64S22 | A64S23 | A64S24 | A64S25 | A64S26 | A64S27
2433            | A64S28 | A64S29 | A64S30 | A64S31 => 32,
2434            A64H0 | A64H1 | A64H2 | A64H3 | A64H4 | A64H5 | A64H6 | A64H7 | A64H8 | A64H9
2435            | A64H10 | A64H11 | A64H12 | A64H13 | A64H14 | A64H15 | A64H16 | A64H17 | A64H18
2436            | A64H19 | A64H20 | A64H21 | A64H22 | A64H23 | A64H24 | A64H25 | A64H26 | A64H27
2437            | A64H28 | A64H29 | A64H30 | A64H31 => 16,
2438            A64B0 | A64B1 | A64B2 | A64B3 | A64B4 | A64B5 | A64B6 | A64B7 | A64B8 | A64B9
2439            | A64B10 | A64B11 | A64B12 | A64B13 | A64B14 | A64B15 | A64B16 | A64B17 | A64B18
2440            | A64B19 | A64B20 | A64B21 | A64B22 | A64B23 | A64B24 | A64B25 | A64B26 | A64B27
2441            | A64B28 | A64B29 | A64B30 | A64B31 => 8,
2442            _ => 0,
2443        }
2444    }
2445
2446    /// Whether this is a 64-bit AArch64 X register (vs 32-bit W register).
2447    #[must_use]
2448    pub fn is_a64_64bit(self) -> bool {
2449        use Register::*;
2450        matches!(
2451            self,
2452            A64X0
2453                | A64X1
2454                | A64X2
2455                | A64X3
2456                | A64X4
2457                | A64X5
2458                | A64X6
2459                | A64X7
2460                | A64X8
2461                | A64X9
2462                | A64X10
2463                | A64X11
2464                | A64X12
2465                | A64X13
2466                | A64X14
2467                | A64X15
2468                | A64X16
2469                | A64X17
2470                | A64X18
2471                | A64X19
2472                | A64X20
2473                | A64X21
2474                | A64X22
2475                | A64X23
2476                | A64X24
2477                | A64X25
2478                | A64X26
2479                | A64X27
2480                | A64X28
2481                | A64X29
2482                | A64X30
2483                | A64Sp
2484                | A64Xzr
2485        )
2486    }
2487
2488    /// Whether this is a RISC-V integer register.
2489    #[must_use]
2490    pub fn is_riscv(self) -> bool {
2491        use Register::*;
2492        matches!(
2493            self,
2494            RvX0 | RvX1
2495                | RvX2
2496                | RvX3
2497                | RvX4
2498                | RvX5
2499                | RvX6
2500                | RvX7
2501                | RvX8
2502                | RvX9
2503                | RvX10
2504                | RvX11
2505                | RvX12
2506                | RvX13
2507                | RvX14
2508                | RvX15
2509                | RvX16
2510                | RvX17
2511                | RvX18
2512                | RvX19
2513                | RvX20
2514                | RvX21
2515                | RvX22
2516                | RvX23
2517                | RvX24
2518                | RvX25
2519                | RvX26
2520                | RvX27
2521                | RvX28
2522                | RvX29
2523                | RvX30
2524                | RvX31
2525        )
2526    }
2527
2528    /// RISC-V 5-bit register number (0–31).
2529    #[must_use]
2530    pub fn rv_reg_num(self) -> u8 {
2531        use Register::*;
2532        match self {
2533            RvX0 => 0,
2534            RvX1 => 1,
2535            RvX2 => 2,
2536            RvX3 => 3,
2537            RvX4 => 4,
2538            RvX5 => 5,
2539            RvX6 => 6,
2540            RvX7 => 7,
2541            RvX8 => 8,
2542            RvX9 => 9,
2543            RvX10 => 10,
2544            RvX11 => 11,
2545            RvX12 => 12,
2546            RvX13 => 13,
2547            RvX14 => 14,
2548            RvX15 => 15,
2549            RvX16 => 16,
2550            RvX17 => 17,
2551            RvX18 => 18,
2552            RvX19 => 19,
2553            RvX20 => 20,
2554            RvX21 => 21,
2555            RvX22 => 22,
2556            RvX23 => 23,
2557            RvX24 => 24,
2558            RvX25 => 25,
2559            RvX26 => 26,
2560            RvX27 => 27,
2561            RvX28 => 28,
2562            RvX29 => 29,
2563            RvX30 => 30,
2564            RvX31 => 31,
2565            _ => 0,
2566        }
2567    }
2568
2569    /// Whether this is a RISC-V floating-point register (f0–f31).
2570    #[must_use]
2571    pub fn is_riscv_fp(self) -> bool {
2572        use Register::*;
2573        matches!(
2574            self,
2575            RvF0 | RvF1
2576                | RvF2
2577                | RvF3
2578                | RvF4
2579                | RvF5
2580                | RvF6
2581                | RvF7
2582                | RvF8
2583                | RvF9
2584                | RvF10
2585                | RvF11
2586                | RvF12
2587                | RvF13
2588                | RvF14
2589                | RvF15
2590                | RvF16
2591                | RvF17
2592                | RvF18
2593                | RvF19
2594                | RvF20
2595                | RvF21
2596                | RvF22
2597                | RvF23
2598                | RvF24
2599                | RvF25
2600                | RvF26
2601                | RvF27
2602                | RvF28
2603                | RvF29
2604                | RvF30
2605                | RvF31
2606        )
2607    }
2608
2609    /// RISC-V FP 5-bit register number (0–31).
2610    #[must_use]
2611    pub fn rv_fp_reg_num(self) -> u8 {
2612        use Register::*;
2613        match self {
2614            RvF0 => 0,
2615            RvF1 => 1,
2616            RvF2 => 2,
2617            RvF3 => 3,
2618            RvF4 => 4,
2619            RvF5 => 5,
2620            RvF6 => 6,
2621            RvF7 => 7,
2622            RvF8 => 8,
2623            RvF9 => 9,
2624            RvF10 => 10,
2625            RvF11 => 11,
2626            RvF12 => 12,
2627            RvF13 => 13,
2628            RvF14 => 14,
2629            RvF15 => 15,
2630            RvF16 => 16,
2631            RvF17 => 17,
2632            RvF18 => 18,
2633            RvF19 => 19,
2634            RvF20 => 20,
2635            RvF21 => 21,
2636            RvF22 => 22,
2637            RvF23 => 23,
2638            RvF24 => 24,
2639            RvF25 => 25,
2640            RvF26 => 26,
2641            RvF27 => 27,
2642            RvF28 => 28,
2643            RvF29 => 29,
2644            RvF30 => 30,
2645            RvF31 => 31,
2646            _ => 0,
2647        }
2648    }
2649
2650    /// Whether this is an AArch64 SVE scalable vector register (Z0–Z31).
2651    #[must_use]
2652    pub fn is_a64_sve_z(self) -> bool {
2653        use Register::*;
2654        matches!(
2655            self,
2656            A64Z0
2657                | A64Z1
2658                | A64Z2
2659                | A64Z3
2660                | A64Z4
2661                | A64Z5
2662                | A64Z6
2663                | A64Z7
2664                | A64Z8
2665                | A64Z9
2666                | A64Z10
2667                | A64Z11
2668                | A64Z12
2669                | A64Z13
2670                | A64Z14
2671                | A64Z15
2672                | A64Z16
2673                | A64Z17
2674                | A64Z18
2675                | A64Z19
2676                | A64Z20
2677                | A64Z21
2678                | A64Z22
2679                | A64Z23
2680                | A64Z24
2681                | A64Z25
2682                | A64Z26
2683                | A64Z27
2684                | A64Z28
2685                | A64Z29
2686                | A64Z30
2687                | A64Z31
2688        )
2689    }
2690
2691    /// Whether this is an AArch64 SVE predicate register (P0–P15).
2692    #[must_use]
2693    pub fn is_a64_sve_p(self) -> bool {
2694        use Register::*;
2695        matches!(
2696            self,
2697            A64P0
2698                | A64P1
2699                | A64P2
2700                | A64P3
2701                | A64P4
2702                | A64P5
2703                | A64P6
2704                | A64P7
2705                | A64P8
2706                | A64P9
2707                | A64P10
2708                | A64P11
2709                | A64P12
2710                | A64P13
2711                | A64P14
2712                | A64P15
2713        )
2714    }
2715
2716    /// AArch64 SVE predicate register number (0–15).
2717    #[must_use]
2718    pub fn a64_p_num(self) -> u8 {
2719        use Register::*;
2720        match self {
2721            A64P0 => 0,
2722            A64P1 => 1,
2723            A64P2 => 2,
2724            A64P3 => 3,
2725            A64P4 => 4,
2726            A64P5 => 5,
2727            A64P6 => 6,
2728            A64P7 => 7,
2729            A64P8 => 8,
2730            A64P9 => 9,
2731            A64P10 => 10,
2732            A64P11 => 11,
2733            A64P12 => 12,
2734            A64P13 => 13,
2735            A64P14 => 14,
2736            A64P15 => 15,
2737            _ => 0,
2738        }
2739    }
2740
2741    /// Whether this is a RISC-V vector register (v0–v31).
2742    #[must_use]
2743    pub fn is_riscv_vec(self) -> bool {
2744        use Register::*;
2745        matches!(
2746            self,
2747            RvV0 | RvV1
2748                | RvV2
2749                | RvV3
2750                | RvV4
2751                | RvV5
2752                | RvV6
2753                | RvV7
2754                | RvV8
2755                | RvV9
2756                | RvV10
2757                | RvV11
2758                | RvV12
2759                | RvV13
2760                | RvV14
2761                | RvV15
2762                | RvV16
2763                | RvV17
2764                | RvV18
2765                | RvV19
2766                | RvV20
2767                | RvV21
2768                | RvV22
2769                | RvV23
2770                | RvV24
2771                | RvV25
2772                | RvV26
2773                | RvV27
2774                | RvV28
2775                | RvV29
2776                | RvV30
2777                | RvV31
2778        )
2779    }
2780
2781    /// RISC-V vector register number (0–31).
2782    #[must_use]
2783    pub fn rv_vec_num(self) -> u8 {
2784        use Register::*;
2785        match self {
2786            RvV0 => 0,
2787            RvV1 => 1,
2788            RvV2 => 2,
2789            RvV3 => 3,
2790            RvV4 => 4,
2791            RvV5 => 5,
2792            RvV6 => 6,
2793            RvV7 => 7,
2794            RvV8 => 8,
2795            RvV9 => 9,
2796            RvV10 => 10,
2797            RvV11 => 11,
2798            RvV12 => 12,
2799            RvV13 => 13,
2800            RvV14 => 14,
2801            RvV15 => 15,
2802            RvV16 => 16,
2803            RvV17 => 17,
2804            RvV18 => 18,
2805            RvV19 => 19,
2806            RvV20 => 20,
2807            RvV21 => 21,
2808            RvV22 => 22,
2809            RvV23 => 23,
2810            RvV24 => 24,
2811            RvV25 => 25,
2812            RvV26 => 26,
2813            RvV27 => 27,
2814            RvV28 => 28,
2815            RvV29 => 29,
2816            RvV30 => 30,
2817            RvV31 => 31,
2818            _ => 0,
2819        }
2820    }
2821}
2822
2823impl fmt::Display for Register {
2824    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2825        // Zero-allocation: write Debug chars lowercased directly to the formatter.
2826        use fmt::Write as _;
2827        struct LowerWriter<'a, 'b>(&'a mut fmt::Formatter<'b>);
2828        impl fmt::Write for LowerWriter<'_, '_> {
2829            fn write_str(&mut self, s: &str) -> fmt::Result {
2830                for c in s.chars() {
2831                    self.0.write_char(c.to_ascii_lowercase())?;
2832                }
2833                Ok(())
2834            }
2835        }
2836        write!(LowerWriter(f), "{:?}", self)
2837    }
2838}
2839
2840/// AArch64 vector arrangement specifier.
2841///
2842/// Describes how a 128-bit (or 64-bit) SIMD register is divided into lanes.
2843/// Used with NEON/ASIMD instructions like `ADD V0.4S, V1.4S, V2.4S`.
2844#[derive(Debug, Clone, Copy, PartialEq, Eq)]
2845#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2846pub enum VectorArrangement {
2847    /// 8 bytes (64-bit: 8×B)
2848    B8,
2849    /// 16 bytes (128-bit: 16×B)
2850    B16,
2851    /// 4 half-words (64-bit: 4×H)
2852    H4,
2853    /// 8 half-words (128-bit: 8×H)
2854    H8,
2855    /// 2 single-words (64-bit: 2×S)
2856    S2,
2857    /// 4 single-words (128-bit: 4×S)
2858    S4,
2859    /// 1 double-word (64-bit: 1×D)
2860    D1,
2861    /// 2 double-words (128-bit: 2×D)
2862    D2,
2863    // ── SVE element sizes (scalable — no lane count) ────────
2864    /// SVE byte elements (`.B`).
2865    SveB,
2866    /// SVE half-word elements (`.H`).
2867    SveH,
2868    /// SVE single-word elements (`.S`).
2869    SveS,
2870    /// SVE double-word elements (`.D`).
2871    SveD,
2872}
2873
2874impl VectorArrangement {
2875    /// Parse a vector arrangement specifier string (e.g., "8b", "16b", "4h").
2876    /// Case-insensitive, zero heap allocations.
2877    pub fn parse(s: &str) -> Option<Self> {
2878        // Stack-based lowercase (arrangement specifiers are at most 3 chars).
2879        let mut buf = [0u8; 4];
2880        let len = s.len().min(4);
2881        buf[..len].copy_from_slice(&s.as_bytes()[..len]);
2882        buf[..len].make_ascii_lowercase();
2883        // Input was valid UTF-8 and ASCII lowercase preserves validity.
2884        let s = core::str::from_utf8(&buf[..len]).unwrap_or("");
2885        match s {
2886            "8b" => Some(VectorArrangement::B8),
2887            "16b" => Some(VectorArrangement::B16),
2888            "4h" => Some(VectorArrangement::H4),
2889            "8h" => Some(VectorArrangement::H8),
2890            "2s" => Some(VectorArrangement::S2),
2891            "4s" => Some(VectorArrangement::S4),
2892            "1d" => Some(VectorArrangement::D1),
2893            "2d" => Some(VectorArrangement::D2),
2894            // SVE scalable element-size specifiers
2895            "b" => Some(VectorArrangement::SveB),
2896            "h" => Some(VectorArrangement::SveH),
2897            "s" => Some(VectorArrangement::SveS),
2898            "d" => Some(VectorArrangement::SveD),
2899            _ => None,
2900        }
2901    }
2902
2903    /// Lane element size in bits.
2904    pub fn element_bits(self) -> u32 {
2905        match self {
2906            VectorArrangement::B8 | VectorArrangement::B16 | VectorArrangement::SveB => 8,
2907            VectorArrangement::H4 | VectorArrangement::H8 | VectorArrangement::SveH => 16,
2908            VectorArrangement::S2 | VectorArrangement::S4 | VectorArrangement::SveS => 32,
2909            VectorArrangement::D1 | VectorArrangement::D2 | VectorArrangement::SveD => 64,
2910        }
2911    }
2912
2913    /// Total vector width in bits (64 or 128 for NEON, 0 for SVE scalable).
2914    pub fn total_bits(self) -> u32 {
2915        match self {
2916            VectorArrangement::B8
2917            | VectorArrangement::H4
2918            | VectorArrangement::S2
2919            | VectorArrangement::D1 => 64,
2920            VectorArrangement::B16
2921            | VectorArrangement::H8
2922            | VectorArrangement::S4
2923            | VectorArrangement::D2 => 128,
2924            // SVE: scalable, width unknown at assembly time
2925            VectorArrangement::SveB
2926            | VectorArrangement::SveH
2927            | VectorArrangement::SveS
2928            | VectorArrangement::SveD => 0,
2929        }
2930    }
2931
2932    /// Number of lanes (0 for SVE scalable arrangements).
2933    pub fn lane_count(self) -> u32 {
2934        let total = self.total_bits();
2935        if total == 0 {
2936            return 0;
2937        }
2938        total / self.element_bits()
2939    }
2940
2941    /// SVE element size encoding (2-bit `sz` field): B=0, H=1, S=2, D=3.
2942    /// Returns `None` for non-SVE arrangements.
2943    pub fn sve_size(self) -> Option<u32> {
2944        match self {
2945            VectorArrangement::SveB => Some(0),
2946            VectorArrangement::SveH => Some(1),
2947            VectorArrangement::SveS => Some(2),
2948            VectorArrangement::SveD => Some(3),
2949            _ => None,
2950        }
2951    }
2952}
2953
2954impl fmt::Display for VectorArrangement {
2955    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2956        match self {
2957            VectorArrangement::B8 => write!(f, "8B"),
2958            VectorArrangement::B16 => write!(f, "16B"),
2959            VectorArrangement::H4 => write!(f, "4H"),
2960            VectorArrangement::H8 => write!(f, "8H"),
2961            VectorArrangement::S2 => write!(f, "2S"),
2962            VectorArrangement::S4 => write!(f, "4S"),
2963            VectorArrangement::D1 => write!(f, "1D"),
2964            VectorArrangement::D2 => write!(f, "2D"),
2965            VectorArrangement::SveB => write!(f, "B"),
2966            VectorArrangement::SveH => write!(f, "H"),
2967            VectorArrangement::SveS => write!(f, "S"),
2968            VectorArrangement::SveD => write!(f, "D"),
2969        }
2970    }
2971}
2972
2973/// SVE predicate qualifier (merging or zeroing).
2974#[derive(Debug, Clone, Copy, PartialEq, Eq)]
2975#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2976pub enum SvePredQual {
2977    /// Merging predication: `/M` — inactive lanes keep their old value.
2978    Merging,
2979    /// Zeroing predication: `/Z` — inactive lanes are set to zero.
2980    Zeroing,
2981}
2982
2983impl fmt::Display for SvePredQual {
2984    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2985        match self {
2986            SvePredQual::Merging => write!(f, "/m"),
2987            SvePredQual::Zeroing => write!(f, "/z"),
2988        }
2989    }
2990}
2991
2992/// Operand size hint (from `byte ptr`, `dword ptr`, etc.).
2993#[derive(Debug, Clone, Copy, PartialEq, Eq)]
2994#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2995pub enum OperandSize {
2996    /// 8-bit (`byte ptr`).
2997    Byte,
2998    /// 16-bit (`word ptr`).
2999    Word,
3000    /// 32-bit (`dword ptr`).
3001    Dword,
3002    /// 64-bit (`qword ptr`).
3003    Qword,
3004    /// 128-bit (`xmmword ptr` / `oword ptr`).
3005    Xmmword,
3006    /// 256-bit (`ymmword ptr`).
3007    Ymmword,
3008    /// 512-bit (`zmmword ptr`).
3009    Zmmword,
3010}
3011
3012impl OperandSize {
3013    /// Return the operand size in bits.
3014    pub fn bits(self) -> u16 {
3015        match self {
3016            OperandSize::Byte => 8,
3017            OperandSize::Word => 16,
3018            OperandSize::Dword => 32,
3019            OperandSize::Qword => 64,
3020            OperandSize::Xmmword => 128,
3021            OperandSize::Ymmword => 256,
3022            OperandSize::Zmmword => 512,
3023        }
3024    }
3025}
3026
3027impl fmt::Display for OperandSize {
3028    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3029        match self {
3030            OperandSize::Byte => write!(f, "byte"),
3031            OperandSize::Word => write!(f, "word"),
3032            OperandSize::Dword => write!(f, "dword"),
3033            OperandSize::Qword => write!(f, "qword"),
3034            OperandSize::Xmmword => write!(f, "xmmword"),
3035            OperandSize::Ymmword => write!(f, "ymmword"),
3036            OperandSize::Zmmword => write!(f, "zmmword"),
3037        }
3038    }
3039}
3040
3041/// Addressing mode for ARM/AArch64 load/store instructions.
3042#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
3043#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
3044pub enum AddrMode {
3045    /// Regular offset: `[Rn, #imm]`
3046    #[default]
3047    Offset,
3048    /// Pre-index with writeback: `[Rn, #imm]!`
3049    PreIndex,
3050    /// Post-index with writeback: `[Rn], #imm`
3051    PostIndex,
3052}
3053
3054/// A memory (indirect) operand.
3055#[derive(Debug, Clone, PartialEq, Eq)]
3056#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
3057pub struct MemoryOperand {
3058    /// Size qualifier (`byte ptr`, `qword ptr`, …) or `None` to infer.
3059    pub size: Option<OperandSize>,
3060    /// Base register (e.g., `rbp` in `[rbp+8]`).
3061    pub base: Option<Register>,
3062    /// Index register for SIB addressing (e.g., `rsi` in `[rbx+rsi*4]`).
3063    pub index: Option<Register>,
3064    /// SIB scale factor: 1, 2, 4, or 8.
3065    pub scale: u8,
3066    /// Displacement (constant offset) in bytes.
3067    pub disp: i64,
3068    /// Segment override prefix, if any (e.g., `fs:`).
3069    pub segment: Option<Register>,
3070    /// When the displacement is a label reference, the label name.
3071    pub disp_label: Option<String>,
3072    /// ARM/AArch64 addressing mode (offset, pre-index, post-index).
3073    pub addr_mode: AddrMode,
3074    /// Whether the index register is subtracted (ARM `[Rn, -Rm]`).
3075    pub index_subtract: bool,
3076}
3077
3078impl Default for MemoryOperand {
3079    fn default() -> Self {
3080        Self {
3081            size: None,
3082            base: None,
3083            index: None,
3084            scale: 1,
3085            disp: 0,
3086            segment: None,
3087            disp_label: None,
3088            addr_mode: AddrMode::Offset,
3089            index_subtract: false,
3090        }
3091    }
3092}
3093
3094/// An expression node for label arithmetic.
3095#[derive(Debug, Clone, PartialEq, Eq)]
3096#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
3097pub enum Expr {
3098    /// A numeric literal.
3099    Num(i128),
3100    /// A label reference.
3101    Label(String),
3102    /// Addition: left + right.
3103    Add(Box<Expr>, Box<Expr>),
3104    /// Subtraction: left - right.
3105    Sub(Box<Expr>, Box<Expr>),
3106}
3107
3108impl Expr {
3109    /// Try to evaluate to a constant integer.
3110    ///
3111    /// Returns `None` if the expression still contains unresolved label references.
3112    pub fn eval(&self) -> Option<i128> {
3113        match self {
3114            Expr::Num(n) => Some(*n),
3115            Expr::Label(_) => None,
3116            Expr::Add(l, r) => Some(l.eval()?.checked_add(r.eval()?)?),
3117            Expr::Sub(l, r) => Some(l.eval()?.checked_sub(r.eval()?)?),
3118        }
3119    }
3120
3121    /// Decompose into a single label reference plus a numeric addend.
3122    ///
3123    /// Returns `Some((label_name, addend))` when the expression is of the form
3124    /// `label`, `label + const`, or `label - const` (after constant folding).
3125    /// Returns `None` if the expression has zero or multiple label references,
3126    /// or a negated label (e.g. `5 - label`).
3127    pub fn label_addend(&self) -> Option<(&str, i64)> {
3128        let mut label: Option<&str> = None;
3129        let mut addend: i64 = 0;
3130        if self.collect_single_label(&mut label, &mut addend, 1) {
3131            label.map(|l| (l, addend))
3132        } else {
3133            None
3134        }
3135    }
3136
3137    /// Replace `Expr::Label(name)` nodes with `Expr::Num(value)` when
3138    /// the given lookup returns a value for the name.
3139    pub fn resolve_constants(&mut self, lookup: impl Fn(&str) -> Option<i128> + Copy) {
3140        match self {
3141            Expr::Label(name) => {
3142                if let Some(val) = lookup(name) {
3143                    *self = Expr::Num(val);
3144                }
3145            }
3146            Expr::Add(l, r) | Expr::Sub(l, r) => {
3147                l.resolve_constants(lookup);
3148                r.resolve_constants(lookup);
3149            }
3150            Expr::Num(_) => {}
3151        }
3152    }
3153
3154    /// Recursively find a single label reference with positive sign (no allocation).
3155    /// Returns `true` if the expression contains exactly one positively-signed label.
3156    fn collect_single_label<'a>(
3157        &'a self,
3158        label: &mut Option<&'a str>,
3159        addend: &mut i64,
3160        sign: i64,
3161    ) -> bool {
3162        match self {
3163            Expr::Num(n) => {
3164                *addend = addend.wrapping_add((*n as i64).wrapping_mul(sign));
3165                true
3166            }
3167            Expr::Label(name) => {
3168                if sign != 1 || label.is_some() {
3169                    // Negated label or second label → invalid
3170                    false
3171                } else {
3172                    *label = Some(name.as_str());
3173                    true
3174                }
3175            }
3176            Expr::Add(l, r) => {
3177                l.collect_single_label(label, addend, sign)
3178                    && r.collect_single_label(label, addend, sign)
3179            }
3180            Expr::Sub(l, r) => {
3181                l.collect_single_label(label, addend, sign)
3182                    && r.collect_single_label(label, addend, -sign)
3183            }
3184        }
3185    }
3186}
3187
3188/// A resolved or unresolved operand.
3189#[derive(Debug, Clone, PartialEq)]
3190#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
3191pub enum Operand {
3192    /// No operand.
3193    ///
3194    /// Fills the unused slots of an [`OperandList`], and is what indexing past
3195    /// the end of one yields. Operand counts come from parsed input, so an
3196    /// encoder that indexes further than the instruction actually goes must
3197    /// produce a diagnostic rather than panic — every operand-extraction
3198    /// helper rejects this variant, so the error falls out naturally.
3199    Missing,
3200    /// A register operand.
3201    Register(Register),
3202    /// An immediate value.
3203    Immediate(i128),
3204    /// A memory (indirect) operand.
3205    Memory(Box<MemoryOperand>),
3206    /// A label reference (resolved later).
3207    Label(String),
3208    /// An expression (e.g., `label + 4`).
3209    Expression(Expr),
3210    /// A register list (ARM `{R0, R1, R4, LR}`).
3211    RegisterList(Vec<Register>),
3212    /// A literal pool value (`LDR Xn, =0x1234`).
3213    /// The assembler will place the constant in a nearby literal pool
3214    /// and emit a PC-relative LDR to load it.
3215    LiteralPoolValue(i128),
3216    /// A vector register with arrangement specifier (AArch64 NEON/SVE).
3217    /// E.g., `V0.4S`, `V1.16B`, `Z0.S`, `Z1.D`.
3218    VectorRegister(Register, VectorArrangement),
3219    /// SVE predicate register with qualifier (`P0/M`, `P0/Z`).
3220    SvePredicate(Register, SvePredQual),
3221    /// A single lane of an AArch64 vector register: `V0.S[0]`.
3222    ///
3223    /// Element accesses name one lane rather than an arrangement, so they
3224    /// carry an element *size* plus an index instead of a
3225    /// [`VectorArrangement`].
3226    VectorElement(Register, ElementSize, u8),
3227    /// An ARM32 program status register with a field selector
3228    /// (`cpsr_f`, `spsr_cxsf`, ...), as used by `MSR` and `MRS`.
3229    PsrField(PsrField),
3230    /// A barrel-shift or register-extend modifier applied to the preceding
3231    /// operand (ARM32, Thumb, AArch64).
3232    ///
3233    /// UAL writes these as a trailing operand — `add x0, x1, x2, lsl #3` is
3234    /// four operands, the last being `lsl #3` — so they are modelled the same
3235    /// way rather than being folded into the register operand. That keeps the
3236    /// IR shaped like the source and lets a shift attach to an immediate
3237    /// (`movz x0, #0x5678, lsl #16`) as naturally as to a register.
3238    Shift(ShiftOp, ShiftAmount),
3239}
3240
3241/// The element size of an AArch64 vector lane access (`V0.S[0]`).
3242#[derive(Debug, Clone, Copy, PartialEq, Eq)]
3243#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
3244pub enum ElementSize {
3245    /// Byte (`.B`) — 16 lanes.
3246    B,
3247    /// Half-word (`.H`) — 8 lanes.
3248    H,
3249    /// Single-word (`.S`) — 4 lanes.
3250    S,
3251    /// Double-word (`.D`) — 2 lanes.
3252    D,
3253}
3254
3255impl ElementSize {
3256    /// Parse a lane-size suffix. Input must already be lowercase.
3257    #[must_use]
3258    pub fn from_lower(s: &str) -> Option<Self> {
3259        Some(match s {
3260            "b" => ElementSize::B,
3261            "h" => ElementSize::H,
3262            "s" => ElementSize::S,
3263            "d" => ElementSize::D,
3264            _ => return None,
3265        })
3266    }
3267
3268    /// Number of lanes of this size in a 128-bit vector register.
3269    #[must_use]
3270    pub fn lane_count(self) -> u8 {
3271        match self {
3272            ElementSize::B => 16,
3273            ElementSize::H => 8,
3274            ElementSize::S => 4,
3275            ElementSize::D => 2,
3276        }
3277    }
3278
3279    /// The `imm5` lane selector shared by `INS`, `UMOV`, `SMOV` and `DUP`.
3280    ///
3281    /// The size is encoded in the position of the lowest set bit, with the
3282    /// index sitting above it — so `imm5` names both at once.
3283    #[must_use]
3284    pub fn imm5(self, index: u8) -> u32 {
3285        let index = u32::from(index);
3286        match self {
3287            ElementSize::B => (index << 1) | 0b1,
3288            ElementSize::H => (index << 2) | 0b10,
3289            ElementSize::S => (index << 3) | 0b100,
3290            ElementSize::D => (index << 4) | 0b1000,
3291        }
3292    }
3293
3294    /// The `imm4` source-lane selector used by `INS` (element).
3295    #[must_use]
3296    pub fn imm4(self, index: u8) -> u32 {
3297        let index = u32::from(index);
3298        match self {
3299            ElementSize::B => index,
3300            ElementSize::H => index << 1,
3301            ElementSize::S => index << 2,
3302            ElementSize::D => index << 3,
3303        }
3304    }
3305}
3306
3307impl fmt::Display for ElementSize {
3308    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3309        f.write_str(match self {
3310            ElementSize::B => "b",
3311            ElementSize::H => "h",
3312            ElementSize::S => "s",
3313            ElementSize::D => "d",
3314        })
3315    }
3316}
3317
3318/// An ARM32 program status register together with the byte fields an `MSR`
3319/// writes to it.
3320///
3321/// The field suffix is not decoration: `msr cpsr_f, r0` updates only the
3322/// condition flags, while `msr cpsr_c, r0` can change the processor mode and
3323/// interrupt masks. Encoding one as the other would be a silent behaviour
3324/// change, so the selector is carried through the IR rather than defaulted.
3325#[derive(Debug, Clone, Copy, PartialEq, Eq)]
3326#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
3327pub struct PsrField {
3328    /// `true` for `SPSR`, `false` for `CPSR`.
3329    pub saved: bool,
3330    /// Field mask, in the bit order the instruction encodes it:
3331    /// bit 0 = `c` (control), 1 = `x` (extension), 2 = `s` (status),
3332    /// 3 = `f` (flags).
3333    pub mask: u8,
3334}
3335
3336impl PsrField {
3337    /// Parse `cpsr` / `spsr`, optionally suffixed with `_` and any combination
3338    /// of the field letters `c`, `x`, `s`, `f` (or `_all`). Input must already
3339    /// be lowercase.
3340    ///
3341    /// A bare `cpsr` selects the `f` and `c` fields, matching GNU `as`, which
3342    /// keeps the pre-UAL spelling meaning what it always did.
3343    #[must_use]
3344    pub fn from_lower(s: &str) -> Option<Self> {
3345        let (name, suffix) = match s.split_once('_') {
3346            Some((n, rest)) => (n, Some(rest)),
3347            None => (s, None),
3348        };
3349        let saved = match name {
3350            "cpsr" => false,
3351            "spsr" => true,
3352            _ => return None,
3353        };
3354        let mask = match suffix {
3355            None => 0b1001,
3356            Some("all") => 0b1111,
3357            Some(fields) => {
3358                let mut m = 0u8;
3359                for ch in fields.chars() {
3360                    m |= match ch {
3361                        'c' => 0b0001,
3362                        'x' => 0b0010,
3363                        's' => 0b0100,
3364                        'f' => 0b1000,
3365                        _ => return None,
3366                    };
3367                }
3368                m
3369            }
3370        };
3371        Some(Self { saved, mask })
3372    }
3373}
3374
3375impl fmt::Display for PsrField {
3376    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3377        f.write_str(if self.saved { "spsr" } else { "cpsr" })?;
3378        if self.mask != 0b1001 {
3379            f.write_str("_")?;
3380            for (bit, ch) in [(0b0001, 'c'), (0b0010, 'x'), (0b0100, 's'), (0b1000, 'f')] {
3381                if self.mask & bit != 0 {
3382                    write!(f, "{}", ch)?;
3383                }
3384            }
3385        }
3386        Ok(())
3387    }
3388}
3389
3390/// A barrel-shift or register-extend operation.
3391#[derive(Debug, Clone, Copy, PartialEq, Eq)]
3392#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
3393pub enum ShiftOp {
3394    /// Logical shift left.
3395    Lsl,
3396    /// Logical shift right.
3397    Lsr,
3398    /// Arithmetic shift right.
3399    Asr,
3400    /// Rotate right.
3401    Ror,
3402    /// Rotate right with extend (ARM32 only; shifts by exactly one through C).
3403    Rrx,
3404    /// Move shifted left, filling with ones (AArch64 SIMD immediates).
3405    Msl,
3406    /// Zero-extend byte (AArch64 register extend).
3407    Uxtb,
3408    /// Zero-extend halfword.
3409    Uxth,
3410    /// Zero-extend word.
3411    Uxtw,
3412    /// Zero-extend doubleword (no-op; the canonical LSL form for X registers).
3413    Uxtx,
3414    /// Sign-extend byte.
3415    Sxtb,
3416    /// Sign-extend halfword.
3417    Sxth,
3418    /// Sign-extend word.
3419    Sxtw,
3420    /// Sign-extend doubleword.
3421    Sxtx,
3422}
3423
3424impl ShiftOp {
3425    /// Parse a shift/extend keyword. Input must already be lowercase.
3426    #[must_use]
3427    pub fn from_lower(s: &str) -> Option<Self> {
3428        Some(match s {
3429            "lsl" => ShiftOp::Lsl,
3430            "lsr" => ShiftOp::Lsr,
3431            "asr" => ShiftOp::Asr,
3432            "ror" => ShiftOp::Ror,
3433            "rrx" => ShiftOp::Rrx,
3434            "msl" => ShiftOp::Msl,
3435            "uxtb" => ShiftOp::Uxtb,
3436            "uxth" => ShiftOp::Uxth,
3437            "uxtw" => ShiftOp::Uxtw,
3438            "uxtx" => ShiftOp::Uxtx,
3439            "sxtb" => ShiftOp::Sxtb,
3440            "sxth" => ShiftOp::Sxth,
3441            "sxtw" => ShiftOp::Sxtw,
3442            "sxtx" => ShiftOp::Sxtx,
3443            _ => return None,
3444        })
3445    }
3446
3447    /// The 2-bit shift-type field used by ARM32 and AArch64 data-processing
3448    /// instructions, or `None` for extends (which use a 3-bit `option` field).
3449    #[must_use]
3450    pub fn shift_type_bits(self) -> Option<u32> {
3451        Some(match self {
3452            ShiftOp::Lsl => 0b00,
3453            ShiftOp::Lsr => 0b01,
3454            ShiftOp::Asr => 0b10,
3455            // RRX is encoded as ROR with an immediate amount of zero.
3456            ShiftOp::Ror | ShiftOp::Rrx => 0b11,
3457            _ => return None,
3458        })
3459    }
3460
3461    /// The 3-bit `option` field for AArch64 register-extend operands.
3462    #[must_use]
3463    pub fn extend_option_bits(self) -> Option<u32> {
3464        Some(match self {
3465            ShiftOp::Uxtb => 0b000,
3466            ShiftOp::Uxth => 0b001,
3467            ShiftOp::Uxtw => 0b010,
3468            ShiftOp::Uxtx => 0b011,
3469            ShiftOp::Sxtb => 0b100,
3470            ShiftOp::Sxth => 0b101,
3471            ShiftOp::Sxtw => 0b110,
3472            ShiftOp::Sxtx => 0b111,
3473            _ => return None,
3474        })
3475    }
3476}
3477
3478impl fmt::Display for ShiftOp {
3479    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3480        let s = match self {
3481            ShiftOp::Lsl => "lsl",
3482            ShiftOp::Lsr => "lsr",
3483            ShiftOp::Asr => "asr",
3484            ShiftOp::Ror => "ror",
3485            ShiftOp::Rrx => "rrx",
3486            ShiftOp::Msl => "msl",
3487            ShiftOp::Uxtb => "uxtb",
3488            ShiftOp::Uxth => "uxth",
3489            ShiftOp::Uxtw => "uxtw",
3490            ShiftOp::Uxtx => "uxtx",
3491            ShiftOp::Sxtb => "sxtb",
3492            ShiftOp::Sxth => "sxth",
3493            ShiftOp::Sxtw => "sxtw",
3494            ShiftOp::Sxtx => "sxtx",
3495        };
3496        f.write_str(s)
3497    }
3498}
3499
3500/// How much a [`ShiftOp`] shifts by.
3501#[derive(Debug, Clone, Copy, PartialEq, Eq)]
3502#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
3503pub enum ShiftAmount {
3504    /// A constant amount (`lsl #3`).
3505    ///
3506    /// `i32`, not `i128`: no architecture encodes a shift wider than 63, and
3507    /// an `i128` here would force 16-byte alignment on `ShiftAmount`, which
3508    /// propagates through `Operand` into every `Instruction`. The signed type
3509    /// is kept so a negative amount can be diagnosed rather than wrapped.
3510    Immediate(i32),
3511    /// A register-supplied amount (`lsl r3`) — ARM32 only.
3512    Register(Register),
3513    /// No amount given (`rrx`, or a bare `uxtb` whose shift defaults to zero).
3514    None,
3515}
3516
3517impl fmt::Display for ShiftAmount {
3518    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3519        match self {
3520            ShiftAmount::Immediate(v) => write!(f, " #{}", v),
3521            ShiftAmount::Register(r) => write!(f, " {}", r),
3522            ShiftAmount::None => Ok(()),
3523        }
3524    }
3525}
3526
3527impl fmt::Display for Operand {
3528    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3529        match self {
3530            Operand::Missing => f.write_str("<none>"),
3531            Operand::Shift(op, amount) => write!(f, "{}{}", op, amount),
3532            Operand::PsrField(psr) => write!(f, "{}", psr),
3533            Operand::VectorElement(r, size, idx) => write!(f, "{}.{}[{}]", r, size, idx),
3534            Operand::Register(r) => write!(f, "{}", r),
3535            Operand::Immediate(v) => {
3536                if *v < 0 {
3537                    write!(f, "-0x{:X}", v.wrapping_neg())
3538                } else {
3539                    write!(f, "0x{:X}", v)
3540                }
3541            }
3542            Operand::Memory(mem) => {
3543                if let Some(sz) = mem.size {
3544                    write!(f, "{} ptr ", sz)?;
3545                }
3546                write!(f, "[")?;
3547                let mut parts = false;
3548                if let Some(base) = mem.base {
3549                    write!(f, "{}", base)?;
3550                    parts = true;
3551                }
3552                if let Some(idx) = mem.index {
3553                    if parts {
3554                        write!(f, "+")?;
3555                    }
3556                    write!(f, "{}*{}", idx, mem.scale)?;
3557                    parts = true;
3558                }
3559                if mem.disp != 0 || !parts {
3560                    if parts && mem.disp >= 0 {
3561                        write!(f, "+")?;
3562                    }
3563                    write!(f, "0x{:X}", mem.disp)?;
3564                }
3565                write!(f, "]")
3566            }
3567            Operand::Label(name) => write!(f, "{}", name),
3568            Operand::Expression(expr) => write!(f, "{}", expr),
3569            Operand::RegisterList(regs) => {
3570                write!(f, "{{")?;
3571                for (i, r) in regs.iter().enumerate() {
3572                    if i > 0 {
3573                        write!(f, ", ")?;
3574                    }
3575                    write!(f, "{}", r)?;
3576                }
3577                write!(f, "}}")
3578            }
3579            Operand::LiteralPoolValue(v) => write!(f, "={}", v),
3580            Operand::VectorRegister(r, arr) => write!(f, "{}.{}", r, arr),
3581            Operand::SvePredicate(r, qual) => write!(f, "{}{}", r, qual),
3582        }
3583    }
3584}
3585
3586impl fmt::Display for Expr {
3587    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3588        match self {
3589            Expr::Num(n) => write!(f, "{}", n),
3590            Expr::Label(name) => write!(f, "{}", name),
3591            Expr::Add(l, r) => write!(f, "({} + {})", l, r),
3592            Expr::Sub(l, r) => write!(f, "({} - {})", l, r),
3593        }
3594    }
3595}
3596
3597/// x86 instruction prefix.
3598#[derive(Debug, Clone, Copy, PartialEq, Eq)]
3599#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
3600pub enum Prefix {
3601    /// `LOCK` prefix — atomic read-modify-write.
3602    Lock,
3603    /// `REP` / `REPE` / `REPZ` prefix — repeat while equal / count.
3604    Rep,
3605    /// `REPNE` / `REPNZ` prefix — repeat while not equal.
3606    Repne,
3607    /// `FS:` segment override.
3608    SegFs,
3609    /// `GS:` segment override.
3610    SegGs,
3611}
3612
3613impl fmt::Display for Prefix {
3614    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3615        match self {
3616            Prefix::Lock => write!(f, "lock"),
3617            Prefix::Rep => write!(f, "rep"),
3618            Prefix::Repne => write!(f, "repne"),
3619            Prefix::SegFs => write!(f, "fs"),
3620            Prefix::SegGs => write!(f, "gs"),
3621        }
3622    }
3623}
3624
3625// ─── Mnemonic: stack-allocated instruction mnemonic ──────────────────
3626
3627/// Stack-allocated instruction mnemonic (max 24 ASCII bytes).
3628///
3629/// Replaces `String` for zero-allocation instruction construction.
3630/// All x86-64, AArch64, ARM, and RISC-V mnemonics fit within 24 bytes
3631/// (longest: `vaeskeygenassist` at 16 bytes).
3632#[derive(Clone, Copy)]
3633pub struct Mnemonic {
3634    buf: [u8; 24],
3635    len: u8,
3636}
3637
3638impl Mnemonic {
3639    /// Maximum mnemonic length in bytes.
3640    pub const MAX_LEN: usize = 24;
3641
3642    /// Creates a new empty `Mnemonic`.
3643    #[inline]
3644    pub const fn new() -> Self {
3645        Self {
3646            buf: [0; 24],
3647            len: 0,
3648        }
3649    }
3650
3651    /// Returns the mnemonic as a string slice.
3652    #[inline]
3653    pub fn as_str(&self) -> &str {
3654        // buf always contains valid UTF-8 (ASCII subset, written via from())
3655        core::str::from_utf8(&self.buf[..self.len as usize]).unwrap_or("")
3656    }
3657
3658    /// Returns the length in bytes.
3659    #[inline]
3660    pub fn len(&self) -> usize {
3661        self.len as usize
3662    }
3663
3664    /// Returns true if the mnemonic is empty.
3665    #[inline]
3666    pub fn is_empty(&self) -> bool {
3667        self.len == 0
3668    }
3669}
3670
3671impl From<&str> for Mnemonic {
3672    #[inline]
3673    fn from(s: &str) -> Self {
3674        let len = s.len().min(Self::MAX_LEN);
3675        let mut buf = [0u8; 24];
3676        buf[..len].copy_from_slice(&s.as_bytes()[..len]);
3677        Self {
3678            buf,
3679            len: len as u8,
3680        }
3681    }
3682}
3683
3684impl From<String> for Mnemonic {
3685    #[inline]
3686    fn from(s: String) -> Self {
3687        Self::from(s.as_str())
3688    }
3689}
3690
3691impl core::ops::Deref for Mnemonic {
3692    type Target = str;
3693    #[inline]
3694    fn deref(&self) -> &str {
3695        self.as_str()
3696    }
3697}
3698
3699impl PartialEq for Mnemonic {
3700    #[inline]
3701    fn eq(&self, other: &Self) -> bool {
3702        self.as_str() == other.as_str()
3703    }
3704}
3705
3706impl Eq for Mnemonic {}
3707
3708impl PartialEq<str> for Mnemonic {
3709    #[inline]
3710    fn eq(&self, other: &str) -> bool {
3711        self.as_str() == other
3712    }
3713}
3714
3715impl PartialEq<&str> for Mnemonic {
3716    #[inline]
3717    fn eq(&self, other: &&str) -> bool {
3718        self.as_str() == *other
3719    }
3720}
3721
3722impl PartialEq<Mnemonic> for str {
3723    #[inline]
3724    fn eq(&self, other: &Mnemonic) -> bool {
3725        self == other.as_str()
3726    }
3727}
3728
3729impl PartialEq<Mnemonic> for &str {
3730    #[inline]
3731    fn eq(&self, other: &Mnemonic) -> bool {
3732        *self == other.as_str()
3733    }
3734}
3735
3736impl PartialEq<String> for Mnemonic {
3737    #[inline]
3738    fn eq(&self, other: &String) -> bool {
3739        self.as_str() == other.as_str()
3740    }
3741}
3742
3743impl fmt::Debug for Mnemonic {
3744    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3745        write!(f, "\"{}\"", self.as_str())
3746    }
3747}
3748
3749impl fmt::Display for Mnemonic {
3750    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3751        write!(f, "{}", self.as_str())
3752    }
3753}
3754
3755impl Default for Mnemonic {
3756    fn default() -> Self {
3757        Self::new()
3758    }
3759}
3760
3761#[cfg(feature = "serde")]
3762impl serde::Serialize for Mnemonic {
3763    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
3764        serializer.serialize_str(self.as_str())
3765    }
3766}
3767
3768#[cfg(feature = "serde")]
3769impl<'de> serde::Deserialize<'de> for Mnemonic {
3770    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
3771        struct V;
3772        impl<'de> serde::de::Visitor<'de> for V {
3773            type Value = Mnemonic;
3774            fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3775                write!(f, "a mnemonic string (max 24 bytes)")
3776            }
3777            fn visit_str<E: serde::de::Error>(self, v: &str) -> Result<Mnemonic, E> {
3778                if v.len() > Mnemonic::MAX_LEN {
3779                    return Err(E::custom("mnemonic exceeds 24 bytes"));
3780                }
3781                Ok(Mnemonic::from(v))
3782            }
3783            fn visit_string<E: serde::de::Error>(self, v: String) -> Result<Mnemonic, E> {
3784                self.visit_str(&v)
3785            }
3786        }
3787        deserializer.deserialize_str(V)
3788    }
3789}
3790
3791// ─── OperandList: stack-allocated operand array ──────────────────────
3792
3793/// Stack-allocated operand list (max 4 operands).
3794///
3795/// Replaces `Vec<Operand>` for zero-allocation instruction construction.
3796/// All instructions across x86-64, AArch64, ARM, and RISC-V use ≤ 6 operands
3797/// (RISC-V vector `vsetvli` uses 6: rd, rs1, sew, lmul, ta/tu, ma/mu).
3798pub struct OperandList {
3799    items: [Operand; 6],
3800    len: u8,
3801}
3802
3803impl OperandList {
3804    /// Maximum number of operands.
3805    ///
3806    /// Six is not a round number picked for headroom: instrumenting the whole
3807    /// test suite shows real instructions reaching both five and six operands
3808    /// (AVX-512 and SVE forms). Lowering it would shrink `Instruction` — the
3809    /// list is stored inline — but would reject valid input, so it stays.
3810    pub const MAX_LEN: usize = 6;
3811
3812    /// Creates a new empty operand list.
3813    #[inline]
3814    pub fn new() -> Self {
3815        Self {
3816            items: core::array::from_fn(|_| Operand::default()),
3817            len: 0,
3818        }
3819    }
3820
3821    /// Appends an operand, returning `false` if the list is already full.
3822    ///
3823    /// Operand counts come from user input, so callers that parse must use
3824    /// this and report a diagnostic rather than relying on [`push`](Self::push),
3825    /// which panics.
3826    #[inline]
3827    #[must_use]
3828    pub fn try_push(&mut self, op: Operand) -> bool {
3829        if (self.len as usize) >= Self::MAX_LEN {
3830            return false;
3831        }
3832        self.items[self.len as usize] = op;
3833        self.len += 1;
3834        true
3835    }
3836
3837    /// Appends an operand to the list.
3838    ///
3839    /// # Panics
3840    ///
3841    /// Panics if the list is already full. Only for callers that construct
3842    /// instructions programmatically and control the operand count; anything
3843    /// driven by parsed input must use [`try_push`](Self::try_push).
3844    #[inline]
3845    pub fn push(&mut self, op: Operand) {
3846        assert!(
3847            (self.len as usize) < Self::MAX_LEN,
3848            "OperandList overflow: max {} operands",
3849            Self::MAX_LEN
3850        );
3851        self.items[self.len as usize] = op;
3852        self.len += 1;
3853    }
3854
3855    /// Returns the number of operands.
3856    #[inline]
3857    pub fn len(&self) -> usize {
3858        self.len as usize
3859    }
3860
3861    /// Returns `true` if empty.
3862    #[inline]
3863    pub fn is_empty(&self) -> bool {
3864        self.len == 0
3865    }
3866
3867    /// Returns the active operands as a slice.
3868    #[inline]
3869    pub fn as_slice(&self) -> &[Operand] {
3870        &self.items[..self.len as usize]
3871    }
3872
3873    /// Returns the active operands as a mutable slice.
3874    #[inline]
3875    pub fn as_mut_slice(&mut self) -> &mut [Operand] {
3876        &mut self.items[..self.len as usize]
3877    }
3878}
3879
3880impl core::ops::Index<usize> for OperandList {
3881    type Output = Operand;
3882
3883    /// Indexing past the operands the instruction actually has yields
3884    /// [`Operand::Missing`] rather than panicking.
3885    ///
3886    /// Encoders index operands positionally after checking the count, but
3887    /// there are hundreds of such arms and the counts come from parsed text;
3888    /// one missing check would otherwise be a panic reachable from untrusted
3889    /// input. `Missing` is rejected by every extraction helper, so a forgotten
3890    /// check surfaces as an ordinary "invalid operands" diagnostic.
3891    #[inline]
3892    fn index(&self, idx: usize) -> &Operand {
3893        match self.items.get(idx) {
3894            Some(op) => op,
3895            // Past the fixed capacity entirely — still not a panic.
3896            None => &Operand::Missing,
3897        }
3898    }
3899}
3900
3901impl core::ops::IndexMut<usize> for OperandList {
3902    /// Unlike the shared [`Index`](core::ops::Index) impl, this panics out of
3903    /// range: writes come from this crate's own transforms, which know how
3904    /// many operands they are working with, so an out-of-range write is a bug
3905    /// worth surfacing rather than input worth diagnosing.
3906    #[inline]
3907    fn index_mut(&mut self, idx: usize) -> &mut Operand {
3908        assert!(
3909            idx < self.len as usize,
3910            "OperandList index {idx} out of range (len {})",
3911            self.len
3912        );
3913        &mut self.items[idx]
3914    }
3915}
3916
3917impl core::ops::Deref for OperandList {
3918    type Target = [Operand];
3919    #[inline]
3920    fn deref(&self) -> &[Operand] {
3921        self.as_slice()
3922    }
3923}
3924
3925impl core::ops::DerefMut for OperandList {
3926    #[inline]
3927    fn deref_mut(&mut self) -> &mut [Operand] {
3928        self.as_mut_slice()
3929    }
3930}
3931
3932impl Clone for OperandList {
3933    fn clone(&self) -> Self {
3934        let mut items: [Operand; 6] = core::array::from_fn(|_| Operand::default());
3935        for (i, op) in self.items[..self.len as usize].iter().enumerate() {
3936            items[i] = op.clone();
3937        }
3938        Self {
3939            items,
3940            len: self.len,
3941        }
3942    }
3943}
3944
3945impl PartialEq for OperandList {
3946    fn eq(&self, other: &Self) -> bool {
3947        self.as_slice() == other.as_slice()
3948    }
3949}
3950
3951impl PartialEq<Vec<Operand>> for OperandList {
3952    fn eq(&self, other: &Vec<Operand>) -> bool {
3953        self.as_slice() == &other[..]
3954    }
3955}
3956
3957impl fmt::Debug for OperandList {
3958    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3959        f.debug_list().entries(self.as_slice().iter()).finish()
3960    }
3961}
3962
3963impl Default for OperandList {
3964    fn default() -> Self {
3965        Self::new()
3966    }
3967}
3968
3969impl From<Vec<Operand>> for OperandList {
3970    fn from(v: Vec<Operand>) -> Self {
3971        assert!(
3972            v.len() <= Self::MAX_LEN,
3973            "OperandList: max {} operands, got {}",
3974            Self::MAX_LEN,
3975            v.len()
3976        );
3977        let mut list = Self::new();
3978        for op in v {
3979            list.push(op);
3980        }
3981        list
3982    }
3983}
3984
3985impl<'a> IntoIterator for &'a OperandList {
3986    type Item = &'a Operand;
3987    type IntoIter = core::slice::Iter<'a, Operand>;
3988    fn into_iter(self) -> Self::IntoIter {
3989        self.as_slice().iter()
3990    }
3991}
3992
3993impl<'a> IntoIterator for &'a mut OperandList {
3994    type Item = &'a mut Operand;
3995    type IntoIter = core::slice::IterMut<'a, Operand>;
3996    fn into_iter(self) -> Self::IntoIter {
3997        self.as_mut_slice().iter_mut()
3998    }
3999}
4000
4001#[cfg(feature = "serde")]
4002impl serde::Serialize for OperandList {
4003    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
4004        use serde::ser::SerializeSeq;
4005        let mut seq = serializer.serialize_seq(Some(self.len()))?;
4006        for op in self.as_slice() {
4007            seq.serialize_element(op)?;
4008        }
4009        seq.end()
4010    }
4011}
4012
4013#[cfg(feature = "serde")]
4014impl<'de> serde::Deserialize<'de> for OperandList {
4015    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
4016        let v: Vec<Operand> = Vec::deserialize(deserializer)?;
4017        if v.len() > Self::MAX_LEN {
4018            return Err(serde::de::Error::custom(alloc::format!(
4019                "too many operands: {} > {}",
4020                v.len(),
4021                Self::MAX_LEN
4022            )));
4023        }
4024        Ok(Self::from(v))
4025    }
4026}
4027
4028// ─── PrefixList: stack-allocated prefix array ────────────────────────
4029
4030/// Stack-allocated prefix list (max 4 prefixes).
4031///
4032/// Replaces `Vec<Prefix>` for zero-allocation instruction construction.
4033/// x86-64 instructions use at most 2–3 prefixes in practice.
4034#[derive(Clone, Copy)]
4035pub struct PrefixList {
4036    items: [Prefix; 4],
4037    len: u8,
4038}
4039
4040impl PrefixList {
4041    /// Maximum number of prefixes.
4042    pub const MAX_LEN: usize = 4;
4043
4044    /// Creates a new empty prefix list.
4045    #[inline]
4046    pub const fn new() -> Self {
4047        Self {
4048            items: [Prefix::Lock; 4], // sentinel, never read beyond len
4049            len: 0,
4050        }
4051    }
4052
4053    /// Appends a prefix to the list.
4054    ///
4055    /// # Panics
4056    /// Panics if the list is full (> 4 prefixes).
4057    #[inline]
4058    pub fn push(&mut self, p: Prefix) {
4059        assert!(
4060            (self.len as usize) < Self::MAX_LEN,
4061            "PrefixList overflow: max {} prefixes",
4062            Self::MAX_LEN
4063        );
4064        self.items[self.len as usize] = p;
4065        self.len += 1;
4066    }
4067
4068    /// Returns the number of prefixes.
4069    #[inline]
4070    pub fn len(&self) -> usize {
4071        self.len as usize
4072    }
4073
4074    /// Returns `true` if empty.
4075    #[inline]
4076    pub fn is_empty(&self) -> bool {
4077        self.len == 0
4078    }
4079
4080    /// Returns the active prefixes as a slice.
4081    #[inline]
4082    pub fn as_slice(&self) -> &[Prefix] {
4083        &self.items[..self.len as usize]
4084    }
4085}
4086
4087impl core::ops::Deref for PrefixList {
4088    type Target = [Prefix];
4089    #[inline]
4090    fn deref(&self) -> &[Prefix] {
4091        self.as_slice()
4092    }
4093}
4094
4095impl PartialEq for PrefixList {
4096    fn eq(&self, other: &Self) -> bool {
4097        self.as_slice() == other.as_slice()
4098    }
4099}
4100
4101impl Eq for PrefixList {}
4102
4103impl PartialEq<Vec<Prefix>> for PrefixList {
4104    fn eq(&self, other: &Vec<Prefix>) -> bool {
4105        self.as_slice() == &other[..]
4106    }
4107}
4108
4109impl fmt::Debug for PrefixList {
4110    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
4111        f.debug_list().entries(self.as_slice().iter()).finish()
4112    }
4113}
4114
4115impl Default for PrefixList {
4116    fn default() -> Self {
4117        Self::new()
4118    }
4119}
4120
4121impl From<Vec<Prefix>> for PrefixList {
4122    fn from(v: Vec<Prefix>) -> Self {
4123        assert!(
4124            v.len() <= Self::MAX_LEN,
4125            "PrefixList: max {} prefixes, got {}",
4126            Self::MAX_LEN,
4127            v.len()
4128        );
4129        let mut list = Self::new();
4130        for p in v {
4131            list.push(p);
4132        }
4133        list
4134    }
4135}
4136
4137impl<'a> IntoIterator for &'a PrefixList {
4138    type Item = &'a Prefix;
4139    type IntoIter = core::slice::Iter<'a, Prefix>;
4140    fn into_iter(self) -> Self::IntoIter {
4141        self.as_slice().iter()
4142    }
4143}
4144
4145#[cfg(feature = "serde")]
4146impl serde::Serialize for PrefixList {
4147    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
4148        use serde::ser::SerializeSeq;
4149        let mut seq = serializer.serialize_seq(Some(self.len()))?;
4150        for p in self.as_slice() {
4151            seq.serialize_element(p)?;
4152        }
4153        seq.end()
4154    }
4155}
4156
4157#[cfg(feature = "serde")]
4158impl<'de> serde::Deserialize<'de> for PrefixList {
4159    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
4160        let v: Vec<Prefix> = Vec::deserialize(deserializer)?;
4161        if v.len() > Self::MAX_LEN {
4162            return Err(serde::de::Error::custom(alloc::format!(
4163                "too many prefixes: {} > {}",
4164                v.len(),
4165                Self::MAX_LEN
4166            )));
4167        }
4168        Ok(Self::from(v))
4169    }
4170}
4171
4172// ─── Default for Operand (used by OperandList) ──────────────────────
4173
4174impl Default for Operand {
4175    /// The sentinel for an absent operand.
4176    #[inline]
4177    fn default() -> Self {
4178        Operand::Missing
4179    }
4180}
4181
4182/// A parsed instruction before encoding.
4183#[derive(Debug, Clone, PartialEq)]
4184#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
4185pub struct Instruction {
4186    /// Instruction mnemonic (lower-cased), e.g. `"mov"`, `"add"`.
4187    pub mnemonic: Mnemonic,
4188    /// Parsed operands (0–4), in Intel order (dest, src, …).
4189    pub operands: OperandList,
4190    /// Explicit operand-size hint from a `ptr` qualifier.
4191    pub size_hint: Option<OperandSize>,
4192    /// Instruction prefixes (`lock`, `rep`, `repne`, segment overrides).
4193    pub prefixes: PrefixList,
4194    /// AVX-512 opmask register decorator (`{k1}`–`{k7}`).
4195    pub opmask: Option<Register>,
4196    /// AVX-512 zeroing-masking decorator (`{z}`). Only valid with opmask.
4197    pub zeroing: bool,
4198    /// AVX-512 broadcast decorator (`{1to2}`, `{1to4}`, `{1to8}`, `{1to16}`).
4199    pub broadcast: Option<BroadcastMode>,
4200    /// Source location of the entire instruction.
4201    pub span: Span,
4202}
4203
4204/// AVX-512 embedded broadcast mode.
4205#[derive(Debug, Clone, Copy, PartialEq, Eq)]
4206#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
4207pub enum BroadcastMode {
4208    /// Broadcast 1 element to 2 lanes (`{1to2}`).
4209    OneToTwo,
4210    /// Broadcast 1 element to 4 lanes (`{1to4}`).
4211    OneToFour,
4212    /// Broadcast 1 element to 8 lanes (`{1to8}`).
4213    OneToEight,
4214    /// Broadcast 1 element to 16 lanes (`{1to16}`).
4215    OneToSixteen,
4216}
4217
4218/// Data declaration sizes.
4219#[derive(Debug, Clone, Copy, PartialEq, Eq)]
4220#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
4221pub enum DataSize {
4222    /// 1 byte (`.byte` / `.db`).
4223    Byte,
4224    /// 2 bytes (`.word` / `.dw` / `.short`).
4225    Word,
4226    /// 4 bytes (`.long` / `.dd` / `.int`).
4227    Long,
4228    /// 8 bytes (`.quad` / `.dq`).
4229    Quad,
4230}
4231
4232impl fmt::Display for DataSize {
4233    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
4234        match self {
4235            DataSize::Byte => write!(f, ".byte"),
4236            DataSize::Word => write!(f, ".word"),
4237            DataSize::Long => write!(f, ".long"),
4238            DataSize::Quad => write!(f, ".quad"),
4239        }
4240    }
4241}
4242
4243/// A data value in a data directive.
4244#[derive(Debug, Clone, PartialEq)]
4245#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
4246pub enum DataValue {
4247    /// A numeric literal.
4248    Integer(i128),
4249    /// A label reference with optional addend — resolved to an address during linking.
4250    Label(String, i64),
4251    /// Raw byte sequence (from `.ascii` / `.asciz`).
4252    Bytes(Vec<u8>),
4253}
4254
4255/// A data declaration (.byte, .word, .ascii, etc.).
4256#[derive(Debug, Clone, PartialEq)]
4257#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
4258pub struct DataDecl {
4259    /// Element size for each value.
4260    pub size: DataSize,
4261    /// One or more data values.
4262    pub values: Vec<DataValue>,
4263    /// Source location.
4264    pub span: Span,
4265}
4266
4267/// Alignment directive.
4268#[derive(Debug, Clone, PartialEq, Eq)]
4269#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
4270pub struct AlignDirective {
4271    /// Required alignment in bytes (must be a power of two).
4272    pub alignment: u32,
4273    /// Fill byte (when `None`, x86 uses multi-byte NOP sequences).
4274    pub fill: Option<u8>,
4275    /// If padding would exceed this many bytes, skip the alignment entirely.
4276    pub max_skip: Option<u32>,
4277    /// Source location.
4278    pub span: Span,
4279}
4280
4281/// A constant definition (.equ, .set, =).
4282#[derive(Debug, Clone, PartialEq)]
4283#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
4284pub struct ConstDef {
4285    /// Constant name.
4286    pub name: String,
4287    /// Constant value.
4288    pub value: i128,
4289    /// Source location.
4290    pub span: Span,
4291}
4292
4293/// Fill directive (.fill count, size, value).
4294#[derive(Debug, Clone, PartialEq, Eq)]
4295#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
4296pub struct FillDirective {
4297    /// Number of repetitions.
4298    pub count: u32,
4299    /// Size of each unit in bytes (1–8).
4300    pub size: u8,
4301    /// Fill value (stored as i64, truncated to `size` bytes in little-endian).
4302    pub value: i64,
4303    /// Source location.
4304    pub span: Span,
4305}
4306
4307/// Space directive (.space n / .skip n).
4308#[derive(Debug, Clone, PartialEq, Eq)]
4309#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
4310pub struct SpaceDirective {
4311    /// Number of bytes to reserve.
4312    pub size: u32,
4313    /// Fill byte value (default 0x00).
4314    pub fill: u8,
4315    /// Source location.
4316    pub span: Span,
4317}
4318
4319/// Org directive (.org offset[, fill]).
4320#[derive(Debug, Clone, PartialEq, Eq)]
4321#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
4322pub struct OrgDirective {
4323    /// Target byte offset.
4324    pub offset: u64,
4325    /// Fill byte for padding (default 0x00).
4326    pub fill: u8,
4327    /// Source location.
4328    pub span: Span,
4329}
4330
4331/// x86 code width (operand/address size mode).
4332///
4333/// Used by `.code16`, `.code32`, `.code64` directives to switch the default
4334/// operand and address size within the same assembly unit.
4335#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
4336#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
4337pub enum X86Mode {
4338    /// 16-bit real mode: default operand size 16, address size 16.
4339    Mode16,
4340    /// 32-bit protected mode: default operand size 32, address size 32.
4341    Mode32,
4342    /// 64-bit long mode: default operand size 32, address size 64.
4343    Mode64,
4344}
4345
4346/// A statement in the IR.
4347#[derive(Debug, Clone, PartialEq)]
4348#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
4349#[allow(clippy::large_enum_variant)] // Instruction is inline to avoid heap allocations
4350pub enum Statement {
4351    /// A label definition.
4352    Label(String, Span),
4353    /// An instruction.
4354    Instruction(Instruction),
4355    /// A data declaration (`.byte`, `.word`, `.ascii`, etc.).
4356    Data(DataDecl),
4357    /// An alignment directive.
4358    Align(AlignDirective),
4359    /// A constant definition (`.equ`, `.set`, `=`).
4360    Const(ConstDef),
4361    /// A `.fill` directive.
4362    Fill(FillDirective),
4363    /// A `.space` / `.skip` directive.
4364    Space(SpaceDirective),
4365    /// An `.org` directive.
4366    Org(OrgDirective),
4367    /// A code-mode switch (`.code16`, `.code32`, `.code64`).
4368    CodeMode(X86Mode, Span),
4369    /// A literal pool flush point (`.ltorg` / `.pool`).
4370    Ltorg(Span),
4371    /// A RISC-V `.option rvc` / `.option norvc` directive.
4372    OptionRvc(bool, Span),
4373    /// A `.thumb` / `.arm` mode switch directive (true = Thumb, false = ARM).
4374    ThumbMode(bool, Span),
4375    /// A `.thumb_func` directive — marks the next label as a Thumb function.
4376    ThumbFunc(Span),
4377}
4378
4379#[cfg(test)]
4380mod tests {
4381    use super::*;
4382
4383    #[test]
4384    fn register_size_bits() {
4385        assert_eq!(Register::Rax.size_bits(), 64);
4386        assert_eq!(Register::Eax.size_bits(), 32);
4387        assert_eq!(Register::Ax.size_bits(), 16);
4388        assert_eq!(Register::Al.size_bits(), 8);
4389        assert_eq!(Register::R8.size_bits(), 64);
4390        assert_eq!(Register::R8d.size_bits(), 32);
4391    }
4392
4393    #[test]
4394    fn register_base_code() {
4395        assert_eq!(Register::Rax.base_code(), 0);
4396        assert_eq!(Register::Rcx.base_code(), 1);
4397        assert_eq!(Register::Rdx.base_code(), 2);
4398        assert_eq!(Register::Rbx.base_code(), 3);
4399        assert_eq!(Register::Rsp.base_code(), 4);
4400        assert_eq!(Register::Rbp.base_code(), 5);
4401        assert_eq!(Register::Rsi.base_code(), 6);
4402        assert_eq!(Register::Rdi.base_code(), 7);
4403    }
4404
4405    #[test]
4406    fn register_is_extended() {
4407        assert!(!Register::Rax.is_extended());
4408        assert!(Register::R8.is_extended());
4409        assert!(Register::R15d.is_extended());
4410        assert!(Register::R8b.is_extended());
4411    }
4412
4413    #[test]
4414    fn register_high_byte() {
4415        assert!(Register::Ah.is_high_byte());
4416        assert!(Register::Ch.is_high_byte());
4417        assert!(!Register::Al.is_high_byte());
4418        assert!(!Register::Spl.is_high_byte());
4419    }
4420
4421    #[test]
4422    fn arch_display() {
4423        assert_eq!(format!("{}", Arch::X86_64), "x86_64");
4424        assert_eq!(format!("{}", Arch::Aarch64), "AArch64");
4425    }
4426
4427    #[test]
4428    fn operand_size_bits() {
4429        assert_eq!(OperandSize::Byte.bits(), 8);
4430        assert_eq!(OperandSize::Word.bits(), 16);
4431        assert_eq!(OperandSize::Dword.bits(), 32);
4432        assert_eq!(OperandSize::Qword.bits(), 64);
4433        assert_eq!(OperandSize::Xmmword.bits(), 128);
4434        assert_eq!(OperandSize::Ymmword.bits(), 256);
4435        assert_eq!(OperandSize::Zmmword.bits(), 512);
4436    }
4437
4438    #[test]
4439    fn register_display() {
4440        assert_eq!(format!("{}", Register::Rax), "rax");
4441        assert_eq!(format!("{}", Register::R8d), "r8d");
4442        assert_eq!(format!("{}", Register::Xmm0), "xmm0");
4443        assert_eq!(format!("{}", Register::Ymm0), "ymm0");
4444        assert_eq!(format!("{}", Register::Zmm0), "zmm0");
4445        assert_eq!(format!("{}", Register::K0), "k0");
4446    }
4447
4448    #[test]
4449    fn operand_size_display() {
4450        assert_eq!(format!("{}", OperandSize::Byte), "byte");
4451        assert_eq!(format!("{}", OperandSize::Qword), "qword");
4452    }
4453
4454    #[test]
4455    fn data_size_display() {
4456        assert_eq!(format!("{}", DataSize::Byte), ".byte");
4457        assert_eq!(format!("{}", DataSize::Quad), ".quad");
4458    }
4459
4460    #[test]
4461    fn prefix_display() {
4462        assert_eq!(format!("{}", Prefix::Lock), "lock");
4463        assert_eq!(format!("{}", Prefix::Rep), "rep");
4464    }
4465
4466    #[test]
4467    fn operand_display() {
4468        assert_eq!(format!("{}", Operand::Register(Register::Rax)), "rax");
4469        assert_eq!(format!("{}", Operand::Immediate(42)), "0x2A");
4470        assert_eq!(format!("{}", Operand::Immediate(-1)), "-0x1");
4471        assert_eq!(format!("{}", Operand::Label(String::from("loop"))), "loop");
4472
4473        let mem = MemoryOperand {
4474            base: Some(Register::Rbp),
4475            disp: 8,
4476            ..Default::default()
4477        };
4478        assert_eq!(format!("{}", Operand::Memory(Box::new(mem))), "[rbp+0x8]");
4479
4480        let mem2 = MemoryOperand {
4481            base: Some(Register::Rbx),
4482            index: Some(Register::Rcx),
4483            scale: 4,
4484            disp: 0,
4485            size: Some(OperandSize::Dword),
4486            ..Default::default()
4487        };
4488        assert_eq!(
4489            format!("{}", Operand::Memory(Box::new(mem2))),
4490            "dword ptr [rbx+rcx*4]"
4491        );
4492    }
4493
4494    #[test]
4495    fn expr_display() {
4496        let expr = Expr::Add(
4497            Box::new(Expr::Label(String::from("foo"))),
4498            Box::new(Expr::Num(4)),
4499        );
4500        assert_eq!(format!("{}", expr), "(foo + 4)");
4501    }
4502
4503    #[test]
4504    fn expr_eval_numeric() {
4505        let e = Expr::Add(Box::new(Expr::Num(10)), Box::new(Expr::Num(20)));
4506        assert_eq!(e.eval(), Some(30));
4507    }
4508
4509    #[test]
4510    fn expr_eval_with_label_returns_none() {
4511        let e = Expr::Add(
4512            Box::new(Expr::Label(String::from("x"))),
4513            Box::new(Expr::Num(5)),
4514        );
4515        assert_eq!(e.eval(), None);
4516    }
4517
4518    #[test]
4519    fn expr_label_addend_add() {
4520        let e = Expr::Add(
4521            Box::new(Expr::Label(String::from("data"))),
4522            Box::new(Expr::Num(8)),
4523        );
4524        assert_eq!(e.label_addend(), Some(("data", 8)));
4525    }
4526
4527    #[test]
4528    fn expr_label_addend_sub() {
4529        let e = Expr::Sub(
4530            Box::new(Expr::Label(String::from("data"))),
4531            Box::new(Expr::Num(3)),
4532        );
4533        assert_eq!(e.label_addend(), Some(("data", -3)));
4534    }
4535
4536    #[test]
4537    fn expr_label_addend_plain_label() {
4538        let e = Expr::Label(String::from("foo"));
4539        assert_eq!(e.label_addend(), Some(("foo", 0)));
4540    }
4541
4542    #[test]
4543    fn expr_label_addend_two_labels_returns_none() {
4544        let e = Expr::Add(
4545            Box::new(Expr::Label(String::from("a"))),
4546            Box::new(Expr::Label(String::from("b"))),
4547        );
4548        assert_eq!(e.label_addend(), None);
4549    }
4550
4551    #[test]
4552    fn expr_resolve_constants() {
4553        let mut e = Expr::Add(
4554            Box::new(Expr::Label(String::from("SIZE"))),
4555            Box::new(Expr::Num(1)),
4556        );
4557        e.resolve_constants(|name| if name == "SIZE" { Some(10) } else { None });
4558        assert_eq!(e.eval(), Some(11));
4559    }
4560
4561    #[test]
4562    fn expr_resolve_constants_partial() {
4563        let mut e = Expr::Add(
4564            Box::new(Expr::Label(String::from("SIZE"))),
4565            Box::new(Expr::Label(String::from("unknown"))),
4566        );
4567        e.resolve_constants(|name| if name == "SIZE" { Some(10) } else { None });
4568        // Still has unresolved label
4569        assert_eq!(e.eval(), None);
4570    }
4571}