Enough philosophy — let's open the hood of a real, modern, gloriously clean ISA. RISC-V
(pronounced "risk-five") is an open, royalty-free
The base RISC-V integer ISA gives you 32 general-purpose registers, named
x0–x31, each 32 bits wide on RV32 (64 on RV64). Because there are 32 of them, a register
needs exactly
The standout is x0. It is hardwired to zero: reads always return 0, and writes are
silently discarded. This one trick eliminates a surprising amount of special-case hardware. Want to copy a
register? add x5, x6, x0. Want a no-op? add x0, x0, x0. Want to load a constant? Add it
to x0. A single hardwired zero turns dozens of "missing" instructions into ordinary arithmetic.
x0–x31, each named by a 5-bit field;x0 is hardwired to 0 — reads give 0, writes vanish;x1–x31 are truly general-purpose (the ABI assigns them roles like
ra, sp, a0, but the hardware treats them identically).Every RISC-V instruction is 32 bits, but those bits are carved up in one of six formats, chosen so that the same field almost always lands in the same place — which keeps the decoder trivial.
| Format | Used for | Example |
|---|---|---|
| R (register) | register–register arithmetic | add x3, x1, x2 |
| I (immediate) | ops with a 12-bit constant; loads | addi x3, x1, 42, lw x3, 8(x1) |
| S (store) | stores (split immediate) | sw x2, 8(x1) |
| B (branch) | conditional branches (PC-relative) | beq x1, x2, label |
| U (upper) | 20-bit upper immediates | lui x3, 0x12345 |
| J (jump) | jump-and-link | jal x1, label |
The genius is the shared layout: the destination rd is always in bits [11:7] when it
exists; rs1 is always in [19:15]; rs2 is always in [24:20]; the
opcode is always in [6:0]. The decoder can pull those fields out before it even
knows the format, then use the opcode to decide what the remaining bits mean. That regularity is exactly the RISC
payoff.
Let's dissect the workhorse format, R-type, used for register-to-register ops like
add, sub, and, or, sll. Its 32 bits split into
six fields:
add
(sub
(
So add and sub differ by a single bit up in funct7 — bit 30, to be exact. Elegant.
An R-type instruction is nothing but its six fields shifted into position and OR-ed together:
Decoding just reverses it — shift each field down and mask off the right number of bits. The code below encodes
add x3, x1, x2 into its 32-bit word, prints it in hex and binary, then decodes it straight back to
prove the round-trip.
RISC-V deliberately does not use every possible opcode. The base integer set is small, and vast regions
of the encoding are reserved. That looks wasteful until you remember what an ISA is: a
M (multiply/divide),
F/D (floating point), A (atomics),
V (vectors)
Beginners often say "the opcode of add is add's whole bit pattern". Not in RISC-V. The
opcode is only bits [6:0], and it is the same (51) for add,
sub, and, or, xor, and every other R-type op. What actually
picks the operation is the combination opcode + funct3 + funct7. Think of opcode as the family surname
and funct3/funct7 as the first name. Treating funct3/funct7 as "part of the opcode" will make your decoder — and
your exam answer — wrong.
Because every instruction is one aligned 32-bit word, the fetch unit always knows the next instruction sits at