diff --git a/asm/riscv_assemble.go b/asm/riscv_assemble.go index 9d9c59d..0760e01 100644 --- a/asm/riscv_assemble.go +++ b/asm/riscv_assemble.go @@ -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 diff --git a/asm/riscv_encode.go b/asm/riscv_encode.go index b4d7e2b..a8b4f6f 100644 --- a/asm/riscv_encode.go +++ b/asm/riscv_encode.go @@ -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 diff --git a/asm/riscv_vecarith_test.go b/asm/riscv_vecarith_test.go new file mode 100644 index 0000000..a3c70a8 --- /dev/null +++ b/asm/riscv_vecarith_test.go @@ -0,0 +1,812 @@ +// Copyright (c) 2026 Petr Balvín (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") +}