feat(arch): the vector-length arithmetic pseudo group

Assisted-by: GLM 5.3 Flash
This commit is contained in:
petrbalvin committed 2026-10-07 20:35:41 +02:00
1 parent bd85f8838d
commit aeb109a64c
2 files changed
+86 -3

No files matched your search

+81 -1
View File
@@ -406,6 +406,7 @@ var (
extFieldPm = ExtField{16, 3} // predicate source P0-P7
extFieldPnc = ExtField{0, 3} // predicate-as-counter destination PN8-PN15, field holds reg-8
extFieldPn4 = ExtField{5, 4} // predicate source P0-P15 at bits 8..5 (counter family)
extFieldImm6 = ExtField{5, 6} // the signed imm6 of the vector-length arithmetic
)
// ExtForm enumerates the operand shapes the extension layer defines, in Plan
@@ -701,6 +702,14 @@ const (
// 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.
ExtFormMulPred
// ExtFormVLArith is the vector-length arithmetic, ADDVL $9, R11, RSP:
// a signed imm6 multiple of the vector length added to a general
// register, either slot spelled RSP. Operands: imm, Rn|SP, Rd|SP.
// Fields: the imm6 at bits 10..5, Rn at bits 20..16, Rd at bits 4..0.
ExtFormVLArith
// ExtFormVLRead is the vector-length read, RDVL $1, R27. Operands:
// imm, Rd (R0-R30). Fields: the imm6 at bits 10..5, Rd at bits 4..0.
ExtFormVLRead
// 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,
@@ -760,7 +769,7 @@ func (f ExtForm) Arity() int {
return 1
case ExtFormZReadBack, ExtFormCountP, ExtFormCountPnW, ExtFormReduce, ExtFormZLastReg:
return 3
case ExtFormZSameReg, ExtFormCountPn, ExtFormCTerm:
case ExtFormZSameReg, ExtFormCountPn, ExtFormCTerm, ExtFormVLRead:
return 2
case ExtFormReduceReadBack:
return 4
@@ -838,6 +847,10 @@ func (f ExtForm) Kinds() []ExtOperandKind {
return []ExtOperandKind{ExtZReg, ExtPReg, ExtSveMem}
case ExtFormNarrow, ExtFormShiftWide, ExtFormLongMul:
return []ExtOperandKind{ExtZReg, ExtZReg, ExtZReg}
case ExtFormVLArith:
return []ExtOperandKind{ExtImm, ExtGReg, ExtGReg}
case ExtFormVLRead:
return []ExtOperandKind{ExtImm, ExtGReg}
case ExtFormConvert:
return []ExtOperandKind{ExtZReg, ExtPReg, ExtZReg}
case ExtFormThreeSource, ExtFormMulPred, ExtFormCompare, ExtFormCompareWide:
@@ -984,6 +997,10 @@ func (f ExtForm) String() string {
return "compare to a predicate"
case ExtFormCompareWide:
return "wide compare to a predicate"
case ExtFormVLArith:
return "vector-length arithmetic"
case ExtFormVLRead:
return "vector-length read"
case ExtFormNone:
return "no operands"
default:
@@ -1254,6 +1271,10 @@ func (in ExtInstr) Encode(ops []ExtOperand) ([]byte, error) {
return in.encodeCompare(ops)
case ExtFormCompareWide:
return in.encodeCompare(ops)
case ExtFormVLArith:
return in.encodeVLArith(ops)
case ExtFormVLRead:
return in.encodeVLRead(ops)
case ExtFormNone:
if len(ops) != 0 {
return nil, fmt.Errorf("%s: the %s form takes no operands, got %d",
@@ -2853,6 +2874,48 @@ func (in ExtInstr) encodeMulPred(ops []ExtOperand) ([]byte, error) {
// 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
// one step above it.
// encodeVLArith fills the vector-length arithmetic: imm, Rn|SP, Rd|SP.
// The signed imm6 counts multiples of the vector length; the register
// slots spell RSP, never a plain R31.
func (in ExtInstr) encodeVLArith(ops []ExtOperand) ([]byte, error) {
imm, rn, rd := ops[0], ops[1], ops[2]
if imm.Kind != ExtImm {
return nil, fmt.Errorf("%s: operand 1 wants an immediate, got %s", in.Name, imm.Kind)
}
if imm.Imm < -32 || imm.Imm > 31 {
return nil, fmt.Errorf("%s: immediate %d is outside the signed 6-bit range -32..31", in.Name, imm.Imm)
}
if err := in.generalOperand(rn, 2, 2); err != nil {
return nil, err
}
if err := in.generalOperand(rd, 3, 2); err != nil {
return nil, err
}
word := in.Word
word = extSet(word, extFieldImm6, uint32(imm.Imm))
word = extSet(word, extFieldRm, uint32(rn.Reg))
word = extSet(word, extFieldRd, uint32(rd.Reg))
return extWordLE(word), nil
}
// encodeVLRead fills the vector-length read: imm, Rd (R0-R30).
func (in ExtInstr) encodeVLRead(ops []ExtOperand) ([]byte, error) {
imm, rd := ops[0], ops[1]
if imm.Kind != ExtImm {
return nil, fmt.Errorf("%s: operand 1 wants an immediate, got %s", in.Name, imm.Kind)
}
if imm.Imm < -32 || imm.Imm > 31 {
return nil, fmt.Errorf("%s: immediate %d is outside the signed 6-bit range -32..31", in.Name, imm.Imm)
}
if err := in.generalOperand(rd, 2, 0); err != nil {
return nil, err
}
word := in.Word
word = extSet(word, extFieldImm6, uint32(imm.Imm))
word = extSet(word, extFieldRd, uint32(rd.Reg))
return extWordLE(word), nil
}
// 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
@@ -3797,6 +3860,23 @@ var arm64Extensions = []ExtInstr{
{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 vector-length arithmetic pseudo group ----------------------------
//
// ADDVL, ADDPL and RDVL over the signed imm6 multiple of the vector
// length or the parameter register. 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: "ADDPL", Summary: "Add a signed multiple of the parameter register count to a register",
Word: 0x04605000, Form: ExtFormVLArith, Feature: ExtFeatureSVE,
Ref: "ARM DDI 0487J: ADDPL; inst_gen.go + arm64sveenc.s"},
{Name: "ADDVL", Summary: "Add a signed multiple of the vector length to a register",
Word: 0x04205000, Form: ExtFormVLArith, Feature: ExtFeatureSVE,
Ref: "ARM DDI 0487J: ADDVL; inst_gen.go + arm64sveenc.s"},
{Name: "RDVL", Summary: "Read the vector length multiplied by a signed immediate",
Word: 0x04bf5000, Form: ExtFormVLRead, Feature: ExtFeatureSVE,
Ref: "ARM DDI 0487J: RDVL; inst_gen.go + arm64sveenc.s"},
// --- the SVE multiple-structure loads and stores --------------------------
//
// The two-, three- and four-register list loads and stores over the
+5 -2
View File
@@ -346,6 +346,9 @@ func TestExtensionNamesARM64(t *testing.T) {
"ZCMPHI",
"ZCMPHS",
"ZCMPNE",
"ADDPL",
"ADDVL",
"RDVL",
"ZLD2B",
"ZLD2D",
"ZLD2H",
@@ -488,7 +491,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 != 497 {
t.Errorf("the family registers %d instructions, want 497", n)
if n := len(arch.Extensions(arch.ARM64)); n != 500 {
t.Errorf("the family registers %d instructions, want 500", n)
}
}