Skip to main content

Crate fARM64

Crate fARM64 

Source
Expand description

§fARM64 — a pure-Rust AArch64 (A64) disassembler and semantic encoder

fARM64 decodes 64-bit ARM (AArch64 / A64) machine code into a rich, Copy value-type Instruction, renders it with a pluggable Formatter, and re-encodes instruction semantics with encode() — including after editing its operands. The Arm architectural decode tree is hand-written from the Arm Architecture Reference Manual (the “Arm ARM”) and cross-checked during development against independent tools and corpora. Apple AMX and GXF are implementation-defined exceptions based on public reverse-engineering references and are separately runtime-gated.

§Portability is a hard, cross-cutting guarantee

This crate is #![no_std] unconditionally. The core decode path and the default formatter perform zero heap allocation and have no dependency on alloc or std at all:

  • The decoder (Decoder::decode_into) writes into a caller-owned, Copy Instruction; there is no Vec, no Box, no internal pointers.
  • The default formatter (format::FmtFormatter) writes into a caller-supplied core::fmt::Write sink or a fixed &mut [u8] buffer via format::BufSink (with overflow tracking, never overrun).
  • All names (registers, mnemonics, system registers) are &'static str sourced from const/static tables.
  • No thread-locals, no environment/IO/time access, no panics-as-control-flow, deterministic, and no floating-point arithmetic in the decoder.

Builds cleanly for hosted targets, wasm32-unknown-unknown, and aarch64-unknown-none (freestanding / no-CRT, no allocator).

§Feature matrix

FeatureTierEffect
(none / default)Ano_std, no alloc, freestanding. Decoder + format::FmtFormatter + all enums. Always builds.
allocBAdds String/Vec conveniences (format_to_string, a cached info::InstructionInfoFactory, and a token-collecting String sink).
stdCImplies alloc; adds std::error::Error for DecodeError, EncodeError, and EnumValueError, plus std-only test/bench helpers.
fmt-gnuAAdds a UAL-equivalent GNU compatibility adapter. Pure no_std.
sveACompiles the SVE/SVE2 decoder and encoder modules.
smeACompiles the SME/SME2 decoder and encoder modules.
cryptoACompiles the Advanced SIMD crypto decoder; public enums and encoder support remain present.
fullAEnables sve, sme, and crypto.

Cargo features decide which optional implementation modules are compiled; the runtime FeatureSet decides what is accepted at decode time. Not every runtime extension has a corresponding Cargo feature.

§Supported targets

TargetNotes
x86_64-*, aarch64-* (hosted)development / std testing
wasm32-unknown-unknowndefault features (no_std, no alloc)
aarch64-unknown-nonebare-metal, no-CRT; checked with --no-default-features
any target providing corethe default tier is core-only

§Quick start (zero-alloc, no_std-friendly)

use fARM64::{Decoder, DecoderOptions, format::{Formatter, FmtFormatter, BufSink}};

// `ADD W0, W1, #1` little-endian; decode at a known address.
let code = [0x20, 0x04, 0x00, 0x11];
let mut dec = Decoder::new(&code, 0x1000, DecoderOptions::default());
let insn = dec.decode();

// Format into a fixed stack buffer — no heap involved.
let mut buf = [0u8; 64];
let mut sink = BufSink::new(&mut buf);
FmtFormatter::new().format(&insn, &mut sink);
let _text: &str = sink.as_str();

§Editing and re-encoding

encode() rebuilds the word from an Instruction’s semantics and never reads Instruction::word, so changing the operands and encoding again yields the word for the changed instruction:

use fARM64::{Decoder, DecoderOptions, Register};

// `ldr x0, [x1, #8]` -> `ldr x0, [x3, #16]`
let bytes = 0xF940_0420u32.to_le_bytes();
let mut insn = Decoder::new(&bytes, 0, DecoderOptions::NONE).decode();
assert!(insn.set_memory_base(Register::X3));
assert!(insn.set_memory_displacement64(16));
assert_eq!(insn.encode(), Ok(0xF940_0860));

Every setter is total: it returns false rather than panicking when the edit does not apply, and a value with no valid field encoding surfaces as an EncodeError from encode(). See the editing rules.

§Implicit register reads and writes

A64 hides real dataflow behind the mnemonic — BL writes X30, PACIASP read-modifies X30 using SP, LD64B <Xt> writes Xt..Xt+7, LDFF1* read-modifies the SVE FFR, ADR reads PC. implicit_registers() reports all of it, using the Register::Nzcv / Register::Ffr / Register::Za / Register::Pc pseudo-registers for state that has no numbered register. instruction_info() merges the list into its used_registers access set.

