feat(asm): encode the riscv64 bit-manipulation families

The Zba address generation, Zbb unary bit operations, Zbc carry-less
multiplication and Zbs single-bit families were names the table carried
and the encoder refused: thirty spellings plus RORI and XNOR fell over.
The register and immediate forms now encode as the toolchain does, the
unary operations carry their fixed rs2 constant, RORI lowers to ROR's
expansion (its reverse shift compressing like ROR's), XNOR XORs and
inverts in place, and ROL/ROLW rotate left through the same temporary
the toolchain uses, taking a register amount only as its own expansion
requires.  The toolchain's whole testdata block for these families is
now a differential test: every word must agree byte for byte.

Assisted-by: GLM 5.3 Flash
This commit is contained in:
petrbalvin committed 2026-10-07 00:47:27 +02:00
1 parent d82ef33fa9
commit ddfa33ccc1
3 files changed
+266 -19

No files matched your search

+38
View File
@@ -204,6 +204,27 @@ var riscvInstrTable = map[string]riscvEnc{
"SLLIW": {0x1B, 0x1, 0x00},
"SRLIW": {0x1B, 0x5, 0x00},
"SRAIW": {0x1B, 0x5, 0x20},
// Zba/Zbs shift-immediate forms: the shamt spans bits [25:20], so the
// funct7 field carries the operation's funct6 and bit 25 comes from the
// amount. SLLIUW (Zba) zeroes the upper 32 bits before the shift.
"BCLRI": {0x13, 0x1, 0x24},
"BEXTI": {0x13, 0x5, 0x24},
"BINVI": {0x13, 0x1, 0x34},
"BSETI": {0x13, 0x1, 0x14},
"SLLIUW": {0x1B, 0x1, 0x04},
// Zbb unary bit operations: one source register, the rs2 field fixed
// (the count or the position the operation works on).
"CLZ": {0x13, 0x1, 0x30},
"CLZW": {0x1B, 0x1, 0x30},
"CPOP": {0x13, 0x1, 0x30},
"CPOPW": {0x1B, 0x1, 0x30},
"CTZ": {0x13, 0x1, 0x30},
"CTZW": {0x1B, 0x1, 0x30},
"SEXTB": {0x13, 0x1, 0x30},
"SEXTH": {0x13, 0x1, 0x30},
"ORCB": {0x13, 0x5, 0x14},
"REV8": {0x13, 0x5, 0x35},
"ZEXTH": {0x3B, 0x4, 0x04},
// RV64M, multiply/divide.
"MUL": {0x33, 0x0, 0x01},
"MULH": {0x33, 0x1, 0x01},
@@ -222,6 +243,23 @@ var riscvInstrTable = map[string]riscvEnc{
// Zicond conditional zeroing.
"CZEROEQZ": {0x33, 0x5, 0x07},
"CZERONEZ": {0x33, 0x7, 0x07},
// Zba address generation and Zbc carry-less multiplication.
"ADDUW": {0x3B, 0x0, 0x04},
"SH1ADD": {0x33, 0x2, 0x10},
"SH1ADDUW": {0x3B, 0x2, 0x10},
"SH2ADD": {0x33, 0x4, 0x10},
"SH2ADDUW": {0x3B, 0x4, 0x10},
"SH3ADD": {0x33, 0x6, 0x10},
"SH3ADDUW": {0x3B, 0x6, 0x10},
"CLMUL": {0x33, 0x1, 0x05},
"CLMULH": {0x33, 0x3, 0x05},
"CLMULR": {0x33, 0x2, 0x05},
// Zbs single-bit: the register forms; the immediate spellings lower to
// the shift-immediate entries below (BCLR $n is BCLRI $n).
"BCLR": {0x33, 0x1, 0x24},
"BEXT": {0x33, 0x5, 0x24},
"BINV": {0x33, 0x1, 0x34},
"BSET": {0x33, 0x1, 0x14},
// RV64I, I-type arithmetic.
"ADDI": {0x13, 0x0, 0x00},
"ADDIW": {0x1B, 0x0, 0x00},