feat(asm): encode the riscv64 vector arithmetic families

Assisted-by: GLM 5.3 Flash
This commit is contained in:
petrbalvin committed 2026-10-07 00:47:27 +02:00
1 parent 5de9e985f8
commit 778c297214
3 files changed
+1812 -102

No files matched your search

+564 -81
View File
@@ -3636,88 +3636,571 @@ func encodeRISCVVector(mnem string, ops []*ast.Operand) ([]byte, bool, error) {
// (0xcd07f657) from GOARCH=riscv64 go tool asm.
ivli := mnem == "VSETIVLI" || isImmOperand(ops[0])
return wordLE(riscvVSetEnc(ivli, avl, riscvVType(vsew, vlmul, vta, vma), rd)), true, nil
case "VADDVV", "VXORVV", "VMSNEVV":
// Vector-vector: INSTR vs1, vs2, vd.
if len(ops) != 3 {
return nil, true, fmt.Errorf("%s expects 3 operands, got %d", mnem, len(ops))
}
vs1, vs2, vd := reg(ops[0]), reg(ops[1]), reg(ops[2])
if vs1 < 0 || vs2 < 0 || vd < 0 {
return nil, true, fmt.Errorf("%s: invalid vector register", mnem)
}
funct6 := map[string]int{"VADDVV": 0x00, "VXORVV": 0x0B, "VMSNEVV": 0x19}[mnem]
return wordLE(riscvVVInstr(funct6, riscvVf3VV, int32(vs1), vs2, vd)), true, nil
case "VADDVX", "VMSEQVX":
// Vector-scalar: INSTR rs1, vs2, vd (the scalar in the rs1 field).
if len(ops) != 3 {
return nil, true, fmt.Errorf("%s expects 3 operands, got %d", mnem, len(ops))
}
rs1, vs2, vd := reg(ops[0]), reg(ops[1]), reg(ops[2])
if rs1 < 0 || vs2 < 0 || vd < 0 {
return nil, true, fmt.Errorf("%s: invalid register operand", mnem)
}
funct6 := 0x00
if mnem == "VMSEQVX" {
funct6 = 0x18
}
return wordLE(riscvVVInstr(funct6, riscvVf3VX, int32(rs1), vs2, vd)), true, nil
case "VSLLVI", "VSRLVI":
// Vector-immediate shift: INSTR $uimm, vs2, vd.
if len(ops) != 3 {
return nil, true, fmt.Errorf("%s expects 3 operands, got %d", mnem, len(ops))
}
imm := int(immFromOperand(ops[0]))
if imm < 0 || imm > 31 {
return nil, true, fmt.Errorf("%s: immediate out of range [0, 31]", mnem)
}
vs2, vd := reg(ops[1]), reg(ops[2])
if vs2 < 0 || vd < 0 {
return nil, true, fmt.Errorf("%s: invalid vector register", mnem)
}
funct6 := 0x25 // vsll.vi
if mnem == "VSRLVI" {
funct6 = 0x28 // vsrl.vi
}
return wordLE(riscvVVInstr(funct6, riscvVf3VI, int32(imm), vs2, vd)), true, nil
case "VFIRSTM":
// vmfirst.m rd, vs2: the unmasked form carries 0x11 in the rs1 field
// and sets the mask bit (funct7 = 0x20 | 1).
if len(ops) != 2 {
return nil, true, fmt.Errorf("VFIRSTM expects 2 operands, got %d", len(ops))
}
vs2, rd := reg(ops[0]), reg(ops[1])
if vs2 < 0 || rd < 0 {
return nil, true, fmt.Errorf("VFIRSTM: invalid register operand")
}
return wordLE(riscvVUnaryInstr(0x10, riscvVf3MV, 0x11, vs2, rd)), true, nil
case "VIDV":
// vid.v vd (vs2 must be v0; the unmasked form sets the mask bit).
if len(ops) != 1 {
return nil, true, fmt.Errorf("VIDV expects 1 operand, got %d", len(ops))
}
vd := reg(ops[0])
if vd < 0 {
return nil, true, fmt.Errorf("VIDV: invalid vector register")
}
return wordLE(riscvVUnaryInstr(0x14, riscvVf3MV, 0x11, 0, vd)), true, nil
case "VMV4RV":
// vmv4r.v vd, vs2: whole-register group move.
if len(ops) != 2 {
return nil, true, fmt.Errorf("VMV4RV expects 2 operands, got %d", len(ops))
}
vs2, vd := reg(ops[0]), reg(ops[1])
if vs2 < 0 || vd < 0 {
return nil, true, fmt.Errorf("VMV4RV: invalid vector register")
}
return wordLE(riscvVUnaryInstr(0x27, 0x3, 0x3, vs2, vd)), true, nil
}
return nil, false, nil
// Every remaining OP-V mnemonic the toolchain knows: the arithmetic
// table, dispatched by operand class.
return encodeRISCVVecOp(mnem, ops)
}
// encodeRISCVVecOp encodes one vector arithmetic instruction through the
// extracted table. The entry's class places the operands in the rs1 and vs2
// fields, an optional V0 between the sources and the destination clears the
// vm bit, and the transform classes rewrite the pseudo forms the toolchain
// expands before encoding (the swapped comparisons, VNEGV and friends).
func encodeRISCVVecOp(mnem string, ops []*ast.Operand) ([]byte, bool, error) {
op, ok := riscvVecOps[mnem]
if !ok {
return nil, false, nil
}
// vecReg reads a register operand; what names the field in the error.
vecReg := func(o *ast.Operand, what string) (int, error) {
r := regFromOperand(o)
if r < 0 {
return 0, fmt.Errorf("%s: invalid %s", mnem, what)
}
return r, nil
}
// vecImm reads the immediate the entry's form bounds: signed five bits
// [-16, 15], or unsigned [0, 31] for the shifts and slides.
vecImm := func(o *ast.Operand) (int32, error) {
if !isImmOperand(o) {
return 0, fmt.Errorf("%s expects an immediate first operand", mnem)
}
v := immFromOperand(o)
if op.immU {
if v < 0 || v > 31 {
return 0, fmt.Errorf("%s: immediate %d out of range [0, 31]", mnem, v)
}
} else if v < -16 || v > 15 {
return 0, fmt.Errorf("%s: immediate %d out of range [-16, 15]", mnem, v)
}
return int32(v), nil
}
// vecMask reads the optional mask operand: only V0 is lawful.
vecMask := func(o *ast.Operand) error {
if regFromOperand(o) != 0 {
return fmt.Errorf("%s: the vector mask register must be V0", mnem)
}
return nil
}
// vm carries the funct7 with the vm bit set for the unmasked form: the
// toolchain ORs 1 when no V0 follows the sources.
vm := func(masked bool) uint32 {
if !masked {
return op.funct7 | 1
}
return op.funct7
}
// word builds the instruction from the entry's fields.
word := func(funct7 uint32, rs1Field int32, vs2 int, funct3 uint32, vd int) ([]byte, bool, error) {
return wordLE(riscvVecWord(funct7, rs1Field, vs2, funct3, vd)), true, nil
}
// rename resolves a transform to its target table entry.
rename := func(to string) (riscvVecOp, error) {
t, ok := riscvVecOps[to]
if !ok {
return riscvVecOp{}, fmt.Errorf("%s: transform target %q not in the table", mnem, to)
}
return t, nil
}
switch op.class {
case vecVV:
// INSTR vs1|$imm, vs2 [, V0], vd.
if len(ops) != 3 && len(ops) != 4 {
return nil, true, fmt.Errorf("%s expects 3 or 4 operands, got %d", mnem, len(ops))
}
masked := len(ops) == 4
if masked {
if err := vecMask(ops[2]); err != nil {
return nil, true, err
}
}
vs2, err := vecReg(ops[1], "vs2")
if err != nil {
return nil, true, err
}
vd, err := vecReg(ops[len(ops)-1], "vd")
if err != nil {
return nil, true, err
}
var rs1Field int32
if op.imm {
if rs1Field, err = vecImm(ops[0]); err != nil {
return nil, true, err
}
} else {
var vs1 int
if vs1, err = vecReg(ops[0], "vs1"); err != nil {
return nil, true, err
}
rs1Field = int32(vs1)
}
return word(vm(masked), rs1Field, vs2, op.funct3, vd)
case vecMACC:
// INSTR vs2, vs1 [, V0], vd: the multiply-accumulate order, the
// addend in the rs1 field and the multiplicand in vs2.
if len(ops) != 3 && len(ops) != 4 {
return nil, true, fmt.Errorf("%s expects 3 or 4 operands, got %d", mnem, len(ops))
}
masked := len(ops) == 4
if masked {
if err := vecMask(ops[2]); err != nil {
return nil, true, err
}
}
vs2, err := vecReg(ops[0], "vs2")
if err != nil {
return nil, true, err
}
vd, err := vecReg(ops[len(ops)-1], "vd")
if err != nil {
return nil, true, err
}
var rs1Field int32
if op.imm {
if rs1Field, err = vecImm(ops[1]); err != nil {
return nil, true, err
}
} else {
var vs1 int
if vs1, err = vecReg(ops[1], "vs1"); err != nil {
return nil, true, err
}
rs1Field = int32(vs1)
}
return word(vm(masked), rs1Field, vs2, op.funct3, vd)
case vecSWAPVV:
// VMSGT*/VMSGE*/VMFGT*/VMFGE* swap the two sources and lower to the
// VMSLT*/VMSLE*/VMFLT*/VMFLE* entries the table carries.
if len(ops) != 3 && len(ops) != 4 {
return nil, true, fmt.Errorf("%s expects 3 or 4 operands, got %d", mnem, len(ops))
}
masked := len(ops) == 4
if masked {
if err := vecMask(ops[2]); err != nil {
return nil, true, err
}
}
t, err := rename(map[string]string{
"VMSGTVV": "VMSLTVV", "VMSGTUVV": "VMSLTUVV",
"VMSGEVV": "VMSLEVV", "VMSGEUVV": "VMSLEUVV",
"VMFGTVV": "VMFLTVV", "VMFGEVV": "VMFLEVV",
}[mnem])
if err != nil {
return nil, true, err
}
vs2, err := vecReg(ops[0], "vs2")
if err != nil {
return nil, true, err
}
vd, err := vecReg(ops[len(ops)-1], "vd")
if err != nil {
return nil, true, err
}
vs1, err := vecReg(ops[1], "vs1")
if err != nil {
return nil, true, err
}
f7 := t.funct7
if !masked {
f7 |= 1
}
return word(f7, int32(vs1), vs2, t.funct3, vd)
case vecSWAPVI:
// VMSLTVI and the VMSGE*VI forms subtract one from the immediate and
// lower to the VMSLE*/VMSGT* entries.
if len(ops) != 3 && len(ops) != 4 {
return nil, true, fmt.Errorf("%s expects 3 or 4 operands, got %d", mnem, len(ops))
}
masked := len(ops) == 4
if masked {
if err := vecMask(ops[2]); err != nil {
return nil, true, err
}
}
t, err := rename(map[string]string{
"VMSLTVI": "VMSLEVI", "VMSLTUVI": "VMSLEUVI",
"VMSGEVI": "VMSGTVI", "VMSGEUVI": "VMSGTUVI",
}[mnem])
if err != nil {
return nil, true, err
}
imm, err := vecImm(ops[0])
if err != nil {
return nil, true, err
}
imm--
if imm < -16 || imm > 15 {
return nil, true, fmt.Errorf("%s: immediate %d leaves [-16, 15] after the swap", mnem, imm+1)
}
vs2, err := vecReg(ops[1], "vs2")
if err != nil {
return nil, true, err
}
vd, err := vecReg(ops[len(ops)-1], "vd")
if err != nil {
return nil, true, err
}
f7 := t.funct7
if !masked {
f7 |= 1
}
return word(f7, imm, vs2, t.funct3, vd)
case vecUNARY, vecM2I:
// INSTR vs2 [, V0], vd: one vector source, the fixed rs1 field; the
// m2i members take the destination in the integer file.
if len(ops) != 2 && len(ops) != 3 {
return nil, true, fmt.Errorf("%s expects 2 or 3 operands, got %d", mnem, len(ops))
}
masked := len(ops) == 3
if masked {
if err := vecMask(ops[1]); err != nil {
return nil, true, err
}
}
vs2, err := vecReg(ops[0], "vs2")
if err != nil {
return nil, true, err
}
vd, err := vecReg(ops[len(ops)-1], "vd")
if err != nil {
return nil, true, err
}
return word(vm(masked), int32(op.rs1), vs2, op.funct3, vd)
case vecNEG:
// VNEGV, VWCVTXXV, VWCVTUXXV and VNCVTXXW read as one-operand forms
// of VRSUBVX, VWADDVX, VWADDUVX and VNSRLWX with X0 in the rs1 field.
if len(ops) != 2 && len(ops) != 3 {
return nil, true, fmt.Errorf("%s expects 2 or 3 operands, got %d", mnem, len(ops))
}
masked := len(ops) == 3
if masked {
if err := vecMask(ops[1]); err != nil {
return nil, true, err
}
}
t, err := rename(map[string]string{
"VNEGV": "VRSUBVX", "VWCVTXXV": "VWADDVX",
"VWCVTUXXV": "VWADDUVX", "VNCVTXXW": "VNSRLWX",
}[mnem])
if err != nil {
return nil, true, err
}
vs2, err := vecReg(ops[0], "vs2")
if err != nil {
return nil, true, err
}
vd, err := vecReg(ops[len(ops)-1], "vd")
if err != nil {
return nil, true, err
}
f7 := t.funct7
if !masked {
f7 |= 1
}
return word(f7, 0, vs2, t.funct3, vd)
case vecVNOT:
// VNOTV reads as VXORVI with the all-ones immediate.
if len(ops) != 2 && len(ops) != 3 {
return nil, true, fmt.Errorf("%s expects 2 or 3 operands, got %d", mnem, len(ops))
}
masked := len(ops) == 3
if masked {
if err := vecMask(ops[1]); err != nil {
return nil, true, err
}
}
t, err := rename("VXORVI")
if err != nil {
return nil, true, err
}
vs2, err := vecReg(ops[0], "vs2")
if err != nil {
return nil, true, err
}
vd, err := vecReg(ops[len(ops)-1], "vd")
if err != nil {
return nil, true, err
}
f7 := t.funct7
if !masked {
f7 |= 1
}
return word(f7, -1, vs2, t.funct3, vd)
case vecVFABS:
// VFABSV and VFNEGV read as VFSGNJXVV/VFSGNJNVVV with the source in
// both the rs1 and vs2 fields.
if len(ops) != 2 && len(ops) != 3 {
return nil, true, fmt.Errorf("%s expects 2 or 3 operands, got %d", mnem, len(ops))
}
masked := len(ops) == 3
if masked {
if err := vecMask(ops[1]); err != nil {
return nil, true, err
}
}
t, err := rename(map[string]string{
"VFABSV": "VFSGNJXVV", "VFNEGV": "VFSGNJNVV",
}[mnem])
if err != nil {
return nil, true, err
}
vs2, err := vecReg(ops[0], "vs2")
if err != nil {
return nil, true, err
}
vd, err := vecReg(ops[len(ops)-1], "vd")
if err != nil {
return nil, true, err
}
f7 := t.funct7
if !masked {
f7 |= 1
}
return word(f7, int32(vs2), vs2, t.funct3, vd)
case vecVMVV:
// INSTR vs2, vd (vmv.v.v/vmv.v.x): the source in the rs1 field, V0
// fixed in vs2, the vm bit from the table.
if len(ops) != 2 {
return nil, true, fmt.Errorf("%s expects 2 operands, got %d", mnem, len(ops))
}
vs2, err := vecReg(ops[0], "vs2")
if err != nil {
return nil, true, err
}
vd, err := vecReg(ops[1], "vd")
if err != nil {
return nil, true, err
}
return word(op.funct7, int32(vs2), 0, op.funct3, vd)
case vecVMVI:
// INSTR $imm, vd (vmv.v.i): the immediate in the rs1 field, V0 in
// vs2, the vm bit from the table.
if len(ops) != 2 {
return nil, true, fmt.Errorf("%s expects 2 operands, got %d", mnem, len(ops))
}
imm, err := vecImm(ops[0])
if err != nil {
return nil, true, err
}
vd, err := vecReg(ops[1], "vd")
if err != nil {
return nil, true, err
}
return word(op.funct7, imm, 0, op.funct3, vd)
case vecVFMVVF:
// INSTR fs1, vd (vfmv.v.f): the scalar in the rs1 field, V0 in vs2.
if len(ops) != 2 {
return nil, true, fmt.Errorf("%s expects 2 operands, got %d", mnem, len(ops))
}
fs1, err := vecReg(ops[0], "fs1")
if err != nil {
return nil, true, err
}
vd, err := vecReg(ops[1], "vd")
if err != nil {
return nil, true, err
}
return word(op.funct7, int32(fs1), 0, op.funct3, vd)
case vecTWO:
// INSTR vs2, vd: two-operand forms with the fixed rs1 field (the
// extensions and conversions, the whole-register moves, the scalar
// reads).
if len(ops) != 2 {
return nil, true, fmt.Errorf("%s expects 2 operands, got %d", mnem, len(ops))
}
vs2, err := vecReg(ops[0], "vs2")
if err != nil {
return nil, true, err
}
vd, err := vecReg(ops[1], "vd")
if err != nil {
return nil, true, err
}
return word(op.funct7, int32(op.rs1), vs2, op.funct3, vd)
case vecTWOX:
// INSTR xs1|fs1, vd: two-operand forms with the fixed vs2 field
// (vmv.s.x and vfmv.s.f).
if len(ops) != 2 {
return nil, true, fmt.Errorf("%s expects 2 operands, got %d", mnem, len(ops))
}
rs1, err := vecReg(ops[0], "rs1")
if err != nil {
return nil, true, err
}
vd, err := vecReg(ops[1], "vd")
if err != nil {
return nil, true, err
}
return word(op.funct7, int32(rs1), int(op.rs1), op.funct3, vd)
case vecADC:
// INSTR vs1|$imm, vs2, V0, vd: the carry forms, the mask mandatory,
// V0 rejected as the destination.
if len(ops) != 4 {
return nil, true, fmt.Errorf("%s expects 4 operands, got %d", mnem, len(ops))
}
if err := vecMask(ops[2]); err != nil {
return nil, true, err
}
vs2, err := vecReg(ops[1], "vs2")
if err != nil {
return nil, true, err
}
vd, err := vecReg(ops[3], "vd")
if err != nil {
return nil, true, err
}
if vd == 0 {
return nil, true, fmt.Errorf("%s: invalid destination register V0", mnem)
}
var rs1Field int32
if op.imm {
if rs1Field, err = vecImm(ops[0]); err != nil {
return nil, true, err
}
} else {
var vs1 int
if vs1, err = vecReg(ops[0], "vs1"); err != nil {
return nil, true, err
}
rs1Field = int32(vs1)
}
return word(op.funct7, rs1Field, vs2, op.funct3, vd)
case vecMERGE:
// INSTR vs1|fs1|$imm, vs2, V0, vd: the merge forms, the mask
// mandatory, V0 allowed as the destination.
if len(ops) != 4 {
return nil, true, fmt.Errorf("%s expects 4 operands, got %d", mnem, len(ops))
}
if err := vecMask(ops[2]); err != nil {
return nil, true, err
}
vs2, err := vecReg(ops[1], "vs2")
if err != nil {
return nil, true, err
}
vd, err := vecReg(ops[3], "vd")
if err != nil {
return nil, true, err
}
var rs1Field int32
if op.imm {
if rs1Field, err = vecImm(ops[0]); err != nil {
return nil, true, err
}
} else {
var vs1 int
if vs1, err = vecReg(ops[0], "vs1"); err != nil {
return nil, true, err
}
rs1Field = int32(vs1)
}
return word(op.funct7, rs1Field, vs2, op.funct3, vd)
case vecVMADC:
// INSTR vs1|$imm, vs2, vd: the carry-producing forms; the third
// operand names the destination and may be V0.
if len(ops) != 3 {
return nil, true, fmt.Errorf("%s expects 3 operands, got %d", mnem, len(ops))
}
vs2, err := vecReg(ops[1], "vs2")
if err != nil {
return nil, true, err
}
vd, err := vecReg(ops[2], "vd")
if err != nil {
return nil, true, err
}
var rs1Field int32
if op.imm {
if rs1Field, err = vecImm(ops[0]); err != nil {
return nil, true, err
}
} else {
var vs1 int
if vs1, err = vecReg(ops[0], "vs1"); err != nil {
return nil, true, err
}
rs1Field = int32(vs1)
}
return word(op.funct7, rs1Field, vs2, op.funct3, vd)
case vecMM:
// INSTR vs1, vs2, vd: the mask-mask forms. VMMVM and VMNOTM take
// two operands and fold the second source into the first; the vm
// bit stays as the table carries it.
folded := mnem == "VMMVM" || mnem == "VMNOTM"
if (folded && len(ops) != 2) || (!folded && len(ops) != 3) {
return nil, true, fmt.Errorf("%s expects %d operands, got %d", mnem, map[bool]int{true: 2, false: 3}[folded], len(ops))
}
vs1, err := vecReg(ops[0], "vs1")
if err != nil {
return nil, true, err
}
vs2 := vs1
if !folded {
if vs2, err = vecReg(ops[1], "vs2"); err != nil {
return nil, true, err
}
}
vd, err := vecReg(ops[len(ops)-1], "vd")
if err != nil {
return nil, true, err
}
return word(op.funct7, int32(vs1), vs2, op.funct3, vd)
case vecVMCLR:
// INSTR vd: the whole-mask clears and sets, one register in all
// three fields.
if len(ops) != 1 {
return nil, true, fmt.Errorf("%s expects 1 operand, got %d", mnem, len(ops))
}
t, err := rename(map[string]string{
"VMCLRM": "VMXORMM", "VMSETM": "VMXNORMM",
}[mnem])
if err != nil {
return nil, true, err
}
r, err := vecReg(ops[0], "vd")
if err != nil {
return nil, true, err
}
return word(t.funct7, int32(r), r, t.funct3, r)
case vecVID:
// INSTR [V0,] vd: the element index, the mask before the destination.
if len(ops) != 1 && len(ops) != 2 {
return nil, true, fmt.Errorf("%s expects 1 or 2 operands, got %d", mnem, len(ops))
}
masked := len(ops) == 2
if masked {
if err := vecMask(ops[0]); err != nil {
return nil, true, err
}
}
vd, err := vecReg(ops[len(ops)-1], "vd")
if err != nil {
return nil, true, err
}
return word(vm(masked), int32(op.rs1), 0, op.funct3, vd)
}
return nil, true, fmt.Errorf("%s: unhandled vector operand class", mnem)
}
// riscvVTypeToken parses a vsetvli configuration token (E8, M8, MF2 and
+436 -21
View File
@@ -540,11 +540,8 @@ func riscvJType(rd int, offset int32) uint32 {
const (
riscvOpV = 0x57 // the vector operation opcode (also OPcfg for vset*)
// funct3 values: 0 OPIVV, 1 OPFVV, 2 OPMVV, 3 OPIVI, 4 OPIVX,
// 5 OPFVF, 6 OPMVX, 7 vsetvli.
riscvVf3VV = 0x0 // vector-vector
riscvVf3MV = 0x2 // vector mask
riscvVf3VI = 0x3 // vector-immediate
riscvVf3VX = 0x4 // vector-scalar
// 5 OPFVF, 6 OPMVX, 7 vsetvli. The subclass a mnemonic carries lives
// in its table entry's funct3.
riscvVf3Cfg = 0x7 // vsetvli
)
@@ -578,27 +575,445 @@ func riscvVLSType(op uint32, nf, mop, width int, rs2 int32, rs1, rd int) uint32
uint32(rd)<<7 | op
}
// riscvVVInstr encodes an OP-V instruction with the six-bit operation code in
// funct7's upper bits, bit 25 as the unmasked flag and the three registers in
// the standard positions. vs1 may name an integer register for the *VX forms
// (the scalar sits in the rs1 field) or an immediate for the *VI forms.
func riscvVVInstr(funct6, funct3 int, vs1 int32, vs2, vd int) uint32 {
return uint32(funct6&0x3F)<<26 | 1<<25 | uint32(vs1)<<15 |
uint32(funct3)<<12 | uint32(vs2)<<20 | uint32(vd)<<7 | riscvOpV
}
// riscvVUnaryInstr encodes a one-vector-operand OP-V instruction whose fixed
// fields live where the second source register would be: rs1Field and vs2 are
// written verbatim (the oracle writes fixed non-zero constants there for some
// instructions, such as 0x11 in the rs1 field of vmfirst.m and vid.v).
func riscvVUnaryInstr(funct6, funct3 int, rs1Field int32, vs2, vd int) uint32 {
return uint32(funct6&0x3F)<<26 | 1<<25 | uint32(vs2&0x1F)<<20 |
uint32(rs1Field&0x1F)<<15 | uint32(funct3&0x7)<<12 | uint32(vd&0x1F)<<7 | riscvOpV
// riscvVecWord composes one OP-V arithmetic word: funct7 carries funct6 << 1
// with the vm bit in its LSB, exactly as the table stores it; rs1Field takes
// the source register, the scalar or the immediate; vs2 and vd name vector
// registers.
func riscvVecWord(funct7 uint32, rs1Field int32, vs2 int, funct3 uint32, vd int) uint32 {
return funct7<<25 | uint32(vs2&0x1F)<<20 | uint32(rs1Field&0x1F)<<15 |
funct3&0x7<<12 | uint32(vd&0x1F)<<7 | riscvOpV
}
// riscvSegNF maps a segment count to the 3-bit nf field (count - 1).
func riscvSegNF(n int) int32 { return int32(n - 1) }
// The table below mirrors the Go toolchain's own instruction table
// (cmd/internal/obj/riscv): funct7 carries funct6 << 1 with the fixed
// vm bit in its LSB, exactly as the toolchain stores it.
// riscvVecOpClass names the operand shape a vector arithmetic mnemonic
// takes: which operands land in the rs1 and vs2 fields, whether a
// V0 mask may sit between them, and whether the class rewrites its
// operands or its mnemonic before encoding.
type riscvVecOpClass uint8
const (
// vs1, vs2 [, v0], vd: the plain vector-vector form
vecVV riscvVecOpClass = iota
// vs2, vs1 [, v0], vd: the multiply-accumulate order
vecMACC
// vs2 [, v0], vd: one vector operand, fixed rs1
vecUNARY
// vs2 [, v0], xrd: mask bookkeeping into an integer register
vecM2I
// vs2, vd: vmv.v.v and vmv.v.x spellings
vecVMVV
// $imm, vd: vmv.v.i
vecVMVI
// fs1, vd: vfmv.v.f
vecVFMVVF
// vs2, vd: two-operand forms with a fixed rs1 field
vecTWO
// xs1|fs1, vd: two-operand forms with a fixed vs2 field
vecTWOX
// vs1, vs2, v0, vd: the carry forms, mask mandatory
vecADC
// vs1, vs2, v0, vd: the merge forms, mask mandatory
vecMERGE
// vs1, vs2, vd: the carry-producing forms
vecVMADC
// vs2 [, v0], vd with rs1 = x0: VNEGV and friends
vecNEG
// vs2 [, v0], vd: XOR with -1
vecVNOT
// vs2, vs1 [, v0], vd: the swapped comparisons
vecSWAPVV
// $imm, vs2 [, v0], vd: swapped, imm-1
vecSWAPVI
// vs2 [, v0], vd with rs1 = vs2: VFABSV and VFNEGV
vecVFABS
// vs1, vs2, vd: the mask-mask forms, no mask operand
vecMM
// vd: the whole-mask clears and sets
vecVMCLR
// [v0,] vd: the element index
vecVID
)
// riscvVecOp is one vector arithmetic instruction's fixed fields: the
// funct3 subclass, the fixed rs1 field (the unary constants), the fixed
// funct7 (funct6 << 1 with the fixed vm bit), the operand class and the
// immediate form the first operand takes.
type riscvVecOp struct {
funct3 uint32
rs1 uint32
funct7 uint32
class riscvVecOpClass
imm bool // the first operand is an immediate in the rs1 field
immU bool // that immediate is unsigned [0, 31] (shifts and slides)
}
// riscvVecOps maps every vector arithmetic mnemonic the toolchain knows
// onto its fields. The loads and stores and the configuration setters
// have their own paths.
var riscvVecOps = map[string]riscvVecOp{
"VAADDUVV": {0x2, 0x0, 0x10, 0, false, false},
"VAADDUVX": {0x6, 0x0, 0x10, 0, false, false},
"VAADDVV": {0x2, 0x0, 0x12, 0, false, false},
"VAADDVX": {0x6, 0x0, 0x12, 0, false, false},
"VADCVIM": {0x3, 0x0, 0x20, 9, true, false},
"VADCVVM": {0x0, 0x0, 0x20, 9, false, false},
"VADCVXM": {0x4, 0x0, 0x20, 9, false, false},
"VADDVI": {0x3, 0x0, 0x00, 0, true, false},
"VADDVV": {0x0, 0x0, 0x00, 0, false, false},
"VADDVX": {0x4, 0x0, 0x00, 0, false, false},
"VANDNVV": {0x0, 0x0, 0x02, 0, false, false},
"VANDNVX": {0x4, 0x0, 0x02, 0, false, false},
"VANDVI": {0x3, 0x0, 0x12, 0, true, false},
"VANDVV": {0x0, 0x0, 0x12, 0, false, false},
"VANDVX": {0x4, 0x0, 0x12, 0, false, false},
"VASUBUVV": {0x2, 0x0, 0x14, 0, false, false},
"VASUBUVX": {0x6, 0x0, 0x14, 0, false, false},
"VASUBVV": {0x2, 0x0, 0x16, 0, false, false},
"VASUBVX": {0x6, 0x0, 0x16, 0, false, false},
"VBREV8V": {0x2, 0x8, 0x24, 2, false, false},
"VBREVV": {0x2, 0xa, 0x24, 2, false, false},
"VCLMULHVV": {0x2, 0x0, 0x1a, 0, false, false},
"VCLMULHVX": {0x6, 0x0, 0x1a, 0, false, false},
"VCLMULVV": {0x2, 0x0, 0x18, 0, false, false},
"VCLMULVX": {0x6, 0x0, 0x18, 0, false, false},
"VCLZV": {0x2, 0xc, 0x24, 2, false, false},
"VCOMPRESSVM": {0x2, 0x0, 0x2f, 17, false, false},
"VCPOPM": {0x2, 0x10, 0x20, 3, false, false},
"VCPOPV": {0x2, 0xe, 0x24, 2, false, false},
"VCTZV": {0x2, 0xd, 0x24, 2, false, false},
"VDIVUVV": {0x2, 0x0, 0x40, 0, false, false},
"VDIVUVX": {0x6, 0x0, 0x40, 0, false, false},
"VDIVVV": {0x2, 0x0, 0x42, 0, false, false},
"VDIVVX": {0x6, 0x0, 0x42, 0, false, false},
"VFABSV": {0x1, 0x0, 0x14, 16, false, false},
"VFADDVF": {0x5, 0x0, 0x00, 0, false, false},
"VFADDVV": {0x1, 0x0, 0x00, 0, false, false},
"VFCLASSV": {0x1, 0x10, 0x26, 2, false, false},
"VFCVTFXUV": {0x1, 0x2, 0x24, 2, false, false},
"VFCVTFXV": {0x1, 0x3, 0x24, 2, false, false},
"VFCVTRTZXFV": {0x1, 0x7, 0x24, 2, false, false},
"VFCVTRTZXUFV": {0x1, 0x6, 0x24, 2, false, false},
"VFCVTXFV": {0x1, 0x1, 0x24, 2, false, false},
"VFCVTXUFV": {0x1, 0x0, 0x24, 2, false, false},
"VFDIVVF": {0x5, 0x0, 0x40, 0, false, false},
"VFDIVVV": {0x1, 0x0, 0x40, 0, false, false},
"VFIRSTM": {0x2, 0x11, 0x20, 3, false, false},
"VFMACCVF": {0x5, 0x0, 0x58, 1, false, false},
"VFMACCVV": {0x1, 0x0, 0x58, 1, false, false},
"VFMADDVF": {0x5, 0x0, 0x50, 1, false, false},
"VFMADDVV": {0x1, 0x0, 0x50, 1, false, false},
"VFMAXVF": {0x5, 0x0, 0x0c, 0, false, false},
"VFMAXVV": {0x1, 0x0, 0x0c, 0, false, false},
"VFMERGEVFM": {0x5, 0x0, 0x2e, 10, false, false},
"VFMINVF": {0x5, 0x0, 0x08, 0, false, false},
"VFMINVV": {0x1, 0x0, 0x08, 0, false, false},
"VFMSACVF": {0x5, 0x0, 0x5c, 1, false, false},
"VFMSACVV": {0x1, 0x0, 0x5c, 1, false, false},
"VFMSUBVF": {0x5, 0x0, 0x54, 1, false, false},
"VFMSUBVV": {0x1, 0x0, 0x54, 1, false, false},
"VFMULVF": {0x5, 0x0, 0x48, 0, false, false},
"VFMULVV": {0x1, 0x0, 0x48, 0, false, false},
"VFMVFS": {0x1, 0x0, 0x21, 7, false, false},
"VFMVSF": {0x5, 0x0, 0x21, 8, false, false},
"VFMVVF": {0x5, 0x0, 0x2f, 6, false, false},
"VFNCVTFFW": {0x1, 0x14, 0x24, 2, false, false},
"VFNCVTFXUW": {0x1, 0x12, 0x24, 2, false, false},
"VFNCVTFXW": {0x1, 0x13, 0x24, 2, false, false},
"VFNCVTRODFFW": {0x1, 0x15, 0x24, 2, false, false},
"VFNCVTRTZXFW": {0x1, 0x17, 0x24, 2, false, false},
"VFNCVTRTZXUFW": {0x1, 0x16, 0x24, 2, false, false},
"VFNCVTXFW": {0x1, 0x11, 0x24, 2, false, false},
"VFNCVTXUFW": {0x1, 0x10, 0x24, 2, false, false},
"VFNEGV": {0x1, 0x0, 0x12, 16, false, false},
"VFNMACCVF": {0x5, 0x0, 0x5a, 1, false, false},
"VFNMACCVV": {0x1, 0x0, 0x5a, 1, false, false},
"VFNMADDVF": {0x5, 0x0, 0x52, 1, false, false},
"VFNMADDVV": {0x1, 0x0, 0x52, 1, false, false},
"VFNMSACVF": {0x5, 0x0, 0x5e, 1, false, false},
"VFNMSACVV": {0x1, 0x0, 0x5e, 1, false, false},
"VFNMSUBVF": {0x5, 0x0, 0x56, 1, false, false},
"VFNMSUBVV": {0x1, 0x0, 0x56, 1, false, false},
"VFRDIVVF": {0x5, 0x0, 0x42, 0, false, false},
"VFREC7V": {0x1, 0x5, 0x26, 2, false, false},
"VFREDMAXVS": {0x1, 0x0, 0x0e, 0, false, false},
"VFREDMINVS": {0x1, 0x0, 0x0a, 0, false, false},
"VFREDOSUMVS": {0x1, 0x0, 0x06, 0, false, false},
"VFREDUSUMVS": {0x1, 0x0, 0x02, 0, false, false},
"VFRSQRT7V": {0x1, 0x4, 0x26, 2, false, false},
"VFRSUBVF": {0x5, 0x0, 0x4e, 0, false, false},
"VFSGNJNVF": {0x5, 0x0, 0x12, 0, false, false},
"VFSGNJNVV": {0x1, 0x0, 0x12, 0, false, false},
"VFSGNJVF": {0x5, 0x0, 0x10, 0, false, false},
"VFSGNJVV": {0x1, 0x0, 0x10, 0, false, false},
"VFSGNJXVF": {0x5, 0x0, 0x14, 0, false, false},
"VFSGNJXVV": {0x1, 0x0, 0x14, 0, false, false},
"VFSLIDE1DOWNVF": {0x5, 0x0, 0x1e, 0, false, false},
"VFSLIDE1UPVF": {0x5, 0x0, 0x1c, 0, false, false},
"VFSQRTV": {0x1, 0x0, 0x26, 2, false, false},
"VFSUBVF": {0x5, 0x0, 0x04, 0, false, false},
"VFSUBVV": {0x1, 0x0, 0x04, 0, false, false},
"VFWADDVF": {0x5, 0x0, 0x60, 0, false, false},
"VFWADDVV": {0x1, 0x0, 0x60, 0, false, false},
"VFWADDWF": {0x5, 0x0, 0x68, 0, false, false},
"VFWADDWV": {0x1, 0x0, 0x68, 0, false, false},
"VFWCVTFFV": {0x1, 0xc, 0x24, 2, false, false},
"VFWCVTFXUV": {0x1, 0xa, 0x24, 2, false, false},
"VFWCVTFXV": {0x1, 0xb, 0x24, 2, false, false},
"VFWCVTRTZXFV": {0x1, 0xf, 0x24, 2, false, false},
"VFWCVTRTZXUFV": {0x1, 0xe, 0x24, 2, false, false},
"VFWCVTXFV": {0x1, 0x9, 0x24, 2, false, false},
"VFWCVTXUFV": {0x1, 0x8, 0x24, 2, false, false},
"VFWMACCVF": {0x5, 0x0, 0x78, 1, false, false},
"VFWMACCVV": {0x1, 0x0, 0x78, 1, false, false},
"VFWMSACVF": {0x5, 0x0, 0x7c, 1, false, false},
"VFWMSACVV": {0x1, 0x0, 0x7c, 1, false, false},
"VFWMULVF": {0x5, 0x0, 0x70, 0, false, false},
"VFWMULVV": {0x1, 0x0, 0x70, 0, false, false},
"VFWNMACCVF": {0x5, 0x0, 0x7a, 1, false, false},
"VFWNMACCVV": {0x1, 0x0, 0x7a, 1, false, false},
"VFWNMSACVF": {0x5, 0x0, 0x7e, 1, false, false},
"VFWNMSACVV": {0x1, 0x0, 0x7e, 1, false, false},
"VFWREDOSUMVS": {0x1, 0x0, 0x66, 0, false, false},
"VFWREDUSUMVS": {0x1, 0x0, 0x62, 0, false, false},
"VFWSUBVF": {0x5, 0x0, 0x64, 0, false, false},
"VFWSUBVV": {0x1, 0x0, 0x64, 0, false, false},
"VFWSUBWF": {0x5, 0x0, 0x6c, 0, false, false},
"VFWSUBWV": {0x1, 0x0, 0x6c, 0, false, false},
"VIDV": {0x2, 0x11, 0x28, 19, false, false},
"VIOTAM": {0x2, 0x10, 0x28, 3, false, false},
"VMACCVV": {0x2, 0x0, 0x5a, 1, false, false},
"VMACCVX": {0x6, 0x0, 0x5a, 1, false, false},
"VMADCVI": {0x3, 0x0, 0x23, 11, true, false},
"VMADCVIM": {0x3, 0x0, 0x22, 10, true, false},
"VMADCVV": {0x0, 0x0, 0x23, 11, false, false},
"VMADCVVM": {0x0, 0x0, 0x22, 10, false, false},
"VMADCVX": {0x4, 0x0, 0x23, 11, false, false},
"VMADCVXM": {0x4, 0x0, 0x22, 10, false, false},
"VMADDVV": {0x2, 0x0, 0x52, 1, false, false},
"VMADDVX": {0x6, 0x0, 0x52, 1, false, false},
"VMANDMM": {0x2, 0x0, 0x33, 17, false, false},
"VMANDNMM": {0x2, 0x0, 0x31, 17, false, false},
"VMAXUVV": {0x0, 0x0, 0x0c, 0, false, false},
"VMAXUVX": {0x4, 0x0, 0x0c, 0, false, false},
"VMAXVV": {0x0, 0x0, 0x0e, 0, false, false},
"VMAXVX": {0x4, 0x0, 0x0e, 0, false, false},
"VMCLRM": {0x2, 0x0, 0x37, 18, false, false},
"VMERGEVIM": {0x3, 0x0, 0x2e, 10, true, false},
"VMERGEVVM": {0x0, 0x0, 0x2e, 10, false, false},
"VMERGEVXM": {0x4, 0x0, 0x2e, 10, false, false},
"VMFEQVF": {0x5, 0x0, 0x30, 0, false, false},
"VMFEQVV": {0x1, 0x0, 0x30, 0, false, false},
"VMFGEVF": {0x5, 0x0, 0x3e, 0, false, false},
"VMFGEVV": {0x1, 0x0, 0x32, 14, false, false},
"VMFGTVF": {0x5, 0x0, 0x3a, 0, false, false},
"VMFGTVV": {0x1, 0x0, 0x36, 14, false, false},
"VMFLEVF": {0x5, 0x0, 0x32, 0, false, false},
"VMFLEVV": {0x1, 0x0, 0x32, 0, false, false},
"VMFLTVF": {0x5, 0x0, 0x36, 0, false, false},
"VMFLTVV": {0x1, 0x0, 0x36, 0, false, false},
"VMFNEVF": {0x5, 0x0, 0x38, 0, false, false},
"VMFNEVV": {0x1, 0x0, 0x38, 0, false, false},
"VMINUVV": {0x0, 0x0, 0x08, 0, false, false},
"VMINUVX": {0x4, 0x0, 0x08, 0, false, false},
"VMINVV": {0x0, 0x0, 0x0a, 0, false, false},
"VMINVX": {0x4, 0x0, 0x0a, 0, false, false},
"VMMVM": {0x2, 0x0, 0x33, 17, false, false},
"VMNANDMM": {0x2, 0x0, 0x3b, 17, false, false},
"VMNORMM": {0x2, 0x0, 0x3d, 17, false, false},
"VMNOTM": {0x2, 0x0, 0x3b, 17, false, false},
"VMORMM": {0x2, 0x0, 0x35, 17, false, false},
"VMORNMM": {0x2, 0x0, 0x39, 17, false, false},
"VMSBCVV": {0x0, 0x0, 0x27, 11, false, false},
"VMSBCVVM": {0x0, 0x0, 0x26, 10, false, false},
"VMSBCVX": {0x4, 0x0, 0x27, 11, false, false},
"VMSBCVXM": {0x4, 0x0, 0x26, 10, false, false},
"VMSBFM": {0x2, 0x1, 0x28, 3, false, false},
"VMSEQVI": {0x3, 0x0, 0x30, 0, true, false},
"VMSEQVV": {0x0, 0x0, 0x30, 0, false, false},
"VMSEQVX": {0x4, 0x0, 0x30, 0, false, false},
"VMSETM": {0x2, 0x0, 0x3f, 18, false, false},
"VMSGEUVI": {0x3, 0x0, 0x3c, 15, true, false},
"VMSGEUVV": {0x0, 0x0, 0x38, 14, false, false},
"VMSGEVI": {0x3, 0x0, 0x3e, 15, true, false},
"VMSGEVV": {0x0, 0x0, 0x3a, 14, false, false},
"VMSGTUVI": {0x3, 0x0, 0x3c, 0, true, false},
"VMSGTUVV": {0x0, 0x0, 0x34, 14, false, false},
"VMSGTUVX": {0x4, 0x0, 0x3c, 0, false, false},
"VMSGTVI": {0x3, 0x0, 0x3e, 0, true, false},
"VMSGTVV": {0x0, 0x0, 0x36, 14, false, false},
"VMSGTVX": {0x4, 0x0, 0x3e, 0, false, false},
"VMSIFM": {0x2, 0x3, 0x28, 3, false, false},
"VMSLEUVI": {0x3, 0x0, 0x38, 0, true, false},
"VMSLEUVV": {0x0, 0x0, 0x38, 0, false, false},
"VMSLEUVX": {0x4, 0x0, 0x38, 0, false, false},
"VMSLEVI": {0x3, 0x0, 0x3a, 0, true, false},
"VMSLEVV": {0x0, 0x0, 0x3a, 0, false, false},
"VMSLEVX": {0x4, 0x0, 0x3a, 0, false, false},
"VMSLTUVI": {0x3, 0x0, 0x38, 15, true, false},
"VMSLTUVV": {0x0, 0x0, 0x34, 0, false, false},
"VMSLTUVX": {0x4, 0x0, 0x34, 0, false, false},
"VMSLTVI": {0x3, 0x0, 0x3a, 15, true, false},
"VMSLTVV": {0x0, 0x0, 0x36, 0, false, false},
"VMSLTVX": {0x4, 0x0, 0x36, 0, false, false},
"VMSNEVI": {0x3, 0x0, 0x32, 0, true, false},
"VMSNEVV": {0x0, 0x0, 0x32, 0, false, false},
"VMSNEVX": {0x4, 0x0, 0x32, 0, false, false},
"VMSOFM": {0x2, 0x2, 0x28, 3, false, false},
"VMULHSUVV": {0x2, 0x0, 0x4c, 0, false, false},
"VMULHSUVX": {0x6, 0x0, 0x4c, 0, false, false},
"VMULHUVV": {0x2, 0x0, 0x48, 0, false, false},
"VMULHUVX": {0x6, 0x0, 0x48, 0, false, false},
"VMULHVV": {0x2, 0x0, 0x4e, 0, false, false},
"VMULHVX": {0x6, 0x0, 0x4e, 0, false, false},
"VMULVV": {0x2, 0x0, 0x4a, 0, false, false},
"VMULVX": {0x6, 0x0, 0x4a, 0, false, false},
"VMV1RV": {0x3, 0x0, 0x4f, 7, false, false},
"VMV2RV": {0x3, 0x1, 0x4f, 7, false, false},
"VMV4RV": {0x3, 0x3, 0x4f, 7, false, false},
"VMV8RV": {0x3, 0x7, 0x4f, 7, false, false},
"VMVSX": {0x6, 0x0, 0x21, 8, false, false},
"VMVVI": {0x3, 0x0, 0x2f, 5, true, false},
"VMVVV": {0x0, 0x0, 0x2f, 4, false, false},
"VMVVX": {0x4, 0x0, 0x2f, 4, false, false},
"VMVXS": {0x2, 0x0, 0x21, 7, false, false},
"VMXNORMM": {0x2, 0x0, 0x3f, 17, false, false},
"VMXORMM": {0x2, 0x0, 0x37, 17, false, false},
"VNCLIPUWI": {0x3, 0x0, 0x5c, 0, true, true},
"VNCLIPUWV": {0x0, 0x0, 0x5c, 0, false, false},
"VNCLIPUWX": {0x4, 0x0, 0x5c, 0, false, false},
"VNCLIPWI": {0x3, 0x0, 0x5e, 0, true, true},
"VNCLIPWV": {0x0, 0x0, 0x5e, 0, false, false},
"VNCLIPWX": {0x4, 0x0, 0x5e, 0, false, false},
"VNCVTXXW": {0x4, 0x0, 0x58, 12, false, false},
"VNEGV": {0x4, 0x0, 0x06, 12, false, false},
"VNMSACVV": {0x2, 0x0, 0x5e, 1, false, false},
"VNMSACVX": {0x6, 0x0, 0x5e, 1, false, false},
"VNMSUBVV": {0x2, 0x0, 0x56, 1, false, false},
"VNMSUBVX": {0x6, 0x0, 0x56, 1, false, false},
"VNOTV": {0x3, 0x0, 0x16, 13, true, false},
"VNSRAWI": {0x3, 0x0, 0x5a, 0, true, true},
"VNSRAWV": {0x0, 0x0, 0x5a, 0, false, false},
"VNSRAWX": {0x4, 0x0, 0x5a, 0, false, false},
"VNSRLWI": {0x3, 0x0, 0x58, 0, true, true},
"VNSRLWV": {0x0, 0x0, 0x58, 0, false, false},
"VNSRLWX": {0x4, 0x0, 0x58, 0, false, false},
"VORVI": {0x3, 0x0, 0x14, 0, true, false},
"VORVV": {0x0, 0x0, 0x14, 0, false, false},
"VORVX": {0x4, 0x0, 0x14, 0, false, false},
"VREDANDVS": {0x2, 0x0, 0x02, 0, false, false},
"VREDMAXUVS": {0x2, 0x0, 0x0c, 0, false, false},
"VREDMAXVS": {0x2, 0x0, 0x0e, 0, false, false},
"VREDMINUVS": {0x2, 0x0, 0x08, 0, false, false},
"VREDMINVS": {0x2, 0x0, 0x0a, 0, false, false},
"VREDORVS": {0x2, 0x0, 0x04, 0, false, false},
"VREDSUMVS": {0x2, 0x0, 0x00, 0, false, false},
"VREDXORVS": {0x2, 0x0, 0x06, 0, false, false},
"VREMUVV": {0x2, 0x0, 0x44, 0, false, false},
"VREMUVX": {0x6, 0x0, 0x44, 0, false, false},
"VREMVV": {0x2, 0x0, 0x46, 0, false, false},
"VREMVX": {0x6, 0x0, 0x46, 0, false, false},
"VREV8V": {0x2, 0x9, 0x24, 2, false, false},
"VRGATHEREI16VV": {0x0, 0x0, 0x1c, 0, false, false},
"VRGATHERVI": {0x3, 0x0, 0x18, 0, true, true},
"VRGATHERVV": {0x0, 0x0, 0x18, 0, false, false},
"VRGATHERVX": {0x4, 0x0, 0x18, 0, false, false},
"VROLVV": {0x0, 0x0, 0x2a, 0, false, false},
"VROLVX": {0x4, 0x0, 0x2a, 0, false, false},
"VRORVI": {0x3, 0x0, 0x28, 0, true, true},
"VRORVV": {0x0, 0x0, 0x28, 0, false, false},
"VRORVX": {0x4, 0x0, 0x28, 0, false, false},
"VRSUBVI": {0x3, 0x0, 0x06, 0, true, false},
"VRSUBVX": {0x4, 0x0, 0x06, 0, false, false},
"VSADDUVI": {0x3, 0x0, 0x40, 0, true, false},
"VSADDUVV": {0x0, 0x0, 0x40, 0, false, false},
"VSADDUVX": {0x4, 0x0, 0x40, 0, false, false},
"VSADDVI": {0x3, 0x0, 0x42, 0, true, false},
"VSADDVV": {0x0, 0x0, 0x42, 0, false, false},
"VSADDVX": {0x4, 0x0, 0x42, 0, false, false},
"VSBCVVM": {0x0, 0x0, 0x24, 9, false, false},
"VSBCVXM": {0x4, 0x0, 0x24, 9, false, false},
"VSEXTVF2": {0x2, 0x7, 0x24, 2, false, false},
"VSEXTVF4": {0x2, 0x5, 0x24, 2, false, false},
"VSEXTVF8": {0x2, 0x3, 0x24, 2, false, false},
"VSLIDE1DOWNVX": {0x6, 0x0, 0x1e, 0, false, false},
"VSLIDE1UPVX": {0x6, 0x0, 0x1c, 0, false, false},
"VSLIDEDOWNVI": {0x3, 0x0, 0x1e, 0, true, true},
"VSLIDEDOWNVX": {0x4, 0x0, 0x1e, 0, false, false},
"VSLIDEUPVI": {0x3, 0x0, 0x1c, 0, true, true},
"VSLIDEUPVX": {0x4, 0x0, 0x1c, 0, false, false},
"VSLLVI": {0x3, 0x0, 0x4a, 0, true, true},
"VSLLVV": {0x0, 0x0, 0x4a, 0, false, false},
"VSLLVX": {0x4, 0x0, 0x4a, 0, false, false},
"VSMULVV": {0x0, 0x0, 0x4e, 0, false, false},
"VSMULVX": {0x4, 0x0, 0x4e, 0, false, false},
"VSRAVI": {0x3, 0x0, 0x52, 0, true, true},
"VSRAVV": {0x0, 0x0, 0x52, 0, false, false},
"VSRAVX": {0x4, 0x0, 0x52, 0, false, false},
"VSRLVI": {0x3, 0x0, 0x50, 0, true, true},
"VSRLVV": {0x0, 0x0, 0x50, 0, false, false},
"VSRLVX": {0x4, 0x0, 0x50, 0, false, false},
"VSSRAVI": {0x3, 0x0, 0x56, 0, true, true},
"VSSRAVV": {0x0, 0x0, 0x56, 0, false, false},
"VSSRAVX": {0x4, 0x0, 0x56, 0, false, false},
"VSSRLVI": {0x3, 0x0, 0x54, 0, true, true},
"VSSRLVV": {0x0, 0x0, 0x54, 0, false, false},
"VSSRLVX": {0x4, 0x0, 0x54, 0, false, false},
"VSSUBUVV": {0x0, 0x0, 0x44, 0, false, false},
"VSSUBUVX": {0x4, 0x0, 0x44, 0, false, false},
"VSSUBVV": {0x0, 0x0, 0x46, 0, false, false},
"VSSUBVX": {0x4, 0x0, 0x46, 0, false, false},
"VSUBVV": {0x0, 0x0, 0x04, 0, false, false},
"VSUBVX": {0x4, 0x0, 0x04, 0, false, false},
"VWADDUVV": {0x2, 0x0, 0x60, 0, false, false},
"VWADDUVX": {0x6, 0x0, 0x60, 0, false, false},
"VWADDUWV": {0x2, 0x0, 0x68, 0, false, false},
"VWADDUWX": {0x6, 0x0, 0x68, 0, false, false},
"VWADDVV": {0x2, 0x0, 0x62, 0, false, false},
"VWADDVX": {0x6, 0x0, 0x62, 0, false, false},
"VWADDWV": {0x2, 0x0, 0x6a, 0, false, false},
"VWADDWX": {0x6, 0x0, 0x6a, 0, false, false},
"VWCVTUXXV": {0x6, 0x0, 0x60, 12, false, false},
"VWCVTXXV": {0x6, 0x0, 0x62, 12, false, false},
"VWMACCSUVV": {0x2, 0x0, 0x7e, 1, false, false},
"VWMACCSUVX": {0x6, 0x0, 0x7e, 1, false, false},
"VWMACCUSVX": {0x6, 0x0, 0x7c, 1, false, false},
"VWMACCUVV": {0x2, 0x0, 0x78, 1, false, false},
"VWMACCUVX": {0x6, 0x0, 0x78, 1, false, false},
"VWMACCVV": {0x2, 0x0, 0x7a, 1, false, false},
"VWMACCVX": {0x6, 0x0, 0x7a, 1, false, false},
"VWMULSUVV": {0x2, 0x0, 0x74, 0, false, false},
"VWMULSUVX": {0x6, 0x0, 0x74, 0, false, false},
"VWMULUVV": {0x2, 0x0, 0x70, 0, false, false},
"VWMULUVX": {0x6, 0x0, 0x70, 0, false, false},
"VWMULVV": {0x2, 0x0, 0x76, 0, false, false},
"VWMULVX": {0x6, 0x0, 0x76, 0, false, false},
"VWREDSUMUVS": {0x0, 0x0, 0x60, 0, false, false},
"VWREDSUMVS": {0x0, 0x0, 0x62, 0, false, false},
"VWSLLVI": {0x3, 0x0, 0x6a, 0, true, true},
"VWSLLVV": {0x0, 0x0, 0x6a, 0, false, false},
"VWSLLVX": {0x4, 0x0, 0x6a, 0, false, false},
"VWSUBUVV": {0x2, 0x0, 0x64, 0, false, false},
"VWSUBUVX": {0x6, 0x0, 0x64, 0, false, false},
"VWSUBUWV": {0x2, 0x0, 0x6c, 0, false, false},
"VWSUBUWX": {0x6, 0x0, 0x6c, 0, false, false},
"VWSUBVV": {0x2, 0x0, 0x66, 0, false, false},
"VWSUBVX": {0x6, 0x0, 0x66, 0, false, false},
"VWSUBWV": {0x2, 0x0, 0x6e, 0, false, false},
"VWSUBWX": {0x6, 0x0, 0x6e, 0, false, false},
"VXORVI": {0x3, 0x0, 0x16, 0, true, false},
"VXORVV": {0x0, 0x0, 0x16, 0, false, false},
"VXORVX": {0x4, 0x0, 0x16, 0, false, false},
"VZEXTVF2": {0x2, 0x6, 0x24, 2, false, false},
"VZEXTVF4": {0x2, 0x4, 0x24, 2, false, false},
"VZEXTVF8": {0x2, 0x2, 0x24, 2, false, false},
}
// ---- RVC (compressed) encoding helpers ----
// isRVCIntReg reports whether a register number can be encoded in the 3-bit
+812
View File
@@ -0,0 +1,812 @@
// Copyright (c) 2026 Petr Balvín <opensource@petrbalvin.org> (https://petrbalvin.org)
// SPDX-License-Identifier: BSD-3-Clause
package asm
import (
"os"
"path/filepath"
"testing"
)
// TestRISCVVecArith_Differential proves the vector arithmetic families
// against the toolchain: sections 31.11 through 31.16 of the "V"
// specification's arithmetic, reductions, mask, slide, gather, compress and
// whole-register-move material plus the Zvbb bit-manipulation and Zvbc
// carryless-multiplication extensions, in the toolchain's own testdata
// wording with every masked and unmasked form, assembled by gasm and by
// go tool asm must agree word for word.
func TestRISCVVecArith_Differential(t *testing.T) {
src := `#include "textflag.h"
TEXT ·vecarith(SB), NOSPLIT, $0
// 31.11.1: Vector Single-Width Integer Add and Subtract
VADDVV V1, V2, V3 // d7812002
VADDVV V1, V2, V0, V3 // d7812000
VADDVX X10, V2, V3 // d7412502
VADDVX X10, V2, V0, V3 // d7412500
VADDVI $15, V2, V3 // d7b12702
VADDVI $15, V2, V0, V3 // d7b12700
VADDVI $-16, V2, V3 // d7312802
VADDVI $-16, V2, V0, V3 // d7312800
VSUBVV V1, V2, V3 // d781200a
VSUBVV V1, V2, V0, V3 // d7812008
VSUBVX X10, V2, V3 // d741250a
VSUBVX X10, V2, V0, V3 // d7412508
VRSUBVX X10, V2, V3 // d741250e
VRSUBVX X10, V2, V0, V3 // d741250c
VRSUBVI $15, V2, V0, V3 // d7b1270c
VRSUBVI $-16, V2, V0, V3 // d731280c
VNEGV V2, V3 // d741200e
VNEGV V2, V0, V3 // d741200c
// 31.11.2: Vector Widening Integer Add/Subtract
VWADDUVV V1, V2, V3 // d7a120c2
VWADDUVV V1, V2, V0, V3 // d7a120c0
VWADDUVX X10, V2, V3 // d76125c2
VWADDUVX X10, V2, V0, V3 // d76125c0
VWSUBUVV V1, V2, V3 // d7a120ca
VWSUBUVV V1, V2, V0, V3 // d7a120c8
VWSUBUVX X10, V2, V3 // d76125ca
VWSUBUVX X10, V2, V0, V3 // d76125c8
VWADDVV V1, V2, V3 // d7a120c6
VWADDVV V1, V2, V0, V3 // d7a120c4
VWADDVX X10, V2, V3 // d76125c6
VWADDVX X10, V2, V0, V3 // d76125c4
VWSUBVV V1, V2, V3 // d7a120ce
VWSUBVV V1, V2, V0, V3 // d7a120cc
VWSUBVX X10, V2, V3 // d76125ce
VWSUBVX X10, V2, V0, V3 // d76125cc
VWADDUWV V1, V2, V3 // d7a120d2
VWADDUWV V1, V2, V0, V3 // d7a120d0
VWADDUWX X10, V2, V3 // d76125d2
VWADDUWX X10, V2, V0, V3 // d76125d0
VWSUBUWV V1, V2, V3 // d7a120da
VWSUBUWV V1, V2, V0, V3 // d7a120d8
VWSUBUWX X10, V2, V3 // d76125da
VWSUBUWX X10, V2, V0, V3 // d76125d8
VWADDWV V1, V2, V3 // d7a120d6
VWADDWV V1, V2, V0, V3 // d7a120d4
VWADDWX X10, V2, V3 // d76125d6
VWADDWX X10, V2, V0, V3 // d76125d4
VWSUBWV V1, V2, V3 // d7a120de
VWSUBWV V1, V2, V0, V3 // d7a120dc
VWSUBWX X10, V2, V3 // d76125de
VWSUBWX X10, V2, V0, V3 // d76125dc
VWCVTXXV V2, V3 // d76120c6
VWCVTXXV V2, V0, V3 // d76120c4
VWCVTUXXV V2, V3 // d76120c2
VWCVTUXXV V2, V0, V3 // d76120c0
// 31.11.3: Vector Integer Extension
VZEXTVF2 V2, V3 // d721234a
VZEXTVF2 V2, V0, V3 // d7212348
VSEXTVF2 V2, V3 // d7a1234a
VSEXTVF2 V2, V0, V3 // d7a12348
VZEXTVF4 V2, V3 // d721224a
VZEXTVF4 V2, V0, V3 // d7212248
VSEXTVF4 V2, V3 // d7a1224a
VSEXTVF4 V2, V0, V3 // d7a12248
VZEXTVF8 V2, V3 // d721214a
VZEXTVF8 V2, V0, V3 // d7212148
VSEXTVF8 V2, V3 // d7a1214a
VSEXTVF8 V2, V0, V3 // d7a12148
// 31.11.4: Vector Integer Add-with-Carry / Subtract-with-Borrow Instructions
VADCVVM V1, V2, V0, V3 // d7812040
VADCVXM X11, V2, V0, V3 // d7c12540
VADCVIM $15, V2, V0, V3 // d7b12740
VMADCVVM V1, V2, V0, V3 // d7812044
VMADCVVM V1, V2, V0, V0 // 57802044
VMADCVXM X11, V2, V0, V3 // d7c12544
VMADCVXM X11, V2, V0, V0 // 57c02544
VMADCVIM $15, V2, V0, V3 // d7b12744
VMADCVIM $15, V2, V0, V0 // 57b02744
VMADCVV V1, V2, V3 // d7812046
VMADCVV V1, V2, V0 // 57802046
VMADCVX X11, V2, V3 // d7c12546
VMADCVX X11, V2, V0 // 57c02546
VMADCVI $15, V2, V3 // d7b12746
VMADCVI $15, V2, V0 // 57b02746
VSBCVVM V1, V2, V0, V3 // d7812048
VSBCVXM X11, V2, V0, V3 // d7c12548
VMSBCVVM V1, V2, V0, V3 // d781204c
VMSBCVVM V1, V2, V0, V0 // 5780204c
VMSBCVXM X11, V2, V0, V3 // d7c1254c
VMSBCVXM X11, V2, V0, V0 // 57c0254c
VMSBCVV V1, V2, V3 // d781204e
VMSBCVV V1, V2, V0 // 5780204e
VMSBCVX X11, V2, V3 // d7c1254e
VMSBCVX X11, V2, V0 // 57c0254e
// 31.11.5: Vector Bitwise Logical Instructions
VANDVV V1, V2, V3 // d7812026
VANDVV V1, V2, V0, V3 // d7812024
VANDVX X11, V2, V3 // d7c12526
VANDVX X11, V2, V0, V3 // d7c12524
VANDVI $15, V2, V3 // d7b12726
VANDVI $15, V2, V0, V3 // d7b12724
VORVV V1, V2, V3 // d781202a
VORVV V1, V2, V0, V3 // d7812028
VORVX X11, V2, V3 // d7c1252a
VORVX X11, V2, V0, V3 // d7c12528
VORVI $15, V2, V3 // d7b1272a
VORVI $15, V2, V0, V3 // d7b12728
VXORVV V1, V2, V3 // d781202e
VXORVV V1, V2, V0, V3 // d781202c
VXORVX X11, V2, V3 // d7c1252e
VXORVX X11, V2, V0, V3 // d7c1252c
VXORVI $15, V2, V3 // d7b1272e
VXORVI $15, V2, V0, V3 // d7b1272c
VNOTV V2, V3 // d7b12f2e
VNOTV V2, V0, V3 // d7b12f2c
// 31.11.6: Vector Single-Width Shift Instructions
VSLLVV V1, V2, V3 // d7812096
VSLLVV V1, V2, V0, V3 // d7812094
VSLLVX X11, V2, V3 // d7c12596
VSLLVX X11, V2, V0, V3 // d7c12594
VSLLVI $15, V2, V3 // d7b12796
VSLLVI $15, V2, V0, V3 // d7b12794
VSRLVV V1, V2, V3 // d78120a2
VSRLVV V1, V2, V0, V3 // d78120a0
VSRLVX X11, V2, V3 // d7c125a2
VSRLVX X11, V2, V0, V3 // d7c125a0
VSRLVI $15, V2, V3 // d7b127a2
VSRLVI $15, V2, V0, V3 // d7b127a0
VSRAVV V1, V2, V3 // d78120a6
VSRAVV V1, V2, V0, V3 // d78120a4
VSRAVX X11, V2, V3 // d7c125a6
VSRAVX X11, V2, V0, V3 // d7c125a4
VSRAVI $15, V2, V3 // d7b127a6
VSRAVI $15, V2, V0, V3 // d7b127a4
// 31.11.7: Vector Narrowing Integer Right Shift Instructions
VNSRLWV V1, V2, V3 // d78120b2
VNSRLWV V1, V2, V0, V3 // d78120b0
VNSRLWX X10, V2, V3 // d74125b2
VNSRLWX X10, V2, V0, V3 // d74125b0
VNSRLWI $31, V2, V3 // d7b12fb2
VNSRLWI $31, V2, V0, V3 // d7b12fb0
VNSRAWV V1, V2, V3 // d78120b6
VNSRAWV V1, V2, V0, V3 // d78120b4
VNSRAWX X10, V2, V3 // d74125b6
VNSRAWX X10, V2, V0, V3 // d74125b4
VNSRAWI $31, V2, V3 // d7b12fb6
VNSRAWI $31, V2, V0, V3 // d7b12fb4
VNCVTXXW V2, V3 // d74120b2
VNCVTXXW V2, V0, V3 // d74120b0
// 31.11.8: Vector Integer Compare Instructions
VMSEQVV V1, V2, V3 // d7812062
VMSEQVV V1, V2, V0, V3 // d7812060
VMSEQVX X10, V2, V3 // d7412562
VMSEQVX X10, V2, V0, V3 // d7412560
VMSEQVI $15, V2, V3 // d7b12762
VMSEQVI $15, V2, V0, V3 // d7b12760
VMSNEVV V1, V2, V3 // d7812066
VMSNEVV V1, V2, V0, V3 // d7812064
VMSNEVX X10, V2, V3 // d7412566
VMSNEVX X10, V2, V0, V3 // d7412564
VMSNEVI $15, V2, V3 // d7b12766
VMSNEVI $15, V2, V0, V3 // d7b12764
VMSLTUVV V1, V2, V3 // d781206a
VMSLTUVV V1, V2, V0, V3 // d7812068
VMSLTUVX X10, V2, V3 // d741256a
VMSLTUVX X10, V2, V0, V3 // d7412568
VMSLTVV V1, V2, V3 // d781206e
VMSLTVV V1, V2, V0, V3 // d781206c
VMSLTVX X10, V2, V3 // d741256e
VMSLTVX X10, V2, V0, V3 // d741256c
VMSLEUVV V1, V2, V3 // d7812072
VMSLEUVV V1, V2, V0, V3 // d7812070
VMSLEUVX X10, V2, V3 // d7412572
VMSLEUVX X10, V2, V0, V3 // d7412570
VMSLEUVI $15, V2, V3 // d7b12772
VMSLEUVI $15, V2, V0, V3 // d7b12770
VMSLEVV V1, V2, V3 // d7812076
VMSLEVV V1, V2, V0, V3 // d7812074
VMSLEVX X10, V2, V3 // d7412576
VMSLEVX X10, V2, V0, V3 // d7412574
VMSLEVI $15, V2, V3 // d7b12776
VMSLEVI $15, V2, V0, V3 // d7b12774
VMSGTUVX X10, V2, V3 // d741257a
VMSGTUVX X10, V2, V0, V3 // d7412578
VMSGTUVI $15, V2, V3 // d7b1277a
VMSGTUVI $15, V2, V0, V3 // d7b12778
VMSGTVX X10, V2, V3 // d741257e
VMSGTVX X10, V2, V0, V3 // d741257c
VMSGTVI $15, V2, V3 // d7b1277e
VMSGTVI $15, V2, V0, V3 // d7b1277c
VMSGTVV V1, V2, V3 // d701116e
VMSGTVV V1, V2, V0, V3 // d701116c
VMSGTUVV V1, V2, V3 // d701116a
VMSGTUVV V1, V2, V0, V3 // d7011168
VMSGEVV V1, V2, V3 // d7011176
VMSGEVV V1, V2, V0, V3 // d7011174
VMSGEUVV V1, V2, V3 // d7011172
VMSGEUVV V1, V2, V0, V3 // d7011170
VMSLTVI $15, V2, V3 // d7312776
VMSLTVI $15, V2, V0, V3 // d7312774
VMSLTUVI $15, V2, V3 // d7312772
VMSLTUVI $15, V2, V0, V3 // d7312770
VMSGEVI $15, V2, V3 // d731277e
VMSGEVI $15, V2, V0, V3 // d731277c
VMSGEUVI $15, V2, V3 // d731277a
VMSGEUVI $15, V2, V0, V3 // d7312778
// 31.11.9: Vector Integer Min/Max Instructions
VMINUVV V1, V2, V3 // d7812012
VMINUVV V1, V2, V0, V3 // d7812010
VMINUVX X10, V2, V3 // d7412512
VMINUVX X10, V2, V0, V3 // d7412510
VMINVV V1, V2, V3 // d7812016
VMINVV V1, V2, V0, V3 // d7812014
VMINVX X10, V2, V3 // d7412516
VMINVX X10, V2, V0, V3 // d7412514
VMAXUVV V1, V2, V3 // d781201a
VMAXUVV V1, V2, V0, V3 // d7812018
VMAXUVX X10, V2, V3 // d741251a
VMAXUVX X10, V2, V0, V3 // d7412518
VMAXVV V1, V2, V3 // d781201e
VMAXVV V1, V2, V0, V3 // d781201c
VMAXVX X10, V2, V3 // d741251e
VMAXVX X10, V2, V0, V3 // d741251c
// 31.11.10: Vector Single-Width Integer Multiply Instructions
VMULVV V1, V2, V3 // d7a12096
VMULVV V1, V2, V0, V3 // d7a12094
VMULVX X10, V2, V3 // d7612596
VMULVX X10, V2, V0, V3 // d7612594
VMULHVV V1, V2, V3 // d7a1209e
VMULHVV V1, V2, V0, V3 // d7a1209c
VMULHVX X10, V2, V3 // d761259e
VMULHVX X10, V2, V0, V3 // d761259c
VMULHUVV V1, V2, V3 // d7a12092
VMULHUVV V1, V2, V0, V3 // d7a12090
VMULHUVX X10, V2, V3 // d7612592
VMULHUVX X10, V2, V0, V3 // d7612590
VMULHSUVV V1, V2, V3 // d7a1209a
VMULHSUVV V1, V2, V0, V3 // d7a12098
VMULHSUVX X10, V2, V3 // d761259a
VMULHSUVX X10, V2, V0, V3 // d7612598
// 31.11.11: Vector Integer Divide Instructions
VDIVUVV V1, V2, V3 // d7a12082
VDIVUVV V1, V2, V0, V3 // d7a12080
VDIVUVX X10, V2, V3 // d7612582
VDIVUVX X10, V2, V0, V3 // d7612580
VDIVVV V1, V2, V3 // d7a12086
VDIVVV V1, V2, V0, V3 // d7a12084
VDIVVX X10, V2, V3 // d7612586
VDIVVX X10, V2, V0, V3 // d7612584
VREMUVV V1, V2, V3 // d7a1208a
VREMUVV V1, V2, V0, V3 // d7a12088
VREMUVX X10, V2, V3 // d761258a
VREMUVX X10, V2, V0, V3 // d7612588
VREMVV V1, V2, V3 // d7a1208e
VREMVV V1, V2, V0, V3 // d7a1208c
VREMVX X10, V2, V3 // d761258e
VREMVX X10, V2, V0, V3 // d761258c
// 31.11.12: Vector Widening Integer Multiply Instructions
VWMULVV V1, V2, V3 // d7a120ee
VWMULVV V1, V2, V0, V3 // d7a120ec
VWMULVX X10, V2, V3 // d76125ee
VWMULVX X10, V2, V0, V3 // d76125ec
VWMULUVV V1, V2, V3 // d7a120e2
VWMULUVV V1, V2, V0, V3 // d7a120e0
VWMULUVX X10, V2, V3 // d76125e2
VWMULUVX X10, V2, V0, V3 // d76125e0
VWMULSUVV V1, V2, V3 // d7a120ea
VWMULSUVV V1, V2, V0, V3 // d7a120e8
VWMULSUVX X10, V2, V3 // d76125ea
VWMULSUVX X10, V2, V0, V3 // d76125e8
// 31.11.13: Vector Single-Width Integer Multiply-Add Instructions
VMACCVV V2, V1, V3 // d7a120b6
VMACCVV V2, V1, V0, V3 // d7a120b4
VMACCVX V2, X10, V3 // d76125b6
VMACCVX V2, X10, V0, V3 // d76125b4
VNMSACVV V2, V1, V3 // d7a120be
VNMSACVV V2, V1, V0, V3 // d7a120bc
VNMSACVX V2, X10, V3 // d76125be
VNMSACVX V2, X10, V0, V3 // d76125bc
VMADDVV V2, V1, V3 // d7a120a6
VMADDVV V2, V1, V0, V3 // d7a120a4
VMADDVX V2, X10, V3 // d76125a6
VMADDVX V2, X10, V0, V3 // d76125a4
VNMSUBVV V2, V1, V3 // d7a120ae
VNMSUBVV V2, V1, V0, V3 // d7a120ac
VNMSUBVX V2, X10, V3 // d76125ae
VNMSUBVX V2, X10, V0, V3 // d76125ac
// 31.11.14: Vector Widening Integer Multiply-Add Instructions
VWMACCUVV V2, V1, V3 // d7a120f2
VWMACCUVV V2, V1, V0, V3 // d7a120f0
VWMACCUVX V2, X10, V3 // d76125f2
VWMACCUVX V2, X10, V0, V3 // d76125f0
VWMACCVV V2, V1, V3 // d7a120f6
VWMACCVV V2, V1, V0, V3 // d7a120f4
VWMACCVX V2, X10, V3 // d76125f6
VWMACCVX V2, X10, V0, V3 // d76125f4
VWMACCSUVV V2, V1, V3 // d7a120fe
VWMACCSUVV V2, V1, V0, V3 // d7a120fc
VWMACCSUVX V2, X10, V3 // d76125fe
VWMACCSUVX V2, X10, V0, V3 // d76125fc
VWMACCUSVX V2, X10, V3 // d76125fa
VWMACCUSVX V2, X10, V0, V3 // d76125f8
// 31.11.15: Vector Integer Merge Instructions
VMERGEVVM V1, V2, V0, V3 // d781205c
VMERGEVXM X10, V2, V0, V3 // d741255c
VMERGEVIM $15, V2, V0, V3 // d7b1275c
// 31.11.16: Vector Integer Move Instructions
VMVVV V2, V3 // d701015e
VMVVX X10, V3 // d741055e
VMVVI $15, V3 // d7b1075e
// 31.12.1: Vector Single-Width Saturating Add and Subtract
VSADDUVV V1, V2, V3 // d7812082
VSADDUVV V1, V2, V0, V3 // d7812080
VSADDUVX X10, V2, V3 // d7412582
VSADDUVX X10, V2, V0, V3 // d7412580
VSADDUVI $15, V2, V3 // d7b12782
VSADDUVI $15, V2, V0, V3 // d7b12780
VSADDVV V1, V2, V3 // d7812086
VSADDVV V1, V2, V0, V3 // d7812084
VSADDVX X10, V2, V3 // d7412586
VSADDVX X10, V2, V0, V3 // d7412584
VSADDVI $15, V2, V3 // d7b12786
VSADDVI $15, V2, V0, V3 // d7b12784
VSSUBUVV V1, V2, V3 // d781208a
VSSUBUVV V1, V2, V0, V3 // d7812088
VSSUBUVX X10, V2, V3 // d741258a
VSSUBUVX X10, V2, V0, V3 // d7412588
VSSUBVV V1, V2, V3 // d781208e
VSSUBVV V1, V2, V0, V3 // d781208c
VSSUBVX X10, V2, V3 // d741258e
VSSUBVX X10, V2, V0, V3 // d741258c
// 31.12.2: Vector Single-Width Averaging Add and Subtract
VAADDUVV V1, V2, V3 // d7a12022
VAADDUVV V1, V2, V0, V3 // d7a12020
VAADDUVX X10, V2, V3 // d7612522
VAADDUVX X10, V2, V0, V3 // d7612520
VAADDVV V1, V2, V3 // d7a12026
VAADDVV V1, V2, V0, V3 // d7a12024
VAADDVX X10, V2, V3 // d7612526
VAADDVX X10, V2, V0, V3 // d7612524
VASUBUVV V1, V2, V3 // d7a1202a
VASUBUVV V1, V2, V0, V3 // d7a12028
VASUBUVX X10, V2, V3 // d761252a
VASUBUVX X10, V2, V0, V3 // d7612528
VASUBVV V1, V2, V3 // d7a1202e
VASUBVV V1, V2, V0, V3 // d7a1202c
VASUBVX X10, V2, V3 // d761252e
VASUBVX X10, V2, V0, V3 // d761252c
// 31.12.3: Vector Single-Width Fractional Multiply with Rounding and Saturation
VSMULVV V1, V2, V3 // d781209e
VSMULVV V1, V2, V0, V3 // d781209c
VSMULVX X10, V2, V3 // d741259e
VSMULVX X10, V2, V0, V3 // d741259c
// 31.12.4: Vector Single-Width Scaling Shift Instructions
VSSRLVV V1, V2, V3 // d78120aa
VSSRLVV V1, V2, V0, V3 // d78120a8
VSSRLVX X10, V2, V3 // d74125aa
VSSRLVX X10, V2, V0, V3 // d74125a8
VSSRLVI $15, V2, V3 // d7b127aa
VSSRLVI $15, V2, V0, V3 // d7b127a8
VSSRAVV V1, V2, V3 // d78120ae
VSSRAVV V1, V2, V0, V3 // d78120ac
VSSRAVX X10, V2, V3 // d74125ae
VSSRAVX X10, V2, V0, V3 // d74125ac
VSSRAVI $16, V2, V3 // d73128ae
VSSRAVI $16, V2, V0, V3 // d73128ac
// 31.12.5: Vector Narrowing Fixed-Point Clip Instructions
VNCLIPUWV V1, V2, V3 // d78120ba
VNCLIPUWV V1, V2, V0, V3 // d78120b8
VNCLIPUWX X10, V2, V3 // d74125ba
VNCLIPUWX X10, V2, V0, V3 // d74125b8
VNCLIPUWI $16, V2, V3 // d73128ba
VNCLIPUWI $16, V2, V0, V3 // d73128b8
VNCLIPWV V1, V2, V3 // d78120be
VNCLIPWV V1, V2, V0, V3 // d78120bc
VNCLIPWX X10, V2, V3 // d74125be
VNCLIPWX X10, V2, V0, V3 // d74125bc
VNCLIPWI $16, V2, V3 // d73128be
VNCLIPWI $16, V2, V0, V3 // d73128bc
// 31.13.2: Vector Single-Width Floating-Point Add/Subtract Instructions
VFADDVV V1, V2, V3 // d7912002
VFADDVV V1, V2, V0, V3 // d7912000
VFADDVF F10, V2, V3 // d7512502
VFADDVF F10, V2, V0, V3 // d7512500
VFSUBVV V1, V2, V3 // d791200a
VFSUBVV V1, V2, V0, V3 // d7912008
VFSUBVF F10, V2, V3 // d751250a
VFSUBVF F10, V2, V0, V3 // d7512508
VFRSUBVF F10, V2, V3 // d751259e
VFRSUBVF F10, V2, V0, V3 // d751259c
// 31.13.3: Vector Widening Floating-Point Add/Subtract Instructions
VFWADDVV V1, V2, V3 // d79120c2
VFWADDVV V1, V2, V0, V3 // d79120c0
VFWADDVF F10, V2, V3 // d75125c2
VFWADDVF F10, V2, V0, V3 // d75125c0
VFWSUBVV V1, V2, V3 // d79120ca
VFWSUBVV V1, V2, V0, V3 // d79120c8
VFWSUBVF F10, V2, V3 // d75125ca
VFWSUBVF F10, V2, V0, V3 // d75125c8
VFWADDWV V1, V2, V3 // d79120d2
VFWADDWV V1, V2, V0, V3 // d79120d0
VFWADDWF F10, V2, V3 // d75125d2
VFWADDWF F10, V2, V0, V3 // d75125d0
VFWSUBWV V1, V2, V3 // d79120da
VFWSUBWV V1, V2, V0, V3 // d79120d8
VFWSUBWF F10, V2, V3 // d75125da
VFWSUBWF F10, V2, V0, V3 // d75125d8
// 31.13.4: Vector Single-Width Floating-Point Multiply/Divide Instructions
VFMULVV V1, V2, V3 // d7912092
VFMULVV V1, V2, V0, V3 // d7912090
VFMULVF F10, V2, V3 // d7512592
VFMULVF F10, V2, V0, V3 // d7512590
VFDIVVV V1, V2, V3 // d7912082
VFDIVVV V1, V2, V0, V3 // d7912080
VFDIVVF F10, V2, V3 // d7512582
VFDIVVF F10, V2, V0, V3 // d7512580
VFRDIVVF F10, V2, V3 // d7512586
VFRDIVVF F10, V2, V0, V3 // d7512584
// 31.13.5: Vector Widening Floating-Point Multiply
VFWMULVV V1, V2, V3 // d79120e2
VFWMULVV V1, V2, V0, V3 // d79120e0
VFWMULVF F10, V2, V3 // d75125e2
VFWMULVF F10, V2, V0, V3 // d75125e0
// 31.13.6: Vector Single-Width Floating-Point Fused Multiply-Add Instructions
VFMACCVV V2, V1, V3 // d79120b2
VFMACCVV V2, V1, V0, V3 // d79120b0
VFMACCVF V2, F10, V3 // d75125b2
VFMACCVF V2, F10, V0, V3 // d75125b0
VFNMACCVV V2, V1, V3 // d79120b6
VFNMACCVV V2, V1, V0, V3 // d79120b4
VFNMACCVF V2, F10, V3 // d75125b6
VFNMACCVF V2, F10, V0, V3 // d75125b4
VFMSACVV V2, V1, V3 // d79120ba
VFMSACVV V2, V1, V0, V3 // d79120b8
VFMSACVF V2, F10, V3 // d75125ba
VFMSACVF V2, F10, V0, V3 // d75125b8
VFNMSACVV V2, V1, V3 // d79120be
VFNMSACVV V2, V1, V0, V3 // d79120bc
VFNMSACVF V2, F10, V3 // d75125be
VFNMSACVF V2, F10, V0, V3 // d75125bc
VFMADDVV V2, V1, V3 // d79120a2
VFMADDVV V2, V1, V0, V3 // d79120a0
VFMADDVF V2, F10, V3 // d75125a2
VFMADDVF V2, F10, V0, V3 // d75125a0
VFNMADDVV V2, V1, V3 // d79120a6
VFNMADDVV V2, V1, V0, V3 // d79120a4
VFNMADDVF V2, F10, V3 // d75125a6
VFNMADDVF V2, F10, V0, V3 // d75125a4
VFMSUBVV V2, V1, V3 // d79120aa
VFMSUBVV V2, V1, V0, V3 // d79120a8
VFMSUBVF V2, F10, V3 // d75125aa
VFMSUBVF V2, F10, V0, V3 // d75125a8
VFNMSUBVV V2, V1, V3 // d79120ae
VFNMSUBVV V2, V1, V0, V3 // d79120ac
VFNMSUBVF V2, F10, V3 // d75125ae
VFNMSUBVF V2, F10, V0, V3 // d75125ac
// 31.13.7: Vector Widening Floating-Point Fused Multiply-Add Instructions
VFWMACCVV V2, V1, V3 // d79120f2
VFWMACCVV V2, V1, V0, V3 // d79120f0
VFWMACCVF V2, F10, V3 // d75125f2
VFWMACCVF V2, F10, V0, V3 // d75125f0
VFWNMACCVV V2, V1, V3 // d79120f6
VFWNMACCVV V2, V1, V0, V3 // d79120f4
VFWNMACCVF V2, F10, V3 // d75125f6
VFWNMACCVF V2, F10, V0, V3 // d75125f4
VFWMSACVV V2, V1, V3 // d79120fa
VFWMSACVV V2, V1, V0, V3 // d79120f8
VFWMSACVF V2, F10, V3 // d75125fa
VFWMSACVF V2, F10, V0, V3 // d75125f8
VFWNMSACVV V2, V1, V3 // d79120fe
VFWNMSACVV V2, V1, V0, V3 // d79120fc
VFWNMSACVF V2, F10, V3 // d75125fe
VFWNMSACVF V2, F10, V0, V3 // d75125fc
// 31.13.8: Vector Floating-Point Square-Root Instruction
VFSQRTV V2, V3 // d711204e
VFSQRTV V2, V0, V3 // d711204c
// 31.13.9: Vector Floating-Point Reciprocal Square-Root Estimate Instruction
VFRSQRT7V V2, V3 // d711224e
VFRSQRT7V V2, V0, V3 // d711224c
// 31.13.10: Vector Floating-Point Reciprocal Estimate Instruction
VFREC7V V2, V3 // d791224e
VFREC7V V2, V0, V3 // d791224c
// 31.13.11: Vector Floating-Point MIN/MAX Instructions
VFMINVV V1, V2, V3 // d7912012
VFMINVV V1, V2, V0, V3 // d7912010
VFMINVF F10, V2, V3 // d7512512
VFMINVF F10, V2, V0, V3 // d7512510
VFMAXVV V1, V2, V3 // d791201a
VFMAXVV V1, V2, V0, V3 // d7912018
VFMAXVF F10, V2, V3 // d751251a
VFMAXVF F10, V2, V0, V3 // d7512518
// 31.13.12: Vector Floating-Point Sign-Injection Instructions
VFSGNJVV V1, V2, V3 // d7912022
VFSGNJVV V1, V2, V0, V3 // d7912020
VFSGNJVF F10, V2, V3 // d7512522
VFSGNJVF F10, V2, V0, V3 // d7512520
VFSGNJNVV V1, V2, V3 // d7912026
VFSGNJNVV V1, V2, V0, V3 // d7912024
VFSGNJNVF F10, V2, V3 // d7512526
VFSGNJNVF F10, V2, V0, V3 // d7512524
VFSGNJXVV V1, V2, V3 // d791202a
VFSGNJXVV V1, V2, V0, V3 // d7912028
VFSGNJXVF F10, V2, V3 // d751252a
VFSGNJXVF F10, V2, V0, V3 // d7512528
VFNEGV V2, V3 // d7112126
VFNEGV V2, V0, V3 // d7112124
VFABSV V2, V3 // d711212a
VFABSV V2, V0, V3 // d7112128
// 31.13.13: Vector Floating-Point Compare Instructions
VMFEQVV V1, V2, V3 // d7912062
VMFEQVV V1, V2, V0, V3 // d7912060
VMFEQVF F10, V2, V3 // d7512562
VMFEQVF F10, V2, V0, V3 // d7512560
VMFNEVV V1, V2, V3 // d7912072
VMFNEVV V1, V2, V0, V3 // d7912070
VMFNEVF F10, V2, V3 // d7512572
VMFNEVF F10, V2, V0, V3 // d7512570
VMFLTVV V1, V2, V3 // d791206e
VMFLTVV V1, V2, V0, V3 // d791206c
VMFLTVF F10, V2, V3 // d751256e
VMFLTVF F10, V2, V0, V3 // d751256c
VMFLEVV V1, V2, V3 // d7912066
VMFLEVV V1, V2, V0, V3 // d7912064
VMFLEVF F10, V2, V3 // d7512566
VMFLEVF F10, V2, V0, V3 // d7512564
VMFGTVF F10, V2, V3 // d7512576
VMFGTVF F10, V2, V0, V3 // d7512574
VMFGEVF F10, V2, V3 // d751257e
VMFGEVF F10, V2, V0, V3 // d751257c
VMFGTVV V1, V2, V3 // d711116e
VMFGTVV V1, V2, V0, V3 // d711116c
VMFGEVV V1, V2, V3 // d7111166
VMFGEVV V1, V2, V0, V3 // d7111164
// 31.13.14: Vector Floating-Point Classify Instruction
VFCLASSV V2, V3 // d711284e
VFCLASSV V2, V0, V3 // d711284c
// 31.13.15: Vector Floating-Point Merge Instruction
VFMERGEVFM F10, V2, V0, V3 // d751255c
// 31.13.16: Vector Floating-Point Move Instruction
VFMVVF F10, V3 // d751055e
// 31.13.17: Single-Width Floating-Point/Integer Type-Convert Instructions
VFCVTXUFV V2, V3 // d711204a
VFCVTXUFV V2, V0, V3 // d7112048
VFCVTXFV V2, V3 // d791204a
VFCVTXFV V2, V0, V3 // d7912048
VFCVTRTZXUFV V2, V3 // d711234a
VFCVTRTZXUFV V2, V0, V3 // d7112348
VFCVTRTZXFV V2, V3 // d791234a
VFCVTRTZXFV V2, V0, V3 // d7912348
VFCVTFXUV V2, V3 // d711214a
VFCVTFXUV V2, V0, V3 // d7112148
VFCVTFXV V2, V3 // d791214a
VFCVTFXV V2, V0, V3 // d7912148
// 31.13.18: Widening Floating-Point/Integer Type-Convert Instructions
VFWCVTXUFV V2, V3 // d711244a
VFWCVTXUFV V2, V0, V3 // d7112448
VFWCVTXFV V2, V3 // d791244a
VFWCVTXFV V2, V0, V3 // d7912448
VFWCVTRTZXUFV V2, V3 // d711274a
VFWCVTRTZXUFV V2, V0, V3 // d7112748
VFWCVTRTZXFV V2, V3 // d791274a
VFWCVTRTZXFV V2, V0, V3 // d7912748
VFWCVTFXUV V2, V3 // d711254a
VFWCVTFXUV V2, V0, V3 // d7112548
VFWCVTFXV V2, V3 // d791254a
VFWCVTFXV V2, V0, V3 // d7912548
VFWCVTFFV V2, V3 // d711264a
VFWCVTFFV V2, V0, V3 // d7112648
// 31.13.19: Narrowing Floating-Point/Integer Type-Convert Instructions
VFNCVTXUFW V2, V3 // d711284a
VFNCVTXUFW V2, V0, V3 // d7112848
VFNCVTXFW V2, V3 // d791284a
VFNCVTXFW V2, V0, V3 // d7912848
VFNCVTRTZXUFW V2, V3 // d7112b4a
VFNCVTRTZXUFW V2, V0, V3 // d7112b48
VFNCVTRTZXFW V2, V3 // d7912b4a
VFNCVTRTZXFW V2, V0, V3 // d7912b48
VFNCVTFXUW V2, V3 // d711294a
VFNCVTFXUW V2, V0, V3 // d7112948
VFNCVTFXW V2, V3 // d791294a
VFNCVTFXW V2, V0, V3 // d7912948
VFNCVTFFW V2, V3 // d7112a4a
VFNCVTFFW V2, V0, V3 // d7112a48
VFNCVTRODFFW V2, V3 // d7912a4a
VFNCVTRODFFW V2, V0, V3 // d7912a48
// 31.14.1: Vector Single-Width Integer Reduction Instructions
VREDSUMVS V1, V2, V3 // d7a12002
VREDSUMVS V1, V2, V0, V3 // d7a12000
VREDMAXUVS V1, V2, V3 // d7a1201a
VREDMAXUVS V1, V2, V0, V3 // d7a12018
VREDMAXVS V1, V2, V3 // d7a1201e
VREDMAXVS V1, V2, V0, V3 // d7a1201c
VREDMINUVS V1, V2, V3 // d7a12012
VREDMINUVS V1, V2, V0, V3 // d7a12010
VREDMINVS V1, V2, V3 // d7a12016
VREDMINVS V1, V2, V0, V3 // d7a12014
VREDANDVS V1, V2, V3 // d7a12006
VREDANDVS V1, V2, V0, V3 // d7a12004
VREDORVS V1, V2, V3 // d7a1200a
VREDORVS V1, V2, V0, V3 // d7a12008
VREDXORVS V1, V2, V3 // d7a1200e
VREDXORVS V1, V2, V0, V3 // d7a1200c
// 31.14.2: Vector Widening Integer Reduction Instructions
VWREDSUMUVS V1, V2, V3 // d78120c2
VWREDSUMUVS V1, V2, V0, V3 // d78120c0
VWREDSUMVS V1, V2, V3 // d78120c6
VWREDSUMVS V1, V2, V0, V3 // d78120c4
// 31.14.3: Vector Single-Width Floating-Point Reduction Instructions
VFREDOSUMVS V1, V2, V3 // d791200e
VFREDOSUMVS V1, V2, V0, V3 // d791200c
VFREDUSUMVS V1, V2, V3 // d7912006
VFREDUSUMVS V1, V2, V0, V3 // d7912004
VFREDMAXVS V1, V2, V3 // d791201e
VFREDMAXVS V1, V2, V0, V3 // d791201c
VFREDMINVS V1, V2, V3 // d7912016
VFREDMINVS V1, V2, V0, V3 // d7912014
// 31.14.4: Vector Widening Floating-Point Reduction Instructions
VFWREDOSUMVS V1, V2, V3 // d79120ce
VFWREDOSUMVS V1, V2, V0, V3 // d79120cc
VFWREDUSUMVS V1, V2, V3 // d79120c6
VFWREDUSUMVS V1, V2, V0, V3 // d79120c4
// 31.15: Vector Mask Instructions
VMANDMM V1, V2, V3 // d7a12066
VMNANDMM V1, V2, V3 // d7a12076
VMANDNMM V1, V2, V3 // d7a12062
VMXORMM V1, V2, V3 // d7a1206e
VMORMM V1, V2, V3 // d7a1206a
VMNORMM V1, V2, V3 // d7a1207a
VMORNMM V1, V2, V3 // d7a12072
VMXNORMM V1, V2, V3 // d7a1207e
VMMVM V2, V3 // d7212166
VMCLRM V3 // d7a1316e
VMSETM V3 // d7a1317e
VMNOTM V2, V3 // d7212176
VCPOPM V2, X10 // 57252842
VCPOPM V2, V0, X10 // 57252840
VFIRSTM V2, X10 // 57a52842
VFIRSTM V2, V0, X10 // 57a52840
VMSBFM V2, V3 // d7a12052
VMSBFM V2, V0, V3 // d7a12050
VMSIFM V2, V3 // d7a12152
VMSIFM V2, V0, V3 // d7a12150
VMSOFM V2, V3 // d7212152
VMSOFM V2, V0, V3 // d7212150
VIOTAM V2, V3 // d7212852
VIOTAM V2, V0, V3 // d7212850
VIDV V3 // d7a10852
VIDV V0, V3 // d7a10850
// 31.16.1: Integer Scalar Move Instructions
VMVXS V2, X10 // 57252042
VMVSX X10, V2 // 57610542
// 31.16.2: Floating-Point Scalar Move Instructions
VFMVFS V2, F10 // 57152042
VFMVSF F10, V2 // 57510542
// 31.16.3: Vector Slide Instructions
VSLIDEUPVX X10, V2, V3 // d741253a
VSLIDEUPVX X10, V2, V0, V3 // d7412538
VSLIDEUPVI $16, V2, V3 // d731283a
VSLIDEUPVI $16, V2, V0, V3 // d7312838
VSLIDEDOWNVX X10, V2, V3 // d741253e
VSLIDEDOWNVX X10, V2, V0, V3 // d741253c
VSLIDEDOWNVI $16, V2, V3 // d731283e
VSLIDEDOWNVI $16, V2, V0, V3 // d731283c
VSLIDE1UPVX X10, V2, V3 // d761253a
VSLIDE1UPVX X10, V2, V0, V3 // d7612538
VFSLIDE1UPVF F10, V2, V3 // d751253a
VFSLIDE1UPVF F10, V2, V0, V3 // d7512538
VSLIDE1DOWNVX X10, V2, V3 // d761253e
VSLIDE1DOWNVX X10, V2, V0, V3 // d761253c
VFSLIDE1DOWNVF F10, V2, V3 // d751253e
VFSLIDE1DOWNVF F10, V2, V0, V3 // d751253c
// 31.16.4: Vector Register Gather Instructions
VRGATHERVV V1, V2, V3 // d7812032
VRGATHERVV V1, V2, V0, V3 // d7812030
VRGATHEREI16VV V1, V2, V3 // d781203a
VRGATHEREI16VV V1, V2, V0, V3 // d7812038
VRGATHERVX X10, V2, V3 // d7412532
VRGATHERVX X10, V2, V0, V3 // d7412530
VRGATHERVI $16, V2, V3 // d7312832
VRGATHERVI $16, V2, V0, V3 // d7312830
// 31.16.5: Vector Compress Instruction
VCOMPRESSVM V1, V2, V3 // d7a1205e
// 31.16.6: Whole Vector Register Move
VMV1RV V2, V1 // d730209e
VMV2RV V12, V10 // 57b5c09e
VMV4RV V8, V4 // 57b2819e
VMV8RV V8, V0 // 57b0839e
// 33.2.1: Vector Basic Bit-manipulation (Zvbb)
VANDNVV V1, V2, V3 // d7812006
VANDNVV V1, V2, V0, V3 // d7812004
VANDNVX X10, V2, V3 // d7412506
VANDNVX X10, V2, V0, V3 // d7412504
VBREVV V2, V3 // d721254a
VBREVV V2, V0, V3 // d7212548
VBREV8V V2, V3 // d721244a
VBREV8V V2, V0, V3 // d7212448
VREV8V V2, V3 // d7a1244a
VREV8V V2, V0, V3 // d7a12448
VCLZV V2, V3 // d721264a
VCLZV V2, V0, V3 // d7212648
VCTZV V2, V3 // d7a1264a
VCTZV V2, V0, V3 // d7a12648
VCPOPV V2, V3 // d721274a
VCPOPV V2, V0, V3 // d7212748
VROLVV V1, V2, V3 // d7812056
VROLVV V1, V2, V0, V3 // d7812054
VROLVX X10, V2, V3 // d7412556
VROLVX X10, V2, V0, V3 // d7412554
VRORVV V1, V2, V3 // d7812052
VRORVV V1, V2, V0, V3 // d7812050
VRORVX X10, V2, V3 // d7412552
VRORVX X10, V2, V0, V3 // d7412550
VRORVI $16, V2, V3 // d7312852
VRORVI $16, V2, V0, V3 // d7312850
VWSLLVV V1, V2, V3 // d78120d6
VWSLLVV V1, V2, V0, V3 // d78120d4
VWSLLVX X10, V2, V3 // d74125d6
VWSLLVX X10, V2, V0, V3 // d74125d4
VWSLLVI $16, V2, V3 // d73128d6
VWSLLVI $16, V2, V0, V3 // d73128d4
// 33.2.2: Vector Carryless Multiplication (Zvbc)
VCLMULVV V1, V2, V3 // d7a12032
VCLMULVV V1, V2, V0, V3 // d7a12030
VCLMULVX X10, V2, V3 // d7612532
VCLMULVX X10, V2, V0, V3 // d7612530
VCLMULHVV V1, V2, V3 // d7a12036
VCLMULHVV V1, V2, V0, V3 // d7a12034
VCLMULHVX X10, V2, V3 // d7612536
VCLMULHVX X10, V2, V0, V3 // d7612534
RET
`
dir := t.TempDir()
path := filepath.Join(dir, "vecarith_riscv64.s")
if err := os.WriteFile(path, []byte(src), 0o644); err != nil {
t.Fatal(err)
}
assertRISCVDifferential(t, path, src, "vecarith")
}