§Licensing & provenance

Licensed under the MIT License. Arm architectural instruction handling is based on the publicly documented Arm ARM. The implementation also contains separately gated Apple implementation-defined AMX/GXF support based on public reverse-engineering references: https://github.com/corsix/amx, https://asahilinux.org/docs/hw/cpu/apple-instructions/, and https://blog.svenpeter.dev/posts/m1_sprr_gxf/.

Re-exports§

pub use crate::decoder::Decoder;
pub use crate::decoder::DecoderIntoIter;
pub use crate::decoder::DecoderIter;
pub use crate::decoder::DecoderOptions;
pub use crate::encode::encode;
pub use crate::encode::EncodeError;
pub use crate::enums::Condition;
pub use crate::enums::ExtendType;
pub use crate::enums::FlagEffect;
pub use crate::enums::FlowControl;
pub use crate::enums::ShiftType;
pub use crate::enums::VectorArrangement;
pub use crate::error::DecodeError;
pub use crate::features::Feature;
pub use crate::features::FeatureSet;
pub use crate::format::Formatter;
pub use crate::format::FormatterOptions;
pub use crate::format::FormatterOutput;
pub use crate::format::SymbolResolver;
pub use crate::format::SymbolResult;
pub use crate::format::TokenKind;
pub use crate::implicit::implicit_registers;
pub use crate::implicit::ImplicitRegisters;
pub use crate::implicit::MAX_IMPLICIT_REGS;
pub use crate::info::instruction_info;
pub use crate::info::InstructionInfo;
pub use crate::info::OpAccess;
pub use crate::info::UsedMemory;
pub use crate::info::UsedRegister;
pub use crate::instruction::Instruction;
pub use crate::mnemonic::Code;
pub use crate::mnemonic::EnumValueError;
pub use crate::mnemonic::Mnemonic;
pub use crate::operand::MemIndexMode;
pub use crate::operand::OpKind;
pub use crate::operand::Operand;
pub use crate::operand::PredQual;
pub use crate::operand::SliceIndicator;
pub use crate::operand::SveMemMode;
pub use crate::register::gp_register;
pub use crate::register::sve_register;
pub use crate::register::RegClass;
pub use crate::register::RegWidth;
pub use crate::register::Register;
pub use crate::sysreg::SystemReg;
pub use crate::format::format_to_string;alloc

Modules§

decode
The hand-written recursive A64 decode tree (derived from the ARM ARM).
decoder
The borrowing, zero-alloc Decoder — the primary entry point.
encode
The hand-written A64 encoder — the inverse of decode.
enums
Small public enums shared across the API: condition codes, shift/extend modifiers, vector arrangements, and flow/flag classifications.
error
The core decode-error enum.
features
Architecture-extension model.
format
Formatting: turn an Instruction into text, zero-alloc by default.
implicit
Implicit register reads/writes — the architectural state an instruction touches without naming it in an operand (the link register, the pointer- authentication X30/SP/X16/X17, the FEAT_LS64 Xt+1..Xt+7 group, the SVE FFR, PC for PC-relative address generation, and the NZCV flags). Implicit register reads and writes — the architectural state an A64 instruction touches without naming it in an operand.
info
Instruction flow / register-and-memory access analysis (iced InstructionInfo analog).
instruction
The Copy value-type Instruction — the public projection of a decoded A64 instruction.
mnemonic
The two large public enums: Code (one variant per ARM encoding row) and Mnemonic (width/encoding-independent instruction name).
operand
The rich, safe, Copy Operand enum and its OpKind discriminant view.
register
Typed registers with stack/zero resolution baked in.
sysop
Fixed system-instruction operation and option name tokens.
sysreg
System-register identity and naming.
tables
Mechanical name / enum lookup tables (the &'static str register, condition, and system-register name tables). These are maintained as committed Rust source and contain no decode logic. The workspace’s xtask is currently only a scaffold for a possible future generator. Mechanical name / enum lookup tables.

Constants§

INSN_LEN
Fixed A64 instruction length, in bytes. A64 is a fixed-width ISA: every instruction is exactly 4 bytes and 4-byte aligned, and PC always advances by 4. Exposed for callers that stride a buffer.
MAX_OPERANDS
The maximum number of explicit operands any A64 encoding produces.