diff --git a/arch/arm64_ext.go b/arch/arm64_ext.go index a101da2..4b0376a 100644 --- a/arch/arm64_ext.go +++ b/arch/arm64_ext.go @@ -735,6 +735,13 @@ const ( // Za.D, Zm.D, Zdn.D, Zdn.D, the last two naming the same register, // which the encoding carries once in the destination slot. ExtFormThreeSource + // ExtFormCountPnVec is the predicate-counter step whose result stays a + // vector, ZDECP P14.S, Z26.S: the vector is decremented in place by the + // predicate's active element count. Operands: Pm.T, Zdn.T; the + // predicate occupies the four-bit field at bits 8..5, the vector the + // destination slot, and the predicate's arrangement feeds the size + // field. + ExtFormCountPnVec ) // Arity returns the operand count the form takes. @@ -771,6 +778,8 @@ func (f ExtForm) Arity() int { return 3 case ExtFormZSameReg, ExtFormCountPn, ExtFormCTerm, ExtFormVLRead: return 2 + case ExtFormCountPnVec: + return 2 case ExtFormReduceReadBack: return 4 case ExtFormSveLoad, ExtFormSveStore, ExtFormNarrow, ExtFormQuadReduce, ExtFormShiftWide, @@ -837,6 +846,8 @@ func (f ExtForm) Kinds() []ExtOperandKind { return []ExtOperandKind{ExtPReg, ExtPReg, ExtGReg} case ExtFormCountPn: return []ExtOperandKind{ExtPReg, ExtGReg} + case ExtFormCountPnVec: + return []ExtOperandKind{ExtPReg, ExtZReg} case ExtFormCountPnW: return []ExtOperandKind{ExtGReg, ExtPReg, ExtGReg} case ExtFormReduce: @@ -971,6 +982,8 @@ func (f ExtForm) String() string { return "count to a register" case ExtFormCountPn: return "counter step, result dropped" + case ExtFormCountPnVec: + return "counter step on a vector" case ExtFormCountPnW: return "counter step to a register" case ExtFormReduce: @@ -1245,6 +1258,8 @@ func (in ExtInstr) Encode(ops []ExtOperand) ([]byte, error) { return in.encodeCountP(ops) case ExtFormCountPn: return in.encodeCountPn(ops) + case ExtFormCountPnVec: + return in.encodeCountPnVec(ops) case ExtFormCountPnW: return in.encodeCountPnW(ops) case ExtFormReduce: @@ -2353,6 +2368,31 @@ func (in ExtInstr) encodeCountPn(ops []ExtOperand) ([]byte, error) { return extWordLE(word), nil } +// encodeCountPnVec fills the predicate-counter step on a vector: Pm.T, +// Zdn.T, the vector decremented in place by the predicate's active element +// count. The predicate occupies the four-bit field at bits 8..5, the +// vector the destination slot, and the predicate's arrangement feeds the +// size field. +func (in ExtInstr) encodeCountPnVec(ops []ExtOperand) ([]byte, error) { + pm, zdn := ops[0], ops[1] + if err := in.predicateOperand(pm, 1, 0, 15, ExtArrNone); err != nil { + return nil, err + } + if err := in.zVector(zdn, 2); err != nil { + return nil, err + } + size, ok := pm.Arr.sizeBits() + if !ok { + return nil, fmt.Errorf("%s: arrangement %s has no size encoding in this class", + in.Name, pm.Arr) + } + word := in.Word + word = extSet(word, extFieldPn4, uint32(pm.Reg)) + word = extSet(word, extFieldRd, uint32(zdn.Reg)) + word = extSet(word, in.Size, size) + return extWordLE(word), nil +} + // encodeCountPnW fills the predicate-counter step with a scalar result: // Rd, Pn.T, Rd, the destination spelled twice. The predicate occupies the // four-bit field at bits 8..5 and its arrangement feeds the size field. @@ -3410,12 +3450,19 @@ var arm64Extensions = []ExtInstr{ Word: 0x0419a000, Form: ExtFormZUnary, Size: extSizeBHSD, PgQual: ExtQualMerging, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZCLZ; inst_gen.go + arm64sveenc.s"}, {Name: "ZCLZ", Summary: "Z-alias of the predicated form, over a governing predicate", Word: 0x0409a000, Form: ExtFormZUnary, Size: extSizeBHSD, PgQual: ExtQualZeroing, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZCLZ; inst_gen.go + arm64sveenc.s"}, + {Name: "ZCNOT", Summary: "Z-alias of the predicated form, over a governing predicate", + Word: 0x041ba000, Form: ExtFormZUnary, Size: extSizeBHSD, PgQual: ExtQualMerging, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZCNOT; inst_gen.go + arm64sveenc.s"}, + {Name: "ZCNOT", Summary: "Z-alias of the predicated form, over a governing predicate", + Word: 0x040ba000, Form: ExtFormZUnary, Size: extSizeBHSD, PgQual: ExtQualZeroing, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZCNOT; inst_gen.go + arm64sveenc.s"}, {Name: "ZCNT", Summary: "Z-alias of the predicated form, over a governing predicate", Word: 0x041aa000, Form: ExtFormZUnary, Size: extSizeBHSD, PgQual: ExtQualMerging, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZCNT; inst_gen.go + arm64sveenc.s"}, {Name: "ZCNT", Summary: "Z-alias of the predicated form, over a governing predicate", Word: 0x040aa000, Form: ExtFormZUnary, Size: extSizeBHSD, PgQual: ExtQualZeroing, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZCNT; inst_gen.go + arm64sveenc.s"}, {Name: "ZCOMPACT", Summary: "Compact or expand over a governing predicate", Word: 0x05218000, Form: ExtFormZGov, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZCOMPACT; inst_gen.go + arm64sveenc.s"}, + {Name: "ZDECP", Summary: "Decrement a vector by a predicate's active elements", + Word: 0x252d8000, Form: ExtFormCountPnVec, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1, + Ref: "ARM DDI 0487J SVE2.1: DECP (vector) as ZDECP; inst_gen.go + arm64sveenc.s"}, {Name: "ZDUP", Summary: "Copy or insert a general register, .D locked", Word: 0x05e03800, Form: ExtFormZFromGeneral, Arr: ExtArrD, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZDUP; inst_gen.go + arm64sveenc.s"}, {Name: "ZEOR", Summary: "Z-alias of the unpredicated three-vector form, locked to .D", diff --git a/arch/arm64_ext_test.go b/arch/arm64_ext_test.go index e27b5e3..b62b9c6 100644 --- a/arch/arm64_ext_test.go +++ b/arch/arm64_ext_test.go @@ -866,6 +866,12 @@ func TestArm64ExtZGolden(t *testing.T) { {"ZCLZ Z7.D, P4.Z, Z13.D", "ZCLZ", ExtFormZUnary, ExtQualZeroing, ExtArrNone, []ExtOperand{ExtVector(7, ExtArrD), ExtPredicate(4, ExtQualZeroing), ExtVector(13, ExtArrD)}, 0x04c9b0ed}, + {"ZCNOT Z7.D, P4.M, Z13.D", "ZCNOT", ExtFormZUnary, ExtQualMerging, ExtArrNone, + []ExtOperand{ExtVector(7, ExtArrD), ExtPredicate(4, ExtQualMerging), ExtVector(13, ExtArrD)}, + 0x04dbb0ed}, + {"ZCNOT Z7.D, P4.Z, Z13.D", "ZCNOT", ExtFormZUnary, ExtQualZeroing, ExtArrNone, + []ExtOperand{ExtVector(7, ExtArrD), ExtPredicate(4, ExtQualZeroing), ExtVector(13, ExtArrD)}, + 0x04cbb0ed}, {"ZCOMPACT Z7.D, P4, Z13.D", "ZCOMPACT", ExtFormZGov, 0, ExtArrNone, []ExtOperand{ExtVector(7, ExtArrD), ExtPredicate(4, ExtQualNone), ExtVector(13, ExtArrD)}, 0x05e190ed}, @@ -1166,6 +1172,9 @@ func TestArm64ExtStage3Golden(t *testing.T) { {"PDECP P14.S, ZR", "PDECP", ExtFormCountPn, ExtArrNone, []ExtOperand{ExtPredicateSized(14, ExtArrS), ExtZeroRegister()}, 0x25ad89df}, + {"ZDECP P14.S, Z26.S", "ZDECP", ExtFormCountPnVec, ExtArrNone, + []ExtOperand{ExtPredicateSized(14, ExtArrS), ExtVector(26, ExtArrS)}, + 0x25ad81da}, {"PINCP P14.S, ZR", "PINCP", ExtFormCountPn, ExtArrNone, []ExtOperand{ExtPredicateSized(14, ExtArrS), ExtZeroRegister()}, 0x25ac89df}, diff --git a/asm/arm64_ext_asm_test.go b/asm/arm64_ext_asm_test.go index 9f8d684..7207471 100644 --- a/asm/arm64_ext_asm_test.go +++ b/asm/arm64_ext_asm_test.go @@ -348,6 +348,8 @@ func TestArm64AssembleExtensionStage2Golden(t *testing.T) { {"ZCLS Z7.D, P4.Z, Z13.D", 0x04c8b0ed}, {"ZCLZ Z7.D, P4.M, Z13.D", 0x04d9b0ed}, {"ZCLZ Z7.D, P4.Z, Z13.D", 0x04c9b0ed}, + {"ZCNOT Z7.D, P4.M, Z13.D", 0x04dbb0ed}, + {"ZCNOT Z7.D, P4.Z, Z13.D", 0x04cbb0ed}, {"ZCOMPACT Z7.D, P4, Z13.D", 0x05e190ed}, {"ZCOMPACT Z7.D, P4, Z13.D", 0x05e190ed}, {"ZEOR Z15.B, Z0.B, P3.M, Z0.B", 0x04190de0}, @@ -461,6 +463,7 @@ func TestArm64AssembleExtensionStage3Golden(t *testing.T) { {"PFIRSTP P2.B, P14, R2", 0x2521b842}, {"PLASTP P2.B, P14, R2", 0x2522b842}, {"PDECP P14.S, ZR", 0x25ad89df}, + {"ZDECP P14.S, Z26.S", 0x25ad81da}, {"PINCP P14.S, ZR", 0x25ac89df}, {"PSQDECP P14.S, ZR", 0x25aa8ddf}, {"PSQINCP P14.S, ZR", 0x25a88ddf}, diff --git a/asm/extension_test.go b/asm/extension_test.go index aa9a3cf..7e74bbc 100644 --- a/asm/extension_test.go +++ b/asm/extension_test.go @@ -234,8 +234,10 @@ func TestExtensionNamesARM64(t *testing.T) { "ZBIC", "ZCLS", "ZCLZ", + "ZCNOT", "ZCNT", "ZCOMPACT", + "ZDECP", "ZDUP", "ZEOR", "ZEXPAND", @@ -491,7 +493,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 != 500 { - t.Errorf("the family registers %d instructions, want 500", n) + if n := len(arch.Extensions(arch.ARM64)); n != 503 { + t.Errorf("the family registers %d instructions, want 503", n) } }