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}