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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
// Copyright (c) 2026 Christopher Swenson
// Licensed under the Apache-2.0 license.
//
// Derived from riscv-disassembler, Copyright (c) 2016-2017 Michael Clark
// and Copyright (c) 2017-2018 SiFive, Inc., under the MIT license; see NOTICE.
//! A RISC-V disassembler.
//!
//! Supports RV32, RV64 and RV128 (and RV32E and RV64E, as the E extension)
//! with these extensions:
//!
//! - M, A, F, D, Q and C
//! - Zicsr and Zifencei
//! - Zba, Zbb, Zbc and Zbs
//! - Zicond
//! - Zawrs
//! - Zicbom, Zicboz and Zicbop; Zihintntl and Zihintpause
//! - Zimop and Zcmop, with the Zicfiss and Zicfilp instructions
//! - Zcb
//! - Zfh and Zfhmin
//! - Zfinx, Zdinx, Zhinx and Zhinxmin, which conflict with F and so are only
//! decoded by a [`Decoder`] that enables them
//! - Zfa
//! - V (vectors)
//! - Zvbb and Zvbc; Zvkg, Zvkned, Zvknha, Zvknhb, Zvksed and Zvksh
//! - H (hypervisor), Svinval, Smrnmi and Ssctr
//! - Zalasr, Zacas and Zabha
//! - Zfbfmin, Zvfbfmin and Zvfbfwma (BFloat16)
//! - Zbkb, Zbkc and Zbkx; Zknd, Zkne, Zknh, Zksed and Zksh (scalar cryptography)
//! - Zca, Zcf and Zcd (the parts of C); Zcmp and Zcmt, which conflict with
//! Zcd and so are only decoded by a [`Decoder`] that enables them
//! - Zilsd; Zclsd, which conflicts with Zcf and so is only decoded by a
//! [`Decoder`] that enables it
//! - T-Head and CORE-V vendor extensions, which are only decoded by a
//! [`Decoder`] that enables them
//!
//! The vector and vendor extensions need the `vector`, `vendor-thead` and
//! `vendor-corev` Cargo features, which are on by default; without them,
//! their instructions are shown as `.insn` and the binary is smaller.
//!
//! The text follows GNU objdump's for a raw binary (`objdump -D -b binary`),
//! so branch targets are written as `0x1008`.
//!
//! [`decode`](fn@decode), [`decode_bytes`] and [`disassemble`] decode every
//! supported extension that does not conflict with another. A [`Decoder`]
//! decodes for a particular target instead, such as [`Decoder::RVA23U64`] or
//! one from an ISA string with [`Decoder::from_march`].
//!
//! ```
//! use disc_v::{disassemble, Isa};
//!
//! let code = [0x13, 0x05, 0x10, 0x00, 0x82, 0x80]; // li a0,1; ret
//! for ins in disassemble(Isa::Rv64, 0x1000, &code) {
//! println!("{:x}: {ins}", ins.pc());
//! }
//! # let text: Vec<_> = disassemble(Isa::Rv64, 0x1000, &code).map(|i| i.to_string()).collect();
//! # assert_eq!(text, ["li a0,1", "ret"]);
//! ```
pub use ;
pub use ;
pub use Operands;
pub use Instruction;
// Compiles and runs the README's examples as doc tests. They use every
// table.
;
/// The base integer ISA, which determines the register width and which
/// encodings are valid.
/// Decodes the instruction `inst`, located at address `pc`.
///
/// Only the low [`inst_length`] bytes of `inst` are part of the instruction; RISC-V encodings are little-endian, so this is the
/// value of those bytes read as a little-endian integer.
///
/// ```
/// use disc_v::{decode, Isa};
///
/// let ins = decode(Isa::Rv32, 0x1000, 0xfe050ee3);
/// assert_eq!(ins.to_string(), "beqz a0,0xffc");
/// ```
/// Decodes the instruction at the start of `bytes`, located at address `pc`.
///
/// Returns `None` if `bytes` is shorter than the instruction.
///
/// ```
/// use disc_v::{decode_bytes, Isa};
///
/// let ins = decode_bytes(Isa::Rv64, 0, &[0x93, 0x81, 0x01, 0x10]).unwrap();
/// assert_eq!(ins.to_string(), "addi gp,gp,256");
/// assert_eq!(ins.length(), 4);
/// ```
/// Disassembles `bytes`, the first of which is at address `pc`.
///
/// Iteration stops when the remaining bytes are too short for the next
/// instruction; see [`Disassembler::remainder`].
/// An iterator over the instructions in a byte slice. Create one with
/// [`disassemble`] or [`Decoder::disassemble`].
/// Returns the length in bytes of the instruction whose first 16-bit parcel
/// is `parcel`, or `None` for the reserved lengths of 10 bytes or more.
///
/// The decoding functions show each 16-bit parcel of an encoding with a
/// reserved length as a 2-byte `.2byte` directive, as objdump does, so that
/// disassembly can continue.
///
/// ```
/// use disc_v::inst_length;
///
/// assert_eq!(inst_length(0x4505), Some(2)); // li a0,1
/// assert_eq!(inst_length(0x0513), Some(4)); // the low half of li a0,10
/// assert_eq!(inst_length(0x007f), None);
/// ```