# disc-v
[](https://github.com/swenson/disc-v/actions/workflows/ci.yml)
A RISC-V disassembler in Rust. It is `no_std`, does not allocate, and its
output follows GNU objdump's (see [Output format](#output-format)).
It is meant to be embedded in various Rust tools: debuggers, emulators, etc.
```rust
use disc_v::{disassemble, Isa};
let code = [0x13, 0x05, 0x10, 0x00, 0x82, 0x80];
for ins in disassemble(Isa::Rv64, 0x1000, &code) {
println!("{:x}: {ins}", ins.pc());
}
// 1000: li a0,1
// 1004: ret
```
Single instructions can be decoded from bytes with `decode_bytes`, or from
an integer with `decode`. An `Instruction` has the mnemonic, operands,
address, length and raw encoding, and `without_aliases()` shows it as
encoded (`c.li a0,1` rather than `li a0,1`), like `objdump -M no-aliases`.
The minimum supported Rust version is 1.85.1.
## Output format
The text is what `objdump -D -b binary` prints for the same bytes: the same
mnemonics, aliases (`li`, `ret`, `csrr`, ...) and operand syntax. Immediates
are decimal (`li a0,-1107`), while shift amounts and upper immediates are
hex (`slli a0,a0,0x3`, `lui a0,0xbad`).
Branch and jump targets are absolute addresses, always written with `0x`:
`beq a0,a1,0x1008`. When objdump disassembles an ELF file it instead writes
the target as bare hex followed by a symbol, as in `beq a0,a1,1008 <foo+0x8>`.
disc-v has no symbol information, so it uses objdump's raw-binary form,
which is unambiguous.
A few encodings are decoded differently from objdump where binutils and the
ISA specification disagree; see [Testing](#testing).
## Supported instructions
- RV32I, RV64I and RV128I
- M, A, F, D, Q and C
- Zicsr and Zifencei
- Zba, Zbb, Zbc and Zbs
- `ecall`, `ebreak`, `sret`, `mret`, `dret`, `wfi` and `sfence.vma`
48- and 64-bit encodings are recognized (so disassembly stays in sync) but
shown as `.insn`, as objdump does.
## Testing
Besides unit tests, the decoder is checked against two references:
- `tests/riscv_opcodes.rs` checks it against the encodings in
[riscv-opcodes](https://github.com/riscv/riscv-opcodes), in both
directions: every listed instruction decodes to its name, and every
encoding disc-v accepts is listed. The data is in
`tests/data/riscv-opcodes.txt`, generated by `scripts/gen-riscv-opcodes.py`.
- `tests/objdump.rs` compares the output with GNU objdump (after rewriting
objdump's `1008 <foo+0x8>` targets as `0x1008`) for every
compressed encoding, random 32-bit encodings, and random encodings of every
instruction in riscv-opcodes. It needs a RISC-V binutils
(`riscv64-elf-objdump`, `riscv64-unknown-elf-objdump` or
`riscv64-linux-gnu-objdump`) and is skipped if none is found; set
`DISC_V_REQUIRE_BINUTILS=1` to make that an error, as CI does.
Where binutils and the ISA specification disagree on whether an encoding is
valid, disc-v follows the specification. The differences, such as RV32 shift
amounts of 32 or more (reserved, but decoded by objdump), are listed in
`known_difference` in `tests/objdump.rs`.
CSR names come from riscv-opcodes, via `scripts/gen-csr-names.py`.
## Origins
disc-v is built on the disassembler from the
[Caliptra MCU emulator](https://github.com/chipsalliance/caliptra-mcu-sw)
(`emulator/app/src/dis.rs`, imported at commit
`20f7fcff1b51d69b03d0b352685fc7360536ad9a`). The Caliptra authors ported it
to Rust and added the bit-manipulation extensions (Zba, Zbb, Zbc, Zbs).
That code is itself a port of Michael Clark and SiFive's C
[riscv-disassembler](https://github.com/michaeljclark/riscv-disassembler).
The name is a nod to Oxide Computer's
[disc-v](https://github.com/oxidecomputer/disc-v), an earlier Rust port of
the same C disassembler by Wladimir J. van der Laan and Adam H. Leventhal.
That repository has no license, so this crate does not use any of its code.
## License
Copyright (c) 2026 Christopher Swenson.
disc-v is licensed under the Apache License, Version 2.0 ([LICENSE](LICENSE)).
It is derived from Michael Clark and SiFive's riscv-disassembler, which is
MIT licensed (Copyright (c) 2016-2017 Michael Clark, (c) 2017-2018 SiFive,
Inc.), by way of the Caliptra port, which is Apache-2.0 licensed. The
original MIT copyright and permission notice is kept in [NOTICE](NOTICE),
and source files derived from that code say so in their headers.
The test data and CSR names derived from riscv-opcodes are Copyright (c) 2022
RISC-V International, under the BSD-3-Clause license
([tests/data/LICENSE-riscv-opcodes](tests/data/LICENSE-riscv-opcodes)).