2026-10-02 17:58:55 +02:00
|
|
|
// Copyright (c) 2026 Petr Balvín <opensource@petrbalvin.org> (https://petrbalvin.org)
|
|
|
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
|
|
|
|
|
|
package arch
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"encoding/hex"
|
|
|
|
|
"strings"
|
|
|
|
|
"testing"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// The SVE encodings have no toolchain oracle: go tool asm knows no SVE at
|
|
|
|
|
// all. The golden words below are therefore transcribed from the ARM
|
|
|
|
|
// Architecture Reference Manual (DDI 0487J, Part C, Chapter C8, the
|
|
|
|
|
// alphabetical list of SVE instructions) and cross-checked against two
|
|
|
|
|
// independent implementations of the manual, the GNU assembler and LLVM:
|
|
|
|
|
// the rows marked "GNU" match a vector in binutils-gdb's own
|
|
|
|
|
// gas/testsuite/gas/aarch64/sve.d (assembled under -march=armv8-a+sve), the
|
|
|
|
|
// rows marked "LLVM" match the Inst field assignments in
|
|
|
|
|
// SVEInstrFormats.td's sve_int_bin_cons_arit_0, sve_int_bin_pred_arit_log,
|
|
|
|
|
// sve_int_arith_imm0 and sve2_int_mul classes. Every class is covered by at
|
|
|
|
|
// least one vector of each source.
|
|
|
|
|
func extInstruction(t *testing.T, mnem string, form ExtForm) ExtInstr {
|
|
|
|
|
t.Helper()
|
|
|
|
|
for _, in := range Extensions(ARM64) {
|
|
|
|
|
if in.Name == mnem && in.Form == form {
|
|
|
|
|
return in
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
t.Fatalf("no extended %s with the %s form", mnem, form)
|
|
|
|
|
return ExtInstr{}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestArm64ExtGoldenBytes(t *testing.T) {
|
|
|
|
|
for _, tt := range []struct {
|
|
|
|
|
name string
|
|
|
|
|
mnem string
|
|
|
|
|
form ExtForm
|
|
|
|
|
ops []ExtOperand
|
|
|
|
|
want uint32
|
|
|
|
|
GNUas string // the matching binutils-gdb sve.d line, empty when the class evidence comes from LLVM alone
|
|
|
|
|
}{
|
|
|
|
|
// Unpredicated three-vector forms: Zn, Zm, Zd.
|
|
|
|
|
{"add z0.b, z0.b, z0.b", "ADD", ExtFormVectors,
|
|
|
|
|
[]ExtOperand{ExtVector(0, ExtArrB), ExtVector(0, ExtArrB), ExtVector(0, ExtArrB)},
|
|
|
|
|
0x04200000, "04200000 add z0.b, z0.b, z0.b"},
|
|
|
|
|
{"add z0.b, z0.b, z31.b", "ADD", ExtFormVectors,
|
|
|
|
|
[]ExtOperand{ExtVector(0, ExtArrB), ExtVector(31, ExtArrB), ExtVector(0, ExtArrB)},
|
|
|
|
|
0x043f0000, "043f0000 add z0.b, z0.b, z31.b"},
|
|
|
|
|
{"add z31.b, z0.b, z0.b", "ADD", ExtFormVectors,
|
|
|
|
|
[]ExtOperand{ExtVector(0, ExtArrB), ExtVector(0, ExtArrB), ExtVector(31, ExtArrB)},
|
|
|
|
|
0x0420001f, "0420001f add z31.b, z0.b, z0.b"},
|
|
|
|
|
{"add z0.b, z2.b, z0.b", "ADD", ExtFormVectors,
|
|
|
|
|
[]ExtOperand{ExtVector(2, ExtArrB), ExtVector(0, ExtArrB), ExtVector(0, ExtArrB)},
|
|
|
|
|
0x04200040, "04200040 add z0.b, z2.b, z0.b"},
|
|
|
|
|
{"add z0.h, z0.h, z0.h", "ADD", ExtFormVectors,
|
|
|
|
|
[]ExtOperand{ExtVector(0, ExtArrH), ExtVector(0, ExtArrH), ExtVector(0, ExtArrH)},
|
|
|
|
|
0x04600000, "04600000 add z0.h, z0.h, z0.h"},
|
|
|
|
|
{"add z0.s, z0.s, z0.s", "ADD", ExtFormVectors,
|
|
|
|
|
[]ExtOperand{ExtVector(0, ExtArrS), ExtVector(0, ExtArrS), ExtVector(0, ExtArrS)},
|
|
|
|
|
0x04a00000, "04a00000 add z0.s, z0.s, z0.s"},
|
|
|
|
|
{"add z0.d, z0.d, z0.d", "ADD", ExtFormVectors,
|
|
|
|
|
[]ExtOperand{ExtVector(0, ExtArrD), ExtVector(0, ExtArrD), ExtVector(0, ExtArrD)},
|
|
|
|
|
0x04e00000, "04e00000 add z0.d, z0.d, z0.d"},
|
|
|
|
|
{"sub z0.b, z0.b, z0.b", "SUB", ExtFormVectors,
|
|
|
|
|
[]ExtOperand{ExtVector(0, ExtArrB), ExtVector(0, ExtArrB), ExtVector(0, ExtArrB)},
|
|
|
|
|
0x04200400, "04200400 sub z0.b, z0.b, z0.b"},
|
|
|
|
|
{"sub z0.b, z0.b, z3.b", "SUB", ExtFormVectors,
|
|
|
|
|
[]ExtOperand{ExtVector(0, ExtArrB), ExtVector(3, ExtArrB), ExtVector(0, ExtArrB)},
|
|
|
|
|
0x04230400, "04230400 sub z0.b, z0.b, z3.b"},
|
|
|
|
|
{"sqadd z0.b, z0.b, z0.b", "SQADD", ExtFormVectors,
|
|
|
|
|
[]ExtOperand{ExtVector(0, ExtArrB), ExtVector(0, ExtArrB), ExtVector(0, ExtArrB)},
|
|
|
|
|
0x04201000, "04201000 sqadd z0.b, z0.b, z0.b"},
|
|
|
|
|
{"sqadd z0.b, z0.b, z3.b", "SQADD", ExtFormVectors,
|
|
|
|
|
[]ExtOperand{ExtVector(0, ExtArrB), ExtVector(3, ExtArrB), ExtVector(0, ExtArrB)},
|
|
|
|
|
0x04231000, "04231000 sqadd z0.b, z0.b, z3.b"},
|
|
|
|
|
{"sqadd z0.d, z0.d, z0.d", "SQADD", ExtFormVectors,
|
|
|
|
|
[]ExtOperand{ExtVector(0, ExtArrD), ExtVector(0, ExtArrD), ExtVector(0, ExtArrD)},
|
|
|
|
|
0x04e01000, "04e01000 sqadd z0.d, z0.d, z0.d"},
|
|
|
|
|
{"uqadd z0.b, z0.b, z0.b", "UQADD", ExtFormVectors,
|
|
|
|
|
[]ExtOperand{ExtVector(0, ExtArrB), ExtVector(0, ExtArrB), ExtVector(0, ExtArrB)},
|
|
|
|
|
0x04201400, "04201400 uqadd z0.b, z0.b, z0.b"},
|
|
|
|
|
{"sqsub z0.b, z0.b, z0.b", "SQSUB", ExtFormVectors,
|
|
|
|
|
[]ExtOperand{ExtVector(0, ExtArrB), ExtVector(0, ExtArrB), ExtVector(0, ExtArrB)},
|
|
|
|
|
0x04201800, "04201800 sqsub z0.b, z0.b, z0.b"},
|
|
|
|
|
{"sqsub z0.h, z0.h, z0.h", "SQSUB", ExtFormVectors,
|
|
|
|
|
[]ExtOperand{ExtVector(0, ExtArrH), ExtVector(0, ExtArrH), ExtVector(0, ExtArrH)},
|
|
|
|
|
0x04601800, "04601800 sqsub z0.h, z0.h, z0.h"},
|
|
|
|
|
{"uqsub z0.b, z0.b, z0.b", "UQSUB", ExtFormVectors,
|
|
|
|
|
[]ExtOperand{ExtVector(0, ExtArrB), ExtVector(0, ExtArrB), ExtVector(0, ExtArrB)},
|
|
|
|
|
0x04201c00, "04201c00 uqsub z0.b, z0.b, z0.b"},
|
|
|
|
|
{"mul z0.b, z0.b, z0.b (sve2)", "MUL", ExtFormVectors,
|
|
|
|
|
[]ExtOperand{ExtVector(0, ExtArrB), ExtVector(0, ExtArrB), ExtVector(0, ExtArrB)},
|
|
|
|
|
0x04206000, "04206000 mul z0.b, z0.b, z0.b"},
|
|
|
|
|
{"mul z17.b, z21.b, z27.b (sve2)", "MUL", ExtFormVectors,
|
|
|
|
|
[]ExtOperand{ExtVector(21, ExtArrB), ExtVector(27, ExtArrB), ExtVector(17, ExtArrB)},
|
|
|
|
|
0x043b62b1, "043b62b1 mul z17.b, z21.b, z27.b"},
|
|
|
|
|
{"mul z0.d, z0.d, z0.d (sve2)", "MUL", ExtFormVectors,
|
|
|
|
|
[]ExtOperand{ExtVector(0, ExtArrD), ExtVector(0, ExtArrD), ExtVector(0, ExtArrD)},
|
|
|
|
|
0x04e06000, "04e06000 mul z0.d, z0.d, z0.d"},
|
|
|
|
|
{"smulh z0.b, z0.b, z0.b (sve2)", "SMULH", ExtFormVectors,
|
|
|
|
|
[]ExtOperand{ExtVector(0, ExtArrB), ExtVector(0, ExtArrB), ExtVector(0, ExtArrB)},
|
|
|
|
|
0x04206800, "04206800 smulh z0.b, z0.b, z0.b"},
|
|
|
|
|
{"smulh z17.b, z21.b, z27.b (sve2)", "SMULH", ExtFormVectors,
|
|
|
|
|
[]ExtOperand{ExtVector(21, ExtArrB), ExtVector(27, ExtArrB), ExtVector(17, ExtArrB)},
|
|
|
|
|
0x043b6ab1, "043b6ab1 smulh z17.b, z21.b, z27.b"},
|
|
|
|
|
{"umulh z0.b, z0.b, z0.b (sve2)", "UMULH", ExtFormVectors,
|
|
|
|
|
[]ExtOperand{ExtVector(0, ExtArrB), ExtVector(0, ExtArrB), ExtVector(0, ExtArrB)},
|
|
|
|
|
0x04206c00, "04206c00 umulh z0.b, z0.b, z0.b"},
|
|
|
|
|
{"umulh z17.b, z21.b, z27.b (sve2)", "UMULH", ExtFormVectors,
|
|
|
|
|
[]ExtOperand{ExtVector(21, ExtArrB), ExtVector(27, ExtArrB), ExtVector(17, ExtArrB)},
|
|
|
|
|
0x043b6eb1, "043b6eb1 umulh z17.b, z21.b, z27.b"},
|
|
|
|
|
|
|
|
|
|
// Governed destructive forms, merging: Zm, Pg/M, Zdn.
|
|
|
|
|
{"add z0.b, p0/m, z0.b", "ADD", ExtFormPredicated,
|
|
|
|
|
[]ExtOperand{ExtVector(0, ExtArrB), ExtPredicate(0, ExtQualMerging), ExtVector(0, ExtArrB)},
|
|
|
|
|
0x04000000, "04000000 add z0.b, p0/m, z0.b, z0.b"},
|
|
|
|
|
{"add z0.b, p2/m, z0.b", "ADD", ExtFormPredicated,
|
|
|
|
|
[]ExtOperand{ExtVector(0, ExtArrB), ExtPredicate(2, ExtQualMerging), ExtVector(0, ExtArrB)},
|
|
|
|
|
0x04000800, "04000800 add z0.b, p2/m, z0.b, z0.b"},
|
|
|
|
|
{"add z0.b, p7/m, z0.b", "ADD", ExtFormPredicated,
|
|
|
|
|
[]ExtOperand{ExtVector(0, ExtArrB), ExtPredicate(7, ExtQualMerging), ExtVector(0, ExtArrB)},
|
|
|
|
|
0x04001c00, "04001c00 add z0.b, p7/m, z0.b, z0.b"},
|
|
|
|
|
{"add z31.b, p0/m, z31.b", "ADD", ExtFormPredicated,
|
|
|
|
|
[]ExtOperand{ExtVector(0, ExtArrB), ExtPredicate(0, ExtQualMerging), ExtVector(31, ExtArrB)},
|
|
|
|
|
0x0400001f, "0400001f add z31.b, p0/m, z31.b, z0.b"},
|
|
|
|
|
{"add z0.b, p0/m, z0.b (zm 31)", "ADD", ExtFormPredicated,
|
|
|
|
|
[]ExtOperand{ExtVector(31, ExtArrB), ExtPredicate(0, ExtQualMerging), ExtVector(0, ExtArrB)},
|
|
|
|
|
0x040003e0, "040003e0 add z0.b, p0/m, z0.b, z31.b"},
|
|
|
|
|
{"add z0.s, p0/m, z0.s", "ADD", ExtFormPredicated,
|
|
|
|
|
[]ExtOperand{ExtVector(0, ExtArrS), ExtPredicate(0, ExtQualMerging), ExtVector(0, ExtArrS)},
|
|
|
|
|
0x04800000, "04800000 add z0.s, p0/m, z0.s, z0.s"},
|
|
|
|
|
{"sub z0.b, p0/m, z0.b", "SUB", ExtFormPredicated,
|
|
|
|
|
[]ExtOperand{ExtVector(0, ExtArrB), ExtPredicate(0, ExtQualMerging), ExtVector(0, ExtArrB)},
|
|
|
|
|
0x04010000, "04010000 sub z0.b, p0/m, z0.b, z0.b"},
|
|
|
|
|
{"sub z0.b, p7/m, z0.b", "SUB", ExtFormPredicated,
|
|
|
|
|
[]ExtOperand{ExtVector(0, ExtArrB), ExtPredicate(7, ExtQualMerging), ExtVector(0, ExtArrB)},
|
|
|
|
|
0x04011c00, "04011c00 sub z0.b, p7/m, z0.b, z0.b"},
|
|
|
|
|
{"sub z3.b, p0/m, z3.b", "SUB", ExtFormPredicated,
|
|
|
|
|
[]ExtOperand{ExtVector(0, ExtArrB), ExtPredicate(0, ExtQualMerging), ExtVector(3, ExtArrB)},
|
|
|
|
|
0x04010003, "04010003 sub z3.b, p0/m, z3.b, z0.b"},
|
|
|
|
|
{"subr z0.b, p0/m, z0.b", "SUBR", ExtFormPredicated,
|
|
|
|
|
[]ExtOperand{ExtVector(0, ExtArrB), ExtPredicate(0, ExtQualMerging), ExtVector(0, ExtArrB)},
|
|
|
|
|
0x04030000, "04030000 subr z0.b, p0/m, z0.b, z0.b"},
|
|
|
|
|
{"subr z0.h, p0/m, z0.h", "SUBR", ExtFormPredicated,
|
|
|
|
|
[]ExtOperand{ExtVector(0, ExtArrH), ExtPredicate(0, ExtQualMerging), ExtVector(0, ExtArrH)},
|
|
|
|
|
0x04430000, "04430000 subr z0.h, p0/m, z0.h, z0.h"},
|
|
|
|
|
{"mul z0.b, p0/m, z0.b", "MUL", ExtFormPredicated,
|
|
|
|
|
[]ExtOperand{ExtVector(0, ExtArrB), ExtPredicate(0, ExtQualMerging), ExtVector(0, ExtArrB)},
|
|
|
|
|
0x04100000, "04100000 mul z0.b, p0/m, z0.b, z0.b"},
|
|
|
|
|
{"mul z0.b, p2/m, z0.b", "MUL", ExtFormPredicated,
|
|
|
|
|
[]ExtOperand{ExtVector(0, ExtArrB), ExtPredicate(2, ExtQualMerging), ExtVector(0, ExtArrB)},
|
|
|
|
|
0x04100800, "04100800 mul z0.b, p2/m, z0.b, z0.b"},
|
|
|
|
|
{"mul z0.b, p0/m, z0.b (zm 31)", "MUL", ExtFormPredicated,
|
|
|
|
|
[]ExtOperand{ExtVector(31, ExtArrB), ExtPredicate(0, ExtQualMerging), ExtVector(0, ExtArrB)},
|
|
|
|
|
0x041003e0, "041003e0 mul z0.b, p0/m, z0.b, z31.b"},
|
|
|
|
|
{"smulh z0.b, p0/m, z0.b", "SMULH", ExtFormPredicated,
|
|
|
|
|
[]ExtOperand{ExtVector(0, ExtArrB), ExtPredicate(0, ExtQualMerging), ExtVector(0, ExtArrB)},
|
|
|
|
|
0x04120000, "04120000 smulh z0.b, p0/m, z0.b, z0.b"},
|
|
|
|
|
{"smulh z0.b, p2/m, z0.b", "SMULH", ExtFormPredicated,
|
|
|
|
|
[]ExtOperand{ExtVector(0, ExtArrB), ExtPredicate(2, ExtQualMerging), ExtVector(0, ExtArrB)},
|
|
|
|
|
0x04120800, "04120800 smulh z0.b, p2/m, z0.b, z0.b"},
|
|
|
|
|
{"smulh z0.s, p0/m, z0.s", "SMULH", ExtFormPredicated,
|
|
|
|
|
[]ExtOperand{ExtVector(0, ExtArrS), ExtPredicate(0, ExtQualMerging), ExtVector(0, ExtArrS)},
|
|
|
|
|
0x04920000, "04920000 smulh z0.s, p0/m, z0.s, z0.s"},
|
|
|
|
|
{"umulh z0.b, p0/m, z0.b", "UMULH", ExtFormPredicated,
|
|
|
|
|
[]ExtOperand{ExtVector(0, ExtArrB), ExtPredicate(0, ExtQualMerging), ExtVector(0, ExtArrB)},
|
|
|
|
|
0x04130000, "04130000 umulh z0.b, p0/m, z0.b, z0.b"},
|
|
|
|
|
|
|
|
|
|
// Immediate forms: imm{, LSL #8}, Zdn.
|
|
|
|
|
{"add z0.b, z0.b, #0", "ADD", ExtFormImmediate,
|
|
|
|
|
[]ExtOperand{ExtImmediate(0), ExtVector(0, ExtArrB)},
|
|
|
|
|
0x2520c000, "2520c000 add z0.b, z0.b, #0"},
|
|
|
|
|
{"add z0.b, z0.b, #127", "ADD", ExtFormImmediate,
|
|
|
|
|
[]ExtOperand{ExtImmediate(127), ExtVector(0, ExtArrB)},
|
|
|
|
|
0x2520cfe0, "2520cfe0 add z0.b, z0.b, #127"},
|
|
|
|
|
{"add z0.h, z0.h, #0, lsl #8", "ADD", ExtFormImmediate,
|
|
|
|
|
[]ExtOperand{ExtShiftedImmediate(0, 8), ExtVector(0, ExtArrH)},
|
|
|
|
|
0x2560e000, "2560e000 add z0.h, z0.h, #0, lsl #8"},
|
|
|
|
|
{"add z0.h, z0.h, #32512 (derived shift)", "ADD", ExtFormImmediate,
|
|
|
|
|
[]ExtOperand{ExtImmediate(32512), ExtVector(0, ExtArrH)},
|
|
|
|
|
0x2560efe0, "2560efe0 is sqsub's GNU word for #32512; the classes share the encoding"},
|
|
|
|
|
{"sub z0.b, z0.b, #0", "SUB", ExtFormImmediate,
|
|
|
|
|
[]ExtOperand{ExtImmediate(0), ExtVector(0, ExtArrB)},
|
|
|
|
|
0x2521c000, "2521c000 sub z0.b, z0.b, #0"},
|
|
|
|
|
{"subr z0.b, z0.b, #0", "SUBR", ExtFormImmediate,
|
|
|
|
|
[]ExtOperand{ExtImmediate(0), ExtVector(0, ExtArrB)},
|
|
|
|
|
0x2523c000, "2523c000 subr z0.b, z0.b, #0"},
|
|
|
|
|
{"subr z0.b, z0.b, #255", "SUBR", ExtFormImmediate,
|
|
|
|
|
[]ExtOperand{ExtImmediate(255), ExtVector(0, ExtArrB)},
|
|
|
|
|
0x2523dfe0, "2523dfe0 subr z0.b, z0.b, #255"},
|
|
|
|
|
{"subr z0.h, z0.h, #0, lsl #8", "SUBR", ExtFormImmediate,
|
|
|
|
|
[]ExtOperand{ExtShiftedImmediate(0, 8), ExtVector(0, ExtArrH)},
|
|
|
|
|
0x2563e000, "2563e000 subr z0.h, z0.h, #0, lsl #8"},
|
|
|
|
|
{"sqadd z0.b, z0.b, #0", "SQADD", ExtFormImmediate,
|
|
|
|
|
[]ExtOperand{ExtImmediate(0), ExtVector(0, ExtArrB)},
|
|
|
|
|
0x2524c000, "2524c000 sqadd z0.b, z0.b, #0"},
|
|
|
|
|
{"uqadd z0.b, z0.b, #0", "UQADD", ExtFormImmediate,
|
|
|
|
|
[]ExtOperand{ExtImmediate(0), ExtVector(0, ExtArrB)},
|
|
|
|
|
0x2525c000, "2525c000 uqadd z0.b, z0.b, #0"},
|
|
|
|
|
{"sqsub z0.b, z0.b, #0", "SQSUB", ExtFormImmediate,
|
|
|
|
|
[]ExtOperand{ExtImmediate(0), ExtVector(0, ExtArrB)},
|
|
|
|
|
0x2526c000, "2526c000 sqsub z0.b, z0.b, #0"},
|
|
|
|
|
{"sqsub z0.b, z0.b, #255", "SQSUB", ExtFormImmediate,
|
|
|
|
|
[]ExtOperand{ExtImmediate(255), ExtVector(0, ExtArrB)},
|
|
|
|
|
0x2526dfe0, "2526dfe0 sqsub z0.b, z0.b, #255"},
|
|
|
|
|
{"sqsub z0.h, z0.h, #0, lsl #8", "SQSUB", ExtFormImmediate,
|
|
|
|
|
[]ExtOperand{ExtShiftedImmediate(0, 8), ExtVector(0, ExtArrH)},
|
|
|
|
|
0x2566e000, "2566e000 sqsub z0.h, z0.h, #0, lsl #8"},
|
|
|
|
|
{"uqsub z0.b, z0.b, #0", "UQSUB", ExtFormImmediate,
|
|
|
|
|
[]ExtOperand{ExtImmediate(0), ExtVector(0, ExtArrB)},
|
|
|
|
|
0x2527c000, "2527c000 uqsub z0.b, z0.b, #0 (class vector from the GNU table and LLVM: sve_int_arith_imm0 opc 0b111)"},
|
|
|
|
|
{"mul z0.b, z0.b, #0", "MUL", ExtFormSignedImmediate,
|
|
|
|
|
[]ExtOperand{ExtImmediate(0), ExtVector(0, ExtArrB)},
|
|
|
|
|
0x2530c000, "2530c000 mul z0.b, z0.b, #0"},
|
|
|
|
|
{"mul z0.b, z0.b, #127", "MUL", ExtFormSignedImmediate,
|
|
|
|
|
[]ExtOperand{ExtImmediate(127), ExtVector(0, ExtArrB)},
|
|
|
|
|
0x2530cfe0, "2530cfe0 mul z0.b, z0.b, #127"},
|
|
|
|
|
{"mul z0.b, z0.b, #-128", "MUL", ExtFormSignedImmediate,
|
|
|
|
|
[]ExtOperand{ExtImmediate(-128), ExtVector(0, ExtArrB)},
|
|
|
|
|
0x2530d000, "2530d000 mul z0.b, z0.b, #-128"},
|
|
|
|
|
{"mul z0.b, z0.b, #-1", "MUL", ExtFormSignedImmediate,
|
|
|
|
|
[]ExtOperand{ExtImmediate(-1), ExtVector(0, ExtArrB)},
|
|
|
|
|
0x2530dfe0, "2530dfe0 mul z0.b, z0.b, #-1"},
|
|
|
|
|
{"mul z0.h, z0.h, #0", "MUL", ExtFormSignedImmediate,
|
|
|
|
|
[]ExtOperand{ExtImmediate(0), ExtVector(0, ExtArrH)},
|
|
|
|
|
0x2570c000, "2570c000 mul z0.h, z0.h, #0"},
|
|
|
|
|
} {
|
|
|
|
|
in := extInstruction(t, tt.mnem, tt.form)
|
|
|
|
|
got, err := in.Encode(tt.ops)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Errorf("%s: encode: %v", tt.name, err)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
if want := hex.EncodeToString(extWordLE(tt.want)); hex.EncodeToString(got) != want {
|
|
|
|
|
t.Errorf("%s:\n got %x\n want %s", tt.name, got, want)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TestArm64ExtGoldenSources pins the cross-check contract: every encoding
|
|
|
|
|
// class in the table carries at least one GNU-assembler vector, so no class
|
|
|
|
|
// rests on transcription alone.
|
|
|
|
|
func TestArm64ExtGoldenSources(t *testing.T) {
|
|
|
|
|
classes := map[ExtForm]bool{}
|
|
|
|
|
for _, tt := range []struct {
|
|
|
|
|
mnem string
|
|
|
|
|
form ExtForm
|
|
|
|
|
}{
|
|
|
|
|
{"ADD", ExtFormVectors}, {"SUB", ExtFormVectors}, {"SQADD", ExtFormVectors},
|
|
|
|
|
{"UQADD", ExtFormVectors}, {"SQSUB", ExtFormVectors}, {"UQSUB", ExtFormVectors},
|
|
|
|
|
{"MUL", ExtFormVectors}, {"SMULH", ExtFormVectors}, {"UMULH", ExtFormVectors},
|
|
|
|
|
{"ADD", ExtFormPredicated}, {"SUB", ExtFormPredicated}, {"SUBR", ExtFormPredicated},
|
|
|
|
|
{"MUL", ExtFormPredicated}, {"SMULH", ExtFormPredicated}, {"UMULH", ExtFormPredicated},
|
|
|
|
|
{"ADD", ExtFormImmediate}, {"SUB", ExtFormImmediate}, {"SUBR", ExtFormImmediate},
|
|
|
|
|
{"SQADD", ExtFormImmediate}, {"UQADD", ExtFormImmediate},
|
|
|
|
|
{"SQSUB", ExtFormImmediate}, {"UQSUB", ExtFormImmediate},
|
|
|
|
|
{"MUL", ExtFormSignedImmediate},
|
|
|
|
|
} {
|
|
|
|
|
if _, ok := extInstructionQuiet(tt.mnem, tt.form); !ok {
|
|
|
|
|
t.Errorf("the table lacks %s with the %s form", tt.mnem, tt.form)
|
|
|
|
|
}
|
|
|
|
|
classes[tt.form] = true
|
|
|
|
|
}
|
|
|
|
|
for _, form := range []ExtForm{ExtFormVectors, ExtFormPredicated, ExtFormImmediate, ExtFormSignedImmediate} {
|
|
|
|
|
if !classes[form] {
|
|
|
|
|
t.Errorf("no golden vectors cover the %s form", form)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func extInstructionQuiet(mnem string, form ExtForm) (ExtInstr, bool) {
|
|
|
|
|
for _, in := range Extensions(ARM64) {
|
|
|
|
|
if in.Name == mnem && in.Form == form {
|
|
|
|
|
return in, true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return ExtInstr{}, false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TestArm64ExtTableIntegrity checks the metadata contract: every entry names
|
2026-10-07 00:11:40 +02:00
|
|
|
// its manual reference, summary and feature, the element-size field sits
|
|
|
|
|
// at bits 23..22 for the classes that carry one, and the destination field
|
|
|
|
|
// stays zero in the fixed word: five bits where a Z register is the
|
|
|
|
|
// destination, four where a predicate is.
|
2026-10-02 17:58:55 +02:00
|
|
|
func TestArm64ExtTableIntegrity(t *testing.T) {
|
|
|
|
|
for _, in := range Extensions(ARM64) {
|
|
|
|
|
if in.Name == "" || in.Summary == "" || in.Ref == "" {
|
|
|
|
|
t.Errorf("%+v: name, summary and reference are mandatory", in)
|
|
|
|
|
}
|
2026-10-07 00:11:40 +02:00
|
|
|
if in.Feature != ExtFeatureSVE && in.Feature != ExtFeatureSVE2 && in.Feature != ExtFeatureSVE2p1 {
|
|
|
|
|
t.Errorf("%s: feature %q is neither sve, sve2 nor sve2p1", in.Name, in.Feature)
|
2026-10-02 17:58:55 +02:00
|
|
|
}
|
2026-10-07 00:11:40 +02:00
|
|
|
if in.Form.Arity() < 0 || in.Form.Arity() > 4 {
|
2026-10-02 17:58:55 +02:00
|
|
|
t.Errorf("%s: form %d carries an unusable arity %d", in.Name, in.Form, in.Form.Arity())
|
|
|
|
|
}
|
2026-10-07 00:11:40 +02:00
|
|
|
if in.Size.Width != 0 && (in.Size.Off != 22 || in.Size.Width != 2) {
|
2026-10-02 17:58:55 +02:00
|
|
|
t.Errorf("%s: the size field sits at bits %d..%d, the classes here put it at 23..22",
|
|
|
|
|
in.Name, in.Size.Off, in.Size.Off+in.Size.Width-1)
|
|
|
|
|
}
|
|
|
|
|
// The destination register field and the element-size field are
|
2026-10-07 00:11:40 +02:00
|
|
|
// operands wherever they exist, so Word carries both zero; the
|
|
|
|
|
// class opcodes live around them and stay where they are. Where
|
|
|
|
|
// the class carries no size field, bits 23..22 are class bits and
|
|
|
|
|
// stay.
|
2026-10-07 02:20:25 +02:00
|
|
|
// Forms whose destination is a predicate carry it in a four-bit
|
|
|
|
|
// field; every other form keeps the five-bit Z or R destination.
|
2026-10-07 00:11:40 +02:00
|
|
|
destMask := uint32(0x1f)
|
2026-10-07 02:20:25 +02:00
|
|
|
switch in.Form {
|
|
|
|
|
case ExtFormPredicateLogical, ExtFormPredicateSelect, ExtFormPredicateLogicalDest,
|
|
|
|
|
ExtFormPredicateBreak, ExtFormPredicateBreakZero, ExtFormPredicatePermute,
|
|
|
|
|
ExtFormPredicateFirst, ExtFormPredicateNext, ExtFormPredicateOne,
|
|
|
|
|
ExtFormPredicateFFRRead, ExtFormPredicateMove, ExtFormPredicateUnpack,
|
|
|
|
|
ExtFormPredicateTest, ExtFormWhile, ExtFormPredicateCounter, ExtFormZUnary:
|
|
|
|
|
destMask = 0xf
|
2026-10-07 00:11:40 +02:00
|
|
|
}
|
2026-10-07 02:20:25 +02:00
|
|
|
roundOne := in.Form == ExtFormVectors || in.Form == ExtFormPredicated ||
|
|
|
|
|
in.Form == ExtFormImmediate || in.Form == ExtFormSignedImmediate
|
|
|
|
|
if in.Word&destMask != 0 || (roundOne && in.Size.Width != 0 && in.Word&(0x3<<22) != 0) {
|
2026-10-02 17:58:55 +02:00
|
|
|
t.Errorf("%s: word %08x carries destination or size bits, want them zero", in.Name, in.Word)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestArm64ExtRejects(t *testing.T) {
|
|
|
|
|
rgb := func(rs ...int) []ExtOperand {
|
|
|
|
|
ops := make([]ExtOperand, len(rs))
|
|
|
|
|
for i, r := range rs {
|
|
|
|
|
ops[i] = ExtVector(r, ExtArrB)
|
|
|
|
|
}
|
|
|
|
|
return ops
|
|
|
|
|
}
|
|
|
|
|
for _, tt := range []struct {
|
|
|
|
|
name string
|
|
|
|
|
mnem string
|
|
|
|
|
form ExtForm
|
|
|
|
|
ops []ExtOperand
|
|
|
|
|
quote string // a fragment the error carries
|
|
|
|
|
}{
|
|
|
|
|
{"no arrangement", "ADD", ExtFormVectors,
|
|
|
|
|
[]ExtOperand{{Kind: ExtZReg, Reg: 0}, ExtVector(0, ExtArrB), ExtVector(0, ExtArrB)},
|
|
|
|
|
"no arrangement"},
|
|
|
|
|
{"mismatched arrangements", "ADD", ExtFormVectors,
|
|
|
|
|
[]ExtOperand{ExtVector(0, ExtArrB), ExtVector(0, ExtArrS), ExtVector(0, ExtArrB)},
|
|
|
|
|
"want .B"},
|
|
|
|
|
{"wrong arity", "ADD", ExtFormVectors, rgb(0, 0), "takes 3 operands"},
|
|
|
|
|
{"predicate in a vector position", "ADD", ExtFormVectors,
|
|
|
|
|
[]ExtOperand{ExtPredicate(0, ExtQualNone), ExtVector(0, ExtArrB), ExtVector(0, ExtArrB)},
|
|
|
|
|
"scalable vector register"},
|
|
|
|
|
{"quadword arrangement has no size encoding", "ADD", ExtFormVectors,
|
|
|
|
|
[]ExtOperand{ExtVector(0, ExtArrQ), ExtVector(0, ExtArrQ), ExtVector(0, ExtArrQ)},
|
|
|
|
|
"no size encoding"},
|
|
|
|
|
{"zeroing qualifier", "ADD", ExtFormPredicated,
|
|
|
|
|
[]ExtOperand{ExtVector(0, ExtArrB), ExtPredicate(0, ExtQualZeroing), ExtVector(0, ExtArrB)},
|
|
|
|
|
"/M"},
|
|
|
|
|
{"predicate beyond the 3-bit field", "ADD", ExtFormPredicated,
|
|
|
|
|
[]ExtOperand{ExtVector(0, ExtArrB), ExtPredicate(8, ExtQualMerging), ExtVector(0, ExtArrB)},
|
|
|
|
|
"P0-P7"},
|
|
|
|
|
{"predicate arrangement suffix", "ADD", ExtFormPredicated,
|
|
|
|
|
[]ExtOperand{ExtVector(0, ExtArrB), ExtOperand{Kind: ExtPReg, Reg: 0, Qual: ExtQualMerging, Arr: ExtArrB}, ExtVector(0, ExtArrB)},
|
|
|
|
|
"arrangement"},
|
|
|
|
|
{"predicate operands disagree on arrangement", "ADD", ExtFormPredicated,
|
|
|
|
|
[]ExtOperand{ExtVector(0, ExtArrB), ExtPredicate(0, ExtQualMerging), ExtVector(0, ExtArrS)},
|
|
|
|
|
"must match"},
|
|
|
|
|
{"bare 256 on .B", "ADD", ExtFormImmediate,
|
|
|
|
|
[]ExtOperand{ExtImmediate(256), ExtVector(0, ExtArrB)},
|
|
|
|
|
"immediate 256"},
|
|
|
|
|
{"negative unsigned immediate", "ADD", ExtFormImmediate,
|
|
|
|
|
[]ExtOperand{ExtImmediate(-1), ExtVector(0, ExtArrB)},
|
|
|
|
|
"immediate -1"},
|
|
|
|
|
{"multiple of 256 beyond the imm8 span", "ADD", ExtFormImmediate,
|
|
|
|
|
[]ExtOperand{ExtImmediate(65536), ExtVector(0, ExtArrH)},
|
|
|
|
|
"immediate 65536"},
|
|
|
|
|
{"shift amount other than 0 or 8", "ADD", ExtFormImmediate,
|
|
|
|
|
[]ExtOperand{ExtShiftedImmediate(1, 4), ExtVector(0, ExtArrS)},
|
|
|
|
|
"0 or 8"},
|
|
|
|
|
{"shifted constant on .B", "ADD", ExtFormImmediate,
|
|
|
|
|
[]ExtOperand{ExtShiftedImmediate(1, 8), ExtVector(0, ExtArrB)},
|
|
|
|
|
".B takes no shift"},
|
|
|
|
|
{"register where the immediate belongs", "ADD", ExtFormImmediate,
|
|
|
|
|
[]ExtOperand{ExtVector(0, ExtArrB), ExtVector(0, ExtArrB)},
|
|
|
|
|
"wants an immediate"},
|
|
|
|
|
{"signed immediate over the top", "MUL", ExtFormSignedImmediate,
|
|
|
|
|
[]ExtOperand{ExtImmediate(128), ExtVector(0, ExtArrB)},
|
|
|
|
|
"128"},
|
|
|
|
|
{"signed immediate under the floor", "MUL", ExtFormSignedImmediate,
|
|
|
|
|
[]ExtOperand{ExtImmediate(-129), ExtVector(0, ExtArrB)},
|
|
|
|
|
"-129"},
|
|
|
|
|
{"shift in the signed class", "MUL", ExtFormSignedImmediate,
|
|
|
|
|
[]ExtOperand{ExtShiftedImmediate(1, 8), ExtVector(0, ExtArrB)},
|
|
|
|
|
"no shift"},
|
|
|
|
|
} {
|
|
|
|
|
in := extInstruction(t, tt.mnem, tt.form)
|
|
|
|
|
_, err := in.Encode(tt.ops)
|
|
|
|
|
if err == nil {
|
|
|
|
|
t.Errorf("%s: encode succeeded, want an error", tt.name)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
if !strings.Contains(err.Error(), tt.quote) {
|
|
|
|
|
t.Errorf("%s: error %q lacks %q", tt.name, err, tt.quote)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TestExtensionsArchBinding pins the registry's architecture binding: the
|
2026-10-06 23:43:23 +02:00
|
|
|
// extended layer exists for arm64 and amd64 (the latter in amd64_ext.go), and
|
|
|
|
|
// no other architecture sees a single instruction of either.
|
2026-10-02 17:58:55 +02:00
|
|
|
func TestExtensionsArchBinding(t *testing.T) {
|
2026-10-06 23:43:23 +02:00
|
|
|
for _, a := range []Arch{RISCV, LOONG64, Unknown} {
|
2026-10-02 17:58:55 +02:00
|
|
|
if got := Extensions(a); len(got) != 0 {
|
|
|
|
|
t.Errorf("Extensions(%s) carries %d instructions, want none", a, len(got))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if got := Extensions(ARM64); len(got) == 0 {
|
|
|
|
|
t.Error("Extensions(ARM64) is empty")
|
|
|
|
|
}
|
2026-10-06 23:43:23 +02:00
|
|
|
if got := Extensions(AMD64); len(got) == 0 {
|
|
|
|
|
t.Error("Extensions(AMD64) is empty")
|
|
|
|
|
}
|
2026-10-02 17:58:55 +02:00
|
|
|
}
|
2026-10-07 00:11:40 +02:00
|
|
|
|
|
|
|
|
// TestArm64ExtPredicateGolden pins the SVE and SVE2.1 predicate family
|
|
|
|
|
// against the toolchain-generated corpus: every row is one arm64sveenc.s
|
|
|
|
|
// line, and the want word is that line's own expected encoding, byte
|
|
|
|
|
// reversed out of the file's big-endian comment into the little-endian
|
|
|
|
|
// instruction word. The corpus and the toolchain's encoding table
|
|
|
|
|
// (inst_gen.go) are two independent generations from Arm's official ISA
|
|
|
|
|
// description; both agree with the field layouts encoded here, and the
|
|
|
|
|
// classes have no single-byte oracle beyond them (go tool asm carries no
|
|
|
|
|
// SVE encodings).
|
|
|
|
|
func TestArm64ExtPredicateGolden(t *testing.T) {
|
|
|
|
|
for _, tt := range []struct {
|
|
|
|
|
name string
|
|
|
|
|
mnem string
|
|
|
|
|
form ExtForm
|
|
|
|
|
ops []ExtOperand
|
|
|
|
|
want uint32
|
|
|
|
|
}{
|
|
|
|
|
{"PAND P4.B, P2.B, P1.Z, P14.B", "PAND",
|
|
|
|
|
ExtFormPredicateLogical,
|
|
|
|
|
[]ExtOperand{ExtPredicateSized(4, ExtArrB), ExtPredicateSized(2, ExtArrB), ExtPredicate(1, ExtQualZeroing), ExtPredicateSized(14, ExtArrB)},
|
|
|
|
|
0x2504444e},
|
|
|
|
|
{"PANDS P4.B, P2.B, P1.Z, P14.B", "PANDS",
|
|
|
|
|
ExtFormPredicateLogical,
|
|
|
|
|
[]ExtOperand{ExtPredicateSized(4, ExtArrB), ExtPredicateSized(2, ExtArrB), ExtPredicate(1, ExtQualZeroing), ExtPredicateSized(14, ExtArrB)},
|
|
|
|
|
0x2544444e},
|
|
|
|
|
{"PBIC P4.B, P2.B, P1.Z, P14.B", "PBIC",
|
|
|
|
|
ExtFormPredicateLogical,
|
|
|
|
|
[]ExtOperand{ExtPredicateSized(4, ExtArrB), ExtPredicateSized(2, ExtArrB), ExtPredicate(1, ExtQualZeroing), ExtPredicateSized(14, ExtArrB)},
|
|
|
|
|
0x2504445e},
|
|
|
|
|
{"PBICS P4.B, P2.B, P1.Z, P14.B", "PBICS",
|
|
|
|
|
ExtFormPredicateLogical,
|
|
|
|
|
[]ExtOperand{ExtPredicateSized(4, ExtArrB), ExtPredicateSized(2, ExtArrB), ExtPredicate(1, ExtQualZeroing), ExtPredicateSized(14, ExtArrB)},
|
|
|
|
|
0x2544445e},
|
|
|
|
|
{"PBRKA P5.B, P9.Z, P2.B", "PBRKA",
|
|
|
|
|
ExtFormPredicateBreak,
|
|
|
|
|
[]ExtOperand{ExtPredicateSized(5, ExtArrB), ExtPredicate(9, ExtQualZeroing), ExtPredicateSized(2, ExtArrB)},
|
|
|
|
|
0x251064a2},
|
|
|
|
|
{"PBRKAS P5.B, P9.Z, P4.B", "PBRKAS",
|
|
|
|
|
ExtFormPredicateBreakZero,
|
|
|
|
|
[]ExtOperand{ExtPredicateSized(5, ExtArrB), ExtPredicate(9, ExtQualZeroing), ExtPredicateSized(4, ExtArrB)},
|
|
|
|
|
0x255064a4},
|
|
|
|
|
{"PBRKB P5.B, P9.Z, P2.B", "PBRKB",
|
|
|
|
|
ExtFormPredicateBreak,
|
|
|
|
|
[]ExtOperand{ExtPredicateSized(5, ExtArrB), ExtPredicate(9, ExtQualZeroing), ExtPredicateSized(2, ExtArrB)},
|
|
|
|
|
0x259064a2},
|
|
|
|
|
{"PBRKBS P5.B, P9.Z, P4.B", "PBRKBS",
|
|
|
|
|
ExtFormPredicateBreakZero,
|
|
|
|
|
[]ExtOperand{ExtPredicateSized(5, ExtArrB), ExtPredicate(9, ExtQualZeroing), ExtPredicateSized(4, ExtArrB)},
|
|
|
|
|
0x25d064a4},
|
|
|
|
|
{"PBRKN P4.B, P2.B, P1.Z, P4.B", "PBRKN",
|
|
|
|
|
ExtFormPredicateLogicalDest,
|
|
|
|
|
[]ExtOperand{ExtPredicateSized(4, ExtArrB), ExtPredicateSized(2, ExtArrB), ExtPredicate(1, ExtQualZeroing), ExtPredicateSized(4, ExtArrB)},
|
|
|
|
|
0x25184444},
|
|
|
|
|
{"PBRKNS P4.B, P2.B, P1.Z, P4.B", "PBRKNS",
|
|
|
|
|
ExtFormPredicateLogicalDest,
|
|
|
|
|
[]ExtOperand{ExtPredicateSized(4, ExtArrB), ExtPredicateSized(2, ExtArrB), ExtPredicate(1, ExtQualZeroing), ExtPredicateSized(4, ExtArrB)},
|
|
|
|
|
0x25584444},
|
|
|
|
|
{"PBRKPA P4.B, P2.B, P1.Z, P14.B", "PBRKPA",
|
|
|
|
|
ExtFormPredicateLogical,
|
|
|
|
|
[]ExtOperand{ExtPredicateSized(4, ExtArrB), ExtPredicateSized(2, ExtArrB), ExtPredicate(1, ExtQualZeroing), ExtPredicateSized(14, ExtArrB)},
|
|
|
|
|
0x2504c44e},
|
|
|
|
|
{"PBRKPAS P4.B, P2.B, P1.Z, P14.B", "PBRKPAS",
|
|
|
|
|
ExtFormPredicateLogical,
|
|
|
|
|
[]ExtOperand{ExtPredicateSized(4, ExtArrB), ExtPredicateSized(2, ExtArrB), ExtPredicate(1, ExtQualZeroing), ExtPredicateSized(14, ExtArrB)},
|
|
|
|
|
0x2544c44e},
|
|
|
|
|
{"PBRKPB P4.B, P2.B, P1.Z, P14.B", "PBRKPB",
|
|
|
|
|
ExtFormPredicateLogical,
|
|
|
|
|
[]ExtOperand{ExtPredicateSized(4, ExtArrB), ExtPredicateSized(2, ExtArrB), ExtPredicate(1, ExtQualZeroing), ExtPredicateSized(14, ExtArrB)},
|
|
|
|
|
0x2504c45e},
|
|
|
|
|
{"PBRKPBS P4.B, P2.B, P1.Z, P14.B", "PBRKPBS",
|
|
|
|
|
ExtFormPredicateLogical,
|
|
|
|
|
[]ExtOperand{ExtPredicateSized(4, ExtArrB), ExtPredicateSized(2, ExtArrB), ExtPredicate(1, ExtQualZeroing), ExtPredicateSized(14, ExtArrB)},
|
|
|
|
|
0x2544c45e},
|
|
|
|
|
{"PEOR P4.B, P2.B, P1.Z, P14.B", "PEOR",
|
|
|
|
|
ExtFormPredicateLogical,
|
|
|
|
|
[]ExtOperand{ExtPredicateSized(4, ExtArrB), ExtPredicateSized(2, ExtArrB), ExtPredicate(1, ExtQualZeroing), ExtPredicateSized(14, ExtArrB)},
|
|
|
|
|
0x2504464e},
|
|
|
|
|
{"PEORS P4.B, P2.B, P1.Z, P14.B", "PEORS",
|
|
|
|
|
ExtFormPredicateLogical,
|
|
|
|
|
[]ExtOperand{ExtPredicateSized(4, ExtArrB), ExtPredicateSized(2, ExtArrB), ExtPredicate(1, ExtQualZeroing), ExtPredicateSized(14, ExtArrB)},
|
|
|
|
|
0x2544464e},
|
|
|
|
|
{"PNAND P4.B, P2.B, P1.Z, P14.B", "PNAND",
|
|
|
|
|
ExtFormPredicateLogical,
|
|
|
|
|
[]ExtOperand{ExtPredicateSized(4, ExtArrB), ExtPredicateSized(2, ExtArrB), ExtPredicate(1, ExtQualZeroing), ExtPredicateSized(14, ExtArrB)},
|
|
|
|
|
0x2584465e},
|
|
|
|
|
{"PNANDS P4.B, P2.B, P1.Z, P14.B", "PNANDS",
|
|
|
|
|
ExtFormPredicateLogical,
|
|
|
|
|
[]ExtOperand{ExtPredicateSized(4, ExtArrB), ExtPredicateSized(2, ExtArrB), ExtPredicate(1, ExtQualZeroing), ExtPredicateSized(14, ExtArrB)},
|
|
|
|
|
0x25c4465e},
|
|
|
|
|
{"PNOR P4.B, P2.B, P1.Z, P14.B", "PNOR",
|
|
|
|
|
ExtFormPredicateLogical,
|
|
|
|
|
[]ExtOperand{ExtPredicateSized(4, ExtArrB), ExtPredicateSized(2, ExtArrB), ExtPredicate(1, ExtQualZeroing), ExtPredicateSized(14, ExtArrB)},
|
|
|
|
|
0x2584464e},
|
|
|
|
|
{"PNORS P4.B, P2.B, P1.Z, P14.B", "PNORS",
|
|
|
|
|
ExtFormPredicateLogical,
|
|
|
|
|
[]ExtOperand{ExtPredicateSized(4, ExtArrB), ExtPredicateSized(2, ExtArrB), ExtPredicate(1, ExtQualZeroing), ExtPredicateSized(14, ExtArrB)},
|
|
|
|
|
0x25c4464e},
|
|
|
|
|
{"PORN P4.B, P2.B, P1.Z, P14.B", "PORN",
|
|
|
|
|
ExtFormPredicateLogical,
|
|
|
|
|
[]ExtOperand{ExtPredicateSized(4, ExtArrB), ExtPredicateSized(2, ExtArrB), ExtPredicate(1, ExtQualZeroing), ExtPredicateSized(14, ExtArrB)},
|
|
|
|
|
0x2584445e},
|
|
|
|
|
{"PORNS P4.B, P2.B, P1.Z, P14.B", "PORNS",
|
|
|
|
|
ExtFormPredicateLogical,
|
|
|
|
|
[]ExtOperand{ExtPredicateSized(4, ExtArrB), ExtPredicateSized(2, ExtArrB), ExtPredicate(1, ExtQualZeroing), ExtPredicateSized(14, ExtArrB)},
|
|
|
|
|
0x25c4445e},
|
|
|
|
|
{"PORR P4.B, P2.B, P1.Z, P14.B", "PORR",
|
|
|
|
|
ExtFormPredicateLogical,
|
|
|
|
|
[]ExtOperand{ExtPredicateSized(4, ExtArrB), ExtPredicateSized(2, ExtArrB), ExtPredicate(1, ExtQualZeroing), ExtPredicateSized(14, ExtArrB)},
|
|
|
|
|
0x2584444e},
|
|
|
|
|
{"PORRS P4.B, P2.B, P1.Z, P14.B", "PORRS",
|
|
|
|
|
ExtFormPredicateLogical,
|
|
|
|
|
[]ExtOperand{ExtPredicateSized(4, ExtArrB), ExtPredicateSized(2, ExtArrB), ExtPredicate(1, ExtQualZeroing), ExtPredicateSized(14, ExtArrB)},
|
|
|
|
|
0x25c4444e},
|
|
|
|
|
{"PPFALSE P13.B", "PPFALSE",
|
|
|
|
|
ExtFormPredicateOne,
|
|
|
|
|
[]ExtOperand{ExtPredicateSized(13, ExtArrB)},
|
|
|
|
|
0x2518e40d},
|
|
|
|
|
{"PPFIRST P5.B, P9, P5.B", "PPFIRST",
|
|
|
|
|
ExtFormPredicateFirst,
|
|
|
|
|
[]ExtOperand{ExtPredicateSized(5, ExtArrB), ExtPredicate(9, ExtQualNone), ExtPredicateSized(5, ExtArrB)},
|
|
|
|
|
0x2558c125},
|
|
|
|
|
{"PPNEXT P5.D, P4, P5.D", "PPNEXT",
|
|
|
|
|
ExtFormPredicateNext,
|
|
|
|
|
[]ExtOperand{ExtPredicateSized(5, ExtArrD), ExtPredicate(4, ExtQualNone), ExtPredicateSized(5, ExtArrD)},
|
|
|
|
|
0x25d9c485},
|
|
|
|
|
{"PPTEST P14.B, P0", "PPTEST",
|
|
|
|
|
ExtFormPredicateTest,
|
|
|
|
|
[]ExtOperand{ExtPredicateSized(14, ExtArrB), ExtPredicate(0, ExtQualNone)},
|
|
|
|
|
0x2550c1c0},
|
|
|
|
|
{"PPTRUE PN14.S", "PPTRUE",
|
|
|
|
|
ExtFormPredicateCounter,
|
|
|
|
|
[]ExtOperand{ExtCounterPredicate(14, ExtArrS)},
|
|
|
|
|
0x25a07816},
|
|
|
|
|
{"PPUNPKHI P14.B, P0.H", "PPUNPKHI",
|
|
|
|
|
ExtFormPredicateUnpack,
|
|
|
|
|
[]ExtOperand{ExtPredicateSized(14, ExtArrB), ExtPredicateSized(0, ExtArrH)},
|
|
|
|
|
0x053141c0},
|
|
|
|
|
{"PPUNPKLO P14.B, P0.H", "PPUNPKLO",
|
|
|
|
|
ExtFormPredicateUnpack,
|
|
|
|
|
[]ExtOperand{ExtPredicateSized(14, ExtArrB), ExtPredicateSized(0, ExtArrH)},
|
|
|
|
|
0x053041c0},
|
|
|
|
|
{"PRDFFR P14.Z, P0.B", "PRDFFR",
|
|
|
|
|
ExtFormPredicateFFRRead,
|
|
|
|
|
[]ExtOperand{ExtPredicate(14, ExtQualZeroing), ExtPredicateSized(0, ExtArrB)},
|
|
|
|
|
0x2518f1c0},
|
|
|
|
|
{"PRDFFR P13.B", "PRDFFR",
|
|
|
|
|
ExtFormPredicateOne,
|
|
|
|
|
[]ExtOperand{ExtPredicateSized(13, ExtArrB)},
|
|
|
|
|
0x2519f00d},
|
|
|
|
|
{"PRDFFRS P14.Z, P0.B", "PRDFFRS",
|
|
|
|
|
ExtFormPredicateFFRRead,
|
|
|
|
|
[]ExtOperand{ExtPredicate(14, ExtQualZeroing), ExtPredicateSized(0, ExtArrB)},
|
|
|
|
|
0x2558f1c0},
|
|
|
|
|
{"PREV P14.S, P13.S", "PREV",
|
|
|
|
|
ExtFormPredicateMove,
|
|
|
|
|
[]ExtOperand{ExtPredicateSized(14, ExtArrS), ExtPredicateSized(13, ExtArrS)},
|
|
|
|
|
0x05b441cd},
|
|
|
|
|
{"PSEL P4.B, P2.B, P1, P14.B", "PSEL",
|
|
|
|
|
ExtFormPredicateSelect,
|
|
|
|
|
[]ExtOperand{ExtPredicateSized(4, ExtArrB), ExtPredicateSized(2, ExtArrB), ExtPredicate(1, ExtQualNone), ExtPredicateSized(14, ExtArrB)},
|
|
|
|
|
0x2504465e},
|
|
|
|
|
{"PTRN1 P5.D, P4.D, P2.D", "PTRN1",
|
|
|
|
|
ExtFormPredicatePermute,
|
|
|
|
|
[]ExtOperand{ExtPredicateSized(5, ExtArrD), ExtPredicateSized(4, ExtArrD), ExtPredicateSized(2, ExtArrD)},
|
|
|
|
|
0x05e55082},
|
|
|
|
|
{"PTRN2 P5.D, P4.D, P2.D", "PTRN2",
|
|
|
|
|
ExtFormPredicatePermute,
|
|
|
|
|
[]ExtOperand{ExtPredicateSized(5, ExtArrD), ExtPredicateSized(4, ExtArrD), ExtPredicateSized(2, ExtArrD)},
|
|
|
|
|
0x05e55482},
|
|
|
|
|
{"PUZP1 P5.D, P4.D, P2.D", "PUZP1",
|
|
|
|
|
ExtFormPredicatePermute,
|
|
|
|
|
[]ExtOperand{ExtPredicateSized(5, ExtArrD), ExtPredicateSized(4, ExtArrD), ExtPredicateSized(2, ExtArrD)},
|
|
|
|
|
0x05e54882},
|
|
|
|
|
{"PUZP2 P5.D, P4.D, P2.D", "PUZP2",
|
|
|
|
|
ExtFormPredicatePermute,
|
|
|
|
|
[]ExtOperand{ExtPredicateSized(5, ExtArrD), ExtPredicateSized(4, ExtArrD), ExtPredicateSized(2, ExtArrD)},
|
|
|
|
|
0x05e54c82},
|
|
|
|
|
{"PWRFFR P13.B", "PWRFFR",
|
|
|
|
|
ExtFormPredicateWrite,
|
|
|
|
|
[]ExtOperand{ExtPredicateSized(13, ExtArrB)},
|
|
|
|
|
0x252891a0},
|
|
|
|
|
{"PZIP1 P5.D, P4.D, P2.D", "PZIP1",
|
|
|
|
|
ExtFormPredicatePermute,
|
|
|
|
|
[]ExtOperand{ExtPredicateSized(5, ExtArrD), ExtPredicateSized(4, ExtArrD), ExtPredicateSized(2, ExtArrD)},
|
|
|
|
|
0x05e54082},
|
|
|
|
|
{"PZIP2 P5.D, P4.D, P2.D", "PZIP2",
|
|
|
|
|
ExtFormPredicatePermute,
|
|
|
|
|
[]ExtOperand{ExtPredicateSized(5, ExtArrD), ExtPredicateSized(4, ExtArrD), ExtPredicateSized(2, ExtArrD)},
|
|
|
|
|
0x05e54482},
|
|
|
|
|
{"SETFFR ", "SETFFR",
|
|
|
|
|
ExtFormNone,
|
|
|
|
|
[]ExtOperand{},
|
|
|
|
|
0x252c9000},
|
|
|
|
|
{"PWHILEGE R2, R10, P10.H", "PWHILEGE",
|
|
|
|
|
ExtFormWhile,
|
|
|
|
|
[]ExtOperand{ExtGeneral(2), ExtGeneral(10), ExtPredicateSized(10, ExtArrH)},
|
|
|
|
|
0x2562114a},
|
|
|
|
|
{"PWHILEGT R2, R10, P10.H", "PWHILEGT",
|
|
|
|
|
ExtFormWhile,
|
|
|
|
|
[]ExtOperand{ExtGeneral(2), ExtGeneral(10), ExtPredicateSized(10, ExtArrH)},
|
|
|
|
|
0x2562115a},
|
|
|
|
|
{"PWHILEHI R2, R10, P10.H", "PWHILEHI",
|
|
|
|
|
ExtFormWhile,
|
|
|
|
|
[]ExtOperand{ExtGeneral(2), ExtGeneral(10), ExtPredicateSized(10, ExtArrH)},
|
|
|
|
|
0x2562195a},
|
|
|
|
|
{"PWHILEHS R2, R10, P10.H", "PWHILEHS",
|
|
|
|
|
ExtFormWhile,
|
|
|
|
|
[]ExtOperand{ExtGeneral(2), ExtGeneral(10), ExtPredicateSized(10, ExtArrH)},
|
|
|
|
|
0x2562194a},
|
|
|
|
|
{"PWHILELE R2, R10, P10.H", "PWHILELE",
|
|
|
|
|
ExtFormWhile,
|
|
|
|
|
[]ExtOperand{ExtGeneral(2), ExtGeneral(10), ExtPredicateSized(10, ExtArrH)},
|
|
|
|
|
0x2562155a},
|
|
|
|
|
{"PWHILELO R2, R10, P10.H", "PWHILELO",
|
|
|
|
|
ExtFormWhile,
|
|
|
|
|
[]ExtOperand{ExtGeneral(2), ExtGeneral(10), ExtPredicateSized(10, ExtArrH)},
|
|
|
|
|
0x25621d4a},
|
|
|
|
|
{"PWHILELS R2, R10, P10.H", "PWHILELS",
|
|
|
|
|
ExtFormWhile,
|
|
|
|
|
[]ExtOperand{ExtGeneral(2), ExtGeneral(10), ExtPredicateSized(10, ExtArrH)},
|
|
|
|
|
0x25621d5a},
|
|
|
|
|
{"PWHILELT R2, R10, P10.H", "PWHILELT",
|
|
|
|
|
ExtFormWhile,
|
|
|
|
|
[]ExtOperand{ExtGeneral(2), ExtGeneral(10), ExtPredicateSized(10, ExtArrH)},
|
|
|
|
|
0x2562154a},
|
|
|
|
|
{"PWHILERW R2, R10, P10.H", "PWHILERW",
|
|
|
|
|
ExtFormWhile,
|
|
|
|
|
[]ExtOperand{ExtGeneral(2), ExtGeneral(10), ExtPredicateSized(10, ExtArrH)},
|
|
|
|
|
0x2562315a},
|
|
|
|
|
{"PWHILEWR R2, R10, P10.H", "PWHILEWR",
|
|
|
|
|
ExtFormWhile,
|
|
|
|
|
[]ExtOperand{ExtGeneral(2), ExtGeneral(10), ExtPredicateSized(10, ExtArrH)},
|
|
|
|
|
0x2562314a},
|
|
|
|
|
} {
|
|
|
|
|
in := extInstruction(t, tt.mnem, tt.form)
|
|
|
|
|
got, err := in.Encode(tt.ops)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Errorf("%s: encode: %v", tt.name, err)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
if want := hex.EncodeToString(extWordLE(tt.want)); hex.EncodeToString(got) != want {
|
|
|
|
|
t.Errorf("%s:\n got %x\n want %s", tt.name, got, want)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TestArm64ExtPredicateSources pins the cross-check contract of the
|
|
|
|
|
// predicate family: every class the layer defines carries at least one
|
|
|
|
|
// golden vector derived from the toolchain-generated corpus, so no class
|
|
|
|
|
// rests on transcription alone.
|
|
|
|
|
func TestArm64ExtPredicateSources(t *testing.T) {
|
|
|
|
|
for _, tt := range []struct {
|
|
|
|
|
mnem string
|
|
|
|
|
form ExtForm
|
|
|
|
|
}{
|
|
|
|
|
{"PAND", ExtFormPredicateLogical}, {"PANDS", ExtFormPredicateLogical},
|
|
|
|
|
{"PBIC", ExtFormPredicateLogical}, {"PBICS", ExtFormPredicateLogical},
|
|
|
|
|
{"PEOR", ExtFormPredicateLogical}, {"PEORS", ExtFormPredicateLogical},
|
|
|
|
|
{"PNAND", ExtFormPredicateLogical}, {"PNANDS", ExtFormPredicateLogical},
|
|
|
|
|
{"PNOR", ExtFormPredicateLogical}, {"PNORS", ExtFormPredicateLogical},
|
|
|
|
|
{"PORN", ExtFormPredicateLogical}, {"PORNS", ExtFormPredicateLogical},
|
|
|
|
|
{"PORR", ExtFormPredicateLogical}, {"PORRS", ExtFormPredicateLogical},
|
|
|
|
|
{"PSEL", ExtFormPredicateSelect},
|
|
|
|
|
{"PBRKA", ExtFormPredicateBreak}, {"PBRKAS", ExtFormPredicateBreakZero},
|
|
|
|
|
{"PBRKB", ExtFormPredicateBreak}, {"PBRKBS", ExtFormPredicateBreakZero},
|
|
|
|
|
{"PBRKN", ExtFormPredicateLogicalDest}, {"PBRKNS", ExtFormPredicateLogicalDest},
|
|
|
|
|
{"PBRKPA", ExtFormPredicateLogical}, {"PBRKPAS", ExtFormPredicateLogical},
|
|
|
|
|
{"PBRKPB", ExtFormPredicateLogical}, {"PBRKPBS", ExtFormPredicateLogical},
|
|
|
|
|
{"PTRN1", ExtFormPredicatePermute}, {"PTRN2", ExtFormPredicatePermute},
|
|
|
|
|
{"PUZP1", ExtFormPredicatePermute}, {"PUZP2", ExtFormPredicatePermute},
|
|
|
|
|
{"PZIP1", ExtFormPredicatePermute}, {"PZIP2", ExtFormPredicatePermute},
|
|
|
|
|
{"PPFALSE", ExtFormPredicateOne},
|
|
|
|
|
{"PPFIRST", ExtFormPredicateFirst},
|
|
|
|
|
{"PPNEXT", ExtFormPredicateNext},
|
|
|
|
|
{"PPTEST", ExtFormPredicateTest},
|
|
|
|
|
{"PPTRUE", ExtFormPredicateCounter},
|
|
|
|
|
{"PPUNPKHI", ExtFormPredicateUnpack}, {"PPUNPKLO", ExtFormPredicateUnpack},
|
|
|
|
|
{"PRDFFR", ExtFormPredicateFFRRead}, {"PRDFFR", ExtFormPredicateOne},
|
|
|
|
|
{"PRDFFRS", ExtFormPredicateFFRRead},
|
|
|
|
|
{"PWRFFR", ExtFormPredicateWrite},
|
|
|
|
|
{"PREV", ExtFormPredicateMove},
|
|
|
|
|
{"SETFFR", ExtFormNone},
|
|
|
|
|
{"PWHILEGE", ExtFormWhile}, {"PWHILEGT", ExtFormWhile},
|
|
|
|
|
{"PWHILEHI", ExtFormWhile}, {"PWHILEHS", ExtFormWhile},
|
|
|
|
|
{"PWHILELE", ExtFormWhile}, {"PWHILELO", ExtFormWhile},
|
|
|
|
|
{"PWHILELS", ExtFormWhile}, {"PWHILELT", ExtFormWhile},
|
|
|
|
|
{"PWHILERW", ExtFormWhile}, {"PWHILEWR", ExtFormWhile},
|
|
|
|
|
} {
|
|
|
|
|
if _, ok := extInstructionQuiet(tt.mnem, tt.form); !ok {
|
|
|
|
|
t.Errorf("the table lacks %s with the %s form", tt.mnem, tt.form)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TestArm64ExtPredicateRejects pins the diagnostics the predicate forms
|
|
|
|
|
// give the operands their classes cannot carry: the register ranges the
|
|
|
|
|
// field widths imply, the arrangements the classes fix, and the read-back
|
|
|
|
|
// constraint of the destination-shared shapes.
|
|
|
|
|
func TestArm64ExtPredicateRejects(t *testing.T) {
|
|
|
|
|
pb := func(r int) ExtOperand { return ExtPredicateSized(r, ExtArrB) }
|
|
|
|
|
for _, tt := range []struct {
|
|
|
|
|
name string
|
|
|
|
|
mnem string
|
|
|
|
|
form ExtForm
|
|
|
|
|
ops []ExtOperand
|
|
|
|
|
quote string
|
|
|
|
|
}{
|
|
|
|
|
{"Pm beyond the three-bit field", "PAND", ExtFormPredicateLogical,
|
|
|
|
|
[]ExtOperand{pb(8), pb(2), ExtPredicate(1, ExtQualZeroing), pb(14)},
|
|
|
|
|
"outside P0-P7"},
|
|
|
|
|
{"governing predicate beyond the narrow field", "PAND", ExtFormPredicateLogical,
|
|
|
|
|
[]ExtOperand{pb(4), pb(2), ExtPredicate(8, ExtQualZeroing), pb(14)},
|
|
|
|
|
"outside P0-P7"},
|
|
|
|
|
{"wrong arrangement on the second source", "PAND", ExtFormPredicateLogical,
|
|
|
|
|
[]ExtOperand{pb(4), ExtPredicateSized(2, ExtArrS), ExtPredicate(1, ExtQualZeroing), pb(14)},
|
|
|
|
|
"want .B"},
|
|
|
|
|
{"bare governing predicate", "PAND", ExtFormPredicateLogical,
|
|
|
|
|
[]ExtOperand{pb(4), pb(2), ExtPredicate(1, ExtQualNone), pb(14)},
|
|
|
|
|
"zeroing qualifier"},
|
|
|
|
|
{"quadword arrangement", "PSEL", ExtFormPredicateSelect,
|
|
|
|
|
[]ExtOperand{ExtPredicateSized(4, ExtArrQ), ExtPredicateSized(2, ExtArrQ), ExtPredicate(1, ExtQualNone), ExtPredicateSized(14, ExtArrQ)},
|
|
|
|
|
"want .B"},
|
|
|
|
|
{"qualifier where PSEL wants none", "PSEL", ExtFormPredicateSelect,
|
|
|
|
|
[]ExtOperand{pb(4), pb(2), ExtPredicate(1, ExtQualZeroing), pb(14)},
|
|
|
|
|
"takes no qualifier"},
|
|
|
|
|
{"read-back operands disagree", "PBRKN", ExtFormPredicateLogicalDest,
|
|
|
|
|
[]ExtOperand{pb(4), pb(2), ExtPredicate(1, ExtQualZeroing), pb(9)},
|
|
|
|
|
"same register Pdm"},
|
|
|
|
|
{"merging qualifier on the zeroing break", "PBRKAS", ExtFormPredicateBreakZero,
|
|
|
|
|
[]ExtOperand{pb(5), ExtPredicate(9, ExtQualMerging), pb(4)},
|
|
|
|
|
"zeroing qualifier"},
|
|
|
|
|
{"governing predicate beyond the wide field", "PBRKA", ExtFormPredicateBreak,
|
|
|
|
|
[]ExtOperand{pb(5), ExtPredicate(16, ExtQualZeroing), pb(2)},
|
|
|
|
|
"outside P0-P15"},
|
|
|
|
|
{"permutations disagree on arrangement", "PTRN1", ExtFormPredicatePermute,
|
|
|
|
|
[]ExtOperand{ExtPredicateSized(5, ExtArrD), ExtPredicateSized(4, ExtArrD), ExtPredicateSized(2, ExtArrS)},
|
|
|
|
|
"want .D"},
|
|
|
|
|
{"bare permutation operand", "PUZP1", ExtFormPredicatePermute,
|
|
|
|
|
[]ExtOperand{ExtPredicateSized(5, ExtArrD), {Kind: ExtPReg, Reg: 4}, ExtPredicateSized(2, ExtArrD)},
|
|
|
|
|
"no arrangement suffix"},
|
|
|
|
|
{"read-back operands disagree on arrangement", "PPNEXT", ExtFormPredicateNext,
|
|
|
|
|
[]ExtOperand{ExtPredicateSized(5, ExtArrD), ExtPredicate(4, ExtQualNone), ExtPredicateSized(5, ExtArrS)},
|
|
|
|
|
"same register Pdn"},
|
|
|
|
|
{"qualifier on the bare source", "PPFIRST", ExtFormPredicateFirst,
|
|
|
|
|
[]ExtOperand{pb(5), ExtPredicate(9, ExtQualZeroing), pb(5)},
|
|
|
|
|
"takes no qualifier"},
|
|
|
|
|
{"PFIRST outside .B", "PPFIRST", ExtFormPredicateFirst,
|
|
|
|
|
[]ExtOperand{ExtPredicateSized(5, ExtArrS), ExtPredicate(9, ExtQualNone), ExtPredicateSized(5, ExtArrS)},
|
|
|
|
|
"want .B"},
|
|
|
|
|
{"merging qualifier on the FFR read", "PRDFFR", ExtFormPredicateFFRRead,
|
|
|
|
|
[]ExtOperand{ExtPredicate(14, ExtQualMerging), pb(0)},
|
|
|
|
|
"zeroing qualifier"},
|
|
|
|
|
{"wrong unpack destination arrangement", "PPUNPKHI", ExtFormPredicateUnpack,
|
|
|
|
|
[]ExtOperand{pb(14), ExtPredicateSized(0, ExtArrB)},
|
|
|
|
|
"want .H"},
|
|
|
|
|
{"qualifier on the tested predicate", "PPTEST", ExtFormPredicateTest,
|
|
|
|
|
[]ExtOperand{pb(14), ExtPredicate(0, ExtQualZeroing)},
|
|
|
|
|
"takes no qualifier"},
|
|
|
|
|
{"general register beyond R30", "PWHILELT", ExtFormWhile,
|
|
|
|
|
[]ExtOperand{ExtGeneral(31), ExtGeneral(10), ExtPredicateSized(10, ExtArrH)},
|
|
|
|
|
"outside R0-R30"},
|
|
|
|
|
{"predicate where the register belongs", "PWHILELT", ExtFormWhile,
|
|
|
|
|
[]ExtOperand{pb(2), ExtGeneral(10), ExtPredicateSized(10, ExtArrH)},
|
|
|
|
|
"wants a general register"},
|
|
|
|
|
{"counter predicate spelled plain", "PPTRUE", ExtFormPredicateCounter,
|
|
|
|
|
[]ExtOperand{ExtPredicateSized(6, ExtArrS)},
|
|
|
|
|
"predicate-as-counter register"},
|
|
|
|
|
{"counter below the counter range", "PPTRUE", ExtFormPredicateCounter,
|
|
|
|
|
[]ExtOperand{ExtCounterPredicate(7, ExtArrS)},
|
|
|
|
|
"outside PN8-PN15"},
|
|
|
|
|
{"operand where none belongs", "SETFFR", ExtFormNone,
|
|
|
|
|
[]ExtOperand{pb(13)},
|
|
|
|
|
"takes 0 operands"},
|
|
|
|
|
} {
|
|
|
|
|
in := extInstruction(t, tt.mnem, tt.form)
|
|
|
|
|
_, err := in.Encode(tt.ops)
|
|
|
|
|
if err == nil {
|
|
|
|
|
t.Errorf("%s: encode succeeded, want an error", tt.name)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
if !strings.Contains(err.Error(), tt.quote) {
|
|
|
|
|
t.Errorf("%s: error %q lacks %q", tt.name, err, tt.quote)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-10-07 02:20:25 +02:00
|
|
|
|
|
|
|
|
// extInstructionMeta finds the row whose name, form, governing-predicate
|
|
|
|
|
// qualifier and fixed arrangement all match.
|
|
|
|
|
func extInstructionMeta(t *testing.T, mnem string, form ExtForm, qual ExtQualifier, arr ExtArrangement) ExtInstr {
|
|
|
|
|
t.Helper()
|
|
|
|
|
for _, in := range Extensions(ARM64) {
|
|
|
|
|
if in.Name == mnem && in.Form == form && in.PgQual == qual && in.Arr == arr {
|
|
|
|
|
return in
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
t.Fatalf("no extended %s with the %s form, %s qualifier and %s arrangement", mnem, form, qual, arr)
|
|
|
|
|
return ExtInstr{}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TestArm64ExtZGolden pins the SVE2.1 Z-alias families (unary and binary
|
|
|
|
|
// predicated forms, immediate aliases, permutations, selects, splices,
|
|
|
|
|
// compact and expand, the register-copy forms and MOVPRFX) against the
|
|
|
|
|
// toolchain-generated corpus, the same provenance as the predicate family
|
|
|
|
|
// above. The lookup matches the qualifier and arrangement metadata the
|
|
|
|
|
// rows carry, because one mnemonic registers several rows over one form.
|
|
|
|
|
func TestArm64ExtZGolden(t *testing.T) {
|
|
|
|
|
for _, tt := range []struct {
|
|
|
|
|
name string
|
|
|
|
|
mnem string
|
|
|
|
|
form ExtForm
|
|
|
|
|
qual ExtQualifier
|
|
|
|
|
arr ExtArrangement
|
|
|
|
|
ops []ExtOperand
|
|
|
|
|
want uint32
|
|
|
|
|
}{
|
|
|
|
|
{"ZABS Z7.D, P4.M, Z13.D", "ZABS", ExtFormZUnary, ExtQualMerging, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrD), ExtPredicate(4, ExtQualMerging), ExtVector(13, ExtArrD)},
|
|
|
|
|
0x04d6b0ed},
|
|
|
|
|
{"ZABS Z7.D, P4.Z, Z13.D", "ZABS", ExtFormZUnary, ExtQualZeroing, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrD), ExtPredicate(4, ExtQualZeroing), ExtVector(13, ExtArrD)},
|
|
|
|
|
0x04c6b0ed},
|
|
|
|
|
{"ZADD Z7.D, Z23.D, Z13.D", "ZADD", ExtFormVectorsZm, 0, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrD), ExtVector(23, ExtArrD), ExtVector(13, ExtArrD)},
|
|
|
|
|
0x04e702ed},
|
|
|
|
|
{"ZAND Z7.D, Z6.D, Z23.D", "ZAND", ExtFormVectorsZm, 0, ExtArrD,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrD), ExtVector(6, ExtArrD), ExtVector(23, ExtArrD)},
|
|
|
|
|
0x042730d7},
|
|
|
|
|
{"ZBIC Z7.D, Z6.D, Z23.D", "ZBIC", ExtFormVectorsZm, 0, ExtArrD,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrD), ExtVector(6, ExtArrD), ExtVector(23, ExtArrD)},
|
|
|
|
|
0x04e730d7},
|
|
|
|
|
{"ZCLS Z7.D, P4.M, Z13.D", "ZCLS", ExtFormZUnary, ExtQualMerging, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrD), ExtPredicate(4, ExtQualMerging), ExtVector(13, ExtArrD)},
|
|
|
|
|
0x04d8b0ed},
|
|
|
|
|
{"ZCLS Z7.D, P4.Z, Z13.D", "ZCLS", ExtFormZUnary, ExtQualZeroing, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrD), ExtPredicate(4, ExtQualZeroing), ExtVector(13, ExtArrD)},
|
|
|
|
|
0x04c8b0ed},
|
|
|
|
|
{"ZCLZ Z7.D, P4.M, Z13.D", "ZCLZ", ExtFormZUnary, ExtQualMerging, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrD), ExtPredicate(4, ExtQualMerging), ExtVector(13, ExtArrD)},
|
|
|
|
|
0x04d9b0ed},
|
|
|
|
|
{"ZCLZ Z7.D, P4.Z, Z13.D", "ZCLZ", ExtFormZUnary, ExtQualZeroing, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrD), ExtPredicate(4, ExtQualZeroing), ExtVector(13, ExtArrD)},
|
|
|
|
|
0x04c9b0ed},
|
|
|
|
|
{"ZCOMPACT Z7.D, P4, Z13.D", "ZCOMPACT", ExtFormZGov, 0, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrD), ExtPredicate(4, ExtQualNone), ExtVector(13, ExtArrD)},
|
|
|
|
|
0x05e190ed},
|
|
|
|
|
{"ZCOMPACT Z7.D, P4, Z13.D", "ZCOMPACT", ExtFormZGov, 0, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrD), ExtPredicate(4, ExtQualNone), ExtVector(13, ExtArrD)},
|
|
|
|
|
0x05e190ed},
|
|
|
|
|
{"ZEOR Z7.D, Z6.D, Z23.D", "ZEOR", ExtFormVectorsZm, 0, ExtArrD,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrD), ExtVector(6, ExtArrD), ExtVector(23, ExtArrD)},
|
|
|
|
|
0x04a730d7},
|
|
|
|
|
{"ZEXPAND Z7.D, P4, Z13.D", "ZEXPAND", ExtFormZGov, 0, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrD), ExtPredicate(4, ExtQualNone), ExtVector(13, ExtArrD)},
|
|
|
|
|
0x05f190ed},
|
|
|
|
|
{"ZMOVPRFX Z7.D, P4.Z, Z21.D", "ZMOVPRFX", ExtFormZUnary, ExtQualAny, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrD), ExtPredicate(4, ExtQualZeroing), ExtVector(21, ExtArrD)},
|
|
|
|
|
0x04d030f5},
|
|
|
|
|
{"ZMOVPRFX Z11, Z6", "ZMOVPRFX", ExtFormZMoveBare, 0, ExtArrNone,
|
|
|
|
|
[]ExtOperand{{Kind: ExtZReg, Reg: 11}, {Kind: ExtZReg, Reg: 6}},
|
|
|
|
|
0x0420bd66},
|
|
|
|
|
{"ZNEG Z7.D, P4.M, Z13.D", "ZNEG", ExtFormZUnary, ExtQualMerging, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrD), ExtPredicate(4, ExtQualMerging), ExtVector(13, ExtArrD)},
|
|
|
|
|
0x04d7b0ed},
|
|
|
|
|
{"ZNEG Z7.D, P4.Z, Z13.D", "ZNEG", ExtFormZUnary, ExtQualZeroing, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrD), ExtPredicate(4, ExtQualZeroing), ExtVector(13, ExtArrD)},
|
|
|
|
|
0x04c7b0ed},
|
|
|
|
|
{"ZNOT Z7.D, P4.M, Z13.D", "ZNOT", ExtFormZUnary, ExtQualMerging, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrD), ExtPredicate(4, ExtQualMerging), ExtVector(13, ExtArrD)},
|
|
|
|
|
0x04deb0ed},
|
|
|
|
|
{"ZNOT Z7.D, P4.Z, Z13.D", "ZNOT", ExtFormZUnary, ExtQualZeroing, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrD), ExtPredicate(4, ExtQualZeroing), ExtVector(13, ExtArrD)},
|
|
|
|
|
0x04ceb0ed},
|
|
|
|
|
{"ZORR Z7.D, Z6.D, Z23.D", "ZORR", ExtFormVectorsZm, 0, ExtArrD,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrD), ExtVector(6, ExtArrD), ExtVector(23, ExtArrD)},
|
|
|
|
|
0x046730d7},
|
|
|
|
|
{"ZREV Z1.S, Z26.S", "ZREV", ExtFormZMove, 0, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtVector(1, ExtArrS), ExtVector(26, ExtArrS)},
|
|
|
|
|
0x05b8383a},
|
|
|
|
|
{"ZREVB Z7.D, P4.M, Z13.D", "ZREVB", ExtFormZUnary, ExtQualMerging, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrD), ExtPredicate(4, ExtQualMerging), ExtVector(13, ExtArrD)},
|
|
|
|
|
0x05e490ed},
|
|
|
|
|
{"ZREVB Z7.D, P4.Z, Z13.D", "ZREVB", ExtFormZUnary, ExtQualZeroing, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrD), ExtPredicate(4, ExtQualZeroing), ExtVector(13, ExtArrD)},
|
|
|
|
|
0x05e4b0ed},
|
|
|
|
|
{"ZREVD Z13.Q, P1.M, Z22.Q", "ZREVD", ExtFormZUnary, ExtQualMerging, ExtArrQ,
|
|
|
|
|
[]ExtOperand{ExtVector(13, ExtArrQ), ExtPredicate(1, ExtQualMerging), ExtVector(22, ExtArrQ)},
|
|
|
|
|
0x052e85b6},
|
|
|
|
|
{"ZREVD Z13.Q, P1.Z, Z22.Q", "ZREVD", ExtFormZUnary, ExtQualZeroing, ExtArrQ,
|
|
|
|
|
[]ExtOperand{ExtVector(13, ExtArrQ), ExtPredicate(1, ExtQualZeroing), ExtVector(22, ExtArrQ)},
|
|
|
|
|
0x052ea5b6},
|
|
|
|
|
{"ZREVH Z7.D, P4.M, Z13.D", "ZREVH", ExtFormZUnary, ExtQualMerging, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrD), ExtPredicate(4, ExtQualMerging), ExtVector(13, ExtArrD)},
|
|
|
|
|
0x05e590ed},
|
|
|
|
|
{"ZREVH Z7.D, P4.Z, Z13.D", "ZREVH", ExtFormZUnary, ExtQualZeroing, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrD), ExtPredicate(4, ExtQualZeroing), ExtVector(13, ExtArrD)},
|
|
|
|
|
0x05e5b0ed},
|
|
|
|
|
{"ZREVW Z13.D, P1.M, Z22.D", "ZREVW", ExtFormZUnary, ExtQualMerging, ExtArrD,
|
|
|
|
|
[]ExtOperand{ExtVector(13, ExtArrD), ExtPredicate(1, ExtQualMerging), ExtVector(22, ExtArrD)},
|
|
|
|
|
0x05e685b6},
|
|
|
|
|
{"ZREVW Z13.D, P1.Z, Z22.D", "ZREVW", ExtFormZUnary, ExtQualZeroing, ExtArrD,
|
|
|
|
|
[]ExtOperand{ExtVector(13, ExtArrD), ExtPredicate(1, ExtQualZeroing), ExtVector(22, ExtArrD)},
|
|
|
|
|
0x05e6a5b6},
|
|
|
|
|
{"ZSEL Z23.B, Z21.B, P14, Z2.B", "ZSEL", ExtFormZSelect, 0, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtVector(23, ExtArrB), ExtVector(21, ExtArrB), ExtPredicate(14, ExtQualNone), ExtVector(2, ExtArrB)},
|
|
|
|
|
0x0537faa2},
|
|
|
|
|
{"ZSQABS Z7.D, P4.M, Z13.D", "ZSQABS", ExtFormZUnary, ExtQualMerging, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrD), ExtPredicate(4, ExtQualMerging), ExtVector(13, ExtArrD)},
|
|
|
|
|
0x44c8b0ed},
|
|
|
|
|
{"ZSQABS Z7.D, P4.Z, Z13.D", "ZSQABS", ExtFormZUnary, ExtQualZeroing, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrD), ExtPredicate(4, ExtQualZeroing), ExtVector(13, ExtArrD)},
|
|
|
|
|
0x44cab0ed},
|
|
|
|
|
{"ZSQNEG Z7.D, P4.M, Z13.D", "ZSQNEG", ExtFormZUnary, ExtQualMerging, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrD), ExtPredicate(4, ExtQualMerging), ExtVector(13, ExtArrD)},
|
|
|
|
|
0x44c9b0ed},
|
|
|
|
|
{"ZSQNEG Z7.D, P4.Z, Z13.D", "ZSQNEG", ExtFormZUnary, ExtQualZeroing, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrD), ExtPredicate(4, ExtQualZeroing), ExtVector(13, ExtArrD)},
|
|
|
|
|
0x44cbb0ed},
|
|
|
|
|
{"ZSUB Z7.D, Z23.D, Z13.D", "ZSUB", ExtFormVectorsZm, 0, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrD), ExtVector(23, ExtArrD), ExtVector(13, ExtArrD)},
|
|
|
|
|
0x04e706ed},
|
|
|
|
|
{"ZSUNPKHI Z15.B, Z0.H", "ZSUNPKHI", ExtFormZUnpack, 0, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtVector(15, ExtArrB), ExtVector(0, ExtArrH)},
|
|
|
|
|
0x057139e0},
|
|
|
|
|
{"ZSUNPKLO Z15.B, Z0.H", "ZSUNPKLO", ExtFormZUnpack, 0, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtVector(15, ExtArrB), ExtVector(0, ExtArrH)},
|
|
|
|
|
0x057039e0},
|
|
|
|
|
{"ZSXTB Z7.D, P4.M, Z13.D", "ZSXTB", ExtFormZUnary, ExtQualMerging, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrD), ExtPredicate(4, ExtQualMerging), ExtVector(13, ExtArrD)},
|
|
|
|
|
0x04d0b0ed},
|
|
|
|
|
{"ZSXTB Z7.D, P4.Z, Z13.D", "ZSXTB", ExtFormZUnary, ExtQualZeroing, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrD), ExtPredicate(4, ExtQualZeroing), ExtVector(13, ExtArrD)},
|
|
|
|
|
0x04c0b0ed},
|
|
|
|
|
{"ZSXTH Z7.D, P4.M, Z13.D", "ZSXTH", ExtFormZUnary, ExtQualMerging, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrD), ExtPredicate(4, ExtQualMerging), ExtVector(13, ExtArrD)},
|
|
|
|
|
0x04d2b0ed},
|
|
|
|
|
{"ZSXTH Z7.D, P4.Z, Z13.D", "ZSXTH", ExtFormZUnary, ExtQualZeroing, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrD), ExtPredicate(4, ExtQualZeroing), ExtVector(13, ExtArrD)},
|
|
|
|
|
0x04c2b0ed},
|
|
|
|
|
{"ZSXTW Z13.D, P1.M, Z22.D", "ZSXTW", ExtFormZUnary, ExtQualMerging, ExtArrD,
|
|
|
|
|
[]ExtOperand{ExtVector(13, ExtArrD), ExtPredicate(1, ExtQualMerging), ExtVector(22, ExtArrD)},
|
|
|
|
|
0x04d4a5b6},
|
|
|
|
|
{"ZSXTW Z13.D, P1.Z, Z22.D", "ZSXTW", ExtFormZUnary, ExtQualZeroing, ExtArrD,
|
|
|
|
|
[]ExtOperand{ExtVector(13, ExtArrD), ExtPredicate(1, ExtQualZeroing), ExtVector(22, ExtArrD)},
|
|
|
|
|
0x04c4a5b6},
|
|
|
|
|
{"ZTBX Z7.D, Z23.D, Z13.D", "ZTBX", ExtFormVectorsZm, 0, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrD), ExtVector(23, ExtArrD), ExtVector(13, ExtArrD)},
|
|
|
|
|
0x05e72eed},
|
|
|
|
|
{"ZTBXQ Z7.D, Z23.D, Z13.D", "ZTBXQ", ExtFormVectorsZm, 0, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrD), ExtVector(23, ExtArrD), ExtVector(13, ExtArrD)},
|
|
|
|
|
0x05e736ed},
|
|
|
|
|
{"ZTRN1 Z7.D, Z23.D, Z13.D", "ZTRN1", ExtFormVectorsZm, 0, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrD), ExtVector(23, ExtArrD), ExtVector(13, ExtArrD)},
|
|
|
|
|
0x05e772ed},
|
|
|
|
|
{"ZTRN1 Z7.Q, Z6.Q, Z23.Q", "ZTRN1", ExtFormVectorsZm, 0, ExtArrQ,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrQ), ExtVector(6, ExtArrQ), ExtVector(23, ExtArrQ)},
|
|
|
|
|
0x05a718d7},
|
|
|
|
|
{"ZTRN2 Z7.D, Z23.D, Z13.D", "ZTRN2", ExtFormVectorsZm, 0, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrD), ExtVector(23, ExtArrD), ExtVector(13, ExtArrD)},
|
|
|
|
|
0x05e776ed},
|
|
|
|
|
{"ZTRN2 Z7.Q, Z6.Q, Z23.Q", "ZTRN2", ExtFormVectorsZm, 0, ExtArrQ,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrQ), ExtVector(6, ExtArrQ), ExtVector(23, ExtArrQ)},
|
|
|
|
|
0x05a71cd7},
|
|
|
|
|
{"ZUUNPKHI Z15.B, Z0.H", "ZUUNPKHI", ExtFormZUnpack, 0, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtVector(15, ExtArrB), ExtVector(0, ExtArrH)},
|
|
|
|
|
0x057339e0},
|
|
|
|
|
{"ZUUNPKLO Z15.B, Z0.H", "ZUUNPKLO", ExtFormZUnpack, 0, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtVector(15, ExtArrB), ExtVector(0, ExtArrH)},
|
|
|
|
|
0x057239e0},
|
|
|
|
|
{"ZUXTB Z7.D, P4.M, Z13.D", "ZUXTB", ExtFormZUnary, ExtQualMerging, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrD), ExtPredicate(4, ExtQualMerging), ExtVector(13, ExtArrD)},
|
|
|
|
|
0x04d1b0ed},
|
|
|
|
|
{"ZUXTB Z7.D, P4.Z, Z13.D", "ZUXTB", ExtFormZUnary, ExtQualZeroing, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrD), ExtPredicate(4, ExtQualZeroing), ExtVector(13, ExtArrD)},
|
|
|
|
|
0x04c1b0ed},
|
|
|
|
|
{"ZUXTH Z7.D, P4.M, Z13.D", "ZUXTH", ExtFormZUnary, ExtQualMerging, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrD), ExtPredicate(4, ExtQualMerging), ExtVector(13, ExtArrD)},
|
|
|
|
|
0x04d3b0ed},
|
|
|
|
|
{"ZUXTH Z7.D, P4.Z, Z13.D", "ZUXTH", ExtFormZUnary, ExtQualZeroing, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrD), ExtPredicate(4, ExtQualZeroing), ExtVector(13, ExtArrD)},
|
|
|
|
|
0x04c3b0ed},
|
|
|
|
|
{"ZUXTW Z13.D, P1.M, Z22.D", "ZUXTW", ExtFormZUnary, ExtQualMerging, ExtArrD,
|
|
|
|
|
[]ExtOperand{ExtVector(13, ExtArrD), ExtPredicate(1, ExtQualMerging), ExtVector(22, ExtArrD)},
|
|
|
|
|
0x04d5a5b6},
|
|
|
|
|
{"ZUXTW Z13.D, P1.Z, Z22.D", "ZUXTW", ExtFormZUnary, ExtQualZeroing, ExtArrD,
|
|
|
|
|
[]ExtOperand{ExtVector(13, ExtArrD), ExtPredicate(1, ExtQualZeroing), ExtVector(22, ExtArrD)},
|
|
|
|
|
0x04c5a5b6},
|
|
|
|
|
{"ZUZP1 Z7.D, Z23.D, Z13.D", "ZUZP1", ExtFormVectorsZm, 0, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrD), ExtVector(23, ExtArrD), ExtVector(13, ExtArrD)},
|
|
|
|
|
0x05e76aed},
|
|
|
|
|
{"ZUZP1 Z7.Q, Z6.Q, Z23.Q", "ZUZP1", ExtFormVectorsZm, 0, ExtArrQ,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrQ), ExtVector(6, ExtArrQ), ExtVector(23, ExtArrQ)},
|
|
|
|
|
0x05a708d7},
|
|
|
|
|
{"ZUZP2 Z7.D, Z23.D, Z13.D", "ZUZP2", ExtFormVectorsZm, 0, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrD), ExtVector(23, ExtArrD), ExtVector(13, ExtArrD)},
|
|
|
|
|
0x05e76eed},
|
|
|
|
|
{"ZUZP2 Z7.Q, Z6.Q, Z23.Q", "ZUZP2", ExtFormVectorsZm, 0, ExtArrQ,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrQ), ExtVector(6, ExtArrQ), ExtVector(23, ExtArrQ)},
|
|
|
|
|
0x05a70cd7},
|
|
|
|
|
{"ZUZPQ1 Z7.D, Z23.D, Z13.D", "ZUZPQ1", ExtFormVectorsZm, 0, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrD), ExtVector(23, ExtArrD), ExtVector(13, ExtArrD)},
|
|
|
|
|
0x44c7eaed},
|
|
|
|
|
{"ZUZPQ2 Z7.D, Z23.D, Z13.D", "ZUZPQ2", ExtFormVectorsZm, 0, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrD), ExtVector(23, ExtArrD), ExtVector(13, ExtArrD)},
|
|
|
|
|
0x44c7eeed},
|
|
|
|
|
{"ZZIP1 Z7.D, Z23.D, Z13.D", "ZZIP1", ExtFormVectorsZm, 0, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrD), ExtVector(23, ExtArrD), ExtVector(13, ExtArrD)},
|
|
|
|
|
0x05e762ed},
|
|
|
|
|
{"ZZIP1 Z7.Q, Z6.Q, Z23.Q", "ZZIP1", ExtFormVectorsZm, 0, ExtArrQ,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrQ), ExtVector(6, ExtArrQ), ExtVector(23, ExtArrQ)},
|
|
|
|
|
0x05a700d7},
|
|
|
|
|
{"ZZIP2 Z7.D, Z23.D, Z13.D", "ZZIP2", ExtFormVectorsZm, 0, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrD), ExtVector(23, ExtArrD), ExtVector(13, ExtArrD)},
|
|
|
|
|
0x05e766ed},
|
|
|
|
|
{"ZZIP2 Z7.Q, Z6.Q, Z23.Q", "ZZIP2", ExtFormVectorsZm, 0, ExtArrQ,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrQ), ExtVector(6, ExtArrQ), ExtVector(23, ExtArrQ)},
|
|
|
|
|
0x05a704d7},
|
|
|
|
|
{"ZZIPQ1 Z7.D, Z23.D, Z13.D", "ZZIPQ1", ExtFormVectorsZm, 0, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrD), ExtVector(23, ExtArrD), ExtVector(13, ExtArrD)},
|
|
|
|
|
0x44c7e2ed},
|
|
|
|
|
{"ZZIPQ2 Z7.D, Z23.D, Z13.D", "ZZIPQ2", ExtFormVectorsZm, 0, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtVector(7, ExtArrD), ExtVector(23, ExtArrD), ExtVector(13, ExtArrD)},
|
|
|
|
|
0x44c7e6ed},
|
|
|
|
|
{"ZDUP R2, Z10.D", "ZDUP", ExtFormZFromGeneral, 0, ExtArrD,
|
|
|
|
|
[]ExtOperand{ExtGeneral(2), ExtVector(10, ExtArrD)},
|
|
|
|
|
0x05e0384a},
|
|
|
|
|
{"ZINSR R2, Z10.D", "ZINSR", ExtFormZFromGeneral, 0, ExtArrD,
|
|
|
|
|
[]ExtOperand{ExtGeneral(2), ExtVector(10, ExtArrD)},
|
|
|
|
|
0x05e4384a},
|
|
|
|
|
{"ZADD $6, Z7.D, Z7.D", "ZADD", ExtFormZImmediateSource, 0, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtImmediate(6), ExtVector(7, ExtArrD), ExtVector(7, ExtArrD)},
|
|
|
|
|
0x25e0c0c7},
|
|
|
|
|
{"ZSUB $6, Z7.D, Z7.D", "ZSUB", ExtFormZImmediateSource, 0, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtImmediate(6), ExtVector(7, ExtArrD), ExtVector(7, ExtArrD)},
|
|
|
|
|
0x25e1c0c7},
|
|
|
|
|
{"ZSUBR $6, Z7.D, Z7.D", "ZSUBR", ExtFormZImmediateSource, 0, ExtArrNone,
|
|
|
|
|
[]ExtOperand{ExtImmediate(6), ExtVector(7, ExtArrD), ExtVector(7, ExtArrD)},
|
|
|
|
|
0x25e3c0c7},
|
|
|
|
|
} {
|
|
|
|
|
in := extInstructionMeta(t, tt.mnem, tt.form, tt.qual, tt.arr)
|
|
|
|
|
got, err := in.Encode(tt.ops)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Errorf("%s: encode: %v", tt.name, err)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
if want := hex.EncodeToString(extWordLE(tt.want)); hex.EncodeToString(got) != want {
|
|
|
|
|
t.Errorf("%s:\n got %x\n want %s", tt.name, got, want)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|