disc-v
A RISC-V disassembler in Rust. It is no_std, does not allocate, and its
output follows GNU objdump's (see Output format).
It is meant to be embedded in various Rust tools: debuggers, emulators, etc.
use ;
let code = ;
for ins in disassemble
// 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.
Supported instructions
- RV32I, RV64I and RV128I
- 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
- Zfa
- V (vectors)
- Zvbb and Zvbc; Zvkg, Zvkned, Zvknha, Zvknhb, Zvksed and Zvksh
- H (hypervisor)
ecall,ebreak,sret,mret,dret,wfiandsfence.vma; Svinval, Smrnmi (mnret) and Ssctr (sctrclr)
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.rschecks it against the encodings in riscv-opcodes, in both directions: every listed instruction decodes to its name, and every encoding disc-v accepts is listed. The data is intests/data/riscv-opcodes.txt, generated byscripts/gen-riscv-opcodes.py.tests/objdump.rscompares the output with GNU objdump (after rewriting objdump's1008 <foo+0x8>targets as0x1008) 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-objdumporriscv64-linux-gnu-objdump) and is skipped if none is found; setDISC_V_REQUIRE_BINUTILS=1to 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. Where riscv-opcodes disagrees with
the specification, disc-v follows the specification, and the differences are
listed in NOT_IN_SPEC in tests/riscv_opcodes.rs.
CSR names come from riscv-opcodes, via scripts/gen-csr-names.py, and so do
the vector instruction tables in src/opcodes/v.rs, via
scripts/gen-vector-opcodes.py, which encodes objdump's operand order. The
generators format their output with rustfmt, so generated code is formatted
and linted like the rest of the crate.
Origins
disc-v is built on the disassembler from the
Caliptra MCU emulator
(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.
The name is a nod to Oxide Computer's 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).
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, 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).