feat(arch): the SVE2.1 last-active vector and compare families
Assisted-by: GLM 5.3 Flash
This commit is contained in:
1 parent
12a5cfff52
commit
bd85f8838d
4 files changed
+147
-9
No files matched your search
+134
-5
@@ -701,6 +701,18 @@ const (
|
|||||||
// Zm.H, Zn.H, Pg/M, Zda.H. Fields: Zm at bits 16..20, Zn in the
|
// Zm.H, Zn.H, Pg/M, Zda.H. Fields: Zm at bits 16..20, Zn in the
|
||||||
// first-source slot, Pg narrow, Zda in the destination slot.
|
// first-source slot, Pg narrow, Zda in the destination slot.
|
||||||
ExtFormMulPred
|
ExtFormMulPred
|
||||||
|
// ExtFormCompare is the SVE2 compare to a predicate destination,
|
||||||
|
// ZCMPEQ Z0.H, Z2.H, P0.Z, P14.H: the comparison writes the zeroing
|
||||||
|
// predicate P0-P7 spelled with its zeroing qualifier. Operands: Zm.T,
|
||||||
|
// Zn.T, Pg/Z, Pd.T under one shared arrangement, which feeds the size
|
||||||
|
// field. Fields: Zm at bits 16..20, Zn in the first-source slot, Pg
|
||||||
|
// narrow, Pd in the four-bit destination slot.
|
||||||
|
ExtFormCompare
|
||||||
|
// ExtFormCompareWide is the wide compare, ZCMPEQ Z0.D, Z12.S, P0.Z,
|
||||||
|
// P14.S: the compared magnitudes ride a double-width vector locked to
|
||||||
|
// .D while the compared data shares one narrower arrangement. Operands:
|
||||||
|
// Zm.D, Zn.T, Pg/Z, Pd.T.
|
||||||
|
ExtFormCompareWide
|
||||||
// ExtFormLongMul is the SVE2 BFloat16 lengthened multiply,
|
// ExtFormLongMul is the SVE2 BFloat16 lengthened multiply,
|
||||||
// ZBFMLALB Z7.H, Z6.H, Z23.S: two halfword vectors multiply into a
|
// ZBFMLALB Z7.H, Z6.H, Z23.S: two halfword vectors multiply into a
|
||||||
// word accumulator, the wide source locked to .S. Operands: Za.H,
|
// word accumulator, the wide source locked to .S. Operands: Za.H,
|
||||||
@@ -725,7 +737,8 @@ func (f ExtForm) Arity() int {
|
|||||||
ExtFormZUnary, ExtFormZGov, ExtFormVectorsZm, ExtFormZImmediateSource:
|
ExtFormZUnary, ExtFormZGov, ExtFormVectorsZm, ExtFormZImmediateSource:
|
||||||
return 3
|
return 3
|
||||||
case ExtFormPredicateLogical, ExtFormPredicateSelect, ExtFormPredicateLogicalDest,
|
case ExtFormPredicateLogical, ExtFormPredicateSelect, ExtFormPredicateLogicalDest,
|
||||||
ExtFormZPredicatedSource, ExtFormZSelect, ExtFormThreeSource, ExtFormMulPred:
|
ExtFormZPredicatedSource, ExtFormZSelect, ExtFormThreeSource, ExtFormMulPred,
|
||||||
|
ExtFormCompare, ExtFormCompareWide:
|
||||||
return 4
|
return 4
|
||||||
case ExtFormImmediate, ExtFormSignedImmediate, ExtFormPredicateFFRRead,
|
case ExtFormImmediate, ExtFormSignedImmediate, ExtFormPredicateFFRRead,
|
||||||
ExtFormPredicateMove, ExtFormPredicateUnpack, ExtFormPredicateTest,
|
ExtFormPredicateMove, ExtFormPredicateUnpack, ExtFormPredicateTest,
|
||||||
@@ -827,7 +840,7 @@ func (f ExtForm) Kinds() []ExtOperandKind {
|
|||||||
return []ExtOperandKind{ExtZReg, ExtZReg, ExtZReg}
|
return []ExtOperandKind{ExtZReg, ExtZReg, ExtZReg}
|
||||||
case ExtFormConvert:
|
case ExtFormConvert:
|
||||||
return []ExtOperandKind{ExtZReg, ExtPReg, ExtZReg}
|
return []ExtOperandKind{ExtZReg, ExtPReg, ExtZReg}
|
||||||
case ExtFormThreeSource, ExtFormMulPred:
|
case ExtFormThreeSource, ExtFormMulPred, ExtFormCompare, ExtFormCompareWide:
|
||||||
return []ExtOperandKind{ExtZReg, ExtZReg, ExtPReg, ExtZReg}
|
return []ExtOperandKind{ExtZReg, ExtZReg, ExtPReg, ExtZReg}
|
||||||
case ExtFormQuadReduce:
|
case ExtFormQuadReduce:
|
||||||
return []ExtOperandKind{ExtZReg, ExtPReg, ExtVReg}
|
return []ExtOperandKind{ExtZReg, ExtPReg, ExtVReg}
|
||||||
@@ -967,6 +980,10 @@ func (f ExtForm) String() string {
|
|||||||
return "multiply-accumulate"
|
return "multiply-accumulate"
|
||||||
case ExtFormLongMul:
|
case ExtFormLongMul:
|
||||||
return "lengthened multiply"
|
return "lengthened multiply"
|
||||||
|
case ExtFormCompare:
|
||||||
|
return "compare to a predicate"
|
||||||
|
case ExtFormCompareWide:
|
||||||
|
return "wide compare to a predicate"
|
||||||
case ExtFormNone:
|
case ExtFormNone:
|
||||||
return "no operands"
|
return "no operands"
|
||||||
default:
|
default:
|
||||||
@@ -1233,6 +1250,10 @@ func (in ExtInstr) Encode(ops []ExtOperand) ([]byte, error) {
|
|||||||
return in.encodeMulPred(ops)
|
return in.encodeMulPred(ops)
|
||||||
case ExtFormLongMul:
|
case ExtFormLongMul:
|
||||||
return in.encodeLongMul(ops)
|
return in.encodeLongMul(ops)
|
||||||
|
case ExtFormCompare:
|
||||||
|
return in.encodeCompare(ops)
|
||||||
|
case ExtFormCompareWide:
|
||||||
|
return in.encodeCompare(ops)
|
||||||
case ExtFormNone:
|
case ExtFormNone:
|
||||||
if len(ops) != 0 {
|
if len(ops) != 0 {
|
||||||
return nil, fmt.Errorf("%s: the %s form takes no operands, got %d",
|
return nil, fmt.Errorf("%s: the %s form takes no operands, got %d",
|
||||||
@@ -1893,9 +1914,9 @@ func (in ExtInstr) encodeZPredicatedSource(ops []ExtOperand) ([]byte, error) {
|
|||||||
if err := in.zVector(ops[3], 4); err != nil {
|
if err := in.zVector(ops[3], 4); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if pg.Qual != ExtQualMerging {
|
if want := in.PgQual; pg.Qual != want {
|
||||||
return nil, fmt.Errorf("%s: operand 3 wants the merging qualifier, got %q",
|
return nil, fmt.Errorf("%s: operand 3 wants the %s qualifier, got %q",
|
||||||
in.Name, pg.Qual)
|
in.Name, want.String(), pg.Qual)
|
||||||
}
|
}
|
||||||
if ops[3].Reg != zdn.Reg || ops[3].Arr != zdn.Arr {
|
if ops[3].Reg != zdn.Reg || ops[3].Arr != zdn.Arr {
|
||||||
return nil, fmt.Errorf("%s: operands 2 and 4 are the same register Zdn, got Z%d and Z%d",
|
return nil, fmt.Errorf("%s: operands 2 and 4 are the same register Zdn, got Z%d and Z%d",
|
||||||
@@ -2832,6 +2853,62 @@ func (in ExtInstr) encodeMulPred(ops []ExtOperand) ([]byte, error) {
|
|||||||
// encodeLongMul fills the SVE2 BFloat16 lengthened multiply: Za.H, Zn.H,
|
// encodeLongMul fills the SVE2 BFloat16 lengthened multiply: Za.H, Zn.H,
|
||||||
// Zm.S, the two halfword vectors under the row's Arr and the wide source
|
// Zm.S, the two halfword vectors under the row's Arr and the wide source
|
||||||
// one step above it.
|
// one step above it.
|
||||||
|
// encodeCompare fills the SVE2 compare forms, the shared-arrangement and
|
||||||
|
// the wide shape alike: Zm, Zn, Pg/Z, Pd. The comparison writes the
|
||||||
|
// zeroing predicate P0-P7; under the wide shape the magnitudes ride the
|
||||||
|
// double-width vector locked to .D. Fields: Zm at bits 16..20, Zn in the
|
||||||
|
// first-source slot, Pg narrow, Pd in the four-bit destination slot.
|
||||||
|
func (in ExtInstr) encodeCompare(ops []ExtOperand) ([]byte, error) {
|
||||||
|
zm, zn, pg, pd := ops[0], ops[1], ops[2], ops[3]
|
||||||
|
if err := in.zVector(zm, 1); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if in.Form == ExtFormCompareWide {
|
||||||
|
if zm.Arr != ExtArrD {
|
||||||
|
return nil, fmt.Errorf("%s: operand 1 carries arrangement %s, want .D", in.Name, zm.Arr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := in.zVector(zn, 2); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if in.Form == ExtFormCompare && zn.Arr != zm.Arr {
|
||||||
|
return nil, fmt.Errorf("%s: operands 1 and 2 carry arrangements %s and %s, they must match", in.Name, zm.Arr, zn.Arr)
|
||||||
|
}
|
||||||
|
if in.Form == ExtFormCompareWide {
|
||||||
|
if zn.Arr == ExtArrD {
|
||||||
|
return nil, fmt.Errorf("%s: operand 2 carries arrangement .D, want .B, .H or .S", in.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := in.predicateOperand(pg, 3, 0, 7, ExtArrNone); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if pg.Qual != ExtQualZeroing {
|
||||||
|
return nil, fmt.Errorf("%s: operand 3 wants the zeroing qualifier, got %q", in.Name, pg.Qual)
|
||||||
|
}
|
||||||
|
if pd.Kind != ExtPReg {
|
||||||
|
return nil, fmt.Errorf("%s: operand 4 wants a predicate register, got %s", in.Name, pd.Kind)
|
||||||
|
}
|
||||||
|
if pd.Reg < 0 || pd.Reg > 15 {
|
||||||
|
return nil, fmt.Errorf("%s: operand 4 is P%d, outside P0-P15", in.Name, pd.Reg)
|
||||||
|
}
|
||||||
|
if in.Form == ExtFormCompare && pd.Arr != zn.Arr {
|
||||||
|
return nil, fmt.Errorf("%s: operand 4 carries arrangement %s, want %s", in.Name, pd.Arr, zn.Arr)
|
||||||
|
}
|
||||||
|
size, err := in.zSize(zn.Arr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
word := in.Word
|
||||||
|
word = extSet(word, extFieldRm, uint32(zm.Reg))
|
||||||
|
word = extSet(word, extFieldRn, uint32(zn.Reg))
|
||||||
|
word = extSet(word, extFieldPgN, uint32(pg.Reg))
|
||||||
|
word = extSet(word, extFieldPd, uint32(pd.Reg))
|
||||||
|
if size != 0 {
|
||||||
|
word = extSet(word, in.Size, size)
|
||||||
|
}
|
||||||
|
return extWordLE(word), nil
|
||||||
|
}
|
||||||
|
|
||||||
func (in ExtInstr) encodeLongMul(ops []ExtOperand) ([]byte, error) {
|
func (in ExtInstr) encodeLongMul(ops []ExtOperand) ([]byte, error) {
|
||||||
za, zn, zm := ops[0], ops[1], ops[2]
|
za, zn, zm := ops[0], ops[1], ops[2]
|
||||||
if err := in.zVector(za, 1); err != nil {
|
if err := in.zVector(za, 1); err != nil {
|
||||||
@@ -3668,6 +3745,58 @@ var arm64Extensions = []ExtInstr{
|
|||||||
{Name: "ZBFSCALE", Summary: "Scale BFloat16 halfwords by a power of two, merging",
|
{Name: "ZBFSCALE", Summary: "Scale BFloat16 halfwords by a power of two, merging",
|
||||||
Word: 0x65098000, Form: ExtFormZPredicatedSource, Arr: ExtArrH, PgQual: ExtQualMerging, Feature: ExtFeatureSVE2,
|
Word: 0x65098000, Form: ExtFormZPredicatedSource, Arr: ExtArrH, PgQual: ExtQualMerging, Feature: ExtFeatureSVE2,
|
||||||
Ref: "ARM DDI 0487J SVE2: ZBFSCALE; inst_gen.go + arm64sveenc.s"},
|
Ref: "ARM DDI 0487J SVE2: ZBFSCALE; inst_gen.go + arm64sveenc.s"},
|
||||||
|
|
||||||
|
// --- the SVE2.1 last-active and compare families --------------------------
|
||||||
|
//
|
||||||
|
// The conditionally-extract-last-active-element vector shape and the
|
||||||
|
// compares to a predicate destination, in their shared-arrangement and
|
||||||
|
// wide spellings. The register-destination shapes of CLASTA and
|
||||||
|
// CLASTB, and the immediate compares, 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: "ZCLASTA", Summary: "Conditionally extract the last active element, vector to vector",
|
||||||
|
Word: 0x05288000, Form: ExtFormZPredicatedSource, Size: extSizeBHSD, PgQual: ExtQualNone, Feature: ExtFeatureSVE2,
|
||||||
|
Ref: "ARM DDI 0487J SVE2: ZCLASTA; inst_gen.go + arm64sveenc.s"},
|
||||||
|
{Name: "ZCLASTB", Summary: "Conditionally extract the last active element from the bottom, vector to vector",
|
||||||
|
Word: 0x05298000, Form: ExtFormZPredicatedSource, Size: extSizeBHSD, PgQual: ExtQualNone, Feature: ExtFeatureSVE2,
|
||||||
|
Ref: "ARM DDI 0487J SVE2: ZCLASTB; inst_gen.go + arm64sveenc.s"},
|
||||||
|
{Name: "ZCMPEQ", Summary: "Compare equal, writing a zeroing predicate",
|
||||||
|
Word: 0x2400a000, Form: ExtFormCompare, Size: extSizeBHSD, Feature: ExtFeatureSVE2,
|
||||||
|
Ref: "ARM DDI 0487J SVE2: ZCMPEQ; inst_gen.go + arm64sveenc.s"},
|
||||||
|
{Name: "ZCMPEQ", Summary: "Compare equal against wide magnitudes, writing a zeroing predicate",
|
||||||
|
Word: 0x24002000, Form: ExtFormCompareWide, Size: extSizeBHSD, Feature: ExtFeatureSVE2,
|
||||||
|
Ref: "ARM DDI 0487J SVE2: ZCMPEQ; inst_gen.go + arm64sveenc.s"},
|
||||||
|
{Name: "ZCMPGE", Summary: "Compare greater or equal signed, writing a zeroing predicate",
|
||||||
|
Word: 0x24008000, Form: ExtFormCompare, Size: extSizeBHSD, Feature: ExtFeatureSVE2,
|
||||||
|
Ref: "ARM DDI 0487J SVE2: ZCMPGE; inst_gen.go + arm64sveenc.s"},
|
||||||
|
{Name: "ZCMPGE", Summary: "Compare greater or equal signed against wide magnitudes, writing a zeroing predicate",
|
||||||
|
Word: 0x24004000, Form: ExtFormCompareWide, Size: extSizeBHSD, Feature: ExtFeatureSVE2,
|
||||||
|
Ref: "ARM DDI 0487J SVE2: ZCMPGE; inst_gen.go + arm64sveenc.s"},
|
||||||
|
{Name: "ZCMPGT", Summary: "Compare greater signed, writing a zeroing predicate",
|
||||||
|
Word: 0x24008010, Form: ExtFormCompare, Size: extSizeBHSD, Feature: ExtFeatureSVE2,
|
||||||
|
Ref: "ARM DDI 0487J SVE2: ZCMPGT; inst_gen.go + arm64sveenc.s"},
|
||||||
|
{Name: "ZCMPGT", Summary: "Compare greater signed against wide magnitudes, writing a zeroing predicate",
|
||||||
|
Word: 0x24004010, Form: ExtFormCompareWide, Size: extSizeBHSD, Feature: ExtFeatureSVE2,
|
||||||
|
Ref: "ARM DDI 0487J SVE2: ZCMPGT; inst_gen.go + arm64sveenc.s"},
|
||||||
|
{Name: "ZCMPHI", Summary: "Compare higher unsigned, writing a zeroing predicate",
|
||||||
|
Word: 0x24000010, Form: ExtFormCompare, Size: extSizeBHSD, Feature: ExtFeatureSVE2,
|
||||||
|
Ref: "ARM DDI 0487J SVE2: ZCMPHI; inst_gen.go + arm64sveenc.s"},
|
||||||
|
{Name: "ZCMPHI", Summary: "Compare higher unsigned against wide magnitudes, writing a zeroing predicate",
|
||||||
|
Word: 0x2400c010, Form: ExtFormCompareWide, Size: extSizeBHSD, Feature: ExtFeatureSVE2,
|
||||||
|
Ref: "ARM DDI 0487J SVE2: ZCMPHI; inst_gen.go + arm64sveenc.s"},
|
||||||
|
{Name: "ZCMPHS", Summary: "Compare higher or same unsigned, writing a zeroing predicate",
|
||||||
|
Word: 0x24000000, Form: ExtFormCompare, Size: extSizeBHSD, Feature: ExtFeatureSVE2,
|
||||||
|
Ref: "ARM DDI 0487J SVE2: ZCMPHS; inst_gen.go + arm64sveenc.s"},
|
||||||
|
{Name: "ZCMPHS", Summary: "Compare higher or same unsigned against wide magnitudes, writing a zeroing predicate",
|
||||||
|
Word: 0x2400c000, Form: ExtFormCompareWide, Size: extSizeBHSD, Feature: ExtFeatureSVE2,
|
||||||
|
Ref: "ARM DDI 0487J SVE2: ZCMPHS; inst_gen.go + arm64sveenc.s"},
|
||||||
|
{Name: "ZCMPNE", Summary: "Compare not equal, writing a zeroing predicate",
|
||||||
|
Word: 0x2400a010, Form: ExtFormCompare, Size: extSizeBHSD, Feature: ExtFeatureSVE2,
|
||||||
|
Ref: "ARM DDI 0487J SVE2: ZCMPNE; inst_gen.go + arm64sveenc.s"},
|
||||||
|
{Name: "ZCMPNE", Summary: "Compare not equal against wide magnitudes, writing a zeroing predicate",
|
||||||
|
Word: 0x24002010, Form: ExtFormCompareWide, Size: extSizeBHSD, Feature: ExtFeatureSVE2,
|
||||||
|
Ref: "ARM DDI 0487J SVE2: ZCMPNE; inst_gen.go + arm64sveenc.s"},
|
||||||
// --- the SVE multiple-structure loads and stores --------------------------
|
// --- the SVE multiple-structure loads and stores --------------------------
|
||||||
//
|
//
|
||||||
// The two-, three- and four-register list loads and stores over the
|
// The two-, three- and four-register list loads and stores over the
|
||||||
|
|||||||
@@ -311,7 +311,8 @@ func TestArm64ExtTableIntegrity(t *testing.T) {
|
|||||||
ExtFormPredicateBreak, ExtFormPredicateBreakZero, ExtFormPredicatePermute,
|
ExtFormPredicateBreak, ExtFormPredicateBreakZero, ExtFormPredicatePermute,
|
||||||
ExtFormPredicateFirst, ExtFormPredicateNext, ExtFormPredicateOne,
|
ExtFormPredicateFirst, ExtFormPredicateNext, ExtFormPredicateOne,
|
||||||
ExtFormPredicateFFRRead, ExtFormPredicateMove, ExtFormPredicateUnpack,
|
ExtFormPredicateFFRRead, ExtFormPredicateMove, ExtFormPredicateUnpack,
|
||||||
ExtFormPredicateTest, ExtFormWhile, ExtFormPredicateCounter, ExtFormZUnary:
|
ExtFormPredicateTest, ExtFormWhile, ExtFormPredicateCounter, ExtFormZUnary,
|
||||||
|
ExtFormCompare, ExtFormCompareWide:
|
||||||
destMask = 0xf
|
destMask = 0xf
|
||||||
}
|
}
|
||||||
roundOne := in.Form == ExtFormVectors || in.Form == ExtFormPredicated ||
|
roundOne := in.Form == ExtFormVectors || in.Form == ExtFormPredicated ||
|
||||||
|
|||||||
@@ -876,7 +876,7 @@ func TestArm64AssembleExtensionStage4Refusals(t *testing.T) {
|
|||||||
{"ZADDHNB Z22.D, Z10.D, Z8.H", "want .S"},
|
{"ZADDHNB Z22.D, Z10.D, Z8.H", "want .S"},
|
||||||
{"ZADDHNB Z22.Q, Z10.Q, Z8.D", "want .H, .S or .D"},
|
{"ZADDHNB Z22.Q, Z10.Q, Z8.D", "want .H, .S or .D"},
|
||||||
{"ZADDHNB Z22.S, Z10.S, Z8", "carries no arrangement suffix"},
|
{"ZADDHNB Z22.S, Z10.S, Z8", "carries no arrangement suffix"},
|
||||||
{"ZADDP Z15.B, Z0.B, P3.Z, Z0.B", "merging qualifier"},
|
{"ZADDP Z15.B, Z0.B, P3.Z, Z0.B", "/M qualifier"},
|
||||||
{"ZADDPT Z7.S, Z6.S, Z23.S", "want .D"},
|
{"ZADDPT Z7.S, Z6.S, Z23.S", "want .D"},
|
||||||
{"ZADDQV Z25.S, P9, V5.S4", "outside P0-P7"},
|
{"ZADDQV Z25.S, P9, V5.S4", "outside P0-P7"},
|
||||||
{"ZADDQV Z25.S, P3/M, V5.S4", "takes no qualifier"},
|
{"ZADDQV Z25.S, P3/M, V5.S4", "takes no qualifier"},
|
||||||
|
|||||||
+10
-2
@@ -338,6 +338,14 @@ func TestExtensionNamesARM64(t *testing.T) {
|
|||||||
"ZBFMLSLT",
|
"ZBFMLSLT",
|
||||||
"ZBFMMLA",
|
"ZBFMMLA",
|
||||||
"ZBFSCALE",
|
"ZBFSCALE",
|
||||||
|
"ZCLASTA",
|
||||||
|
"ZCLASTB",
|
||||||
|
"ZCMPEQ",
|
||||||
|
"ZCMPGE",
|
||||||
|
"ZCMPGT",
|
||||||
|
"ZCMPHI",
|
||||||
|
"ZCMPHS",
|
||||||
|
"ZCMPNE",
|
||||||
"ZLD2B",
|
"ZLD2B",
|
||||||
"ZLD2D",
|
"ZLD2D",
|
||||||
"ZLD2H",
|
"ZLD2H",
|
||||||
@@ -480,7 +488,7 @@ func TestExtensionNamesARM64(t *testing.T) {
|
|||||||
if strings.Join(got, ",") != strings.Join(want, ",") {
|
if strings.Join(got, ",") != strings.Join(want, ",") {
|
||||||
t.Errorf("ExtensionNames(ARM64) = %v, want %v", got, want)
|
t.Errorf("ExtensionNames(ARM64) = %v, want %v", got, want)
|
||||||
}
|
}
|
||||||
if n := len(arch.Extensions(arch.ARM64)); n != 483 {
|
if n := len(arch.Extensions(arch.ARM64)); n != 497 {
|
||||||
t.Errorf("the family registers %d instructions, want 483", n)
|
t.Errorf("the family registers %d instructions, want 497", n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user