The vector bitmanip primitives (Zvbb) and the carry-less multiply (Zvbc) — general SIMD operations that also serve as crypto building blocks.
| Per-element operation | In | |
|---|---|---|
| vbrev.v | Reverse ALL bits of each element. | Zvbb |
| vbrev8.v | Reverse bits WITHIN each byte (bytes stay put) — GHASH bit-reflection. | Zvbb / Zvkb |
| vrev8.v (next page) | Reverse BYTE order of each element — endianness conversion. | Zvbb / Zvkb |
| vclz.v / vctz.v | Per-element count leading / trailing zeros. | Zvbb |
| vcpop.v | Per-element population count. | Zvbb |
| vclmul.[vv,vx] / vclmulh.[vv,vx] | Lane-wise carry-less (GF(2)-polynomial) product: vclmul the low 64 bits, vclmulh the high. 64-bit elements (needs Zve64x). | Zvbc |
Hardware Designer Notes
The carry-less multiplier is the one area cost here — a per-lane XOR-tree multiplier (half an integer multiplier). The reverses and counts are nearly free wiring. For a GCM-heavy server, decide between general clmul (flexible) and dedicated vghsh (denser) by how much non-GCM GF(2) work you also do.
Minimal Linux-boot hart MUST
- The reverses and counts are per-lane wiring/reduction trees (like the scalar Zbb versions) at vector width
- vclmul/vclmulh: replicate the carry-less multiplier per 64-bit lane; Zvkt makes them constant-time
MAY simplify / trap-and-emulate
- Share the carry-less multiplier array between vclmul and the dedicated vghsh datapath if you implement both
- Reuse scalar Zbb count/reverse logic widened to lanes
Check yourself — vector bitmanip & clmul
1.vclmul.vv and vclmulh.vv (Zvbc) operate on 64-bit elements. What do they produce, and why does GCM need them?
2.vbrev8.v vs vrev8.v — what's the difference?