RV32E & RV64E: The 16-Register Bases

Part III Linux boot: optional Vol. I (Unprivileged) p. 40 · ~2 min read

E bases are I bases with 16 registers — encodings bit-identical, x16–x31 reserved — and the real cost is a different calling convention, not different hardware.

Why this matters

For a Linux-bootable core this chapter is a non-event (Linux requires full I) — but drop a tiny M-mode companion core into the same SoC and E is roughly a quarter of small-core area saved.

One page, one change: E bases are I bases with 16 registers (x0–x15, x0 still hardwired zero). Encodings are bit-identical to RV32I/RV64I; every encoding naming x16–x31 is reserved — not custom, not aliased. Standard extensions remain compatible unless they say otherwise (the notable exception: the H extension explicitly requires full I).

The real cost is ABI, not hardware: with only 16 registers the calling convention has fewer argument and saved registers, so E and I binaries are not link-compatible — a toolchain decision, not a decoder one. Note that the C extension already anticipated small register files: its three-bit register fields address x8–x15, which is why compressed code density survives the cut intact.

If you remember only three things
  • E = I with x0–x15 only; every encoding naming x16–x31 is reserved — detected by one OR-gate per specifier field.
  • The point is area: the upper 16 registers measure ~25% of a small core (excluding memories), with matching power.
  • The real cost is ABI: fewer argument/saved registers means E and I binaries are not link-compatible — yet C’s code density survives, because its 3-bit register fields already target x8–x15.

Hardware Designer Notes

For a Linux-bootable core this chapter is a non-event — Linux requires full I (glibc, the ABI, and H all assume 32 registers). E matters when you’re also dropping an M-mode-only microcontroller companion core into the same SoC and want it tiny.

Minimal Linux-boot hart MUST

  • Trap any register specifier with bit 4 set as an illegal instruction — one OR-gate per specifier field feeding the decoder’s reserved detection
  • Keep x0 semantics and all I-base behavior otherwise unchanged

MAY simplify / trap-and-emulate

  • Physically implement a 16-entry register file (the point of the exercise) — or gate off the upper half of an existing 32-entry design

Check yourself — RV32E/RV64E

1.An RV32E core decodes ADD x20, x1, x2. What must happen?

2.What does cutting x16–x31 actually buy, per the spec's measurements?

2 questions