diff --git a/arch/arm64_ext.go b/arch/arm64_ext.go index a63360a..292ae71 100644 --- a/arch/arm64_ext.go +++ b/arch/arm64_ext.go @@ -2597,8 +2597,19 @@ func (in ExtInstr) encodeQuadReduce(ops []ExtOperand) ([]byte, error) { if err := in.barePredicate(pg, 2, 0, 7); err != nil { return nil, err } - if err := in.simdReg(vn, 3); err != nil { - return nil, err + if vn.Kind != ExtVReg { + return nil, fmt.Errorf("%s: operand 3 wants a SIMD register, got %s", + in.Name, vn.Kind) + } + if vn.Reg < 0 || vn.Reg > 31 { + return nil, fmt.Errorf("%s: operand 3 is V%d, outside V0-V31", in.Name, vn.Reg) + } + if vn.Qual != ExtQualNone { + return nil, fmt.Errorf("%s: operand 3 takes no qualifier, got %q", in.Name, vn.Qual) + } + if vn.Arr == ExtArrNone { + return nil, fmt.Errorf("%s: operand 3 carries no quadword suffix, want .B16, .H8, .S4 or .D2", + in.Name) } if vn.Arr != zdn.Arr { return nil, fmt.Errorf("%s: operand 3 carries arrangement %s, want %s", @@ -3189,6 +3200,65 @@ var arm64Extensions = []ExtInstr{ Word: 0x45207400, Form: ExtFormNarrow, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZSUBHNT; inst_gen.go + arm64sveenc.s"}, + // --- the SVE2.1 pairwise and quadword-reduction families ------------------ + // + // ADDP sums the halves of two vectors pairwise under a governing + // predicate, ADDPT the top halves of 128-bit pairs (predicated and + // unpredicated), and the QV class reduces a quadword vector into a + // scalable accumulator. The QV vector operand carries the counted + // quadword spelling the corpus writes, V5.S4 and friends. Provenance + // as above: the toolchain encoding table and its generated corpus, both + // produced from Arm's official ISA description, and the golden test + // pins every corpus line of each class. + {Name: "ZADDP", Summary: "Add vector halves pairwise, merging", + Word: 0x4411a000, Form: ExtFormZPredicatedSource, Size: extSizeBHSD, PgQual: ExtQualMerging, Feature: ExtFeatureSVE2p1, + Ref: "ARM DDI 0487J SVE2.1: ZADDP; inst_gen.go + arm64sveenc.s"}, + {Name: "ZADDPT", Summary: "Add the top halves of 128-bit pairs, merging", + Word: 0x04c40000, Form: ExtFormZPredicatedSource, Arr: ExtArrD, PgQual: ExtQualMerging, Feature: ExtFeatureSVE2p1, + Ref: "ARM DDI 0487J SVE2.1: ZADDPT; inst_gen.go + arm64sveenc.s"}, + {Name: "ZADDPT", Summary: "Add the top halves of 128-bit pairs, unpredicated", + Word: 0x04e00800, Form: ExtFormVectorsZm, Arr: ExtArrD, Feature: ExtFeatureSVE2p1, + Ref: "ARM DDI 0487J SVE2.1: ZADDPT; inst_gen.go + arm64sveenc.s"}, + {Name: "ZADDQV", Summary: "Add a quadword vector into a scalable accumulator", + Word: 0x04052000, Form: ExtFormQuadReduce, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1, + Ref: "ARM DDI 0487J SVE2.1: ZADDQV; inst_gen.go + arm64sveenc.s"}, + {Name: "ZANDQV", Summary: "And a quadword vector into a scalable accumulator", + Word: 0x041e2000, Form: ExtFormQuadReduce, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1, + Ref: "ARM DDI 0487J SVE2.1: ZANDQV; inst_gen.go + arm64sveenc.s"}, + {Name: "ZEORQV", Summary: "Exclusive-or a quadword vector into a scalable accumulator", + Word: 0x041d2000, Form: ExtFormQuadReduce, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1, + Ref: "ARM DDI 0487J SVE2.1: ZEORQV; inst_gen.go + arm64sveenc.s"}, + {Name: "ZFADDQV", Summary: "Add floating-point a quadword vector into a scalable accumulator", + Word: 0x6410a000, Form: ExtFormQuadReduce, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1, + Ref: "ARM DDI 0487J SVE2.1: ZFADDQV; inst_gen.go + arm64sveenc.s"}, + {Name: "ZFMAXNMQV", Summary: "Maximum number of a quadword vector into a scalable accumulator", + Word: 0x6414a000, Form: ExtFormQuadReduce, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1, + Ref: "ARM DDI 0487J SVE2.1: ZFMAXNMQV; inst_gen.go + arm64sveenc.s"}, + {Name: "ZFMAXQV", Summary: "Maximum of a quadword vector into a scalable accumulator", + Word: 0x6416a000, Form: ExtFormQuadReduce, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1, + Ref: "ARM DDI 0487J SVE2.1: ZFMAXQV; inst_gen.go + arm64sveenc.s"}, + {Name: "ZFMINNMQV", Summary: "Minimum number of a quadword vector into a scalable accumulator", + Word: 0x6415a000, Form: ExtFormQuadReduce, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1, + Ref: "ARM DDI 0487J SVE2.1: ZFMINNMQV; inst_gen.go + arm64sveenc.s"}, + {Name: "ZFMINQV", Summary: "Minimum of a quadword vector into a scalable accumulator", + Word: 0x6417a000, Form: ExtFormQuadReduce, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1, + Ref: "ARM DDI 0487J SVE2.1: ZFMINQV; inst_gen.go + arm64sveenc.s"}, + {Name: "ZORQV", Summary: "Or a quadword vector into a scalable accumulator", + Word: 0x041c2000, Form: ExtFormQuadReduce, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1, + Ref: "ARM DDI 0487J SVE2.1: ZORQV; inst_gen.go + arm64sveenc.s"}, + {Name: "ZSMAXQV", Summary: "Signed maximum of a quadword vector into a scalable accumulator", + Word: 0x040c2000, Form: ExtFormQuadReduce, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1, + Ref: "ARM DDI 0487J SVE2.1: ZSMAXQV; inst_gen.go + arm64sveenc.s"}, + {Name: "ZSMINQV", Summary: "Signed minimum of a quadword vector into a scalable accumulator", + Word: 0x040e2000, Form: ExtFormQuadReduce, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1, + Ref: "ARM DDI 0487J SVE2.1: ZSMINQV; inst_gen.go + arm64sveenc.s"}, + {Name: "ZUMAXQV", Summary: "Unsigned maximum of a quadword vector into a scalable accumulator", + Word: 0x040d2000, Form: ExtFormQuadReduce, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1, + Ref: "ARM DDI 0487J SVE2.1: ZUMAXQV; inst_gen.go + arm64sveenc.s"}, + {Name: "ZUMINQV", Summary: "Unsigned minimum of a quadword vector into a scalable accumulator", + Word: 0x040f2000, Form: ExtFormQuadReduce, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1, + Ref: "ARM DDI 0487J SVE2.1: ZUMINQV; inst_gen.go + arm64sveenc.s"}, + // --- the SVE2 crypto family ---------------------------------------------- // // The multi-precision carry steps (ADCLB, ADCLT, SBCLB, SBCLT), the SHA3 diff --git a/arch/arm64_ext_test.go b/arch/arm64_ext_test.go index b34701b..3513be5 100644 --- a/arch/arm64_ext_test.go +++ b/arch/arm64_ext_test.go @@ -1348,41 +1348,100 @@ func TestArm64ExtStage4Golden(t *testing.T) { name string mnem string form ExtForm + qual ExtQualifier + arr ExtArrangement ops []ExtOperand want uint32 }{ - {"ZADDHNB Z22.S, Z10.S, Z8.H", "ZADDHNB", ExtFormNarrow, + {"ZADDHNB Z22.S, Z10.S, Z8.H", "ZADDHNB", ExtFormNarrow, ExtQualNone, ExtArrNone, []ExtOperand{ExtVector(22, ExtArrS), ExtVector(10, ExtArrS), ExtVector(8, ExtArrH)}, 0x45b66148}, - {"ZADDHNT Z22.S, Z10.S, Z8.H", "ZADDHNT", ExtFormNarrow, + {"ZADDHNT Z22.S, Z10.S, Z8.H", "ZADDHNT", ExtFormNarrow, ExtQualNone, ExtArrNone, []ExtOperand{ExtVector(22, ExtArrS), ExtVector(10, ExtArrS), ExtVector(8, ExtArrH)}, 0x45b66548}, - {"ZRADDHNB Z22.S, Z10.S, Z8.H", "ZRADDHNB", ExtFormNarrow, + {"ZRADDHNB Z22.S, Z10.S, Z8.H", "ZRADDHNB", ExtFormNarrow, ExtQualNone, ExtArrNone, []ExtOperand{ExtVector(22, ExtArrS), ExtVector(10, ExtArrS), ExtVector(8, ExtArrH)}, 0x45b66948}, - {"ZRADDHNT Z22.S, Z10.S, Z8.H", "ZRADDHNT", ExtFormNarrow, + {"ZRADDHNT Z22.S, Z10.S, Z8.H", "ZRADDHNT", ExtFormNarrow, ExtQualNone, ExtArrNone, []ExtOperand{ExtVector(22, ExtArrS), ExtVector(10, ExtArrS), ExtVector(8, ExtArrH)}, 0x45b66d48}, - {"ZRSUBHNB Z22.S, Z10.S, Z8.H", "ZRSUBHNB", ExtFormNarrow, + {"ZRSUBHNB Z22.S, Z10.S, Z8.H", "ZRSUBHNB", ExtFormNarrow, ExtQualNone, ExtArrNone, []ExtOperand{ExtVector(22, ExtArrS), ExtVector(10, ExtArrS), ExtVector(8, ExtArrH)}, 0x45b67948}, - {"ZRSUBHNT Z22.S, Z10.S, Z8.H", "ZRSUBHNT", ExtFormNarrow, + {"ZRSUBHNT Z22.S, Z10.S, Z8.H", "ZRSUBHNT", ExtFormNarrow, ExtQualNone, ExtArrNone, []ExtOperand{ExtVector(22, ExtArrS), ExtVector(10, ExtArrS), ExtVector(8, ExtArrH)}, 0x45b67d48}, - {"ZSUBHNB Z22.S, Z10.S, Z8.H", "ZSUBHNB", ExtFormNarrow, + {"ZSUBHNB Z22.S, Z10.S, Z8.H", "ZSUBHNB", ExtFormNarrow, ExtQualNone, ExtArrNone, []ExtOperand{ExtVector(22, ExtArrS), ExtVector(10, ExtArrS), ExtVector(8, ExtArrH)}, 0x45b67148}, - {"ZSUBHNT Z22.S, Z10.S, Z8.H", "ZSUBHNT", ExtFormNarrow, + {"ZSUBHNT Z22.S, Z10.S, Z8.H", "ZSUBHNT", ExtFormNarrow, ExtQualNone, ExtArrNone, []ExtOperand{ExtVector(22, ExtArrS), ExtVector(10, ExtArrS), ExtVector(8, ExtArrH)}, 0x45b67548}, - {"ZADDHNB Z8.H, Z10.H, Z11.B", "ZADDHNB", ExtFormNarrow, + {"ZADDHNB Z8.H, Z10.H, Z11.B", "ZADDHNB", ExtFormNarrow, ExtQualNone, ExtArrNone, []ExtOperand{ExtVector(8, ExtArrH), ExtVector(10, ExtArrH), ExtVector(11, ExtArrB)}, 0x4568614b}, - {"ZSUBHNT Z26.D, Z4.D, Z13.S", "ZSUBHNT", ExtFormNarrow, + {"ZSUBHNT Z26.D, Z4.D, Z13.S", "ZSUBHNT", ExtFormNarrow, ExtQualNone, ExtArrNone, []ExtOperand{ExtVector(26, ExtArrD), ExtVector(4, ExtArrD), ExtVector(13, ExtArrS)}, 0x45fa748d}, + // The pairwise and quadword-reduction classes. + {"ZADDP Z15.B, Z0.B, P3.M, Z0.B", "ZADDP", ExtFormZPredicatedSource, ExtQualMerging, ExtArrNone, + []ExtOperand{ExtVector(15, ExtArrB), ExtVector(0, ExtArrB), ExtPredicate(3, ExtQualMerging), ExtVector(0, ExtArrB)}, + 0x4411ade0}, + {"ZADDP Z9.S, Z2.S, P5.M, Z2.S", "ZADDP", ExtFormZPredicatedSource, ExtQualMerging, ExtArrNone, + []ExtOperand{ExtVector(9, ExtArrS), ExtVector(2, ExtArrS), ExtPredicate(5, ExtQualMerging), ExtVector(2, ExtArrS)}, + 0x4491b522}, + {"ZADDPT Z23.D, Z13.D, P1.M, Z13.D", "ZADDPT", ExtFormZPredicatedSource, ExtQualMerging, ExtArrD, + []ExtOperand{ExtVector(23, ExtArrD), ExtVector(13, ExtArrD), ExtPredicate(1, ExtQualMerging), ExtVector(13, ExtArrD)}, + 0x04c406ed}, + {"ZADDPT Z7.D, Z6.D, Z23.D", "ZADDPT", ExtFormVectorsZm, ExtQualNone, ExtArrD, + []ExtOperand{ExtVector(7, ExtArrD), ExtVector(6, ExtArrD), ExtVector(23, ExtArrD)}, + 0x04e708d7}, + // The quadword reductions, one vector per class word, the corpus + // line shared, plus a .D width the corpus line does not show. + {"ZADDQV Z25.S, P3, V5.S4", "ZADDQV", ExtFormQuadReduce, ExtQualNone, ExtArrNone, + []ExtOperand{ExtVector(25, ExtArrS), ExtPredicateSized(3, ExtArrNone), ExtOperand{Kind: ExtVReg, Reg: 5, Arr: ExtArrS}}, + 0x04852f25}, + {"ZADDQV Z9.D, P1, V7.D2", "ZADDQV", ExtFormQuadReduce, ExtQualNone, ExtArrNone, + []ExtOperand{ExtVector(9, ExtArrD), ExtPredicateSized(1, ExtArrNone), ExtOperand{Kind: ExtVReg, Reg: 7, Arr: ExtArrD}}, + 0x04c52527}, + {"ZANDQV Z25.S, P3, V5.S4", "ZANDQV", ExtFormQuadReduce, ExtQualNone, ExtArrNone, + []ExtOperand{ExtVector(25, ExtArrS), ExtPredicateSized(3, ExtArrNone), ExtOperand{Kind: ExtVReg, Reg: 5, Arr: ExtArrS}}, + 0x049e2f25}, + {"ZEORQV Z25.S, P3, V5.S4", "ZEORQV", ExtFormQuadReduce, ExtQualNone, ExtArrNone, + []ExtOperand{ExtVector(25, ExtArrS), ExtPredicateSized(3, ExtArrNone), ExtOperand{Kind: ExtVReg, Reg: 5, Arr: ExtArrS}}, + 0x049d2f25}, + {"ZORQV Z25.S, P3, V5.S4", "ZORQV", ExtFormQuadReduce, ExtQualNone, ExtArrNone, + []ExtOperand{ExtVector(25, ExtArrS), ExtPredicateSized(3, ExtArrNone), ExtOperand{Kind: ExtVReg, Reg: 5, Arr: ExtArrS}}, + 0x049c2f25}, + {"ZSMAXQV Z25.S, P3, V5.S4", "ZSMAXQV", ExtFormQuadReduce, ExtQualNone, ExtArrNone, + []ExtOperand{ExtVector(25, ExtArrS), ExtPredicateSized(3, ExtArrNone), ExtOperand{Kind: ExtVReg, Reg: 5, Arr: ExtArrS}}, + 0x048c2f25}, + {"ZSMINQV Z25.S, P3, V5.S4", "ZSMINQV", ExtFormQuadReduce, ExtQualNone, ExtArrNone, + []ExtOperand{ExtVector(25, ExtArrS), ExtPredicateSized(3, ExtArrNone), ExtOperand{Kind: ExtVReg, Reg: 5, Arr: ExtArrS}}, + 0x048e2f25}, + {"ZUMAXQV Z25.S, P3, V5.S4", "ZUMAXQV", ExtFormQuadReduce, ExtQualNone, ExtArrNone, + []ExtOperand{ExtVector(25, ExtArrS), ExtPredicateSized(3, ExtArrNone), ExtOperand{Kind: ExtVReg, Reg: 5, Arr: ExtArrS}}, + 0x048d2f25}, + {"ZUMINQV Z25.S, P3, V5.S4", "ZUMINQV", ExtFormQuadReduce, ExtQualNone, ExtArrNone, + []ExtOperand{ExtVector(25, ExtArrS), ExtPredicateSized(3, ExtArrNone), ExtOperand{Kind: ExtVReg, Reg: 5, Arr: ExtArrS}}, + 0x048f2f25}, + {"ZFADDQV Z25.S, P3, V5.S4", "ZFADDQV", ExtFormQuadReduce, ExtQualNone, ExtArrNone, + []ExtOperand{ExtVector(25, ExtArrS), ExtPredicateSized(3, ExtArrNone), ExtOperand{Kind: ExtVReg, Reg: 5, Arr: ExtArrS}}, + 0x6490af25}, + {"ZFMAXNMQV Z25.S, P3, V5.S4", "ZFMAXNMQV", ExtFormQuadReduce, ExtQualNone, ExtArrNone, + []ExtOperand{ExtVector(25, ExtArrS), ExtPredicateSized(3, ExtArrNone), ExtOperand{Kind: ExtVReg, Reg: 5, Arr: ExtArrS}}, + 0x6494af25}, + {"ZFMAXQV Z25.S, P3, V5.S4", "ZFMAXQV", ExtFormQuadReduce, ExtQualNone, ExtArrNone, + []ExtOperand{ExtVector(25, ExtArrS), ExtPredicateSized(3, ExtArrNone), ExtOperand{Kind: ExtVReg, Reg: 5, Arr: ExtArrS}}, + 0x6496af25}, + {"ZFMINNMQV Z25.S, P3, V5.S4", "ZFMINNMQV", ExtFormQuadReduce, ExtQualNone, ExtArrNone, + []ExtOperand{ExtVector(25, ExtArrS), ExtPredicateSized(3, ExtArrNone), ExtOperand{Kind: ExtVReg, Reg: 5, Arr: ExtArrS}}, + 0x6495af25}, + {"ZFMINQV Z25.S, P3, V5.S4", "ZFMINQV", ExtFormQuadReduce, ExtQualNone, ExtArrNone, + []ExtOperand{ExtVector(25, ExtArrS), ExtPredicateSized(3, ExtArrNone), ExtOperand{Kind: ExtVReg, Reg: 5, Arr: ExtArrS}}, + 0x6497af25}, } { - in := extInstructionMeta(t, tt.mnem, tt.form, ExtQualNone, ExtArrNone) + 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) diff --git a/asm/arm64_ext.go b/asm/arm64_ext.go index 58cea82..f3f76a9 100644 --- a/asm/arm64_ext.go +++ b/asm/arm64_ext.go @@ -286,17 +286,35 @@ func arm64ExtGeneral(text string) (arch.ExtOperand, bool) { // arm64ExtSIMD parses a 128-bit SIMD register operand: V0..V31, written // bare, the scalar destination the reductions and the crypto read-back -// forms take. The register range is left to the encoding. +// forms take, or with the counted quadword suffix of the SVE2.1 QV class, +// V5.S4 reading four 32-bit lanes (the spellings .B16, .H8, .S4 and .D2; +// no other suffix parses). The register range is left to the encoding. func arm64ExtSIMD(text string) (arch.ExtOperand, bool) { rest, ok := strings.CutPrefix(text, "V") if !ok { return arch.ExtOperand{}, false } - reg, arr, ok := arm64ExtRegDigits(rest) - if !ok || arr != arch.ExtArrNone { + arr := arch.ExtArrNone + for _, q := range []struct { + suffix string + arr arch.ExtArrangement + }{ + {"B16", arch.ExtArrB}, + {"H8", arch.ExtArrH}, + {"S4", arch.ExtArrS}, + {"D2", arch.ExtArrD}, + } { + if s := "." + q.suffix; strings.HasSuffix(rest, s) { + arr = q.arr + rest = rest[:len(rest)-len(s)] + break + } + } + reg, bare, ok := arm64ExtRegDigits(rest) + if !ok || bare != arch.ExtArrNone { return arch.ExtOperand{}, false } - return arch.ExtOperand{Kind: arch.ExtVReg, Reg: reg}, true + return arch.ExtOperand{Kind: arch.ExtVReg, Reg: reg, Arr: arr}, true } // arm64ExtSveMem parses the gather/scatter memory operand off a normalised diff --git a/asm/arm64_ext_asm_test.go b/asm/arm64_ext_asm_test.go index df2fd08..b133ef2 100644 --- a/asm/arm64_ext_asm_test.go +++ b/asm/arm64_ext_asm_test.go @@ -763,6 +763,26 @@ func TestArm64AssembleExtensionStage4Golden(t *testing.T) { {"ZSUBHNT Z22.S, Z10.S, Z8.H", 0x45b67548}, {"ZADDHNB Z8.H, Z10.H, Z11.B", 0x4568614b}, {"ZSUBHNT Z26.D, Z4.D, Z13.S", 0x45fa748d}, + // The pairwise and quadword-reduction classes: corpus lines plus a + // width extension each. + {"ZADDP Z15.B, Z0.B, P3.M, Z0.B", 0x4411ade0}, + {"ZADDP Z9.S, Z2.S, P5.M, Z2.S", 0x4491b522}, + {"ZADDPT Z23.D, Z13.D, P1.M, Z13.D", 0x04c406ed}, + {"ZADDPT Z7.D, Z6.D, Z23.D", 0x04e708d7}, + {"ZADDQV Z25.S, P3, V5.S4", 0x04852f25}, + {"ZADDQV Z9.D, P1, V7.D2", 0x04c52527}, + {"ZANDQV Z25.S, P3, V5.S4", 0x049e2f25}, + {"ZEORQV Z25.S, P3, V5.S4", 0x049d2f25}, + {"ZORQV Z25.S, P3, V5.S4", 0x049c2f25}, + {"ZSMAXQV Z25.S, P3, V5.S4", 0x048c2f25}, + {"ZSMINQV Z25.S, P3, V5.S4", 0x048e2f25}, + {"ZUMAXQV Z25.S, P3, V5.S4", 0x048d2f25}, + {"ZUMINQV Z25.S, P3, V5.S4", 0x048f2f25}, + {"ZFADDQV Z25.S, P3, V5.S4", 0x6490af25}, + {"ZFMAXNMQV Z25.S, P3, V5.S4", 0x6494af25}, + {"ZFMAXQV Z25.S, P3, V5.S4", 0x6496af25}, + {"ZFMINNMQV Z25.S, P3, V5.S4", 0x6495af25}, + {"ZFMINQV Z25.S, P3, V5.S4", 0x6497af25}, } for _, tt := range tests { words := assembleArm64Words(t, arm64ExtProbeHead+"\t"+tt.stmt+"\n\tRET\n") @@ -779,8 +799,9 @@ func TestArm64AssembleExtensionStage4Golden(t *testing.T) { } // TestArm64AssembleExtensionStage4Refusals pins the diagnostics the -// narrowing statements get from the layer: the arrangement pair the single -// size field over-determines. +// narrowing, pairwise and quadword-reduction statements get from the layer: +// the arrangement pair the single size field over-determines, the locked +// pairwise top arrangement and the accumulator's bare predicate. func TestArm64AssembleExtensionStage4Refusals(t *testing.T) { tests := []struct { stmt string @@ -792,6 +813,12 @@ func TestArm64AssembleExtensionStage4Refusals(t *testing.T) { {"ZADDHNB Z22.D, Z10.D, Z8.H", "want .S"}, {"ZADDHNB Z22.Q, Z10.Q, Z8.D", "want .H, .S or .D"}, {"ZADDHNB Z22.S, Z10.S, Z8", "carries no arrangement suffix"}, + {"ZADDP Z15.B, Z0.B, P3.Z, Z0.B", "merging qualifier"}, + {"ZADDPT Z7.S, Z6.S, Z23.S", "want .D"}, + {"ZADDQV Z25.S, P9, V5.S4", "outside P0-P7"}, + {"ZADDQV Z25.S, P3/M, V5.S4", "takes no qualifier"}, + {"ZADDQV Z25.S, P3, V5", "no quadword suffix"}, + {"ZADDQV Z25.S, P3, V5.D2", "carries arrangement .D, want .S"}, } for _, tt := range tests { got := assembleArm64SrcError(t, arm64ExtProbeHead+"\t"+tt.stmt+"\n\tRET\n") diff --git a/asm/extension_test.go b/asm/extension_test.go index 5e1abb4..6b713db 100644 --- a/asm/extension_test.go +++ b/asm/extension_test.go @@ -273,7 +273,8 @@ func TestExtensionNamesARM64(t *testing.T) { "ZZIP2", "ZZIPQ1", "ZZIPQ2", - // The stage-four families: the SVE2.1 narrowing two-to-one set. + // The stage-four families: the SVE2.1 narrowing two-to-one set, the + // pairwise forms and the quadword reductions. "ZADDHNB", "ZADDHNT", "ZRADDHNB", @@ -282,6 +283,21 @@ func TestExtensionNamesARM64(t *testing.T) { "ZRSUBHNT", "ZSUBHNB", "ZSUBHNT", + "ZADDP", + "ZADDPT", + "ZADDQV", + "ZANDQV", + "ZEORQV", + "ZFADDQV", + "ZFMAXNMQV", + "ZFMAXQV", + "ZFMINNMQV", + "ZFMINQV", + "ZORQV", + "ZSMAXQV", + "ZSMINQV", + "ZUMAXQV", + "ZUMINQV", // The stage-three families: the SVE2 crypto group, the predicate // counters and loop terminators with the 32-bit while compares, and // the reductions into a SIMD register. @@ -394,7 +410,7 @@ func TestExtensionNamesARM64(t *testing.T) { if strings.Join(got, ",") != strings.Join(want, ",") { t.Errorf("ExtensionNames(ARM64) = %v, want %v", got, want) } - if n := len(arch.Extensions(arch.ARM64)); n != 389 { - t.Errorf("the family registers %d instructions, want 389", n) + if n := len(arch.Extensions(arch.ARM64)); n != 405 { + t.Errorf("the family registers %d instructions, want 405", n) } }