diff --git a/arch/amd64_ext.go b/arch/amd64_ext.go index 55409b4..dca9b4d 100644 --- a/arch/amd64_ext.go +++ b/arch/amd64_ext.go @@ -514,30 +514,74 @@ var amd64Extensions = []ExtInstr{ Bytes: []byte{0x62, 0x05, 0x86, 0x00, 0x79, 0xC0}, Form: ExtFormAmdVecGpr, Feature: ExtFeatureFP16, Ref: "Intel SDM Vol. 2C, VCVTSH2USI (EVEX.LIG.F3.MAP5.W1 79 /r)"}, - // AVX512-FP16 packed, the 512-bit arithmetic the scalar core mirrors: - // full ZMM lanes, EVEX.NDS.MAP5 with no mandatory prefix, rounding - // control left to MXCSR. + // AVX512-FP16 packed arithmetic: the full ZMM lanes the scalar core + // mirrors plus the VL forms, EVEX.NDS.MAP5 with no mandatory prefix, + // rounding control left to MXCSR. The 512-bit register forms are + // quoted from x86-64-avx512_fp16.d, the 256- and 128-bit ones from + // avx512_fp16_vl.d, on the same low registers the suite uses. {Name: "VADDPH", Summary: "Add packed FP16 values", Bytes: []byte{0x62, 0x05, 0x04, 0x40, 0x58, 0xC0}, Form: ExtFormAmdVec3, Feature: ExtFeatureFP16, Ref: "Intel SDM Vol. 2C, VADDPH (EVEX.NDS.512.MAP5.W0 58 /r)"}, + {Name: "VADDPH", Summary: "Add packed FP16 values", + Bytes: []byte{0x62, 0x05, 0x04, 0x20, 0x58, 0xC0}, Form: ExtFormAmdVec3, Feature: ExtFeatureFP16, + Ref: "Intel SDM Vol. 2C, VADDPH (EVEX.NDS.256.MAP5.W0 58 /r)"}, + {Name: "VADDPH", Summary: "Add packed FP16 values", + Bytes: []byte{0x62, 0x05, 0x04, 0x00, 0x58, 0xC0}, Form: ExtFormAmdVec3, Feature: ExtFeatureFP16, + Ref: "Intel SDM Vol. 2C, VADDPH (EVEX.NDS.128.MAP5.W0 58 /r)"}, {Name: "VSUBPH", Summary: "Subtract packed FP16 values", Bytes: []byte{0x62, 0x05, 0x04, 0x40, 0x5C, 0xC0}, Form: ExtFormAmdVec3, Feature: ExtFeatureFP16, Ref: "Intel SDM Vol. 2C, VSUBPH (EVEX.NDS.512.MAP5.W0 5C /r)"}, + {Name: "VSUBPH", Summary: "Subtract packed FP16 values", + Bytes: []byte{0x62, 0x05, 0x04, 0x20, 0x5C, 0xC0}, Form: ExtFormAmdVec3, Feature: ExtFeatureFP16, + Ref: "Intel SDM Vol. 2C, VSUBPH (EVEX.NDS.256.MAP5.W0 5C /r)"}, + {Name: "VSUBPH", Summary: "Subtract packed FP16 values", + Bytes: []byte{0x62, 0x05, 0x04, 0x00, 0x5C, 0xC0}, Form: ExtFormAmdVec3, Feature: ExtFeatureFP16, + Ref: "Intel SDM Vol. 2C, VSUBPH (EVEX.NDS.128.MAP5.W0 5C /r)"}, {Name: "VMULPH", Summary: "Multiply packed FP16 values", Bytes: []byte{0x62, 0x05, 0x04, 0x40, 0x59, 0xC0}, Form: ExtFormAmdVec3, Feature: ExtFeatureFP16, Ref: "Intel SDM Vol. 2C, VMULPH (EVEX.NDS.512.MAP5.W0 59 /r)"}, + {Name: "VMULPH", Summary: "Multiply packed FP16 values", + Bytes: []byte{0x62, 0x05, 0x04, 0x20, 0x59, 0xC0}, Form: ExtFormAmdVec3, Feature: ExtFeatureFP16, + Ref: "Intel SDM Vol. 2C, VMULPH (EVEX.NDS.256.MAP5.W0 59 /r)"}, + {Name: "VMULPH", Summary: "Multiply packed FP16 values", + Bytes: []byte{0x62, 0x05, 0x04, 0x00, 0x59, 0xC0}, Form: ExtFormAmdVec3, Feature: ExtFeatureFP16, + Ref: "Intel SDM Vol. 2C, VMULPH (EVEX.NDS.128.MAP5.W0 59 /r)"}, {Name: "VDIVPH", Summary: "Divide packed FP16 values", Bytes: []byte{0x62, 0x05, 0x04, 0x40, 0x5E, 0xC0}, Form: ExtFormAmdVec3, Feature: ExtFeatureFP16, Ref: "Intel SDM Vol. 2C, VDIVPH (EVEX.NDS.512.MAP5.W0 5E /r)"}, + {Name: "VDIVPH", Summary: "Divide packed FP16 values", + Bytes: []byte{0x62, 0x05, 0x04, 0x20, 0x5E, 0xC0}, Form: ExtFormAmdVec3, Feature: ExtFeatureFP16, + Ref: "Intel SDM Vol. 2C, VDIVPH (EVEX.NDS.256.MAP5.W0 5E /r)"}, + {Name: "VDIVPH", Summary: "Divide packed FP16 values", + Bytes: []byte{0x62, 0x05, 0x04, 0x00, 0x5E, 0xC0}, Form: ExtFormAmdVec3, Feature: ExtFeatureFP16, + Ref: "Intel SDM Vol. 2C, VDIVPH (EVEX.NDS.128.MAP5.W0 5E /r)"}, {Name: "VMINPH", Summary: "Return the minimum of packed FP16 values", Bytes: []byte{0x62, 0x05, 0x04, 0x40, 0x5D, 0xC0}, Form: ExtFormAmdVec3, Feature: ExtFeatureFP16, Ref: "Intel SDM Vol. 2C, VMINPH (EVEX.NDS.512.MAP5.W0 5D /r)"}, + {Name: "VMINPH", Summary: "Return the minimum of packed FP16 values", + Bytes: []byte{0x62, 0x05, 0x04, 0x20, 0x5D, 0xC0}, Form: ExtFormAmdVec3, Feature: ExtFeatureFP16, + Ref: "Intel SDM Vol. 2C, VMINPH (EVEX.NDS.256.MAP5.W0 5D /r)"}, + {Name: "VMINPH", Summary: "Return the minimum of packed FP16 values", + Bytes: []byte{0x62, 0x05, 0x04, 0x00, 0x5D, 0xC0}, Form: ExtFormAmdVec3, Feature: ExtFeatureFP16, + Ref: "Intel SDM Vol. 2C, VMINPH (EVEX.NDS.128.MAP5.W0 5D /r)"}, {Name: "VMAXPH", Summary: "Return the maximum of packed FP16 values", Bytes: []byte{0x62, 0x05, 0x04, 0x40, 0x5F, 0xC0}, Form: ExtFormAmdVec3, Feature: ExtFeatureFP16, Ref: "Intel SDM Vol. 2C, VMAXPH (EVEX.NDS.512.MAP5.W0 5F /r)"}, + {Name: "VMAXPH", Summary: "Return the maximum of packed FP16 values", + Bytes: []byte{0x62, 0x05, 0x04, 0x20, 0x5F, 0xC0}, Form: ExtFormAmdVec3, Feature: ExtFeatureFP16, + Ref: "Intel SDM Vol. 2C, VMAXPH (EVEX.NDS.256.MAP5.W0 5F /r)"}, + {Name: "VMAXPH", Summary: "Return the maximum of packed FP16 values", + Bytes: []byte{0x62, 0x05, 0x04, 0x00, 0x5F, 0xC0}, Form: ExtFormAmdVec3, Feature: ExtFeatureFP16, + Ref: "Intel SDM Vol. 2C, VMAXPH (EVEX.NDS.128.MAP5.W0 5F /r)"}, {Name: "VSQRTPH", Summary: "Compute the square root of packed FP16 values", Bytes: []byte{0x62, 0x05, 0x04, 0x40, 0x51, 0xC0}, Form: ExtFormAmdVec2, Feature: ExtFeatureFP16, Ref: "Intel SDM Vol. 2C, VSQRTPH (EVEX.512.MAP5.W0 51 /r)"}, + {Name: "VSQRTPH", Summary: "Compute the square root of packed FP16 values", + Bytes: []byte{0x62, 0x05, 0x04, 0x20, 0x51, 0xC0}, Form: ExtFormAmdVec2, Feature: ExtFeatureFP16, + Ref: "Intel SDM Vol. 2C, VSQRTPH (EVEX.256.MAP5.W0 51 /r)"}, + {Name: "VSQRTPH", Summary: "Compute the square root of packed FP16 values", + Bytes: []byte{0x62, 0x05, 0x04, 0x00, 0x51, 0xC0}, Form: ExtFormAmdVec2, Feature: ExtFeatureFP16, + Ref: "Intel SDM Vol. 2C, VSQRTPH (EVEX.128.MAP5.W0 51 /r)"}, // AVX512-FP16 scalar, the imm8-control group: mantissa extraction, // reduction, rounding to fraction bits and the compare into an opmask. diff --git a/arch/amd64_ext_test.go b/arch/amd64_ext_test.go index dea67c7..e1b003c 100644 --- a/arch/amd64_ext_test.go +++ b/arch/amd64_ext_test.go @@ -14,8 +14,8 @@ import ( // transcribed from the Intel SDM instruction entries and cross-checked // against binutils-gdb's own assembler testsuite: every row marked "GNU" // matches a vector in gas/testsuite/gas/i386/avx512_bf16.d, -// avx512_bf16_vl.d, x86-64-vp2intersect.d or x86-64-avx512_fp16.d byte for -// byte, so no entry rests on transcription alone. The two VMOVW rows are +// avx512_bf16_vl.d, x86-64-vp2intersect.d, x86-64-avx512_fp16.d or +// avx512_fp16_vl.d byte for byte, so no entry rests on transcription alone. The two VMOVW rows are // class vectors: the GNU file proves the 66.MAP5 opcode row on the m16 // memory forms, and the register form follows the manual's ModR/M reg row. // The GNU dumps print AT&T order (sources first, destination last), which is @@ -176,29 +176,72 @@ var amd64GoldenRows = []amd64GoldenRow{ []ExtOperand{ExtXmm(30), ExtGpr32(12)}, "62157d087ee6", ""}, - // AVX512-FP16 packed arithmetic, EVEX.NDS.512.MAP5.W0 with no - // mandatory prefix. The GNU vector again sits on high registers. + // AVX512-FP16 packed arithmetic, EVEX.NDS.MAP5.W0 with no mandatory + // prefix. The 512-bit GNU rows sit on high registers, the VL rows + // quote avx512_fp16_vl.d on the suite's low registers. {"vaddph", "VADDPH", []ExtOperand{ExtZmm(29), ExtZmm(28), ExtZmm(30)}, "6205144058f4", "62 05 14 40 58 f4 vaddph %zmm28,%zmm29,%zmm30"}, + {"vaddph ymm", "VADDPH", + []ExtOperand{ExtYmm(5), ExtYmm(4), ExtYmm(6)}, + "62f5542858f4", "62 f5 54 28 58 f4 vaddph %ymm4,%ymm5,%ymm6"}, + {"vaddph xmm", "VADDPH", + []ExtOperand{ExtXmm(5), ExtXmm(4), ExtXmm(6)}, + "62f5540858f4", "62 f5 54 08 58 f4 vaddph %xmm4,%xmm5,%xmm6"}, {"vsubph", "VSUBPH", []ExtOperand{ExtZmm(29), ExtZmm(28), ExtZmm(30)}, "620514405cf4", "62 05 14 40 5c f4 vsubph %zmm28,%zmm29,%zmm30"}, + {"vsubph ymm", "VSUBPH", + []ExtOperand{ExtYmm(5), ExtYmm(4), ExtYmm(6)}, + "62f554285cf4", "62 f5 54 28 5c f4 vsubph %ymm4,%ymm5,%ymm6"}, + {"vsubph xmm", "VSUBPH", + []ExtOperand{ExtXmm(5), ExtXmm(4), ExtXmm(6)}, + "62f554085cf4", "62 f5 54 08 5c f4 vsubph %xmm4,%xmm5,%xmm6"}, {"vmulph", "VMULPH", []ExtOperand{ExtZmm(29), ExtZmm(28), ExtZmm(30)}, "6205144059f4", "62 05 14 40 59 f4 vmulph %zmm28,%zmm29,%zmm30"}, + {"vmulph ymm", "VMULPH", + []ExtOperand{ExtYmm(5), ExtYmm(4), ExtYmm(6)}, + "62f5542859f4", "62 f5 54 28 59 f4 vmulph %ymm4,%ymm5,%ymm6"}, + {"vmulph xmm", "VMULPH", + []ExtOperand{ExtXmm(5), ExtXmm(4), ExtXmm(6)}, + "62f5540859f4", "62 f5 54 08 59 f4 vmulph %xmm4,%xmm5,%xmm6"}, {"vdivph", "VDIVPH", []ExtOperand{ExtZmm(29), ExtZmm(28), ExtZmm(30)}, "620514405ef4", "62 05 14 40 5e f4 vdivph %zmm28,%zmm29,%zmm30"}, + {"vdivph ymm", "VDIVPH", + []ExtOperand{ExtYmm(5), ExtYmm(4), ExtYmm(6)}, + "62f554285ef4", "62 f5 54 28 5e f4 vdivph %ymm4,%ymm5,%ymm6"}, + {"vdivph xmm", "VDIVPH", + []ExtOperand{ExtXmm(5), ExtXmm(4), ExtXmm(6)}, + "62f554085ef4", "62 f5 54 08 5e f4 vdivph %xmm4,%xmm5,%xmm6"}, {"vminph", "VMINPH", []ExtOperand{ExtZmm(29), ExtZmm(28), ExtZmm(30)}, "620514405df4", "62 05 14 40 5d f4 vminph %zmm28,%zmm29,%zmm30"}, + {"vminph ymm", "VMINPH", + []ExtOperand{ExtYmm(5), ExtYmm(4), ExtYmm(6)}, + "62f554285df4", "62 f5 54 28 5d f4 vminph %ymm4,%ymm5,%ymm6"}, + {"vminph xmm", "VMINPH", + []ExtOperand{ExtXmm(5), ExtXmm(4), ExtXmm(6)}, + "62f554085df4", "62 f5 54 08 5d f4 vminph %xmm4,%xmm5,%xmm6"}, {"vmaxph", "VMAXPH", []ExtOperand{ExtZmm(29), ExtZmm(28), ExtZmm(30)}, "620514405ff4", "62 05 14 40 5f f4 vmaxph %zmm28,%zmm29,%zmm30"}, + {"vmaxph ymm", "VMAXPH", + []ExtOperand{ExtYmm(5), ExtYmm(4), ExtYmm(6)}, + "62f554285ff4", "62 f5 54 28 5f f4 vmaxph %ymm4,%ymm5,%ymm6"}, + {"vmaxph xmm", "VMAXPH", + []ExtOperand{ExtXmm(5), ExtXmm(4), ExtXmm(6)}, + "62f554085ff4", "62 f5 54 08 5f f4 vmaxph %xmm4,%xmm5,%xmm6"}, {"vsqrtph", "VSQRTPH", []ExtOperand{ExtZmm(29), ExtZmm(30)}, "62057c4851f5", "62 05 7c 48 51 f5 vsqrtph %zmm29,%zmm30"}, + {"vsqrtph ymm", "VSQRTPH", + []ExtOperand{ExtYmm(5), ExtYmm(6)}, + "62f57c2851f5", "62 f5 7c 28 51 f5 vsqrtph %ymm5,%ymm6"}, + {"vsqrtph xmm", "VSQRTPH", + []ExtOperand{ExtXmm(5), ExtXmm(6)}, + "62f57c0851f5", "62 f5 7c 08 51 f5 vsqrtph %xmm5,%xmm6"}, // The imm8-control group of the scalar core. The rows take the // immediate first and the sources after it as src1, src2, the reverse @@ -511,7 +554,7 @@ func TestAmd64ExtArchBinding(t *testing.T) { t.Errorf("Extensions(%s) carries %d instructions, want none", a, len(got)) } } - if got := Extensions(AMD64); len(got) != 52 { - t.Errorf("the amd64 layer registers %d instructions, want 52", len(got)) + if got := Extensions(AMD64); len(got) != 66 { + t.Errorf("the amd64 layer registers %d instructions, want 66", len(got)) } } diff --git a/asm/extension_amd64_test.go b/asm/extension_amd64_test.go index 54b87cc..ae814c6 100644 --- a/asm/extension_amd64_test.go +++ b/asm/extension_amd64_test.go @@ -33,8 +33,8 @@ func TestAmd64ExtensionRegistry(t *testing.T) { {"VCVTSH2SS", 1}, {"VCVTSI2SH", 2}, {"VCVTSH2SI", 2}, - {"VADDPH", 1}, - {"VSQRTPH", 1}, + {"VADDPH", 3}, + {"VSQRTPH", 3}, {"VSCALEFSH", 1}, {"VGETEXPSH", 1}, {"VCMPSH", 1}, @@ -54,8 +54,8 @@ func TestAmd64ExtensionRegistry(t *testing.T) { t.Errorf("the %s lookup is not case-insensitive", tt.mnem) } } - if got := arch.Extensions(arch.AMD64); len(got) != 52 { - t.Errorf("the amd64 layer registers %d instructions, want 52", len(got)) + if got := arch.Extensions(arch.AMD64); len(got) != 66 { + t.Errorf("the amd64 layer registers %d instructions, want 66", len(got)) } if _, ok := LookupExtension(arch.AMD64, "NOSUCHINSTR"); ok { t.Error("a non-extended mnemonic resolved")