Immediate rotates, the sign-extenders, and the first shift-adds.
| Semantics | Encoding | In | |
|---|---|---|---|
| rori rd, rs1, shamt | Rotate right by a constant — the SHA-2 sigma workhorse. | OP-IMM 0110000 / 101 | Zbb, Zbkb |
| roriw rd, rs1, shamt (RV64) | Rotate within the low 32 bits (wrap at bit 31), sign-extend — 32-bit crypto on 64-bit cores. | OP-IMM-32 0110000 / 101 | Zbb, Zbkb |
| rorw rd, rs1, rs2 (RV64) | Register-amount 32-bit rotate. | OP-32 0110000 / 101 | Zbb, Zbkb |
| sext.b rd, rs | Sign-extend the low byte — replaces the slli/srai pair. | OP-IMM funct12 0110000_00100 / 001 | Zbb |
| sext.h rd, rs | Sign-extend the low halfword. | OP-IMM funct12 0110000_00101 / 001 | Zbb |
| sh1add rd, rs1, rs2 | rd = rs2 + (rs1 << 1) — halfword-array indexing. | OP 0010000 / 010 | Zba |
| sh1add.uw rd, rs1, rs2 (RV64) | rd = rs2 + (zext32(rs1) << 1) — unsigned-word index. | OP-32 0010000 / 010 | Zba |
| sh2add rd, rs1, rs2 | rd = rs2 + (rs1 << 2) — the int/float array indexer, likely the most-executed Zba instruction. | OP 0010000 / 100 | Zba |
The shNadd family’s encoding economy: one funct7 (0010000), the
shift amount riding in funct3 (010/100/110), with the .uw twins at
the same points in OP-32. Compilers emit these from any indexed
access — a[i] with 2/4/8-byte elements — turning the
slli-then-add pair into one instruction on the adder’s existing
timing.
Hardware Designer Notes
sh2add deserves its own performance counter: measure it on pointer-heavy code and you’ll find it firing once per several loads. That’s the Zba pitch in one number.
Minimal Linux-boot hart MUST
- Distinguish the two rotate wrap modes (bit 63 vs bit 31 + sign-extension) in the shared rotator — the w-forms are separate permutations, not truncations
- Wire sext.b/sext.h as writeback extend muxes (the load unit’s logic, applied to an ALU result)
MAY simplify / trap-and-emulate
- Emit rol-immediate as rori with the complement amount in the assembler (why no roli exists)
Check yourself — rori, sext, shNadd
1.sext.b previously took two instructions. Which, and why does one instruction beat them beyond count?
2.sh1add/sh2add/sh3add share funct7 0010000. How is the shift amount encoded?
3.Why do rori (RV64) and roriw both exist when rori can encode any rotation?