feat(arch): add the imm8 scalar FP16 controls to the amd64 extension layer
Assisted-by: GLM 5.3 Flash
This commit is contained in:
1 parent
0354a1f4c1
commit
aa9c7ca030
4 files changed
+288
-8
No files matched your search
+90
-3
@@ -200,6 +200,27 @@ var amd64GoldenRows = []amd64GoldenRow{
|
||||
[]ExtOperand{ExtZmm(29), ExtZmm(30)},
|
||||
"62057c4851f5", "62 05 7c 48 51 f5 vsqrtph %zmm29,%zmm30"},
|
||||
|
||||
// The imm8-control group of the scalar core. The rows take the
|
||||
// immediate first and the sources after it as src1, src2, the reverse
|
||||
// of the listing's AT&T register order; every control byte is the $0x7b
|
||||
// the suite drives through each imm8 form, save VGETMANTSH: the upper
|
||||
// nibble of its control is reserved, so the layer enforces the SDM and
|
||||
// encodes $0x0b where the suite's $0x7b would fault. The GNU line
|
||||
// still proves the six opcode bytes, the immediate rides last as the
|
||||
// operand it is.
|
||||
{"vcmpsh", "VCMPSH",
|
||||
[]ExtOperand{ExtImmediate(0x7b), ExtXmm(29), ExtXmm(28), ExtMask(5)},
|
||||
"62931600c2ec7b", "62 93 16 00 c2 ec 7b vcmpsh $0x7b,%xmm28,%xmm29,%k5"},
|
||||
{"vgetmantsh", "VGETMANTSH",
|
||||
[]ExtOperand{ExtImmediate(0x0b), ExtXmm(29), ExtXmm(28), ExtXmm(30)},
|
||||
"6203140027f40b", "62 03 14 00 27 f4 7b vgetmantsh $0x7b,%xmm28,%xmm29,%xmm30 (opcode row only)"},
|
||||
{"vreducesh", "VREDUCESH",
|
||||
[]ExtOperand{ExtImmediate(0x7b), ExtXmm(29), ExtXmm(28), ExtXmm(30)},
|
||||
"6203140057f47b", "62 03 14 00 57 f4 7b vreducesh $0x7b,%xmm28,%xmm29,%xmm30"},
|
||||
{"vrndscalesh", "VRNDSCALESH",
|
||||
[]ExtOperand{ExtImmediate(0x7b), ExtXmm(29), ExtXmm(28), ExtXmm(30)},
|
||||
"620314000af47b", "62 03 14 00 0a f4 7b vrndscalesh $0x7b,%xmm28,%xmm29,%xmm30"},
|
||||
|
||||
// High registers in a 512-bit form exercise the EVEX extension bits:
|
||||
// with both sources above 15 the B bar and X bar bits clear, while the
|
||||
// destination zmm23 keeps R bar set in byte one (derived from the
|
||||
@@ -319,7 +340,7 @@ func TestAmd64ExtTemplateIntegrity(t *testing.T) {
|
||||
if in.Bytes[5]&0x3f != 0 || in.Bytes[5]&0xc0 != 0xc0 {
|
||||
t.Errorf("%s: byte five is %08b, want mod 11 with the reg and rm fields zero", in.Name, in.Bytes[5])
|
||||
}
|
||||
if in.Form.Arity() < 2 || in.Form.Arity() > 3 {
|
||||
if in.Form.Arity() < 2 || in.Form.Arity() > 4 {
|
||||
t.Errorf("%s: form %s carries an unusable arity %d", in.Name, in.Form, in.Form.Arity())
|
||||
}
|
||||
}
|
||||
@@ -381,6 +402,27 @@ func TestAmd64ExtRejects(t *testing.T) {
|
||||
{"predicate qualifier", "VCVTNEPS2BF16",
|
||||
[]ExtOperand{{Kind: ExtZMM, Reg: 1, Qual: ExtQualZeroing}, ExtZmm(2)},
|
||||
"predicate qualifier"},
|
||||
{"vector where the control byte belongs", "VGETMANTSH",
|
||||
[]ExtOperand{ExtXmm(28), ExtXmm(29), ExtXmm(30), ExtXmm(31)},
|
||||
"wants an immediate control byte"},
|
||||
{"reserved upper nibble on the mantissa control", "VGETMANTSH",
|
||||
[]ExtOperand{ExtImmediate(0x7b), ExtXmm(28), ExtXmm(29), ExtXmm(30)},
|
||||
"reserved and must be zero"},
|
||||
{"control byte under the floor", "VREDUCESH",
|
||||
[]ExtOperand{ExtImmediate(-1), ExtXmm(28), ExtXmm(29), ExtXmm(30)},
|
||||
"outside the unsigned byte range"},
|
||||
{"control byte over the top", "VRNDSCALESH",
|
||||
[]ExtOperand{ExtImmediate(256), ExtXmm(28), ExtXmm(29), ExtXmm(30)},
|
||||
"outside the unsigned byte range"},
|
||||
{"shift on the control byte", "VRNDSCALESH",
|
||||
[]ExtOperand{ExtShiftedImmediate(0x0b, 8), ExtXmm(29), ExtXmm(28), ExtXmm(30)},
|
||||
"take none"},
|
||||
{"vector in the mask position of the compare", "VCMPSH",
|
||||
[]ExtOperand{ExtImmediate(7), ExtXmm(28), ExtXmm(29), ExtXmm(30)},
|
||||
"wants an opmask register"},
|
||||
{"mask beyond k7 on the compare", "VCMPSH",
|
||||
[]ExtOperand{ExtImmediate(7), ExtXmm(28), ExtXmm(29), ExtMask(8)},
|
||||
"outside 0-7"},
|
||||
} {
|
||||
in := amd64ExtInstr(t, tt.mnem, operandClass(t, tt.ops))
|
||||
_, err := in.Encode(tt.ops)
|
||||
@@ -415,6 +457,51 @@ func operandClass(t *testing.T, ops []ExtOperand) ExtOperandKind {
|
||||
return ExtXMM
|
||||
}
|
||||
|
||||
// TestAmd64ExtImm8Tables pins the imm8 semantics the layer carries as data
|
||||
// against the SDM tables they are transcribed from: the rounding modes of
|
||||
// the round control, the sign control of the mantissa extraction and the 32
|
||||
// comparison predicates, in encoding order.
|
||||
func TestAmd64ExtImm8Tables(t *testing.T) {
|
||||
roundModes := [4]string{
|
||||
"round to nearest (even)",
|
||||
"round down (toward -infinity)",
|
||||
"round up (toward +infinity)",
|
||||
"round toward zero (truncate)",
|
||||
}
|
||||
if ExtFP16RoundingModes != roundModes {
|
||||
t.Errorf("rounding modes %q, want the SDM RC field order", ExtFP16RoundingModes)
|
||||
}
|
||||
for i, sign := range ExtFP16GetMantSigns {
|
||||
switch i {
|
||||
case 0:
|
||||
if sign != "the sign of the source" {
|
||||
t.Errorf("sign control 0b00 = %q, want the source's own sign", sign)
|
||||
}
|
||||
case 1:
|
||||
if sign != "positive" {
|
||||
t.Errorf("sign control 0b01 = %q, want a forced positive", sign)
|
||||
}
|
||||
default:
|
||||
if sign != "the indefinite NaN when the source is negative" {
|
||||
t.Errorf("sign control 0b1x = %q, want the indefinite NaN branch", sign)
|
||||
}
|
||||
}
|
||||
}
|
||||
predicates := map[int]string{
|
||||
0: "EQ_OQ", 1: "LT_OS", 2: "LE_OS", 3: "UNORD_Q", 4: "NEQ_UQ",
|
||||
5: "NLT_US", 6: "NLE_US", 7: "ORD_Q", 8: "EQ_UQ", 15: "TRUE_UQ",
|
||||
16: "EQ_OS", 23: "ORD_S", 24: "EQ_US", 27: "FALSE_OS", 31: "TRUE_US",
|
||||
}
|
||||
for i, want := range predicates {
|
||||
if got := ExtFP16CmpPredicates[i]; got != want {
|
||||
t.Errorf("predicate 0x%02x = %q, want %q", i, got, want)
|
||||
}
|
||||
}
|
||||
if ExtFP16CmpPredicates[31] != "TRUE_US" {
|
||||
t.Errorf("the predicate table ends at %q, want TRUE_US", ExtFP16CmpPredicates[31])
|
||||
}
|
||||
}
|
||||
|
||||
// TestAmd64ExtArchBinding pins the layer's architecture binding: only riscv
|
||||
// and loong64 have no extended layer, arm64's lives in arm64_ext.go and the
|
||||
// amd64 one here.
|
||||
@@ -424,7 +511,7 @@ func TestAmd64ExtArchBinding(t *testing.T) {
|
||||
t.Errorf("Extensions(%s) carries %d instructions, want none", a, len(got))
|
||||
}
|
||||
}
|
||||
if got := Extensions(AMD64); len(got) != 48 {
|
||||
t.Errorf("the amd64 layer registers %d instructions, want 48", len(got))
|
||||
if got := Extensions(AMD64); len(got) != 52 {
|
||||
t.Errorf("the amd64 layer registers %d instructions, want 52", len(got))
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user