RV32I is the mandatory core: 40 unique instructions, deliberately small enough that a minimal implementation can shrink further (trap all SYSTEM instructions to one handler, implement FENCE as a NOP) yet complete enough to be a serious compiler and OS target. Almost everything else in this book is layered on the decisions made in these seven pages.
2.1 The programmers’ model
The unprivileged integer state is exactly 33 registers: x0–x31,
each XLEN = 32 bits wide, plus the
program counter program counter (pc) The one additional unprivileged register besides x0-x31: holds the address of the current instruction.
defined in ch. I·2 — open in glossary
.
x0 x0 (zero register) Register x0 is hardwired to all-zero bits: writes are discarded, reads return 0. Many encodings with rd=x0 are repurposed as HINTs; loads to x0 still raise exceptions and side effects.
defined in ch. I·2 — open in glossary
is hardwired to zero — the
architectural constant that turns MV, NOT, NOP and unconditional jumps into
special cases of ordinary instructions.
Crucially, the architecture dedicates no stack pointer and no link
register — any x register works. Those roles come from the standard
calling convention calling convention Software contract, not architecture: x1 = return address (ra), x5 = alternate link register, x2 = stack pointer (sp). Hardware may exploit it (return-address stacks, compressed encodings assume it).
defined in ch. I·2 — open in glossary
, and hardware is
explicitly invited to exploit them:
| ABI name | Convention role | Hardware significance | |
|---|---|---|---|
| x0 | zero | Constant 0 | Hardwired; rd=x0 encodings become HINT space |
| x1 | ra | Return address | RAS push/pop hint register |
| x2 | sp | Stack pointer | C extension assumes it |
| x5 | t0 | Alternate link register | Second RAS hint register |
| x3, x4 | gp, tp | Global / thread pointer | No hardware meaning in the base ISA |
| x6–x31 | t1…, s0…, a0… | Temporaries, saved regs, arguments | Uniform — no special treatment anywhere in RV32I |
| pc | — | Current instruction address | Only readable via AUIPC/JAL |
2.2 The four core formats
Everything 32-bit in the base ISA is one of four formats — R, I, S, U — and the geometry is the point:
Two rules you can build a decoder around:
- Register specifiers never move. rs1 = [19:15], rs2 = [24:20], rd = [11:7], in every format that has them. Your regfile read can begin before format decode finishes.
- The immediate sign bit is always inst[31], so sign extension runs in parallel with everything else.
IALIGN = 32 in the base ISA: a taken branch or jump to a non-4-byte-aligned target raises instruction-address-misaligned — reported on the branch or jump, not the target (a not-taken branch never faults). Decoding a reserved instruction reserved instruction An encoding saved for future standard use; decoding one is UNSPECIFIED behavior (a platform may require illegal-instruction traps). defined in ch. I·2 — open in glossary is UNSPECIFIED.
2.3 B and J: immediates that rotate instead of shift
Branches need offsets in multiples of 2, jumps likewise. Conventional ISAs shift the whole immediate left by one in hardware; RISC-V instead rewires one bit per format and keeps everything else in place. Explore the actual wiring — this is Figure 1 made clickable:
The payoff, per the architects: immediate-mux fanout roughly halved in the simplest implementations, at the cost of a scrambled-looking encoding that only bothers humans and JIT compilers.
2.4 Integer computational instructions
All computation is XLEN-bit, register-immediate (I-type) or
register-register (R-type), destination rd. No arithmetic exceptions
exist — overflow is ignored, results are the low XLEN bits, and overflow
checks are short branch sequences (add t0,t1,t2; bltu t0,t1,overflow
for unsigned). There is no flags register anywhere in RISC-V.
Register-immediate: ADDI (also the canonical MV), SLTI/SLTIU
(compare against the sign-extended immediate — note SLTIU rd,rs,1 is
SEQZ), ANDI/ORI/XORI (XORI rd,rs,-1 is NOT). Constant shifts
specialize I-type: the shamt shamt Shift amount field: constant shifts encode the amount in imm[4:0] (RV32) with the right-shift type selected by instruction bit 30 (SRLI vs SRAI).
defined in ch. I·2 — open in glossary
lives in imm[4:0] and
bit 30 selects the right-shift type:
Upper-immediate pair: LUI rd, imm20 writes imm20 ≪ 12 (low 12 bits
zero); AUIPC rd, imm20 adds that shifted value to its own address.
Together with 12-bit I/S immediates they make any 32-bit constant a
two-instruction job and any 32-bit PC-relative address reachable:
AUIPC+JALR for calls, AUIPC+load/store for data. AUIPC rd, 0 is the
idiomatic “give me my PC”.
Register-register: ADD/SUB, SLT/SLTU (SLTU rd,x0,rs2 =
SNEZ), AND/OR/XOR, SLL/SRL/SRA (shift amount = low 5 bits of
rs2). funct7 bit 30 again selects SUB/SRA.
NOP is pseudoinstruction pseudoinstruction An assembler alias for a real encoding: MV=ADDI rd,rs,0; NOT=XORI rd,rs,-1; SEQZ=SLTIU rd,rs,1; SNEZ=SLTU rd,x0,rs; J=JAL x0; RET=JALR x0,x1,0; NOP=ADDI x0,x0,0.
defined in ch. I·2 — open in glossary
ADDI x0, x0, 0 — chosen canonically so decoders can recognize (or
eliminate) one specific encoding, and because an ADDI costs the fewest
resources: one register read, executable by any address-generation adder.
Hardware Designer Notes
The format geometry is a gift to your decoder: two fixed invariants (register slices, sign bit) remove the format mux from the two paths that matter — regfile index and sign extension. The immediate “scrambling” is where the saved multiplexers went; resist the urge to normalize it in an intermediate representation on the critical path. Bit 30 doing double duty (SUB/SRA, SRLI/SRAI) means your ALU op-select is funct3 plus exactly one extra wire.
Minimal Linux-boot hart MUST
- Fix rs1/rs2/rd extraction to constant bit slices — no format conditioning
- Sign-extend all immediates from inst[31]; implement the B/J bit rotation as wiring, not a shifter
- Raise instruction-address-misaligned on the taken branch/jump itself (target misaligned, IALIGN=32)
- No flags, no arithmetic exceptions — the integer ALU writes back unconditionally
MAY simplify / trap-and-emulate
- Decode-eliminate the canonical NOP (and only it) for zero-cost padding
- Special-case x0 as reads-as-zero in the regfile or bypass network — either works
- Treat reserved encodings as illegal-instruction (UNSPECIFIED allows it; many platforms require it)
Check yourself — registers, formats & computation
1.Why do rs1, rs2 and rd occupy the same bit positions in every RV32I format?
2.Your decoder wants to start sign-extending the immediate before it even knows the instruction format. Legal?
3.ADD overflows. What does the hardware do?
4.How does hardware tell SRAI from SRLI, given both are OP-IMM shifts?
5.What does the sequence AUIPC t0, 0 give you, and why prefer it over JAL +4 tricks?