1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
//! # isa_lang
//!
//! Machine instructions to bytes and back, driven by target-description
//! tables. Each instruction form is one row of data — an encoding recipe and
//! an operand signature written as the architecture manual writes them — and
//! one table-driven encoder, decoder, and Intel-syntax disassembler interpret
//! the rows. Adding a form is adding a row.
//!
//! This release covers the x86-64 integer, control-flow, and memory core in
//! [`x86_64`]. AArch64 follows in the same model (see the roadmap).
//!
//! ## Quick start
//!
//! ```
//! use isa_lang::x86_64::{decode, encode, Inst, Mem, Mnemonic, Reg, Size};
//!
//! // mov rax, qword ptr [rdi+0x10]
//! let load = Inst::new(Mnemonic::Mov, [Reg::RAX.into(), Mem::new(Size::Qword, Reg::RDI).with_disp(16).into()]);
//! let bytes = encode(&load)?;
//! assert_eq!(&*bytes, [0x48, 0x8B, 0x47, 0x10]);
//!
//! let decoded = decode(&bytes).unwrap();
//! assert_eq!(decoded.inst(), load);
//! assert_eq!(decoded.inst().to_string(), "mov rax, qword ptr [rdi+0x10]");
//! # Ok::<(), isa_lang::x86_64::EncodeError>(())
//! ```
//!
//! With labels:
//!
//! ```
//! use isa_lang::x86_64::{Assembler, Cond, Inst, Mnemonic, Operand, Reg};
//!
//! let mut asm = Assembler::new();
//! let positive = asm.label();
//! asm.emit(&Inst::new(Mnemonic::Mov, [Reg::EAX.into(), Reg::EDI.into()]))?;
//! asm.emit(&Inst::new(Mnemonic::Test, [Reg::EAX.into(), Reg::EAX.into()]))?;
//! asm.jcc(Cond::Ns, positive)?;
//! asm.emit(&Inst::new(Mnemonic::Neg, [Reg::EAX.into()]))?;
//! asm.bind(positive)?;
//! asm.emit(&Inst::new(Mnemonic::Ret, []))?;
//! let code = asm.finish()?;
//! assert_eq!(code.bytes(), [0x89, 0xF8, 0x85, 0xC0, 0x79, 0x02, 0xF7, 0xD8, 0xC3]);
//! # Ok::<(), isa_lang::x86_64::AsmError>(())
//! ```
//!
//! ## Guarantees
//!
//! - `decode(encode(i)) == i` for every instruction the encoder accepts,
//! checked over every form's whole operand space.
//! - Anything the decoder accepts, the encoder can encode back to the same
//! instruction.
//! - The decoder never panics, on any input, and every error names the byte
//! at fault.
//! - Encodings match the Intel SDM byte for byte (known-answer tests).
//!
//! ## Features
//!
//! - `std` (default): no effect today; the crate is `no_std` and needs only
//! `alloc` (for [`x86_64::Assembler`]).
extern crate alloc;
/// Compiles and runs the `rust` code blocks in `README.md` and `docs/API.md` as
/// part of `cargo test`, so the published examples cannot drift from the API.
///
/// Present only while collecting doctests (`#[cfg(doctest)]`); it is not part of
/// the public surface and does not appear in the built library or its docs.
;