feat(arch): the SVE predicate family in the extended layer
Assisted-by: GLM 5.3 Flash
This commit is contained in:
1 parent
83052ab466
commit
8231302bca
5 files changed
+1451
-42
No files matched your search
+404
-9
@@ -279,27 +279,36 @@ func extInstructionQuiet(mnem string, form ExtForm) (ExtInstr, bool) {
|
||||
}
|
||||
|
||||
// TestArm64ExtTableIntegrity checks the metadata contract: every entry names
|
||||
// its manual reference, summary and feature, and the element-size field sits
|
||||
// at bits 23..22 where the manual puts it for every class in the family.
|
||||
// its manual reference, summary and feature, the element-size field sits
|
||||
// at bits 23..22 for the classes that carry one, and the destination field
|
||||
// stays zero in the fixed word: five bits where a Z register is the
|
||||
// destination, four where a predicate is.
|
||||
func TestArm64ExtTableIntegrity(t *testing.T) {
|
||||
for _, in := range Extensions(ARM64) {
|
||||
if in.Name == "" || in.Summary == "" || in.Ref == "" {
|
||||
t.Errorf("%+v: name, summary and reference are mandatory", in)
|
||||
}
|
||||
if in.Feature != ExtFeatureSVE && in.Feature != ExtFeatureSVE2 {
|
||||
t.Errorf("%s: feature %q is neither sve nor sve2", in.Name, in.Feature)
|
||||
if in.Feature != ExtFeatureSVE && in.Feature != ExtFeatureSVE2 && in.Feature != ExtFeatureSVE2p1 {
|
||||
t.Errorf("%s: feature %q is neither sve, sve2 nor sve2p1", in.Name, in.Feature)
|
||||
}
|
||||
if in.Form.Arity() < 2 || in.Form.Arity() > 3 {
|
||||
if in.Form.Arity() < 0 || in.Form.Arity() > 4 {
|
||||
t.Errorf("%s: form %d carries an unusable arity %d", in.Name, in.Form, in.Form.Arity())
|
||||
}
|
||||
if in.Size.Off != 22 || in.Size.Width != 2 {
|
||||
if in.Size.Width != 0 && (in.Size.Off != 22 || in.Size.Width != 2) {
|
||||
t.Errorf("%s: the size field sits at bits %d..%d, the classes here put it at 23..22",
|
||||
in.Name, in.Size.Off, in.Size.Off+in.Size.Width-1)
|
||||
}
|
||||
// The destination register field and the element-size field are
|
||||
// operands everywhere in this family, so Word carries both zero; the
|
||||
// class opcodes live around them and stay where they are.
|
||||
if in.Word&0x1f != 0 || in.Word&(0x3<<22) != 0 {
|
||||
// operands wherever they exist, so Word carries both zero; the
|
||||
// class opcodes live around them and stay where they are. Where
|
||||
// the class carries no size field, bits 23..22 are class bits and
|
||||
// stay.
|
||||
destMask := uint32(0x1f)
|
||||
if in.Form != ExtFormVectors && in.Form != ExtFormPredicated &&
|
||||
in.Form != ExtFormImmediate && in.Form != ExtFormSignedImmediate {
|
||||
destMask = 0xf // the predicate destination is a four-bit field
|
||||
}
|
||||
if in.Word&destMask != 0 || (in.Size.Width != 0 && in.Word&(0x3<<22) != 0) {
|
||||
t.Errorf("%s: word %08x carries destination or size bits, want them zero", in.Name, in.Word)
|
||||
}
|
||||
}
|
||||
@@ -401,3 +410,389 @@ func TestExtensionsArchBinding(t *testing.T) {
|
||||
t.Error("Extensions(AMD64) is empty")
|
||||
}
|
||||
}
|
||||
|
||||
// TestArm64ExtPredicateGolden pins the SVE and SVE2.1 predicate family
|
||||
// against the toolchain-generated corpus: every row is one arm64sveenc.s
|
||||
// line, and the want word is that line's own expected encoding, byte
|
||||
// reversed out of the file's big-endian comment into the little-endian
|
||||
// instruction word. The corpus and the toolchain's encoding table
|
||||
// (inst_gen.go) are two independent generations from Arm's official ISA
|
||||
// description; both agree with the field layouts encoded here, and the
|
||||
// classes have no single-byte oracle beyond them (go tool asm carries no
|
||||
// SVE encodings).
|
||||
func TestArm64ExtPredicateGolden(t *testing.T) {
|
||||
for _, tt := range []struct {
|
||||
name string
|
||||
mnem string
|
||||
form ExtForm
|
||||
ops []ExtOperand
|
||||
want uint32
|
||||
}{
|
||||
{"PAND P4.B, P2.B, P1.Z, P14.B", "PAND",
|
||||
ExtFormPredicateLogical,
|
||||
[]ExtOperand{ExtPredicateSized(4, ExtArrB), ExtPredicateSized(2, ExtArrB), ExtPredicate(1, ExtQualZeroing), ExtPredicateSized(14, ExtArrB)},
|
||||
0x2504444e},
|
||||
{"PANDS P4.B, P2.B, P1.Z, P14.B", "PANDS",
|
||||
ExtFormPredicateLogical,
|
||||
[]ExtOperand{ExtPredicateSized(4, ExtArrB), ExtPredicateSized(2, ExtArrB), ExtPredicate(1, ExtQualZeroing), ExtPredicateSized(14, ExtArrB)},
|
||||
0x2544444e},
|
||||
{"PBIC P4.B, P2.B, P1.Z, P14.B", "PBIC",
|
||||
ExtFormPredicateLogical,
|
||||
[]ExtOperand{ExtPredicateSized(4, ExtArrB), ExtPredicateSized(2, ExtArrB), ExtPredicate(1, ExtQualZeroing), ExtPredicateSized(14, ExtArrB)},
|
||||
0x2504445e},
|
||||
{"PBICS P4.B, P2.B, P1.Z, P14.B", "PBICS",
|
||||
ExtFormPredicateLogical,
|
||||
[]ExtOperand{ExtPredicateSized(4, ExtArrB), ExtPredicateSized(2, ExtArrB), ExtPredicate(1, ExtQualZeroing), ExtPredicateSized(14, ExtArrB)},
|
||||
0x2544445e},
|
||||
{"PBRKA P5.B, P9.Z, P2.B", "PBRKA",
|
||||
ExtFormPredicateBreak,
|
||||
[]ExtOperand{ExtPredicateSized(5, ExtArrB), ExtPredicate(9, ExtQualZeroing), ExtPredicateSized(2, ExtArrB)},
|
||||
0x251064a2},
|
||||
{"PBRKAS P5.B, P9.Z, P4.B", "PBRKAS",
|
||||
ExtFormPredicateBreakZero,
|
||||
[]ExtOperand{ExtPredicateSized(5, ExtArrB), ExtPredicate(9, ExtQualZeroing), ExtPredicateSized(4, ExtArrB)},
|
||||
0x255064a4},
|
||||
{"PBRKB P5.B, P9.Z, P2.B", "PBRKB",
|
||||
ExtFormPredicateBreak,
|
||||
[]ExtOperand{ExtPredicateSized(5, ExtArrB), ExtPredicate(9, ExtQualZeroing), ExtPredicateSized(2, ExtArrB)},
|
||||
0x259064a2},
|
||||
{"PBRKBS P5.B, P9.Z, P4.B", "PBRKBS",
|
||||
ExtFormPredicateBreakZero,
|
||||
[]ExtOperand{ExtPredicateSized(5, ExtArrB), ExtPredicate(9, ExtQualZeroing), ExtPredicateSized(4, ExtArrB)},
|
||||
0x25d064a4},
|
||||
{"PBRKN P4.B, P2.B, P1.Z, P4.B", "PBRKN",
|
||||
ExtFormPredicateLogicalDest,
|
||||
[]ExtOperand{ExtPredicateSized(4, ExtArrB), ExtPredicateSized(2, ExtArrB), ExtPredicate(1, ExtQualZeroing), ExtPredicateSized(4, ExtArrB)},
|
||||
0x25184444},
|
||||
{"PBRKNS P4.B, P2.B, P1.Z, P4.B", "PBRKNS",
|
||||
ExtFormPredicateLogicalDest,
|
||||
[]ExtOperand{ExtPredicateSized(4, ExtArrB), ExtPredicateSized(2, ExtArrB), ExtPredicate(1, ExtQualZeroing), ExtPredicateSized(4, ExtArrB)},
|
||||
0x25584444},
|
||||
{"PBRKPA P4.B, P2.B, P1.Z, P14.B", "PBRKPA",
|
||||
ExtFormPredicateLogical,
|
||||
[]ExtOperand{ExtPredicateSized(4, ExtArrB), ExtPredicateSized(2, ExtArrB), ExtPredicate(1, ExtQualZeroing), ExtPredicateSized(14, ExtArrB)},
|
||||
0x2504c44e},
|
||||
{"PBRKPAS P4.B, P2.B, P1.Z, P14.B", "PBRKPAS",
|
||||
ExtFormPredicateLogical,
|
||||
[]ExtOperand{ExtPredicateSized(4, ExtArrB), ExtPredicateSized(2, ExtArrB), ExtPredicate(1, ExtQualZeroing), ExtPredicateSized(14, ExtArrB)},
|
||||
0x2544c44e},
|
||||
{"PBRKPB P4.B, P2.B, P1.Z, P14.B", "PBRKPB",
|
||||
ExtFormPredicateLogical,
|
||||
[]ExtOperand{ExtPredicateSized(4, ExtArrB), ExtPredicateSized(2, ExtArrB), ExtPredicate(1, ExtQualZeroing), ExtPredicateSized(14, ExtArrB)},
|
||||
0x2504c45e},
|
||||
{"PBRKPBS P4.B, P2.B, P1.Z, P14.B", "PBRKPBS",
|
||||
ExtFormPredicateLogical,
|
||||
[]ExtOperand{ExtPredicateSized(4, ExtArrB), ExtPredicateSized(2, ExtArrB), ExtPredicate(1, ExtQualZeroing), ExtPredicateSized(14, ExtArrB)},
|
||||
0x2544c45e},
|
||||
{"PEOR P4.B, P2.B, P1.Z, P14.B", "PEOR",
|
||||
ExtFormPredicateLogical,
|
||||
[]ExtOperand{ExtPredicateSized(4, ExtArrB), ExtPredicateSized(2, ExtArrB), ExtPredicate(1, ExtQualZeroing), ExtPredicateSized(14, ExtArrB)},
|
||||
0x2504464e},
|
||||
{"PEORS P4.B, P2.B, P1.Z, P14.B", "PEORS",
|
||||
ExtFormPredicateLogical,
|
||||
[]ExtOperand{ExtPredicateSized(4, ExtArrB), ExtPredicateSized(2, ExtArrB), ExtPredicate(1, ExtQualZeroing), ExtPredicateSized(14, ExtArrB)},
|
||||
0x2544464e},
|
||||
{"PNAND P4.B, P2.B, P1.Z, P14.B", "PNAND",
|
||||
ExtFormPredicateLogical,
|
||||
[]ExtOperand{ExtPredicateSized(4, ExtArrB), ExtPredicateSized(2, ExtArrB), ExtPredicate(1, ExtQualZeroing), ExtPredicateSized(14, ExtArrB)},
|
||||
0x2584465e},
|
||||
{"PNANDS P4.B, P2.B, P1.Z, P14.B", "PNANDS",
|
||||
ExtFormPredicateLogical,
|
||||
[]ExtOperand{ExtPredicateSized(4, ExtArrB), ExtPredicateSized(2, ExtArrB), ExtPredicate(1, ExtQualZeroing), ExtPredicateSized(14, ExtArrB)},
|
||||
0x25c4465e},
|
||||
{"PNOR P4.B, P2.B, P1.Z, P14.B", "PNOR",
|
||||
ExtFormPredicateLogical,
|
||||
[]ExtOperand{ExtPredicateSized(4, ExtArrB), ExtPredicateSized(2, ExtArrB), ExtPredicate(1, ExtQualZeroing), ExtPredicateSized(14, ExtArrB)},
|
||||
0x2584464e},
|
||||
{"PNORS P4.B, P2.B, P1.Z, P14.B", "PNORS",
|
||||
ExtFormPredicateLogical,
|
||||
[]ExtOperand{ExtPredicateSized(4, ExtArrB), ExtPredicateSized(2, ExtArrB), ExtPredicate(1, ExtQualZeroing), ExtPredicateSized(14, ExtArrB)},
|
||||
0x25c4464e},
|
||||
{"PORN P4.B, P2.B, P1.Z, P14.B", "PORN",
|
||||
ExtFormPredicateLogical,
|
||||
[]ExtOperand{ExtPredicateSized(4, ExtArrB), ExtPredicateSized(2, ExtArrB), ExtPredicate(1, ExtQualZeroing), ExtPredicateSized(14, ExtArrB)},
|
||||
0x2584445e},
|
||||
{"PORNS P4.B, P2.B, P1.Z, P14.B", "PORNS",
|
||||
ExtFormPredicateLogical,
|
||||
[]ExtOperand{ExtPredicateSized(4, ExtArrB), ExtPredicateSized(2, ExtArrB), ExtPredicate(1, ExtQualZeroing), ExtPredicateSized(14, ExtArrB)},
|
||||
0x25c4445e},
|
||||
{"PORR P4.B, P2.B, P1.Z, P14.B", "PORR",
|
||||
ExtFormPredicateLogical,
|
||||
[]ExtOperand{ExtPredicateSized(4, ExtArrB), ExtPredicateSized(2, ExtArrB), ExtPredicate(1, ExtQualZeroing), ExtPredicateSized(14, ExtArrB)},
|
||||
0x2584444e},
|
||||
{"PORRS P4.B, P2.B, P1.Z, P14.B", "PORRS",
|
||||
ExtFormPredicateLogical,
|
||||
[]ExtOperand{ExtPredicateSized(4, ExtArrB), ExtPredicateSized(2, ExtArrB), ExtPredicate(1, ExtQualZeroing), ExtPredicateSized(14, ExtArrB)},
|
||||
0x25c4444e},
|
||||
{"PPFALSE P13.B", "PPFALSE",
|
||||
ExtFormPredicateOne,
|
||||
[]ExtOperand{ExtPredicateSized(13, ExtArrB)},
|
||||
0x2518e40d},
|
||||
{"PPFIRST P5.B, P9, P5.B", "PPFIRST",
|
||||
ExtFormPredicateFirst,
|
||||
[]ExtOperand{ExtPredicateSized(5, ExtArrB), ExtPredicate(9, ExtQualNone), ExtPredicateSized(5, ExtArrB)},
|
||||
0x2558c125},
|
||||
{"PPNEXT P5.D, P4, P5.D", "PPNEXT",
|
||||
ExtFormPredicateNext,
|
||||
[]ExtOperand{ExtPredicateSized(5, ExtArrD), ExtPredicate(4, ExtQualNone), ExtPredicateSized(5, ExtArrD)},
|
||||
0x25d9c485},
|
||||
{"PPTEST P14.B, P0", "PPTEST",
|
||||
ExtFormPredicateTest,
|
||||
[]ExtOperand{ExtPredicateSized(14, ExtArrB), ExtPredicate(0, ExtQualNone)},
|
||||
0x2550c1c0},
|
||||
{"PPTRUE PN14.S", "PPTRUE",
|
||||
ExtFormPredicateCounter,
|
||||
[]ExtOperand{ExtCounterPredicate(14, ExtArrS)},
|
||||
0x25a07816},
|
||||
{"PPUNPKHI P14.B, P0.H", "PPUNPKHI",
|
||||
ExtFormPredicateUnpack,
|
||||
[]ExtOperand{ExtPredicateSized(14, ExtArrB), ExtPredicateSized(0, ExtArrH)},
|
||||
0x053141c0},
|
||||
{"PPUNPKLO P14.B, P0.H", "PPUNPKLO",
|
||||
ExtFormPredicateUnpack,
|
||||
[]ExtOperand{ExtPredicateSized(14, ExtArrB), ExtPredicateSized(0, ExtArrH)},
|
||||
0x053041c0},
|
||||
{"PRDFFR P14.Z, P0.B", "PRDFFR",
|
||||
ExtFormPredicateFFRRead,
|
||||
[]ExtOperand{ExtPredicate(14, ExtQualZeroing), ExtPredicateSized(0, ExtArrB)},
|
||||
0x2518f1c0},
|
||||
{"PRDFFR P13.B", "PRDFFR",
|
||||
ExtFormPredicateOne,
|
||||
[]ExtOperand{ExtPredicateSized(13, ExtArrB)},
|
||||
0x2519f00d},
|
||||
{"PRDFFRS P14.Z, P0.B", "PRDFFRS",
|
||||
ExtFormPredicateFFRRead,
|
||||
[]ExtOperand{ExtPredicate(14, ExtQualZeroing), ExtPredicateSized(0, ExtArrB)},
|
||||
0x2558f1c0},
|
||||
{"PREV P14.S, P13.S", "PREV",
|
||||
ExtFormPredicateMove,
|
||||
[]ExtOperand{ExtPredicateSized(14, ExtArrS), ExtPredicateSized(13, ExtArrS)},
|
||||
0x05b441cd},
|
||||
{"PSEL P4.B, P2.B, P1, P14.B", "PSEL",
|
||||
ExtFormPredicateSelect,
|
||||
[]ExtOperand{ExtPredicateSized(4, ExtArrB), ExtPredicateSized(2, ExtArrB), ExtPredicate(1, ExtQualNone), ExtPredicateSized(14, ExtArrB)},
|
||||
0x2504465e},
|
||||
{"PTRN1 P5.D, P4.D, P2.D", "PTRN1",
|
||||
ExtFormPredicatePermute,
|
||||
[]ExtOperand{ExtPredicateSized(5, ExtArrD), ExtPredicateSized(4, ExtArrD), ExtPredicateSized(2, ExtArrD)},
|
||||
0x05e55082},
|
||||
{"PTRN2 P5.D, P4.D, P2.D", "PTRN2",
|
||||
ExtFormPredicatePermute,
|
||||
[]ExtOperand{ExtPredicateSized(5, ExtArrD), ExtPredicateSized(4, ExtArrD), ExtPredicateSized(2, ExtArrD)},
|
||||
0x05e55482},
|
||||
{"PUZP1 P5.D, P4.D, P2.D", "PUZP1",
|
||||
ExtFormPredicatePermute,
|
||||
[]ExtOperand{ExtPredicateSized(5, ExtArrD), ExtPredicateSized(4, ExtArrD), ExtPredicateSized(2, ExtArrD)},
|
||||
0x05e54882},
|
||||
{"PUZP2 P5.D, P4.D, P2.D", "PUZP2",
|
||||
ExtFormPredicatePermute,
|
||||
[]ExtOperand{ExtPredicateSized(5, ExtArrD), ExtPredicateSized(4, ExtArrD), ExtPredicateSized(2, ExtArrD)},
|
||||
0x05e54c82},
|
||||
{"PWRFFR P13.B", "PWRFFR",
|
||||
ExtFormPredicateWrite,
|
||||
[]ExtOperand{ExtPredicateSized(13, ExtArrB)},
|
||||
0x252891a0},
|
||||
{"PZIP1 P5.D, P4.D, P2.D", "PZIP1",
|
||||
ExtFormPredicatePermute,
|
||||
[]ExtOperand{ExtPredicateSized(5, ExtArrD), ExtPredicateSized(4, ExtArrD), ExtPredicateSized(2, ExtArrD)},
|
||||
0x05e54082},
|
||||
{"PZIP2 P5.D, P4.D, P2.D", "PZIP2",
|
||||
ExtFormPredicatePermute,
|
||||
[]ExtOperand{ExtPredicateSized(5, ExtArrD), ExtPredicateSized(4, ExtArrD), ExtPredicateSized(2, ExtArrD)},
|
||||
0x05e54482},
|
||||
{"SETFFR ", "SETFFR",
|
||||
ExtFormNone,
|
||||
[]ExtOperand{},
|
||||
0x252c9000},
|
||||
{"PWHILEGE R2, R10, P10.H", "PWHILEGE",
|
||||
ExtFormWhile,
|
||||
[]ExtOperand{ExtGeneral(2), ExtGeneral(10), ExtPredicateSized(10, ExtArrH)},
|
||||
0x2562114a},
|
||||
{"PWHILEGT R2, R10, P10.H", "PWHILEGT",
|
||||
ExtFormWhile,
|
||||
[]ExtOperand{ExtGeneral(2), ExtGeneral(10), ExtPredicateSized(10, ExtArrH)},
|
||||
0x2562115a},
|
||||
{"PWHILEHI R2, R10, P10.H", "PWHILEHI",
|
||||
ExtFormWhile,
|
||||
[]ExtOperand{ExtGeneral(2), ExtGeneral(10), ExtPredicateSized(10, ExtArrH)},
|
||||
0x2562195a},
|
||||
{"PWHILEHS R2, R10, P10.H", "PWHILEHS",
|
||||
ExtFormWhile,
|
||||
[]ExtOperand{ExtGeneral(2), ExtGeneral(10), ExtPredicateSized(10, ExtArrH)},
|
||||
0x2562194a},
|
||||
{"PWHILELE R2, R10, P10.H", "PWHILELE",
|
||||
ExtFormWhile,
|
||||
[]ExtOperand{ExtGeneral(2), ExtGeneral(10), ExtPredicateSized(10, ExtArrH)},
|
||||
0x2562155a},
|
||||
{"PWHILELO R2, R10, P10.H", "PWHILELO",
|
||||
ExtFormWhile,
|
||||
[]ExtOperand{ExtGeneral(2), ExtGeneral(10), ExtPredicateSized(10, ExtArrH)},
|
||||
0x25621d4a},
|
||||
{"PWHILELS R2, R10, P10.H", "PWHILELS",
|
||||
ExtFormWhile,
|
||||
[]ExtOperand{ExtGeneral(2), ExtGeneral(10), ExtPredicateSized(10, ExtArrH)},
|
||||
0x25621d5a},
|
||||
{"PWHILELT R2, R10, P10.H", "PWHILELT",
|
||||
ExtFormWhile,
|
||||
[]ExtOperand{ExtGeneral(2), ExtGeneral(10), ExtPredicateSized(10, ExtArrH)},
|
||||
0x2562154a},
|
||||
{"PWHILERW R2, R10, P10.H", "PWHILERW",
|
||||
ExtFormWhile,
|
||||
[]ExtOperand{ExtGeneral(2), ExtGeneral(10), ExtPredicateSized(10, ExtArrH)},
|
||||
0x2562315a},
|
||||
{"PWHILEWR R2, R10, P10.H", "PWHILEWR",
|
||||
ExtFormWhile,
|
||||
[]ExtOperand{ExtGeneral(2), ExtGeneral(10), ExtPredicateSized(10, ExtArrH)},
|
||||
0x2562314a},
|
||||
} {
|
||||
in := extInstruction(t, tt.mnem, tt.form)
|
||||
got, err := in.Encode(tt.ops)
|
||||
if err != nil {
|
||||
t.Errorf("%s: encode: %v", tt.name, err)
|
||||
continue
|
||||
}
|
||||
if want := hex.EncodeToString(extWordLE(tt.want)); hex.EncodeToString(got) != want {
|
||||
t.Errorf("%s:\n got %x\n want %s", tt.name, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestArm64ExtPredicateSources pins the cross-check contract of the
|
||||
// predicate family: every class the layer defines carries at least one
|
||||
// golden vector derived from the toolchain-generated corpus, so no class
|
||||
// rests on transcription alone.
|
||||
func TestArm64ExtPredicateSources(t *testing.T) {
|
||||
for _, tt := range []struct {
|
||||
mnem string
|
||||
form ExtForm
|
||||
}{
|
||||
{"PAND", ExtFormPredicateLogical}, {"PANDS", ExtFormPredicateLogical},
|
||||
{"PBIC", ExtFormPredicateLogical}, {"PBICS", ExtFormPredicateLogical},
|
||||
{"PEOR", ExtFormPredicateLogical}, {"PEORS", ExtFormPredicateLogical},
|
||||
{"PNAND", ExtFormPredicateLogical}, {"PNANDS", ExtFormPredicateLogical},
|
||||
{"PNOR", ExtFormPredicateLogical}, {"PNORS", ExtFormPredicateLogical},
|
||||
{"PORN", ExtFormPredicateLogical}, {"PORNS", ExtFormPredicateLogical},
|
||||
{"PORR", ExtFormPredicateLogical}, {"PORRS", ExtFormPredicateLogical},
|
||||
{"PSEL", ExtFormPredicateSelect},
|
||||
{"PBRKA", ExtFormPredicateBreak}, {"PBRKAS", ExtFormPredicateBreakZero},
|
||||
{"PBRKB", ExtFormPredicateBreak}, {"PBRKBS", ExtFormPredicateBreakZero},
|
||||
{"PBRKN", ExtFormPredicateLogicalDest}, {"PBRKNS", ExtFormPredicateLogicalDest},
|
||||
{"PBRKPA", ExtFormPredicateLogical}, {"PBRKPAS", ExtFormPredicateLogical},
|
||||
{"PBRKPB", ExtFormPredicateLogical}, {"PBRKPBS", ExtFormPredicateLogical},
|
||||
{"PTRN1", ExtFormPredicatePermute}, {"PTRN2", ExtFormPredicatePermute},
|
||||
{"PUZP1", ExtFormPredicatePermute}, {"PUZP2", ExtFormPredicatePermute},
|
||||
{"PZIP1", ExtFormPredicatePermute}, {"PZIP2", ExtFormPredicatePermute},
|
||||
{"PPFALSE", ExtFormPredicateOne},
|
||||
{"PPFIRST", ExtFormPredicateFirst},
|
||||
{"PPNEXT", ExtFormPredicateNext},
|
||||
{"PPTEST", ExtFormPredicateTest},
|
||||
{"PPTRUE", ExtFormPredicateCounter},
|
||||
{"PPUNPKHI", ExtFormPredicateUnpack}, {"PPUNPKLO", ExtFormPredicateUnpack},
|
||||
{"PRDFFR", ExtFormPredicateFFRRead}, {"PRDFFR", ExtFormPredicateOne},
|
||||
{"PRDFFRS", ExtFormPredicateFFRRead},
|
||||
{"PWRFFR", ExtFormPredicateWrite},
|
||||
{"PREV", ExtFormPredicateMove},
|
||||
{"SETFFR", ExtFormNone},
|
||||
{"PWHILEGE", ExtFormWhile}, {"PWHILEGT", ExtFormWhile},
|
||||
{"PWHILEHI", ExtFormWhile}, {"PWHILEHS", ExtFormWhile},
|
||||
{"PWHILELE", ExtFormWhile}, {"PWHILELO", ExtFormWhile},
|
||||
{"PWHILELS", ExtFormWhile}, {"PWHILELT", ExtFormWhile},
|
||||
{"PWHILERW", ExtFormWhile}, {"PWHILEWR", ExtFormWhile},
|
||||
} {
|
||||
if _, ok := extInstructionQuiet(tt.mnem, tt.form); !ok {
|
||||
t.Errorf("the table lacks %s with the %s form", tt.mnem, tt.form)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestArm64ExtPredicateRejects pins the diagnostics the predicate forms
|
||||
// give the operands their classes cannot carry: the register ranges the
|
||||
// field widths imply, the arrangements the classes fix, and the read-back
|
||||
// constraint of the destination-shared shapes.
|
||||
func TestArm64ExtPredicateRejects(t *testing.T) {
|
||||
pb := func(r int) ExtOperand { return ExtPredicateSized(r, ExtArrB) }
|
||||
for _, tt := range []struct {
|
||||
name string
|
||||
mnem string
|
||||
form ExtForm
|
||||
ops []ExtOperand
|
||||
quote string
|
||||
}{
|
||||
{"Pm beyond the three-bit field", "PAND", ExtFormPredicateLogical,
|
||||
[]ExtOperand{pb(8), pb(2), ExtPredicate(1, ExtQualZeroing), pb(14)},
|
||||
"outside P0-P7"},
|
||||
{"governing predicate beyond the narrow field", "PAND", ExtFormPredicateLogical,
|
||||
[]ExtOperand{pb(4), pb(2), ExtPredicate(8, ExtQualZeroing), pb(14)},
|
||||
"outside P0-P7"},
|
||||
{"wrong arrangement on the second source", "PAND", ExtFormPredicateLogical,
|
||||
[]ExtOperand{pb(4), ExtPredicateSized(2, ExtArrS), ExtPredicate(1, ExtQualZeroing), pb(14)},
|
||||
"want .B"},
|
||||
{"bare governing predicate", "PAND", ExtFormPredicateLogical,
|
||||
[]ExtOperand{pb(4), pb(2), ExtPredicate(1, ExtQualNone), pb(14)},
|
||||
"zeroing qualifier"},
|
||||
{"quadword arrangement", "PSEL", ExtFormPredicateSelect,
|
||||
[]ExtOperand{ExtPredicateSized(4, ExtArrQ), ExtPredicateSized(2, ExtArrQ), ExtPredicate(1, ExtQualNone), ExtPredicateSized(14, ExtArrQ)},
|
||||
"want .B"},
|
||||
{"qualifier where PSEL wants none", "PSEL", ExtFormPredicateSelect,
|
||||
[]ExtOperand{pb(4), pb(2), ExtPredicate(1, ExtQualZeroing), pb(14)},
|
||||
"takes no qualifier"},
|
||||
{"read-back operands disagree", "PBRKN", ExtFormPredicateLogicalDest,
|
||||
[]ExtOperand{pb(4), pb(2), ExtPredicate(1, ExtQualZeroing), pb(9)},
|
||||
"same register Pdm"},
|
||||
{"merging qualifier on the zeroing break", "PBRKAS", ExtFormPredicateBreakZero,
|
||||
[]ExtOperand{pb(5), ExtPredicate(9, ExtQualMerging), pb(4)},
|
||||
"zeroing qualifier"},
|
||||
{"governing predicate beyond the wide field", "PBRKA", ExtFormPredicateBreak,
|
||||
[]ExtOperand{pb(5), ExtPredicate(16, ExtQualZeroing), pb(2)},
|
||||
"outside P0-P15"},
|
||||
{"permutations disagree on arrangement", "PTRN1", ExtFormPredicatePermute,
|
||||
[]ExtOperand{ExtPredicateSized(5, ExtArrD), ExtPredicateSized(4, ExtArrD), ExtPredicateSized(2, ExtArrS)},
|
||||
"want .D"},
|
||||
{"bare permutation operand", "PUZP1", ExtFormPredicatePermute,
|
||||
[]ExtOperand{ExtPredicateSized(5, ExtArrD), {Kind: ExtPReg, Reg: 4}, ExtPredicateSized(2, ExtArrD)},
|
||||
"no arrangement suffix"},
|
||||
{"read-back operands disagree on arrangement", "PPNEXT", ExtFormPredicateNext,
|
||||
[]ExtOperand{ExtPredicateSized(5, ExtArrD), ExtPredicate(4, ExtQualNone), ExtPredicateSized(5, ExtArrS)},
|
||||
"same register Pdn"},
|
||||
{"qualifier on the bare source", "PPFIRST", ExtFormPredicateFirst,
|
||||
[]ExtOperand{pb(5), ExtPredicate(9, ExtQualZeroing), pb(5)},
|
||||
"takes no qualifier"},
|
||||
{"PFIRST outside .B", "PPFIRST", ExtFormPredicateFirst,
|
||||
[]ExtOperand{ExtPredicateSized(5, ExtArrS), ExtPredicate(9, ExtQualNone), ExtPredicateSized(5, ExtArrS)},
|
||||
"want .B"},
|
||||
{"merging qualifier on the FFR read", "PRDFFR", ExtFormPredicateFFRRead,
|
||||
[]ExtOperand{ExtPredicate(14, ExtQualMerging), pb(0)},
|
||||
"zeroing qualifier"},
|
||||
{"wrong unpack destination arrangement", "PPUNPKHI", ExtFormPredicateUnpack,
|
||||
[]ExtOperand{pb(14), ExtPredicateSized(0, ExtArrB)},
|
||||
"want .H"},
|
||||
{"qualifier on the tested predicate", "PPTEST", ExtFormPredicateTest,
|
||||
[]ExtOperand{pb(14), ExtPredicate(0, ExtQualZeroing)},
|
||||
"takes no qualifier"},
|
||||
{"general register beyond R30", "PWHILELT", ExtFormWhile,
|
||||
[]ExtOperand{ExtGeneral(31), ExtGeneral(10), ExtPredicateSized(10, ExtArrH)},
|
||||
"outside R0-R30"},
|
||||
{"predicate where the register belongs", "PWHILELT", ExtFormWhile,
|
||||
[]ExtOperand{pb(2), ExtGeneral(10), ExtPredicateSized(10, ExtArrH)},
|
||||
"wants a general register"},
|
||||
{"counter predicate spelled plain", "PPTRUE", ExtFormPredicateCounter,
|
||||
[]ExtOperand{ExtPredicateSized(6, ExtArrS)},
|
||||
"predicate-as-counter register"},
|
||||
{"counter below the counter range", "PPTRUE", ExtFormPredicateCounter,
|
||||
[]ExtOperand{ExtCounterPredicate(7, ExtArrS)},
|
||||
"outside PN8-PN15"},
|
||||
{"operand where none belongs", "SETFFR", ExtFormNone,
|
||||
[]ExtOperand{pb(13)},
|
||||
"takes 0 operands"},
|
||||
} {
|
||||
in := extInstruction(t, tt.mnem, tt.form)
|
||||
_, err := in.Encode(tt.ops)
|
||||
if err == nil {
|
||||
t.Errorf("%s: encode succeeded, want an error", tt.name)
|
||||
continue
|
||||
}
|
||||
if !strings.Contains(err.Error(), tt.quote) {
|
||||
t.Errorf("%s: error %q lacks %q", tt.name, err, tt.quote)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user