The four statuses
Every instruction the decoder shows has a status (the same idea as the “undocumented” highlights of the 6502 pages), drawn with a highlight and a word in the viewer, and listed in its legend:
| Status | Meaning |
|---|---|
| Documented | A defined instruction. This includes the encodings the manual makes HINTs but gives a name: pause, ntl.*, c.ntl.*. |
| HINT | An encoding the manual defines as a HINT: a standard instruction format whose destination is x0 (or another field combination) so that it has no effect a program can see. A processor may use it as a hint and an ordinary one does nothing. |
| Reserved | A combination of fields that the manual reserves, or that has no meaning: the processor may trap or ignore. The decoder still shows the instruction it would be and says it is reserved. |
| Illegal | Defined to be illegal: the 16-bit 0x0000 and the 32-bit 0x00000000. Written c.unimp or unimp. |
An encoding that is none of these (a custom or vendor instruction, a future standard one, an extension not in the
chosen profile, a 48-bit or longer format) is “not an instruction” in the disassembly: the bytes are shown
as .2byte, .4byte or .byte with the reason, and the extension that would
decode it where the decoder knows one.
The HINT encodings
| Instruction | HINT when |
|---|---|
lui, auipc | rd = x0 |
addi | rd = x0 (addi x0, x0, 0 is the nop, not a hint) |
slti, sltiu, xori, ori, andi, slli, srli, srai | rd = x0 |
add, sub, sll, slt, sltu, xor, srl, sra, or, and | rd = x0 (add x0, x0, x2 to x5 are the named ntl.* hints) |
fence | rd = rs1 = x0, fm = 0 and the predecessor or successor set is empty (except pause) |
c.nop, c.addi | c.nop with a non-zero immediate; c.addi with rd ≠ 0 and imm = 0 (also rd = 0 with imm ≠ 0, which is the former) |
c.li, c.mv, c.add | rd = x0 (c.add x0, x2 to x5 are the named c.ntl.*) |
c.lui | rd = x0 and the immediate is not zero |
c.slli | rd = x0, or shamt = 0 |
c.srli, c.srai | shamt = 0 |
The multiply, atomic, floating-point and other extensions’ instructions are not HINTs when their destination is x0: they are decoded as the instruction. The manual keeps the rest of the HINT space for future standard hints and for custom ones; the decoder does not claim it.
The reserved combinations the decoder knows
- A
fencewith a non-zero fm (other than thefence.tsoform), rs1 or rd. - A floating-point instruction whose rounding mode (
rm) is 5 or 6. - An RV32 shift whose shamt has bit 5 set (these are RV64 shifts), including the compressed ones.
- Compressed:
c.addi4spnwith a zero immediate,c.addi16spwith a zero immediate,c.luiwith a zero immediate,c.addiw,c.lwspandc.ldspwith rd = x0,c.jrandc.jalrwith rs1 = x0, Zcmp’s rlist 0 to 3 and equal registers incm.mvsa01. aes64ks1iwith a round number above 10.- A register number above 15 in RV32E and RV64E.
- A register pair (
amocas.q;amocas.don RV32) with an odd register number; whole-register vector moves, loads and stores of 2, 4 or 8 registers that do not start at a multiple of that number.
Where llvm and this decoder differ
Compared with llvm-mc (LLVM 22), a reserved or HINT encoding is the one place the two can disagree, and
the comparison counts it:
- Every encoding this decoder calls reserved or illegal was also refused by llvm, except these, which llvm
decodes as the instruction:
aes64ks1iwith a round number of 11 to 15 (6 words in the sample) and a few Zcmp encodings (8 words in the sample). - llvm does not know
fcvt.q.handfcvt.h.q(Zfh with Q); the manual defines them, so the decoder reads them. - llvm reads Zicsr and Zifencei instructions even when the extension is not named; the decoder follows the profile.
- llvm writes the upper immediate of
lui,auipcandc.luiin decimal and the explorer in hex.