RV64I is RV32I with XLEN = 64 — same 31 general registers plus x0, same formats, same opcodes — described purely as a delta. For a Linux-bootable core this is your base ISA, and the entire delta hangs on one idea:
4.1–4.2 The sign-extension invariant
Every 32-bit value in a 64-bit register is kept sign-extended — bits 63:32 always replicate bit 31, even for unsigned values. The invariant sign-extension invariant RV64 convention: every 32-bit value is held sign-extended in its 64-bit register (bits 63:32 = bit 31), even for unsigned values. W-suffix instructions re-establish it after 32-bit adds/subs/shifts; conversions signed<->unsigned-32 and signed 32->64 become no-ops. defined in ch. I·4 — open in glossary buys a remarkable amount for free:
- signed ↔ unsigned 32-bit conversion: no-op;
- signed 32 → signed 64 widening: no-op;
- 64-bit
SLTUand unsigned branches work unchanged on 32-bit data; - 64-bit logical ops preserve the invariant by construction.
What it can’t make free are operations where bit 31 changes: 32-bit adds, subs, and shifts. Those get W-suffix variants w-suffix instruction RV64I-only 32-bit operate variants (ADDIW, ADDW, SUBW, SLLIW/SRLIW/SRAIW, SLLW/SRLW/SRAW) under opcodes OP-IMM-32/OP-32: ignore upper input bits, compute a 32-bit result, sign-extend to 64. SEXT.W = ADDIW rd,rs,0. defined in ch. I·4 — open in glossary under two new major opcodes (OP-IMM-32, OP-32): they ignore the upper 32 input bits, compute a 32-bit result, and sign-extend it to 64.
A W instruction in a 64-bit datapath: the normal ALU plus one bit-31-replication mux at writeback — not a second 32-bit ALU.
The full RV64I delta:
| Semantics | Hardware note | |
|---|---|---|
| ADDIW | rd = sext32(rs1[31:0] + imm) | ADDIW rd,rs,0 = SEXT.W |
| ADDW / SUBW | rd = sext32(rs1[31:0] ± rs2[31:0]) | OP-32; funct7 bit 30 selects SUB, exactly as in OP |
| SLLIW / SRLIW / SRAIW | 32-bit constant shifts, shamt[4:0] | imm[5] ≠ 0 reserved |
| SLLW / SRLW / SRAW | 32-bit register shifts, amount = rs2[4:0] | The 64-bit forms read rs2[5:0] — one extra bit of shifter control |
| SLLI / SRLI / SRAI (widened) | 64-bit constant shifts, shamt[5:0] | Same opcodes as RV32I — imm[5] joins the shamt; bit 30 still selects arithmetic |
| LD / SD | 64-bit load / store | The doubleword datapath width everything else assumes |
| LW / LWU | LW sign-extends; LWU zero-extends | LW changes meaning vs RV32 |
| LUI / AUIPC (widened) | 32-bit result sign-extended to 64 | Pair range [−2³¹−2¹¹, 2³¹−2¹¹−1] |
The W constant shifts, concretely:
RV64I’s HINT space (Table 6) is the RV32I map plus rd=x0 encodings of all the W instructions in the future-standard pool; NTL.*, PAUSE, and the semihosting markers sit at the same code points, and the custom rows grow slightly (6-bit shamts).
Hardware Designer Notes
A Linux-capable hart is RV64: this page is your integer datapath spec. The practical checklist is short — one writeback mux for sign-extension, one extra shamt bit, LD/SD/LWU in the load/store unit — but the invariant has a verification bite: any path that writes a register with bits 63:32 ≠ replicated bit 31 while software believes it holds a 32-bit value is a silent miscompare later, in code far from the bug. Assert the invariant on W-instruction results in your testbench.
Minimal Linux-boot hart MUST
- Implement W forms as low-32 operate + bit-31 replication at writeback — full-width register writes, never partial
- Widen shifter control: 64-bit shifts consume shamt[5:0] / rs2[5:0]; W shifts consume [4:0] only
- Sign-extend LW and LUI/AUIPC results; add LWU as the zero-extend path
MAY simplify / trap-and-emulate
- Trap or accept SLLIW/SRLIW/SRAIW with imm[5]=1 — reserved, your documented choice
- Fuse ADDIW rd,rs,0 (SEXT.W) with a preceding W-producer if your pipeline benefits
Check yourself — RV64I
1.On RV64, a register holds the unsigned 32-bit value 0x8000_0000 per the calling convention. What are bits 63:32?
2.What does ADDW actually compute in hardware?
3.Your decoder sees SLLIW with shamt bit 5 set. What does the current spec say?
4.Why does RV64I need LWU when RV32I never needed unsigned word loads?