feat(arch): the SVE2.1 narrowing two-to-one family

Assisted-by: GLM 5.3 Flash
This commit is contained in:
petrbalvin committed 2026-10-07 20:35:41 +02:00
1 parent ee2c6d51b3
commit 31ab584eee
4 files changed
+254 -3

No files matched your search

+131 -1
View File
@@ -666,6 +666,19 @@ const (
// Operands: Zt.T (the row's locked list arrangement), Pg (bare, P0-P7),
// mem. The field layout mirrors the load with the list first.
ExtFormSveStore
// ExtFormNarrow is the SVE2.1 two-to-one narrowing form, ZADDHNB Z22.S,
// Z10.S, Z8.H: two wide vectors sum and the destination keeps the high
// half of each result. Operands: Zm.T2, Zn.T2, Zd.T, where T2 is one
// step wider than T (.H+.B, .S+.H, .D+.S). The single size field
// over-determines the pair, so the arrangements are validated together.
ExtFormNarrow
// ExtFormQuadReduce is the SVE2.1 quadword reduction, the accumulator
// first: ZADDQV Z25.S, P3, V5.S4. Operands: Zdn.T, Pg (bare, P0-P7),
// Vn with the counted quadword spelling .B16, .H8, .S4 or .D2 matching
// Zdn's arrangement. The fields place Zdn in the first-source slot,
// the predicate in the narrow governing field and the vector in the
// destination slot, the reduction class's own layout.
ExtFormQuadReduce
)
// Arity returns the operand count the form takes.
@@ -703,7 +716,7 @@ func (f ExtForm) Arity() int {
return 2
case ExtFormReduceReadBack:
return 4
case ExtFormSveLoad, ExtFormSveStore:
case ExtFormSveLoad, ExtFormSveStore, ExtFormNarrow, ExtFormQuadReduce:
return 3
case ExtFormNone:
return 0
@@ -774,6 +787,10 @@ func (f ExtForm) Kinds() []ExtOperandKind {
return []ExtOperandKind{ExtSveMem, ExtPReg, ExtZReg}
case ExtFormSveStore:
return []ExtOperandKind{ExtZReg, ExtPReg, ExtSveMem}
case ExtFormNarrow:
return []ExtOperandKind{ExtZReg, ExtZReg, ExtZReg}
case ExtFormQuadReduce:
return []ExtOperandKind{ExtZReg, ExtPReg, ExtVReg}
case ExtFormNone:
return nil
default:
@@ -896,6 +913,10 @@ func (f ExtForm) String() string {
return "gather load"
case ExtFormSveStore:
return "scatter store"
case ExtFormNarrow:
return "narrowing two-to-one"
case ExtFormQuadReduce:
return "quadword reduction"
case ExtFormNone:
return "no operands"
default:
@@ -1148,6 +1169,10 @@ func (in ExtInstr) Encode(ops []ExtOperand) ([]byte, error) {
return in.encodeSveLoad(ops)
case ExtFormSveStore:
return in.encodeSveStore(ops)
case ExtFormNarrow:
return in.encodeNarrow(ops)
case ExtFormQuadReduce:
return in.encodeQuadReduce(ops)
case ExtFormNone:
if len(ops) != 0 {
return nil, fmt.Errorf("%s: the %s form takes no operands, got %d",
@@ -2522,6 +2547,77 @@ func (in ExtInstr) encodeSveStore(ops []ExtOperand) ([]byte, error) {
return extWordLE(word), nil
}
// encodeNarrow fills the two-to-one narrowing form: Zm.T2, Zn.T2, Zd.T,
// where T is one step below T2. The wide sources combine and the
// destination keeps the high half of each result; the single size field
// serves both widths, the wide ladder on the sources and the narrow ladder
// on the destination carrying the same value, so the arrangement pair is
// validated as a whole.
func (in ExtInstr) encodeNarrow(ops []ExtOperand) ([]byte, error) {
zm, zn, zd := ops[0], ops[1], ops[2]
for i, op := range []ExtOperand{zm, zn, zd} {
if err := in.zVector(op, i+1); err != nil {
return nil, err
}
}
if zm.Arr != zn.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 zm.Arr < ExtArrH || zm.Arr > ExtArrD {
return nil, fmt.Errorf("%s: the wide sources carry arrangement %s, want .H, .S or .D",
in.Name, zm.Arr)
}
if zd.Arr != zm.Arr-1 {
return nil, fmt.Errorf("%s: the destination carries arrangement %s, want %s",
in.Name, zd.Arr, zm.Arr-1)
}
size, _ := zm.Arr.sizeBits()
word := in.Word
word = extSet(word, extFieldRm, uint32(zm.Reg))
word = extSet(word, extFieldRn, uint32(zn.Reg))
word = extSet(word, extFieldRd, uint32(zd.Reg))
word = extSet(word, in.Size, size)
return extWordLE(word), nil
}
// encodeQuadReduce fills the SVE2.1 quadword reduction, the accumulator
// first: Zdn.T, Pg (bare), Vn.T2. The scalable vector register accumulates
// the reduction of the quadword vector, whose counted spelling (.B16, .H8,
// .S4, .D2) names the lane width the class reduces over and must match the
// accumulator's arrangement; the encoding carries the accumulator's own
// size field. The fields mirror the reduction class: Zdn in the
// first-source slot, the predicate in the narrow governing field, the
// vector in the destination slot.
func (in ExtInstr) encodeQuadReduce(ops []ExtOperand) ([]byte, error) {
zdn, pg, vn := ops[0], ops[1], ops[2]
if err := in.zVector(zdn, 1); err != nil {
return nil, err
}
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.Arr != zdn.Arr {
return nil, fmt.Errorf("%s: operand 3 carries arrangement %s, want %s",
in.Name, vn.Arr, zdn.Arr)
}
size, err := in.zSize(zdn.Arr)
if err != nil {
return nil, err
}
word := in.Word
word = extSet(word, extFieldRn, uint32(zdn.Reg))
word = extSet(word, extFieldPgN, uint32(pg.Reg))
word = extSet(word, extFieldRd, uint32(vn.Reg))
if size != 0 {
word = extSet(word, in.Size, size)
}
return extWordLE(word), nil
}
// sharedSize returns the one element-size encoding the given arrangements
// agree on, or an error when any operand is bare, they disagree, or the
// arrangement has no size field.
@@ -3059,6 +3155,40 @@ var arm64Extensions = []ExtInstr{
{Name: "ZZIPQ2", Summary: "Z-alias of the unpredicated three-vector form",
Word: 0x4400e400, Form: ExtFormVectorsZm, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZZIPQ2; inst_gen.go + arm64sveenc.s"},
// --- the SVE2.1 narrowing two-to-one family ------------------------------
//
// The add, rounding add, subtract and rounding subtract narrow steps:
// two wide vectors combine and the destination keeps the high half of
// each result, bottom or top. The sources carry .H, .S or .D and the
// destination the arrangement one step below; one size field serves
// both. 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 family.
{Name: "ZADDHNB", Summary: "Add narrow high, bottom half destination",
Word: 0x45206000, Form: ExtFormNarrow, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1,
Ref: "ARM DDI 0487J SVE2.1: ZADDHNB; inst_gen.go + arm64sveenc.s"},
{Name: "ZADDHNT", Summary: "Add narrow high, top half destination",
Word: 0x45206400, Form: ExtFormNarrow, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1,
Ref: "ARM DDI 0487J SVE2.1: ZADDHNT; inst_gen.go + arm64sveenc.s"},
{Name: "ZRADDHNB", Summary: "Add narrow high with rounding, bottom half destination",
Word: 0x45206800, Form: ExtFormNarrow, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1,
Ref: "ARM DDI 0487J SVE2.1: ZRADDHNB; inst_gen.go + arm64sveenc.s"},
{Name: "ZRADDHNT", Summary: "Add narrow high with rounding, top half destination",
Word: 0x45206c00, Form: ExtFormNarrow, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1,
Ref: "ARM DDI 0487J SVE2.1: ZRADDHNT; inst_gen.go + arm64sveenc.s"},
{Name: "ZRSUBHNB", Summary: "Subtract narrow high with rounding, bottom half destination",
Word: 0x45207800, Form: ExtFormNarrow, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1,
Ref: "ARM DDI 0487J SVE2.1: ZRSUBHNB; inst_gen.go + arm64sveenc.s"},
{Name: "ZRSUBHNT", Summary: "Subtract narrow high with rounding, top half destination",
Word: 0x45207c00, Form: ExtFormNarrow, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1,
Ref: "ARM DDI 0487J SVE2.1: ZRSUBHNT; inst_gen.go + arm64sveenc.s"},
{Name: "ZSUBHNB", Summary: "Subtract narrow high, bottom half destination",
Word: 0x45207000, Form: ExtFormNarrow, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1,
Ref: "ARM DDI 0487J SVE2.1: ZSUBHNB; inst_gen.go + arm64sveenc.s"},
{Name: "ZSUBHNT", Summary: "Subtract narrow high, top half destination",
Word: 0x45207400, Form: ExtFormNarrow, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1,
Ref: "ARM DDI 0487J SVE2.1: ZSUBHNT; inst_gen.go + arm64sveenc.s"},
// --- the SVE2 crypto family ----------------------------------------------
//
// The multi-precision carry steps (ADCLB, ADCLT, SBCLB, SBCLT), the SHA3