diff --git a/arch/arm64_ext.go b/arch/arm64_ext.go index 7216041..d852967 100644 --- a/arch/arm64_ext.go +++ b/arch/arm64_ext.go @@ -2036,8 +2036,12 @@ func (in ExtInstr) encodeVectorsZm(ops []ExtOperand) ([]byte, error) { // riding the destination's arrangement. func (in ExtInstr) encodeZUnpack(ops []ExtOperand) ([]byte, error) { pn, zd := ops[0], ops[1] - if err := in.zVector(pn, 1); err != nil { - return nil, err + if pn.Kind != ExtZReg { + return nil, fmt.Errorf("%s: operand 1 wants a scalable vector register, got %s", + in.Name, pn.Kind) + } + if pn.Reg < 0 || pn.Reg > 31 { + return nil, fmt.Errorf("%s: operand 1 is Z%d, outside Z0-Z31", in.Name, pn.Reg) } if pn.Arr != ExtArrB { return nil, fmt.Errorf("%s: operand 1 carries arrangement %s, want .B", in.Name, pn.Arr) @@ -3426,6 +3430,63 @@ var arm64Extensions = []ExtInstr{ Word: 0x04e03c00, Form: ExtFormThreeSource, Arr: ExtArrD, Feature: ExtFeatureSVE2, Ref: "ARM DDI 0487J SVE2: ZNBSL; inst_gen.go + arm64sveenc.s"}, + // --- the SVE2 BFloat16 arithmetic core ------------------------------------ + // + // The two-shape arithmetic (ADD, MAX, MAXNM, MIN, MINNM, MUL, SUB) + // over halfwords only: the predicated-source and unpredicated + // three-vector spellings, the clamp over the unpredicated shape, and + // the B-to-H conversions of the F1CVT and F2CVT pairs. The remaining + // BFloat16 shapes (dot products, lengthened multiplies, converts with + // a governing predicate) stay unwired. 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 the covered classes. + {Name: "ZBF1CVT", Summary: "Convert BFloat16 pairs from bytes to halfwords, bottom", + Word: 0x65083800, Form: ExtFormZUnpack, Arr: ExtArrH, Feature: ExtFeatureSVE2, + Ref: "ARM DDI 0487J SVE2: ZBF1CVT; inst_gen.go + arm64sveenc.s"}, + {Name: "ZBF1CVTLT", Summary: "Convert BFloat16 pairs from bytes to halfwords, bottom, no rounding", + Word: 0x65093800, Form: ExtFormZUnpack, Arr: ExtArrH, Feature: ExtFeatureSVE2, + Ref: "ARM DDI 0487J SVE2: ZBF1CVTLT; inst_gen.go + arm64sveenc.s"}, + {Name: "ZBF2CVT", Summary: "Convert BFloat16 pairs from bytes to halfwords, top", + Word: 0x65083c00, Form: ExtFormZUnpack, Arr: ExtArrH, Feature: ExtFeatureSVE2, + Ref: "ARM DDI 0487J SVE2: ZBF2CVT; inst_gen.go + arm64sveenc.s"}, + {Name: "ZBF2CVTLT", Summary: "Convert BFloat16 pairs from bytes to halfwords, top, no rounding", + Word: 0x65093c00, Form: ExtFormZUnpack, Arr: ExtArrH, Feature: ExtFeatureSVE2, + Ref: "ARM DDI 0487J SVE2: ZBF2CVTLT; inst_gen.go + arm64sveenc.s"}, + {Name: "ZBFADD", Summary: "Add BFloat16 halfwords, merging", + Word: 0x65008000, Form: ExtFormZPredicatedSource, Arr: ExtArrH, PgQual: ExtQualMerging, Feature: ExtFeatureSVE2, + Ref: "ARM DDI 0487J SVE2: ZBFADD; inst_gen.go + arm64sveenc.s"}, + {Name: "ZBFADD", Summary: "Add BFloat16 halfwords, unpredicated", + Word: 0x65000000, Form: ExtFormVectorsZm, Arr: ExtArrH, Feature: ExtFeatureSVE2, + Ref: "ARM DDI 0487J SVE2: ZBFADD; inst_gen.go + arm64sveenc.s"}, + {Name: "ZBFCLAMP", Summary: "Clamp BFloat16 halfwords between bounds, unpredicated", + Word: 0x64202400, Form: ExtFormVectorsZm, Arr: ExtArrH, Feature: ExtFeatureSVE2, + Ref: "ARM DDI 0487J SVE2: ZBFCLAMP; inst_gen.go + arm64sveenc.s"}, + {Name: "ZBFMAX", Summary: "Maximum of BFloat16 halfwords, merging", + Word: 0x65068000, Form: ExtFormZPredicatedSource, Arr: ExtArrH, PgQual: ExtQualMerging, Feature: ExtFeatureSVE2, + Ref: "ARM DDI 0487J SVE2: ZBFMAX; inst_gen.go + arm64sveenc.s"}, + {Name: "ZBFMAXNM", Summary: "Maximum number of BFloat16 halfwords, merging", + Word: 0x65048000, Form: ExtFormZPredicatedSource, Arr: ExtArrH, PgQual: ExtQualMerging, Feature: ExtFeatureSVE2, + Ref: "ARM DDI 0487J SVE2: ZBFMAXNM; inst_gen.go + arm64sveenc.s"}, + {Name: "ZBFMIN", Summary: "Minimum of BFloat16 halfwords, merging", + Word: 0x65078000, Form: ExtFormZPredicatedSource, Arr: ExtArrH, PgQual: ExtQualMerging, Feature: ExtFeatureSVE2, + Ref: "ARM DDI 0487J SVE2: ZBFMIN; inst_gen.go + arm64sveenc.s"}, + {Name: "ZBFMINNM", Summary: "Minimum number of BFloat16 halfwords, merging", + Word: 0x65058000, Form: ExtFormZPredicatedSource, Arr: ExtArrH, PgQual: ExtQualMerging, Feature: ExtFeatureSVE2, + Ref: "ARM DDI 0487J SVE2: ZBFMINNM; inst_gen.go + arm64sveenc.s"}, + {Name: "ZBFMUL", Summary: "Multiply BFloat16 halfwords, merging", + Word: 0x65028000, Form: ExtFormZPredicatedSource, Arr: ExtArrH, PgQual: ExtQualMerging, Feature: ExtFeatureSVE2, + Ref: "ARM DDI 0487J SVE2: ZBFMUL; inst_gen.go + arm64sveenc.s"}, + {Name: "ZBFMUL", Summary: "Multiply BFloat16 halfwords, unpredicated", + Word: 0x65000800, Form: ExtFormVectorsZm, Arr: ExtArrH, Feature: ExtFeatureSVE2, + Ref: "ARM DDI 0487J SVE2: ZBFMUL; inst_gen.go + arm64sveenc.s"}, + {Name: "ZBFSUB", Summary: "Subtract BFloat16 halfwords, merging", + Word: 0x65018000, Form: ExtFormZPredicatedSource, Arr: ExtArrH, PgQual: ExtQualMerging, Feature: ExtFeatureSVE2, + Ref: "ARM DDI 0487J SVE2: ZBFSUB; inst_gen.go + arm64sveenc.s"}, + {Name: "ZBFSUB", Summary: "Subtract BFloat16 halfwords, unpredicated", + Word: 0x65000400, Form: ExtFormVectorsZm, Arr: ExtArrH, Feature: ExtFeatureSVE2, + Ref: "ARM DDI 0487J SVE2: ZBFSUB; 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 f1a03c5..38bc3fe 100644 --- a/arch/arm64_ext_test.go +++ b/arch/arm64_ext_test.go @@ -1505,6 +1505,52 @@ func TestArm64ExtStage4Golden(t *testing.T) { {"ZEORTB Z7.D, Z23.D, Z13.D", "ZEORTB", ExtFormVectorsZm, ExtQualNone, ExtArrNone, []ExtOperand{ExtVector(7, ExtArrD), ExtVector(23, ExtArrD), ExtVector(13, ExtArrD)}, 0x45c796ed}, + // The BFloat16 arithmetic core, halfwords throughout. + {"ZBF1CVT Z11.B, Z6.H", "ZBF1CVT", ExtFormZUnpack, ExtQualNone, ExtArrH, + []ExtOperand{ExtVector(11, ExtArrB), ExtVector(6, ExtArrH)}, + 0x65083966}, + {"ZBF1CVTLT Z11.B, Z6.H", "ZBF1CVTLT", ExtFormZUnpack, ExtQualNone, ExtArrH, + []ExtOperand{ExtVector(11, ExtArrB), ExtVector(6, ExtArrH)}, + 0x65093966}, + {"ZBF2CVT Z11.B, Z6.H", "ZBF2CVT", ExtFormZUnpack, ExtQualNone, ExtArrH, + []ExtOperand{ExtVector(11, ExtArrB), ExtVector(6, ExtArrH)}, + 0x65083d66}, + {"ZBF2CVTLT Z11.B, Z6.H", "ZBF2CVTLT", ExtFormZUnpack, ExtQualNone, ExtArrH, + []ExtOperand{ExtVector(11, ExtArrB), ExtVector(6, ExtArrH)}, + 0x65093d66}, + {"ZBFADD Z23.H, Z13.H, P1.M, Z13.H", "ZBFADD", ExtFormZPredicatedSource, ExtQualMerging, ExtArrH, + []ExtOperand{ExtVector(23, ExtArrH), ExtVector(13, ExtArrH), ExtPredicate(1, ExtQualMerging), ExtVector(13, ExtArrH)}, + 0x650086ed}, + {"ZBFADD Z7.H, Z6.H, Z23.H", "ZBFADD", ExtFormVectorsZm, ExtQualNone, ExtArrH, + []ExtOperand{ExtVector(7, ExtArrH), ExtVector(6, ExtArrH), ExtVector(23, ExtArrH)}, + 0x650700d7}, + {"ZBFCLAMP Z7.H, Z6.H, Z23.H", "ZBFCLAMP", ExtFormVectorsZm, ExtQualNone, ExtArrH, + []ExtOperand{ExtVector(7, ExtArrH), ExtVector(6, ExtArrH), ExtVector(23, ExtArrH)}, + 0x642724d7}, + {"ZBFMAX Z23.H, Z13.H, P1.M, Z13.H", "ZBFMAX", ExtFormZPredicatedSource, ExtQualMerging, ExtArrH, + []ExtOperand{ExtVector(23, ExtArrH), ExtVector(13, ExtArrH), ExtPredicate(1, ExtQualMerging), ExtVector(13, ExtArrH)}, + 0x650686ed}, + {"ZBFMAXNM Z23.H, Z13.H, P1.M, Z13.H", "ZBFMAXNM", ExtFormZPredicatedSource, ExtQualMerging, ExtArrH, + []ExtOperand{ExtVector(23, ExtArrH), ExtVector(13, ExtArrH), ExtPredicate(1, ExtQualMerging), ExtVector(13, ExtArrH)}, + 0x650486ed}, + {"ZBFMIN Z23.H, Z13.H, P1.M, Z13.H", "ZBFMIN", ExtFormZPredicatedSource, ExtQualMerging, ExtArrH, + []ExtOperand{ExtVector(23, ExtArrH), ExtVector(13, ExtArrH), ExtPredicate(1, ExtQualMerging), ExtVector(13, ExtArrH)}, + 0x650786ed}, + {"ZBFMINNM Z23.H, Z13.H, P1.M, Z13.H", "ZBFMINNM", ExtFormZPredicatedSource, ExtQualMerging, ExtArrH, + []ExtOperand{ExtVector(23, ExtArrH), ExtVector(13, ExtArrH), ExtPredicate(1, ExtQualMerging), ExtVector(13, ExtArrH)}, + 0x650586ed}, + {"ZBFMUL Z23.H, Z13.H, P1.M, Z13.H", "ZBFMUL", ExtFormZPredicatedSource, ExtQualMerging, ExtArrH, + []ExtOperand{ExtVector(23, ExtArrH), ExtVector(13, ExtArrH), ExtPredicate(1, ExtQualMerging), ExtVector(13, ExtArrH)}, + 0x650286ed}, + {"ZBFMUL Z7.H, Z6.H, Z23.H", "ZBFMUL", ExtFormVectorsZm, ExtQualNone, ExtArrH, + []ExtOperand{ExtVector(7, ExtArrH), ExtVector(6, ExtArrH), ExtVector(23, ExtArrH)}, + 0x650708d7}, + {"ZBFSUB Z23.H, Z13.H, P1.M, Z13.H", "ZBFSUB", ExtFormZPredicatedSource, ExtQualMerging, ExtArrH, + []ExtOperand{ExtVector(23, ExtArrH), ExtVector(13, ExtArrH), ExtPredicate(1, ExtQualMerging), ExtVector(13, ExtArrH)}, + 0x650186ed}, + {"ZBFSUB Z7.H, Z6.H, Z23.H", "ZBFSUB", ExtFormVectorsZm, ExtQualNone, ExtArrH, + []ExtOperand{ExtVector(7, ExtArrH), ExtVector(6, ExtArrH), ExtVector(23, ExtArrH)}, + 0x650704d7}, } { in := extInstructionMeta(t, tt.mnem, tt.form, tt.qual, tt.arr) got, err := in.Encode(tt.ops) diff --git a/asm/arm64_ext_asm_test.go b/asm/arm64_ext_asm_test.go index f533129..3c8cde2 100644 --- a/asm/arm64_ext_asm_test.go +++ b/asm/arm64_ext_asm_test.go @@ -806,6 +806,22 @@ func TestArm64AssembleExtensionStage4Golden(t *testing.T) { {"ZBGRP Z7.D, Z23.D, Z13.D", 0x45c7baed}, {"ZEORBT Z7.D, Z23.D, Z13.D", 0x45c792ed}, {"ZEORTB Z7.D, Z23.D, Z13.D", 0x45c796ed}, + // The BFloat16 arithmetic core, halfwords throughout. + {"ZBF1CVT Z11.B, Z6.H", 0x65083966}, + {"ZBF1CVTLT Z11.B, Z6.H", 0x65093966}, + {"ZBF2CVT Z11.B, Z6.H", 0x65083d66}, + {"ZBF2CVTLT Z11.B, Z6.H", 0x65093d66}, + {"ZBFADD Z23.H, Z13.H, P1.M, Z13.H", 0x650086ed}, + {"ZBFADD Z7.H, Z6.H, Z23.H", 0x650700d7}, + {"ZBFCLAMP Z7.H, Z6.H, Z23.H", 0x642724d7}, + {"ZBFMAX Z23.H, Z13.H, P1.M, Z13.H", 0x650686ed}, + {"ZBFMAXNM Z23.H, Z13.H, P1.M, Z13.H", 0x650486ed}, + {"ZBFMIN Z23.H, Z13.H, P1.M, Z13.H", 0x650786ed}, + {"ZBFMINNM Z23.H, Z13.H, P1.M, Z13.H", 0x650586ed}, + {"ZBFMUL Z23.H, Z13.H, P1.M, Z13.H", 0x650286ed}, + {"ZBFMUL Z7.H, Z6.H, Z23.H", 0x650708d7}, + {"ZBFSUB Z23.H, Z13.H, P1.M, Z13.H", 0x650186ed}, + {"ZBFSUB Z7.H, Z6.H, Z23.H", 0x650704d7}, } for _, tt := range tests { words := assembleArm64Words(t, arm64ExtProbeHead+"\t"+tt.stmt+"\n\tRET\n") diff --git a/asm/extension_test.go b/asm/extension_test.go index 75ac6a2..616779a 100644 --- a/asm/extension_test.go +++ b/asm/extension_test.go @@ -315,6 +315,18 @@ func TestExtensionNamesARM64(t *testing.T) { "ZEORBT", "ZEORTB", "ZNBSL", + "ZBF1CVT", + "ZBF1CVTLT", + "ZBF2CVT", + "ZBF2CVTLT", + "ZBFADD", + "ZBFCLAMP", + "ZBFMAX", + "ZBFMAXNM", + "ZBFMIN", + "ZBFMINNM", + "ZBFMUL", + "ZBFSUB", // 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. @@ -427,7 +439,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 != 425 { - t.Errorf("the family registers %d instructions, want 425", n) + if n := len(arch.Extensions(arch.ARM64)); n != 440 { + t.Errorf("the family registers %d instructions, want 440", n) } }