whatcanGOwrong
This commit is contained in:
@@ -0,0 +1,913 @@
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/arch/x86/xeddata"
|
||||
)
|
||||
|
||||
func newTestContext(t testing.TB) *context {
|
||||
ctx := &context{xedPath: filepath.Join("testdata", "xedpath")}
|
||||
db, err := xeddata.NewDatabase(ctx.xedPath)
|
||||
if err != nil {
|
||||
t.Fatalf("open test database: %v", err)
|
||||
}
|
||||
ctx.db = db
|
||||
return ctx
|
||||
}
|
||||
|
||||
func newStringSet(keys ...string) map[string]bool {
|
||||
set := make(map[string]bool)
|
||||
for _, k := range keys {
|
||||
set[k] = true
|
||||
}
|
||||
return set
|
||||
}
|
||||
|
||||
func generateToString(t *testing.T) string {
|
||||
ctx := newTestContext(t)
|
||||
buildTables(ctx)
|
||||
var buf bytes.Buffer
|
||||
writeTables(&buf, ctx)
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func TestOutput(t *testing.T) {
|
||||
// Ytab lists and optabs output checks.
|
||||
//
|
||||
// These tests are very fragile.
|
||||
// Slight changes can invalidate them.
|
||||
// It is better to keep testCases count at the minimum.
|
||||
|
||||
type testCase struct {
|
||||
opcode string
|
||||
ytabs string
|
||||
optabLines string
|
||||
}
|
||||
var testCases []testCase
|
||||
{
|
||||
opcodeRE := regexp.MustCompile(`as: ([A-Z][A-Z0-9]*)`)
|
||||
data, err := ioutil.ReadFile(filepath.Join("testdata", "golden.txt"))
|
||||
if err != nil {
|
||||
t.Fatalf("read golden file: %v", err)
|
||||
}
|
||||
for _, entry := range bytes.Split(data, []byte("======")) {
|
||||
parts := bytes.Split(entry, []byte("----"))
|
||||
ytabs := parts[0]
|
||||
optabLines := parts[1]
|
||||
opcode := opcodeRE.FindSubmatch(optabLines)[1]
|
||||
testCases = append(testCases, testCase{
|
||||
ytabs: strings.TrimSpace(string(ytabs)),
|
||||
optabLines: strings.TrimSpace(string(optabLines)),
|
||||
opcode: string(opcode)[len("A"):],
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
output := generateToString(t)
|
||||
for _, tc := range testCases {
|
||||
if !strings.Contains(output, tc.ytabs) {
|
||||
t.Errorf("%s: ytabs not matched", tc.opcode)
|
||||
}
|
||||
if !strings.Contains(output, tc.optabLines) {
|
||||
t.Errorf("%s: optab lines not matched", tc.opcode)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestOutputStability(t *testing.T) {
|
||||
// Generate output count+1 times and check that every time
|
||||
// it is exactly the same string.
|
||||
//
|
||||
// The output should be deterministic to avoid unwanted diffs
|
||||
// between each code generation.
|
||||
const count = 8
|
||||
|
||||
want := generateToString(t)
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < count; i++ {
|
||||
wg.Add(1)
|
||||
go func(i int) {
|
||||
if want != generateToString(t) {
|
||||
t.Errorf("output #%d mismatches", i)
|
||||
}
|
||||
wg.Done()
|
||||
}(i)
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
func TestOpcodeCoverage(t *testing.T) {
|
||||
// Check that generator produces all expected opcodes from testdata files.
|
||||
// All opcodes are in Go syntax.
|
||||
|
||||
// VEX/EVEX opcodes collected from XED-based x86.csv.
|
||||
expectedOpcodes := newStringSet(
|
||||
"ANDNL",
|
||||
"ANDNQ",
|
||||
"BEXTRL",
|
||||
"BEXTRQ",
|
||||
"BLSIL",
|
||||
"BLSIQ",
|
||||
"BLSMSKL",
|
||||
"BLSMSKQ",
|
||||
"BLSRL",
|
||||
"BLSRQ",
|
||||
"BZHIL",
|
||||
"BZHIQ",
|
||||
"KADDB",
|
||||
"KADDD",
|
||||
"KADDQ",
|
||||
"KADDW",
|
||||
"KANDB",
|
||||
"KANDD",
|
||||
"KANDNB",
|
||||
"KANDND",
|
||||
"KANDNQ",
|
||||
"KANDNW",
|
||||
"KANDQ",
|
||||
"KANDW",
|
||||
"KMOVB",
|
||||
"KMOVD",
|
||||
"KMOVQ",
|
||||
"KMOVW",
|
||||
"KNOTB",
|
||||
"KNOTD",
|
||||
"KNOTQ",
|
||||
"KNOTW",
|
||||
"KORB",
|
||||
"KORD",
|
||||
"KORQ",
|
||||
"KORTESTB",
|
||||
"KORTESTD",
|
||||
"KORTESTQ",
|
||||
"KORTESTW",
|
||||
"KORW",
|
||||
"KSHIFTLB",
|
||||
"KSHIFTLD",
|
||||
"KSHIFTLQ",
|
||||
"KSHIFTLW",
|
||||
"KSHIFTRB",
|
||||
"KSHIFTRD",
|
||||
"KSHIFTRQ",
|
||||
"KSHIFTRW",
|
||||
"KTESTB",
|
||||
"KTESTD",
|
||||
"KTESTQ",
|
||||
"KTESTW",
|
||||
"KUNPCKBW",
|
||||
"KUNPCKDQ",
|
||||
"KUNPCKWD",
|
||||
"KXNORB",
|
||||
"KXNORD",
|
||||
"KXNORQ",
|
||||
"KXNORW",
|
||||
"KXORB",
|
||||
"KXORD",
|
||||
"KXORQ",
|
||||
"KXORW",
|
||||
"MULXL",
|
||||
"MULXQ",
|
||||
"PDEPL",
|
||||
"PDEPQ",
|
||||
"PEXTL",
|
||||
"PEXTQ",
|
||||
"RORXL",
|
||||
"RORXQ",
|
||||
"SARXL",
|
||||
"SARXQ",
|
||||
"SHLXL",
|
||||
"SHLXQ",
|
||||
"SHRXL",
|
||||
"SHRXQ",
|
||||
"V4FMADDPS",
|
||||
"V4FMADDSS",
|
||||
"V4FNMADDPS",
|
||||
"V4FNMADDSS",
|
||||
"VADDPD",
|
||||
"VADDPS",
|
||||
"VADDSD",
|
||||
"VADDSS",
|
||||
"VADDSUBPD",
|
||||
"VADDSUBPS",
|
||||
"VAESDEC",
|
||||
"VAESDECLAST",
|
||||
"VAESENC",
|
||||
"VAESENCLAST",
|
||||
"VAESIMC",
|
||||
"VAESKEYGENASSIST",
|
||||
"VALIGND",
|
||||
"VALIGNQ",
|
||||
"VANDNPD",
|
||||
"VANDNPS",
|
||||
"VANDPD",
|
||||
"VANDPS",
|
||||
"VBLENDMPD",
|
||||
"VBLENDMPS",
|
||||
"VBLENDPD",
|
||||
"VBLENDPS",
|
||||
"VBLENDVPD",
|
||||
"VBLENDVPS",
|
||||
"VBROADCASTF128",
|
||||
"VBROADCASTF32X2",
|
||||
"VBROADCASTF32X4",
|
||||
"VBROADCASTF32X8",
|
||||
"VBROADCASTF64X2",
|
||||
"VBROADCASTF64X4",
|
||||
"VBROADCASTI128",
|
||||
"VBROADCASTI32X2",
|
||||
"VBROADCASTI32X4",
|
||||
"VBROADCASTI32X8",
|
||||
"VBROADCASTI64X2",
|
||||
"VBROADCASTI64X4",
|
||||
"VBROADCASTSD",
|
||||
"VBROADCASTSS",
|
||||
"VCMPPD",
|
||||
"VCMPPS",
|
||||
"VCMPSD",
|
||||
"VCMPSS",
|
||||
"VCOMISD",
|
||||
"VCOMISS",
|
||||
"VCOMPRESSPD",
|
||||
"VCOMPRESSPS",
|
||||
"VCVTDQ2PD",
|
||||
"VCVTDQ2PS",
|
||||
"VCVTPD2DQ",
|
||||
"VCVTPD2DQX",
|
||||
"VCVTPD2DQY",
|
||||
"VCVTPD2PS",
|
||||
"VCVTPD2PSX",
|
||||
"VCVTPD2PSY",
|
||||
"VCVTPD2QQ",
|
||||
"VCVTPD2UDQ",
|
||||
"VCVTPD2UDQX",
|
||||
"VCVTPD2UDQY",
|
||||
"VCVTPD2UQQ",
|
||||
"VCVTPH2PS",
|
||||
"VCVTPS2DQ",
|
||||
"VCVTPS2PD",
|
||||
"VCVTPS2PH",
|
||||
"VCVTPS2QQ",
|
||||
"VCVTPS2UDQ",
|
||||
"VCVTPS2UQQ",
|
||||
"VCVTQQ2PD",
|
||||
"VCVTQQ2PS",
|
||||
"VCVTQQ2PSX",
|
||||
"VCVTQQ2PSY",
|
||||
"VCVTSD2SI",
|
||||
"VCVTSD2SIQ",
|
||||
"VCVTSD2SS",
|
||||
"VCVTSD2USIL",
|
||||
"VCVTSD2USIQ",
|
||||
"VCVTSI2SDL",
|
||||
"VCVTSI2SDQ",
|
||||
"VCVTSI2SSL",
|
||||
"VCVTSI2SSQ",
|
||||
"VCVTSS2SD",
|
||||
"VCVTSS2SI",
|
||||
"VCVTSS2SIQ",
|
||||
"VCVTSS2USIL",
|
||||
"VCVTSS2USIQ",
|
||||
"VCVTTPD2DQ",
|
||||
"VCVTTPD2DQX",
|
||||
"VCVTTPD2DQY",
|
||||
"VCVTTPD2QQ",
|
||||
"VCVTTPD2UDQ",
|
||||
"VCVTTPD2UDQX",
|
||||
"VCVTTPD2UDQY",
|
||||
"VCVTTPD2UQQ",
|
||||
"VCVTTPS2DQ",
|
||||
"VCVTTPS2QQ",
|
||||
"VCVTTPS2UDQ",
|
||||
"VCVTTPS2UQQ",
|
||||
"VCVTTSD2SI",
|
||||
"VCVTTSD2SIQ",
|
||||
"VCVTTSD2USIL",
|
||||
"VCVTTSD2USIQ",
|
||||
"VCVTTSS2SI",
|
||||
"VCVTTSS2SIQ",
|
||||
"VCVTTSS2USIL",
|
||||
"VCVTTSS2USIQ",
|
||||
"VCVTUDQ2PD",
|
||||
"VCVTUDQ2PS",
|
||||
"VCVTUQQ2PD",
|
||||
"VCVTUQQ2PS",
|
||||
"VCVTUQQ2PSX",
|
||||
"VCVTUQQ2PSY",
|
||||
"VCVTUSI2SDL",
|
||||
"VCVTUSI2SDQ",
|
||||
"VCVTUSI2SSL",
|
||||
"VCVTUSI2SSQ",
|
||||
"VDBPSADBW",
|
||||
"VDIVPD",
|
||||
"VDIVPS",
|
||||
"VDIVSD",
|
||||
"VDIVSS",
|
||||
"VDPPD",
|
||||
"VDPPS",
|
||||
"VEXP2PD",
|
||||
"VEXP2PS",
|
||||
"VEXPANDPD",
|
||||
"VEXPANDPS",
|
||||
"VEXTRACTF128",
|
||||
"VEXTRACTF32X4",
|
||||
"VEXTRACTF32X8",
|
||||
"VEXTRACTF64X2",
|
||||
"VEXTRACTF64X4",
|
||||
"VEXTRACTI128",
|
||||
"VEXTRACTI32X4",
|
||||
"VEXTRACTI32X8",
|
||||
"VEXTRACTI64X2",
|
||||
"VEXTRACTI64X4",
|
||||
"VEXTRACTPS",
|
||||
"VFIXUPIMMPD",
|
||||
"VFIXUPIMMPS",
|
||||
"VFIXUPIMMSD",
|
||||
"VFIXUPIMMSS",
|
||||
"VFMADD132PD",
|
||||
"VFMADD132PS",
|
||||
"VFMADD132SD",
|
||||
"VFMADD132SS",
|
||||
"VFMADD213PD",
|
||||
"VFMADD213PS",
|
||||
"VFMADD213SD",
|
||||
"VFMADD213SS",
|
||||
"VFMADD231PD",
|
||||
"VFMADD231PS",
|
||||
"VFMADD231SD",
|
||||
"VFMADD231SS",
|
||||
"VFMADDPD",
|
||||
"VFMADDPS",
|
||||
"VFMADDSD",
|
||||
"VFMADDSS",
|
||||
"VFMADDSUB132PD",
|
||||
"VFMADDSUB132PS",
|
||||
"VFMADDSUB213PD",
|
||||
"VFMADDSUB213PS",
|
||||
"VFMADDSUB231PD",
|
||||
"VFMADDSUB231PS",
|
||||
"VFMADDSUBPD",
|
||||
"VFMADDSUBPS",
|
||||
"VFMSUB132PD",
|
||||
"VFMSUB132PS",
|
||||
"VFMSUB132SD",
|
||||
"VFMSUB132SS",
|
||||
"VFMSUB213PD",
|
||||
"VFMSUB213PS",
|
||||
"VFMSUB213SD",
|
||||
"VFMSUB213SS",
|
||||
"VFMSUB231PD",
|
||||
"VFMSUB231PS",
|
||||
"VFMSUB231SD",
|
||||
"VFMSUB231SS",
|
||||
"VFMSUBADD132PD",
|
||||
"VFMSUBADD132PS",
|
||||
"VFMSUBADD213PD",
|
||||
"VFMSUBADD213PS",
|
||||
"VFMSUBADD231PD",
|
||||
"VFMSUBADD231PS",
|
||||
"VFMSUBADDPD",
|
||||
"VFMSUBADDPS",
|
||||
"VFMSUBPD",
|
||||
"VFMSUBPS",
|
||||
"VFMSUBSD",
|
||||
"VFMSUBSS",
|
||||
"VFNMADD132PD",
|
||||
"VFNMADD132PS",
|
||||
"VFNMADD132SD",
|
||||
"VFNMADD132SS",
|
||||
"VFNMADD213PD",
|
||||
"VFNMADD213PS",
|
||||
"VFNMADD213SD",
|
||||
"VFNMADD213SS",
|
||||
"VFNMADD231PD",
|
||||
"VFNMADD231PS",
|
||||
"VFNMADD231SD",
|
||||
"VFNMADD231SS",
|
||||
"VFNMADDPD",
|
||||
"VFNMADDPS",
|
||||
"VFNMADDSD",
|
||||
"VFNMADDSS",
|
||||
"VFNMSUB132PD",
|
||||
"VFNMSUB132PS",
|
||||
"VFNMSUB132SD",
|
||||
"VFNMSUB132SS",
|
||||
"VFNMSUB213PD",
|
||||
"VFNMSUB213PS",
|
||||
"VFNMSUB213SD",
|
||||
"VFNMSUB213SS",
|
||||
"VFNMSUB231PD",
|
||||
"VFNMSUB231PS",
|
||||
"VFNMSUB231SD",
|
||||
"VFNMSUB231SS",
|
||||
"VFNMSUBPD",
|
||||
"VFNMSUBPS",
|
||||
"VFNMSUBSD",
|
||||
"VFNMSUBSS",
|
||||
"VFPCLASSPDX",
|
||||
"VFPCLASSPDY",
|
||||
"VFPCLASSPDZ",
|
||||
"VFPCLASSPSX",
|
||||
"VFPCLASSPSY",
|
||||
"VFPCLASSPSZ",
|
||||
"VFPCLASSSD",
|
||||
"VFPCLASSSS",
|
||||
"VGATHERDPD",
|
||||
"VGATHERDPS",
|
||||
"VGATHERPF0DPD",
|
||||
"VGATHERPF0DPS",
|
||||
"VGATHERPF0QPD",
|
||||
"VGATHERPF0QPS",
|
||||
"VGATHERPF1DPD",
|
||||
"VGATHERPF1DPS",
|
||||
"VGATHERPF1QPD",
|
||||
"VGATHERPF1QPS",
|
||||
"VGATHERQPD",
|
||||
"VGATHERQPS",
|
||||
"VGETEXPPD",
|
||||
"VGETEXPPS",
|
||||
"VGETEXPSD",
|
||||
"VGETEXPSS",
|
||||
"VGETMANTPD",
|
||||
"VGETMANTPS",
|
||||
"VGETMANTSD",
|
||||
"VGETMANTSS",
|
||||
"VGF2P8AFFINEINVQB",
|
||||
"VGF2P8AFFINEQB",
|
||||
"VGF2P8MULB",
|
||||
"VHADDPD",
|
||||
"VHADDPS",
|
||||
"VHSUBPD",
|
||||
"VHSUBPS",
|
||||
"VINSERTF128",
|
||||
"VINSERTF32X4",
|
||||
"VINSERTF32X8",
|
||||
"VINSERTF64X2",
|
||||
"VINSERTF64X4",
|
||||
"VINSERTI128",
|
||||
"VINSERTI32X4",
|
||||
"VINSERTI32X8",
|
||||
"VINSERTI64X2",
|
||||
"VINSERTI64X4",
|
||||
"VINSERTPS",
|
||||
"VLDDQU",
|
||||
"VLDMXCSR",
|
||||
"VMASKMOVDQU",
|
||||
"VMASKMOVPD",
|
||||
"VMASKMOVPS",
|
||||
"VMAXPD",
|
||||
"VMAXPS",
|
||||
"VMAXSD",
|
||||
"VMAXSS",
|
||||
"VMINPD",
|
||||
"VMINPS",
|
||||
"VMINSD",
|
||||
"VMINSS",
|
||||
"VMOVAPD",
|
||||
"VMOVAPS",
|
||||
"VMOVD",
|
||||
"VMOVDDUP",
|
||||
"VMOVDQA",
|
||||
"VMOVDQA32",
|
||||
"VMOVDQA64",
|
||||
"VMOVDQU",
|
||||
"VMOVDQU16",
|
||||
"VMOVDQU32",
|
||||
"VMOVDQU64",
|
||||
"VMOVDQU8",
|
||||
"VMOVHLPS",
|
||||
"VMOVHPD",
|
||||
"VMOVHPS",
|
||||
"VMOVLHPS",
|
||||
"VMOVLPD",
|
||||
"VMOVLPS",
|
||||
"VMOVMSKPD",
|
||||
"VMOVMSKPS",
|
||||
"VMOVNTDQ",
|
||||
"VMOVNTDQA",
|
||||
"VMOVNTPD",
|
||||
"VMOVNTPS",
|
||||
"VMOVQ",
|
||||
"VMOVSD",
|
||||
"VMOVSHDUP",
|
||||
"VMOVSLDUP",
|
||||
"VMOVSS",
|
||||
"VMOVUPD",
|
||||
"VMOVUPS",
|
||||
"VMPSADBW",
|
||||
"VMULPD",
|
||||
"VMULPS",
|
||||
"VMULSD",
|
||||
"VMULSS",
|
||||
"VORPD",
|
||||
"VORPS",
|
||||
"VP4DPWSSD",
|
||||
"VP4DPWSSDS",
|
||||
"VPABSB",
|
||||
"VPABSD",
|
||||
"VPABSQ",
|
||||
"VPABSW",
|
||||
"VPACKSSDW",
|
||||
"VPACKSSWB",
|
||||
"VPACKUSDW",
|
||||
"VPACKUSWB",
|
||||
"VPADDB",
|
||||
"VPADDD",
|
||||
"VPADDQ",
|
||||
"VPADDSB",
|
||||
"VPADDSW",
|
||||
"VPADDUSB",
|
||||
"VPADDUSW",
|
||||
"VPADDW",
|
||||
"VPALIGNR",
|
||||
"VPAND",
|
||||
"VPANDD",
|
||||
"VPANDN",
|
||||
"VPANDND",
|
||||
"VPANDNQ",
|
||||
"VPANDQ",
|
||||
"VPAVGB",
|
||||
"VPAVGW",
|
||||
"VPBLENDD",
|
||||
"VPBLENDMB",
|
||||
"VPBLENDMD",
|
||||
"VPBLENDMQ",
|
||||
"VPBLENDMW",
|
||||
"VPBLENDVB",
|
||||
"VPBLENDW",
|
||||
"VPBROADCASTB",
|
||||
"VPBROADCASTD",
|
||||
"VPBROADCASTMB2Q",
|
||||
"VPBROADCASTMW2D",
|
||||
"VPBROADCASTQ",
|
||||
"VPBROADCASTW",
|
||||
"VPCLMULQDQ",
|
||||
"VPCMPB",
|
||||
"VPCMPD",
|
||||
"VPCMPEQB",
|
||||
"VPCMPEQD",
|
||||
"VPCMPEQQ",
|
||||
"VPCMPEQW",
|
||||
"VPCMPESTRI",
|
||||
"VPCMPESTRM",
|
||||
"VPCMPGTB",
|
||||
"VPCMPGTD",
|
||||
"VPCMPGTQ",
|
||||
"VPCMPGTW",
|
||||
"VPCMPISTRI",
|
||||
"VPCMPISTRM",
|
||||
"VPCMPQ",
|
||||
"VPCMPUB",
|
||||
"VPCMPUD",
|
||||
"VPCMPUQ",
|
||||
"VPCMPUW",
|
||||
"VPCMPW",
|
||||
"VPCOMPRESSB",
|
||||
"VPCOMPRESSD",
|
||||
"VPCOMPRESSQ",
|
||||
"VPCOMPRESSW",
|
||||
"VPCONFLICTD",
|
||||
"VPCONFLICTQ",
|
||||
"VPDPBUSD",
|
||||
"VPDPBUSDS",
|
||||
"VPDPWSSD",
|
||||
"VPDPWSSDS",
|
||||
"VPERM2F128",
|
||||
"VPERM2I128",
|
||||
"VPERMB",
|
||||
"VPERMD",
|
||||
"VPERMI2B",
|
||||
"VPERMI2D",
|
||||
"VPERMI2PD",
|
||||
"VPERMI2PS",
|
||||
"VPERMI2Q",
|
||||
"VPERMI2W",
|
||||
"VPERMIL2PD",
|
||||
"VPERMIL2PS",
|
||||
"VPERMILPD",
|
||||
"VPERMILPS",
|
||||
"VPERMPD",
|
||||
"VPERMPS",
|
||||
"VPERMQ",
|
||||
"VPERMT2B",
|
||||
"VPERMT2D",
|
||||
"VPERMT2PD",
|
||||
"VPERMT2PS",
|
||||
"VPERMT2Q",
|
||||
"VPERMT2W",
|
||||
"VPERMW",
|
||||
"VPEXPANDB",
|
||||
"VPEXPANDD",
|
||||
"VPEXPANDQ",
|
||||
"VPEXPANDW",
|
||||
"VPEXTRB",
|
||||
"VPEXTRD",
|
||||
"VPEXTRQ",
|
||||
"VPEXTRW",
|
||||
"VPGATHERDD",
|
||||
"VPGATHERDQ",
|
||||
"VPGATHERQD",
|
||||
"VPGATHERQQ",
|
||||
"VPHADDD",
|
||||
"VPHADDSW",
|
||||
"VPHADDW",
|
||||
"VPHMINPOSUW",
|
||||
"VPHSUBD",
|
||||
"VPHSUBSW",
|
||||
"VPHSUBW",
|
||||
"VPINSRB",
|
||||
"VPINSRD",
|
||||
"VPINSRQ",
|
||||
"VPINSRW",
|
||||
"VPLZCNTD",
|
||||
"VPLZCNTQ",
|
||||
"VPMADD52HUQ",
|
||||
"VPMADD52LUQ",
|
||||
"VPMADDUBSW",
|
||||
"VPMADDWD",
|
||||
"VPMASKMOVD",
|
||||
"VPMASKMOVQ",
|
||||
"VPMAXSB",
|
||||
"VPMAXSD",
|
||||
"VPMAXSQ",
|
||||
"VPMAXSW",
|
||||
"VPMAXUB",
|
||||
"VPMAXUD",
|
||||
"VPMAXUQ",
|
||||
"VPMAXUW",
|
||||
"VPMINSB",
|
||||
"VPMINSD",
|
||||
"VPMINSQ",
|
||||
"VPMINSW",
|
||||
"VPMINUB",
|
||||
"VPMINUD",
|
||||
"VPMINUQ",
|
||||
"VPMINUW",
|
||||
"VPMOVB2M",
|
||||
"VPMOVD2M",
|
||||
"VPMOVDB",
|
||||
"VPMOVDW",
|
||||
"VPMOVM2B",
|
||||
"VPMOVM2D",
|
||||
"VPMOVM2Q",
|
||||
"VPMOVM2W",
|
||||
"VPMOVMSKB",
|
||||
"VPMOVQ2M",
|
||||
"VPMOVQB",
|
||||
"VPMOVQD",
|
||||
"VPMOVQW",
|
||||
"VPMOVSDB",
|
||||
"VPMOVSDW",
|
||||
"VPMOVSQB",
|
||||
"VPMOVSQD",
|
||||
"VPMOVSQW",
|
||||
"VPMOVSWB",
|
||||
"VPMOVSXBD",
|
||||
"VPMOVSXBQ",
|
||||
"VPMOVSXBW",
|
||||
"VPMOVSXDQ",
|
||||
"VPMOVSXWD",
|
||||
"VPMOVSXWQ",
|
||||
"VPMOVUSDB",
|
||||
"VPMOVUSDW",
|
||||
"VPMOVUSQB",
|
||||
"VPMOVUSQD",
|
||||
"VPMOVUSQW",
|
||||
"VPMOVUSWB",
|
||||
"VPMOVW2M",
|
||||
"VPMOVWB",
|
||||
"VPMOVZXBD",
|
||||
"VPMOVZXBQ",
|
||||
"VPMOVZXBW",
|
||||
"VPMOVZXDQ",
|
||||
"VPMOVZXWD",
|
||||
"VPMOVZXWQ",
|
||||
"VPMULDQ",
|
||||
"VPMULHRSW",
|
||||
"VPMULHUW",
|
||||
"VPMULHW",
|
||||
"VPMULLD",
|
||||
"VPMULLQ",
|
||||
"VPMULLW",
|
||||
"VPMULTISHIFTQB",
|
||||
"VPMULUDQ",
|
||||
"VPOPCNTB",
|
||||
"VPOPCNTD",
|
||||
"VPOPCNTQ",
|
||||
"VPOPCNTW",
|
||||
"VPOR",
|
||||
"VPORD",
|
||||
"VPORQ",
|
||||
"VPROLD",
|
||||
"VPROLQ",
|
||||
"VPROLVD",
|
||||
"VPROLVQ",
|
||||
"VPRORD",
|
||||
"VPRORQ",
|
||||
"VPRORVD",
|
||||
"VPRORVQ",
|
||||
"VPSADBW",
|
||||
"VPSCATTERDD",
|
||||
"VPSCATTERDQ",
|
||||
"VPSCATTERQD",
|
||||
"VPSCATTERQQ",
|
||||
"VPSHLDD",
|
||||
"VPSHLDQ",
|
||||
"VPSHLDVD",
|
||||
"VPSHLDVQ",
|
||||
"VPSHLDVW",
|
||||
"VPSHLDW",
|
||||
"VPSHRDD",
|
||||
"VPSHRDQ",
|
||||
"VPSHRDVD",
|
||||
"VPSHRDVQ",
|
||||
"VPSHRDVW",
|
||||
"VPSHRDW",
|
||||
"VPSHUFB",
|
||||
"VPSHUFBITQMB",
|
||||
"VPSHUFD",
|
||||
"VPSHUFHW",
|
||||
"VPSHUFLW",
|
||||
"VPSIGNB",
|
||||
"VPSIGND",
|
||||
"VPSIGNW",
|
||||
"VPSLLD",
|
||||
"VPSLLDQ",
|
||||
"VPSLLQ",
|
||||
"VPSLLVD",
|
||||
"VPSLLVQ",
|
||||
"VPSLLVW",
|
||||
"VPSLLW",
|
||||
"VPSRAD",
|
||||
"VPSRAQ",
|
||||
"VPSRAVD",
|
||||
"VPSRAVQ",
|
||||
"VPSRAVW",
|
||||
"VPSRAW",
|
||||
"VPSRLD",
|
||||
"VPSRLDQ",
|
||||
"VPSRLQ",
|
||||
"VPSRLVD",
|
||||
"VPSRLVQ",
|
||||
"VPSRLVW",
|
||||
"VPSRLW",
|
||||
"VPSUBB",
|
||||
"VPSUBD",
|
||||
"VPSUBQ",
|
||||
"VPSUBSB",
|
||||
"VPSUBSW",
|
||||
"VPSUBUSB",
|
||||
"VPSUBUSW",
|
||||
"VPSUBW",
|
||||
"VPTERNLOGD",
|
||||
"VPTERNLOGQ",
|
||||
"VPTEST",
|
||||
"VPTESTMB",
|
||||
"VPTESTMD",
|
||||
"VPTESTMQ",
|
||||
"VPTESTMW",
|
||||
"VPTESTNMB",
|
||||
"VPTESTNMD",
|
||||
"VPTESTNMQ",
|
||||
"VPTESTNMW",
|
||||
"VPUNPCKHBW",
|
||||
"VPUNPCKHDQ",
|
||||
"VPUNPCKHQDQ",
|
||||
"VPUNPCKHWD",
|
||||
"VPUNPCKLBW",
|
||||
"VPUNPCKLDQ",
|
||||
"VPUNPCKLQDQ",
|
||||
"VPUNPCKLWD",
|
||||
"VPXOR",
|
||||
"VPXORD",
|
||||
"VPXORQ",
|
||||
"VRANGEPD",
|
||||
"VRANGEPS",
|
||||
"VRANGESD",
|
||||
"VRANGESS",
|
||||
"VRCP14PD",
|
||||
"VRCP14PS",
|
||||
"VRCP14SD",
|
||||
"VRCP14SS",
|
||||
"VRCP28PD",
|
||||
"VRCP28PS",
|
||||
"VRCP28SD",
|
||||
"VRCP28SS",
|
||||
"VRCPPS",
|
||||
"VRCPSS",
|
||||
"VREDUCEPD",
|
||||
"VREDUCEPS",
|
||||
"VREDUCESD",
|
||||
"VREDUCESS",
|
||||
"VRNDSCALEPD",
|
||||
"VRNDSCALEPS",
|
||||
"VRNDSCALESD",
|
||||
"VRNDSCALESS",
|
||||
"VROUNDPD",
|
||||
"VROUNDPS",
|
||||
"VROUNDSD",
|
||||
"VROUNDSS",
|
||||
"VRSQRT14PD",
|
||||
"VRSQRT14PS",
|
||||
"VRSQRT14SD",
|
||||
"VRSQRT14SS",
|
||||
"VRSQRT28PD",
|
||||
"VRSQRT28PS",
|
||||
"VRSQRT28SD",
|
||||
"VRSQRT28SS",
|
||||
"VRSQRTPS",
|
||||
"VRSQRTSS",
|
||||
"VSCALEFPD",
|
||||
"VSCALEFPS",
|
||||
"VSCALEFSD",
|
||||
"VSCALEFSS",
|
||||
"VSCATTERDPD",
|
||||
"VSCATTERDPS",
|
||||
"VSCATTERPF0DPD",
|
||||
"VSCATTERPF0DPS",
|
||||
"VSCATTERPF0QPD",
|
||||
"VSCATTERPF0QPS",
|
||||
"VSCATTERPF1DPD",
|
||||
"VSCATTERPF1DPS",
|
||||
"VSCATTERPF1QPD",
|
||||
"VSCATTERPF1QPS",
|
||||
"VSCATTERQPD",
|
||||
"VSCATTERQPS",
|
||||
"VSHUFF32X4",
|
||||
"VSHUFF64X2",
|
||||
"VSHUFI32X4",
|
||||
"VSHUFI64X2",
|
||||
"VSHUFPD",
|
||||
"VSHUFPS",
|
||||
"VSQRTPD",
|
||||
"VSQRTPS",
|
||||
"VSQRTSD",
|
||||
"VSQRTSS",
|
||||
"VSTMXCSR",
|
||||
"VSUBPD",
|
||||
"VSUBPS",
|
||||
"VSUBSD",
|
||||
"VSUBSS",
|
||||
"VTESTPD",
|
||||
"VTESTPS",
|
||||
"VUCOMISD",
|
||||
"VUCOMISS",
|
||||
"VUNPCKHPD",
|
||||
"VUNPCKHPS",
|
||||
"VUNPCKLPD",
|
||||
"VUNPCKLPS",
|
||||
"VXORPD",
|
||||
"VXORPS",
|
||||
"VZEROALL",
|
||||
"VZEROUPPER")
|
||||
|
||||
// AMD-specific VEX opcodes.
|
||||
// Excluded from x86avxgen output for now.
|
||||
amdOpcodes := newStringSet(
|
||||
"VFMADDPD",
|
||||
"VFMADDPS",
|
||||
"VFMADDSD",
|
||||
"VFMADDSS",
|
||||
"VFMADDSUBPD",
|
||||
"VFMADDSUBPS",
|
||||
"VFMSUBADDPD",
|
||||
"VFMSUBADDPS",
|
||||
"VFMSUBPD",
|
||||
"VFMSUBPS",
|
||||
"VFMSUBSD",
|
||||
"VFMSUBSS",
|
||||
"VFNMADDPD",
|
||||
"VFNMADDPS",
|
||||
"VFNMADDSD",
|
||||
"VFNMADDSS",
|
||||
"VFNMSUBPD",
|
||||
"VFNMSUBPS",
|
||||
"VFNMSUBSD",
|
||||
"VFNMSUBSS",
|
||||
"VPERMIL2PD",
|
||||
"VPERMIL2PS")
|
||||
|
||||
ctx := newTestContext(t)
|
||||
buildTables(ctx)
|
||||
|
||||
for op := range amdOpcodes {
|
||||
delete(expectedOpcodes, op)
|
||||
}
|
||||
for op := range ctx.optabs {
|
||||
delete(expectedOpcodes, op)
|
||||
}
|
||||
|
||||
for op := range expectedOpcodes {
|
||||
t.Errorf("missing opcode: %s", op)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,395 @@
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/arch/x86/xeddata"
|
||||
)
|
||||
|
||||
// encoding is decoded XED instruction pattern.
|
||||
type encoding struct {
|
||||
// opbyte is opcode byte (one that follows [E]VEX prefix).
|
||||
// It's called "opcode" in Intel manual, but we use that for
|
||||
// instruction name (iclass in XED terms).
|
||||
opbyte string
|
||||
|
||||
// opdigit is ModRM.Reg field used to encode opcode extension.
|
||||
// In Intel manual, "/digit" notation is used.
|
||||
opdigit string
|
||||
|
||||
// vex represents [E]VEX fields that are used in a first [E]VEX
|
||||
// opBytes element (see prefixExpr function).
|
||||
vex struct {
|
||||
P string // 66/F2/F3
|
||||
L string // 128/256/512
|
||||
M string // 0F/0F38/0F3A
|
||||
W string // W0/W1
|
||||
}
|
||||
|
||||
// evexScale is a scaling factor used to calculate compact disp-8.
|
||||
evexScale string
|
||||
|
||||
// evexBcstScale is like evexScale, but used during broadcasting.
|
||||
// Empty for optab entries that do not have broadcasting support.
|
||||
evexBcstScale string
|
||||
|
||||
// evex describes which features of EVEX can be used by optab entry.
|
||||
// All flags are "false" for VEX-encoded insts.
|
||||
evex struct {
|
||||
// There is no "broadcast" flag because it's inferred
|
||||
// from non-empty evexBcstScale.
|
||||
|
||||
SAE bool // EVEX.b controls SAE for reg-reg insts
|
||||
Rounding bool // EVEX.b + EVEX.RC (VL) control rounding for FP insts
|
||||
Zeroing bool // Instruction can use zeroing.
|
||||
}
|
||||
}
|
||||
|
||||
type decoder struct {
|
||||
ctx *context
|
||||
insts []*instruction
|
||||
}
|
||||
|
||||
// decodeGroups fills ctx.groups with decoded instruction groups.
|
||||
//
|
||||
// Reads XED objects from ctx.xedPath.
|
||||
func decodeGroups(ctx *context) {
|
||||
d := decoder{ctx: ctx}
|
||||
groups := make(map[string][]*instruction)
|
||||
for _, inst := range d.DecodeAll() {
|
||||
groups[inst.opcode] = append(groups[inst.opcode], inst)
|
||||
}
|
||||
for op, insts := range groups {
|
||||
ctx.groups = append(ctx.groups, &instGroup{
|
||||
opcode: op,
|
||||
list: insts,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// DecodeAll decodes every XED instruction.
|
||||
func (d *decoder) DecodeAll() []*instruction {
|
||||
err := xeddata.WalkInsts(d.ctx.xedPath, func(inst *xeddata.Inst) {
|
||||
inst.Pattern = xeddata.ExpandStates(d.ctx.db, inst.Pattern)
|
||||
pset := xeddata.NewPatternSet(inst.Pattern)
|
||||
|
||||
opcode := inst.Iclass
|
||||
|
||||
switch {
|
||||
case inst.HasAttribute("AMDONLY") || inst.Extension == "XOP":
|
||||
return // Only VEX and EVEX are supported
|
||||
case !pset.Is("VEX") && !pset.Is("EVEX"):
|
||||
return // Skip non-AVX instructions
|
||||
case inst.RealOpcode == "N":
|
||||
return // Skip unstable instructions
|
||||
}
|
||||
|
||||
// Expand some patterns to simplify decodePattern.
|
||||
pset.Replace("FIX_ROUND_LEN128()", "VL=0")
|
||||
pset.Replace("FIX_ROUND_LEN512()", "VL=2")
|
||||
|
||||
mask, args := d.decodeArgs(pset, inst)
|
||||
d.insts = append(d.insts, &instruction{
|
||||
pset: pset,
|
||||
opcode: opcode,
|
||||
mask: mask,
|
||||
args: args,
|
||||
enc: d.decodePattern(pset, inst),
|
||||
})
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("walk insts: %v", err)
|
||||
}
|
||||
return d.insts
|
||||
}
|
||||
|
||||
// registerArgs maps XED argument name RHS to its decoded version.
|
||||
var registerArgs = map[string]argument{
|
||||
"GPR32_R()": {"Yrl", "reg"},
|
||||
"GPR64_R()": {"Yrl", "reg"},
|
||||
"VGPR32_R()": {"Yrl", "reg"},
|
||||
"VGPR64_R()": {"Yrl", "reg"},
|
||||
"VGPR32_N()": {"Yrl", "regV"},
|
||||
"VGPR64_N()": {"Yrl", "regV"},
|
||||
"GPR32_B()": {"Yrl", "reg/mem"},
|
||||
"GPR64_B()": {"Yrl", "reg/mem"},
|
||||
"VGPR32_B()": {"Yrl", "reg/mem"},
|
||||
"VGPR64_B()": {"Yrl", "reg/mem"},
|
||||
|
||||
"XMM_R()": {"Yxr", "reg"},
|
||||
"XMM_R3()": {"YxrEvex", "reg"},
|
||||
"XMM_N()": {"Yxr", "regV"},
|
||||
"XMM_N3()": {"YxrEvex", "regV"},
|
||||
"XMM_B()": {"Yxr", "reg/mem"},
|
||||
"XMM_B3()": {"YxrEvex", "reg/mem"},
|
||||
"XMM_SE()": {"Yxr", "regIH"},
|
||||
|
||||
"YMM_R()": {"Yyr", "reg"},
|
||||
"YMM_R3()": {"YyrEvex", "reg"},
|
||||
"YMM_N()": {"Yyr", "regV"},
|
||||
"YMM_N3()": {"YyrEvex", "regV"},
|
||||
"YMM_B()": {"Yyr", "reg/mem"},
|
||||
"YMM_B3()": {"YyrEvex", "reg/mem"},
|
||||
"YMM_SE()": {"Yyr", "regIH"},
|
||||
|
||||
"ZMM_R3()": {"Yzr", "reg"},
|
||||
"ZMM_N3()": {"Yzr", "regV"},
|
||||
"ZMM_B3()": {"Yzr", "reg/mem"},
|
||||
|
||||
"MASK_R()": {"Yk", "reg"},
|
||||
"MASK_N()": {"Yk", "regV"},
|
||||
"MASK_B()": {"Yk", "reg/mem"},
|
||||
|
||||
"MASKNOT0()": {"Yknot0", "kmask"},
|
||||
|
||||
// Handled specifically in "generate".
|
||||
"MASK1()": {"MASK1()", "MASK1()"},
|
||||
}
|
||||
|
||||
func (d *decoder) decodeArgs(pset xeddata.PatternSet, inst *xeddata.Inst) (mask *argument, args []*argument) {
|
||||
for i, f := range strings.Fields(inst.Operands) {
|
||||
xarg, err := xeddata.NewOperand(d.ctx.db, f)
|
||||
if err != nil {
|
||||
log.Fatalf("%s: args[%d]: %v", inst, i, err)
|
||||
}
|
||||
|
||||
switch {
|
||||
case xarg.Action == "":
|
||||
continue // Skip meta args like EMX_BROADCAST_1TO32_8
|
||||
case !xarg.IsVisible():
|
||||
continue
|
||||
}
|
||||
|
||||
arg := &argument{}
|
||||
args = append(args, arg)
|
||||
|
||||
switch xarg.NameLHS() {
|
||||
case "IMM0":
|
||||
if xarg.Width != "b" {
|
||||
log.Fatalf("%s: args[%d]: expected width=b, found %s", inst, i, xarg.Width)
|
||||
}
|
||||
if pset["IMM0SIGNED=1"] {
|
||||
arg.ytype = "Yi8"
|
||||
} else {
|
||||
arg.ytype = "Yu8"
|
||||
}
|
||||
arg.zkind = "imm8"
|
||||
|
||||
case "REG0", "REG1", "REG2", "REG3":
|
||||
rhs := xarg.NameRHS()
|
||||
if rhs == "MASK1()" {
|
||||
mask = arg
|
||||
}
|
||||
*arg = registerArgs[rhs]
|
||||
if arg.ytype == "" {
|
||||
log.Fatalf("%s: args[%d]: unexpected %s reg", inst, i, rhs)
|
||||
}
|
||||
if xarg.Attributes["MULTISOURCE4"] {
|
||||
arg.ytype += "Multi4"
|
||||
}
|
||||
|
||||
case "MEM0":
|
||||
arg.ytype = pset.MatchOrDefault("Ym",
|
||||
"VMODRM_XMM()", "Yxvm",
|
||||
"VMODRM_YMM()", "Yyvm",
|
||||
"UISA_VMODRM_XMM()", "YxvmEvex",
|
||||
"UISA_VMODRM_YMM()", "YyvmEvex",
|
||||
"UISA_VMODRM_ZMM()", "Yzvm",
|
||||
)
|
||||
arg.zkind = "reg/mem"
|
||||
|
||||
default:
|
||||
log.Fatalf("%s: args[%d]: unexpected %s", inst, i, xarg.NameRHS())
|
||||
}
|
||||
}
|
||||
|
||||
// Reverse args.
|
||||
for i := len(args)/2 - 1; i >= 0; i-- {
|
||||
j := len(args) - 1 - i
|
||||
args[i], args[j] = args[j], args[i]
|
||||
}
|
||||
|
||||
return mask, args
|
||||
}
|
||||
|
||||
func (d *decoder) decodePattern(pset xeddata.PatternSet, inst *xeddata.Inst) *encoding {
|
||||
var enc encoding
|
||||
|
||||
enc.opdigit = d.findOpdigit(pset)
|
||||
enc.opbyte = d.findOpbyte(pset, inst)
|
||||
|
||||
if strings.Contains(inst.Attributes, "DISP8_") {
|
||||
enc.evexScale = d.findEVEXScale(pset)
|
||||
enc.evexBcstScale = d.findEVEXBcstScale(pset, inst)
|
||||
}
|
||||
|
||||
enc.vex.P = pset.Match(
|
||||
"VEX_PREFIX=1", "66",
|
||||
"VEX_PREFIX=2", "F2",
|
||||
"VEX_PREFIX=3", "F3")
|
||||
enc.vex.M = pset.Match(
|
||||
"MAP=1", "0F",
|
||||
"MAP=2", "0F38",
|
||||
"MAP=3", "0F3A")
|
||||
enc.vex.L = pset.MatchOrDefault("128",
|
||||
"VL=0", "128",
|
||||
"VL=1", "256",
|
||||
"VL=2", "512")
|
||||
enc.vex.W = pset.MatchOrDefault("W0",
|
||||
"REXW=0", "W0",
|
||||
"REXW=1", "W1")
|
||||
|
||||
if pset.Is("EVEX") {
|
||||
enc.evex.SAE = strings.Contains(inst.Operands, "TXT=SAESTR")
|
||||
enc.evex.Rounding = strings.Contains(inst.Operands, "TXT=ROUNDC")
|
||||
enc.evex.Zeroing = strings.Contains(inst.Operands, "TXT=ZEROSTR")
|
||||
}
|
||||
|
||||
// Prefix each non-empty part with vex or evex.
|
||||
parts := [...]*string{
|
||||
&enc.evexScale, &enc.evexBcstScale,
|
||||
&enc.vex.P, &enc.vex.M, &enc.vex.L, &enc.vex.W,
|
||||
}
|
||||
for _, p := range parts {
|
||||
if *p == "" {
|
||||
continue
|
||||
}
|
||||
if pset.Is("EVEX") {
|
||||
*p = "evex" + *p
|
||||
} else {
|
||||
*p = "vex" + *p
|
||||
}
|
||||
}
|
||||
|
||||
return &enc
|
||||
}
|
||||
|
||||
func (d *decoder) findOpdigit(pset xeddata.PatternSet) string {
|
||||
reg := pset.Index(
|
||||
"REG[0b000]",
|
||||
"REG[0b001]",
|
||||
"REG[0b010]",
|
||||
"REG[0b011]",
|
||||
"REG[0b100]",
|
||||
"REG[0b101]",
|
||||
"REG[0b110]",
|
||||
"REG[0b111]",
|
||||
)
|
||||
// Fixed ModRM.Reg field means that it is used for opcode extension.
|
||||
if reg != -1 {
|
||||
return fmt.Sprintf("0%d", reg)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// opbyteRE matches uint8 hex literal.
|
||||
var opbyteRE = regexp.MustCompile(`0x[0-9A-F]{2}`)
|
||||
|
||||
func (d *decoder) findOpbyte(pset xeddata.PatternSet, inst *xeddata.Inst) string {
|
||||
opbyte := ""
|
||||
for k := range pset {
|
||||
if opbyteRE.MatchString(k) {
|
||||
if opbyte == "" {
|
||||
opbyte = k
|
||||
} else {
|
||||
log.Fatalf("%s: multiple opbytes", inst)
|
||||
}
|
||||
}
|
||||
}
|
||||
return opbyte
|
||||
}
|
||||
|
||||
func (d *decoder) findEVEXScale(pset xeddata.PatternSet) string {
|
||||
switch {
|
||||
case pset["NELEM_FULL()"], pset["NELEM_FULLMEM()"]:
|
||||
return pset.Match(
|
||||
"VL=0", "N16",
|
||||
"VL=1", "N32",
|
||||
"VL=2", "N64")
|
||||
case pset["NELEM_MOVDDUP()"]:
|
||||
return pset.Match(
|
||||
"VL=0", "N8",
|
||||
"VL=1", "N32",
|
||||
"VL=2", "N64")
|
||||
case pset["NELEM_HALF()"], pset["NELEM_HALFMEM()"]:
|
||||
return pset.Match(
|
||||
"VL=0", "N8",
|
||||
"VL=1", "N16",
|
||||
"VL=2", "N32")
|
||||
case pset["NELEM_QUARTERMEM()"]:
|
||||
return pset.Match(
|
||||
"VL=0", "N4",
|
||||
"VL=1", "N8",
|
||||
"VL=2", "N16")
|
||||
case pset["NELEM_EIGHTHMEM()"]:
|
||||
return pset.Match(
|
||||
"VL=0", "N2",
|
||||
"VL=1", "N4",
|
||||
"VL=2", "N8")
|
||||
case pset["NELEM_TUPLE2()"]:
|
||||
return pset.Match(
|
||||
"ESIZE_32_BITS()", "N8",
|
||||
"ESIZE_64_BITS()", "N16")
|
||||
case pset["NELEM_TUPLE4()"]:
|
||||
return pset.Match(
|
||||
"ESIZE_32_BITS()", "N16",
|
||||
"ESIZE_64_BITS()", "N32")
|
||||
case pset["NELEM_TUPLE8()"]:
|
||||
return "N32"
|
||||
case pset["NELEM_MEM128()"], pset["NELEM_TUPLE1_4X()"]:
|
||||
return "N16"
|
||||
}
|
||||
|
||||
// Explicit list is required to make it possible to
|
||||
// detect unhandled nonterminals for the caller.
|
||||
scalars := [...]string{
|
||||
"NELEM_SCALAR()",
|
||||
"NELEM_GSCAT()",
|
||||
"NELEM_GPR_READER()",
|
||||
"NELEM_GPR_READER_BYTE()",
|
||||
"NELEM_GPR_READER_WORD()",
|
||||
"NELEM_GPR_WRITER_STORE()",
|
||||
"NELEM_GPR_WRITER_STORE_BYTE()",
|
||||
"NELEM_GPR_WRITER_STORE_WORD()",
|
||||
"NELEM_GPR_WRITER_LDOP_D()",
|
||||
"NELEM_GPR_WRITER_LDOP_Q()",
|
||||
"NELEM_TUPLE1()",
|
||||
"NELEM_TUPLE1_BYTE()",
|
||||
"NELEM_TUPLE1_WORD()",
|
||||
}
|
||||
for _, scalar := range scalars {
|
||||
if pset[scalar] {
|
||||
return pset.Match(
|
||||
"ESIZE_8_BITS()", "N1",
|
||||
"ESIZE_16_BITS()", "N2",
|
||||
"ESIZE_32_BITS()", "N4",
|
||||
"ESIZE_64_BITS()", "N8")
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func (d *decoder) findEVEXBcstScale(pset xeddata.PatternSet, inst *xeddata.Inst) string {
|
||||
// Only FULL and HALF tuples are affected by the broadcasting.
|
||||
switch {
|
||||
case pset["NELEM_FULL()"]:
|
||||
return pset.Match(
|
||||
"ESIZE_32_BITS()", "BcstN4",
|
||||
"ESIZE_64_BITS()", "BcstN8")
|
||||
case pset["NELEM_HALF()"]:
|
||||
return "BcstN4"
|
||||
default:
|
||||
if inst.HasAttribute("BROADCAST_ENABLED") {
|
||||
log.Fatalf("%s: unexpected tuple for bcst", inst)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,255 @@
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"log"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ytab is ytabList element.
|
||||
type ytab struct {
|
||||
Zcase string
|
||||
Zoffset int
|
||||
ArgList string // Ytypes that are matched by this ytab.
|
||||
}
|
||||
|
||||
// ytabList is a named set of ytab objects.
|
||||
// In asm6.go represented as []ytab.
|
||||
type ytabList struct {
|
||||
Name string
|
||||
Ytabs []ytab
|
||||
}
|
||||
|
||||
// optab describes instruction encodings for specific opcode.
|
||||
type optab struct {
|
||||
Opcode string
|
||||
YtabList *ytabList
|
||||
OpLines []string
|
||||
}
|
||||
|
||||
type generator struct {
|
||||
ctx *context
|
||||
ytabLists map[string]*ytabList
|
||||
}
|
||||
|
||||
// generateOptabs fills ctx.optabs and ctx.ytabLists with objects created
|
||||
// from decoded instructions.
|
||||
func generateOptabs(ctx *context) {
|
||||
gen := generator{ctx: ctx, ytabLists: make(map[string]*ytabList)}
|
||||
optabs := make(map[string]*optab)
|
||||
for _, g := range ctx.groups {
|
||||
optabs[g.opcode] = gen.GenerateGroup(g)
|
||||
}
|
||||
ctx.optabs = optabs
|
||||
ctx.ytabLists = gen.ytabLists
|
||||
}
|
||||
|
||||
// GenerateGroup converts g into optab.
|
||||
// Populates internal ytab list map.
|
||||
func (gen *generator) GenerateGroup(g *instGroup) *optab {
|
||||
var opLines []string
|
||||
for _, inst := range g.list {
|
||||
opLines = append(opLines, gen.generateOpLine(inst))
|
||||
}
|
||||
return &optab{
|
||||
Opcode: "A" + g.opcode,
|
||||
OpLines: opLines,
|
||||
YtabList: gen.internYtabList(g),
|
||||
}
|
||||
}
|
||||
|
||||
// generateOpLine returns string that describes opBytes for single instruction form.
|
||||
func (gen *generator) generateOpLine(inst *instruction) string {
|
||||
parts := []string{gen.prefixExpr(inst)}
|
||||
if inst.pset.Is("EVEX") {
|
||||
parts = append(parts, gen.evexPrefixExpr(inst))
|
||||
}
|
||||
parts = append(parts, inst.enc.opbyte)
|
||||
if inst.enc.opdigit != "" {
|
||||
parts = append(parts, inst.enc.opdigit)
|
||||
}
|
||||
return strings.Join(parts, ", ")
|
||||
}
|
||||
|
||||
func (gen *generator) prefixExpr(inst *instruction) string {
|
||||
enc := inst.enc
|
||||
return gen.joinPrefixParts([]string{
|
||||
// Special constant that makes AVX byte different from 0x0F,
|
||||
// making it unnecessary to check for both VEX+EVEX when
|
||||
// assigning dealing with legacy instructions that skip it
|
||||
// without advancing "z" counter.
|
||||
"avxEscape",
|
||||
enc.vex.L,
|
||||
enc.vex.P,
|
||||
enc.vex.M,
|
||||
enc.vex.W,
|
||||
})
|
||||
}
|
||||
|
||||
func (gen *generator) evexPrefixExpr(inst *instruction) string {
|
||||
enc := inst.enc
|
||||
parts := []string{
|
||||
enc.evexScale,
|
||||
enc.evexBcstScale,
|
||||
}
|
||||
if enc.evex.SAE {
|
||||
parts = append(parts, "evexSaeEnabled")
|
||||
}
|
||||
if enc.evex.Rounding {
|
||||
parts = append(parts, "evexRoundingEnabled")
|
||||
}
|
||||
if enc.evex.Zeroing {
|
||||
parts = append(parts, "evexZeroingEnabled")
|
||||
}
|
||||
return gen.joinPrefixParts(parts)
|
||||
}
|
||||
|
||||
// joinPrefixParts returns the Go OR-expression for every non-empty name.
|
||||
// If every name is empty, returns "0".
|
||||
func (gen *generator) joinPrefixParts(names []string) string {
|
||||
filterEmptyStrings := func(xs []string) []string {
|
||||
ys := xs[:0]
|
||||
for _, x := range xs {
|
||||
if x != "" {
|
||||
ys = append(ys, x)
|
||||
}
|
||||
}
|
||||
return ys
|
||||
}
|
||||
|
||||
names = filterEmptyStrings(names)
|
||||
if len(names) == 0 {
|
||||
return "0"
|
||||
}
|
||||
return strings.Join(names, "|")
|
||||
}
|
||||
|
||||
// internYtabList returns ytabList for given group.
|
||||
//
|
||||
// Returned ytab lists are interned.
|
||||
// Same ytab list can be returned for different groups.
|
||||
func (gen *generator) internYtabList(g *instGroup) *ytabList {
|
||||
var key string
|
||||
{
|
||||
var buf bytes.Buffer
|
||||
for _, inst := range g.list {
|
||||
buf.WriteString(inst.zform)
|
||||
buf.WriteByte('=')
|
||||
buf.WriteString(inst.YtypeListString())
|
||||
buf.WriteByte(';')
|
||||
}
|
||||
key = buf.String()
|
||||
}
|
||||
if ylist := gen.ytabLists[key]; ylist != nil {
|
||||
return ylist
|
||||
}
|
||||
|
||||
var ytabs []ytab
|
||||
for _, inst := range g.list {
|
||||
zoffset := 2
|
||||
if inst.pset.Is("EVEX") {
|
||||
zoffset++ // Always at least 3 bytes
|
||||
}
|
||||
if inst.enc.opdigit != "" {
|
||||
zoffset++
|
||||
}
|
||||
|
||||
if inst.mask != nil {
|
||||
ytabs = append(ytabs, gen.makeMaskYtabs(zoffset, inst)...)
|
||||
} else {
|
||||
ytabs = append(ytabs, gen.makeYtab(zoffset, inst.zform, inst.args))
|
||||
}
|
||||
}
|
||||
ylist := &ytabList{
|
||||
Name: "_y" + strings.ToLower(g.opcode),
|
||||
Ytabs: ytabs,
|
||||
}
|
||||
gen.ytabLists[key] = ylist
|
||||
return ylist
|
||||
}
|
||||
|
||||
var zcaseByZform = map[string]string{
|
||||
"evex imm8 reg kmask reg/mem": "Zevex_i_r_k_rm",
|
||||
"evex imm8 reg reg/mem": "Zevex_i_r_rm",
|
||||
"evex imm8 reg/mem kmask reg": "Zevex_i_rm_k_r",
|
||||
"evex imm8 reg/mem kmask regV opdigit": "Zevex_i_rm_k_vo",
|
||||
"evex imm8 reg/mem reg": "Zevex_i_rm_r",
|
||||
"evex imm8 reg/mem regV opdigit": "Zevex_i_rm_vo",
|
||||
"evex imm8 reg/mem regV kmask reg": "Zevex_i_rm_v_k_r",
|
||||
"evex imm8 reg/mem regV reg": "Zevex_i_rm_v_r",
|
||||
"evex kmask reg/mem opdigit": "Zevex_k_rmo",
|
||||
"evex reg kmask reg/mem": "Zevex_r_k_rm",
|
||||
"evex reg reg/mem": "Zevex_r_v_rm",
|
||||
"evex reg regV kmask reg/mem": "Zevex_r_v_k_rm",
|
||||
"evex reg regV reg/mem": "Zevex_r_v_rm",
|
||||
"evex reg/mem kmask reg": "Zevex_rm_k_r",
|
||||
"evex reg/mem reg": "Zevex_rm_v_r",
|
||||
"evex reg/mem regV kmask reg": "Zevex_rm_v_k_r",
|
||||
"evex reg/mem regV reg": "Zevex_rm_v_r",
|
||||
|
||||
"": "Zvex",
|
||||
"imm8 reg reg/mem": "Zvex_i_r_rm",
|
||||
"imm8 reg/mem reg": "Zvex_i_rm_r",
|
||||
"imm8 reg/mem regV opdigit": "Zvex_i_rm_vo",
|
||||
"imm8 reg/mem regV reg": "Zvex_i_rm_v_r",
|
||||
"reg reg/mem": "Zvex_r_v_rm",
|
||||
"reg regV reg/mem": "Zvex_r_v_rm",
|
||||
"reg/mem opdigit": "Zvex_rm_v_ro",
|
||||
"reg/mem reg": "Zvex_rm_v_r",
|
||||
"reg/mem regV opdigit": "Zvex_rm_r_vo",
|
||||
"reg/mem regV reg": "Zvex_rm_v_r",
|
||||
"reg/mem": "Zvex_rm_v_r",
|
||||
"regIH reg/mem regV reg": "Zvex_hr_rm_v_r",
|
||||
"regV reg/mem reg": "Zvex_v_rm_r",
|
||||
}
|
||||
|
||||
func (gen *generator) makeYtab(zoffset int, zform string, args []*argument) ytab {
|
||||
var ytypes []string
|
||||
for _, arg := range args {
|
||||
if arg.ytype != "Ynone" {
|
||||
ytypes = append(ytypes, arg.ytype)
|
||||
}
|
||||
}
|
||||
argList := strings.Join(ytypes, ", ")
|
||||
zcase := zcaseByZform[zform]
|
||||
if zcase == "" {
|
||||
log.Fatalf("no zcase for %q", zform)
|
||||
}
|
||||
return ytab{
|
||||
Zcase: zcase,
|
||||
Zoffset: zoffset,
|
||||
ArgList: argList,
|
||||
}
|
||||
}
|
||||
|
||||
// makeMaskYtabs returns 2 ytabs created from instruction with MASK1() argument.
|
||||
//
|
||||
// This is required due to how masking is implemented in asm6.
|
||||
// Single MASK1() instruction produces 2 ytabs, for example:
|
||||
// 1. OP xmm, mem | Yxr, Yxm | Does not permit K arguments (K0 implied)
|
||||
// 2. OP xmm, K2, mem | Yxr, Yknot0, Yxm | Does not permit K0 argument
|
||||
//
|
||||
// This function also exploits that both ytab entries have same opbytes,
|
||||
// hence it is efficient to emit only one opbytes line and 0 Z-offset
|
||||
// for first ytab object.
|
||||
func (gen *generator) makeMaskYtabs(zoffset int, inst *instruction) []ytab {
|
||||
var k0 ytab
|
||||
{
|
||||
zform := strings.Replace(inst.zform, "MASK1() ", "", 1)
|
||||
inst.mask.ytype = "Ynone"
|
||||
k0 = gen.makeYtab(0, zform, inst.args)
|
||||
}
|
||||
var knot0 ytab
|
||||
{
|
||||
zform := strings.Replace(inst.zform, "MASK1() ", "kmask ", 1)
|
||||
inst.mask.ytype = "Yknot0"
|
||||
knot0 = gen.makeYtab(zoffset, zform, inst.args)
|
||||
}
|
||||
|
||||
inst.mask.ytype = "MASK1()" // Restore Y-type
|
||||
return []ytab{k0, knot0}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"golang.org/x/arch/x86/xeddata"
|
||||
)
|
||||
|
||||
// argument is a describes single instruction operand properties.
|
||||
type argument struct {
|
||||
// ytype is argument class as returned by asm6 "oclass" function.
|
||||
ytype string
|
||||
|
||||
// zkind is a partial Z-case matcher.
|
||||
// Determines which Z-case handles the encoding of instruction.
|
||||
zkind string
|
||||
}
|
||||
|
||||
// instruction is decoded XED instruction.
|
||||
// Used to produce ytabs and optabs in later phases.
|
||||
type instruction struct {
|
||||
// opcode is instruction symbolic name.
|
||||
opcode string
|
||||
|
||||
pset xeddata.PatternSet
|
||||
enc *encoding
|
||||
|
||||
// mask is EVEX K-register argument; points to args element.
|
||||
// Used to emit Yk0+Yknot0 table entries.
|
||||
// Nil for VEX-encoded insts.
|
||||
mask *argument
|
||||
args []*argument
|
||||
|
||||
// zform is a pattern that determines which encoder Z-case is used.
|
||||
// We store zform instead of zcase directly because it's further
|
||||
// expanded during optabs generation.
|
||||
zform string
|
||||
}
|
||||
|
||||
// String returns short inst printed representation.
|
||||
func (inst *instruction) String() string { return inst.opcode }
|
||||
|
||||
// YtypeListString joins each argument Y-type and returns the result.
|
||||
func (inst *instruction) YtypeListString() string {
|
||||
var parts []string
|
||||
for _, arg := range inst.args {
|
||||
parts = append(parts, arg.ytype)
|
||||
}
|
||||
return strings.Join(parts, " ")
|
||||
}
|
||||
|
||||
// ArgIndexByZkind returns first argument matching given zkind or -1.
|
||||
func (inst *instruction) ArgIndexByZkind(zkind string) int {
|
||||
for i, arg := range inst.args {
|
||||
if arg.zkind == zkind {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
@@ -0,0 +1,361 @@
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/arch/x86/xeddata"
|
||||
)
|
||||
|
||||
// instGroup holds a list of instructions with same opcode.
|
||||
type instGroup struct {
|
||||
opcode string
|
||||
list []*instruction
|
||||
}
|
||||
|
||||
// context is x86avxgen program execution state.
|
||||
type context struct {
|
||||
db *xeddata.Database
|
||||
|
||||
groups []*instGroup
|
||||
|
||||
optabs map[string]*optab
|
||||
ytabLists map[string]*ytabList
|
||||
|
||||
// Command line arguments:
|
||||
|
||||
xedPath string
|
||||
}
|
||||
|
||||
func main() {
|
||||
log.SetPrefix("x86avxgen: ")
|
||||
log.SetFlags(log.Lshortfile)
|
||||
|
||||
var ctx context
|
||||
|
||||
runSteps(&ctx,
|
||||
parseFlags,
|
||||
openDatabase,
|
||||
buildTables,
|
||||
printTables)
|
||||
}
|
||||
|
||||
func buildTables(ctx *context) {
|
||||
// Order of steps is significant.
|
||||
runSteps(ctx,
|
||||
decodeGroups,
|
||||
mergeRegMem,
|
||||
addGoSuffixes,
|
||||
mergeWIG,
|
||||
assignZforms,
|
||||
sortGroups,
|
||||
generateOptabs)
|
||||
}
|
||||
|
||||
func runSteps(ctx *context, steps ...func(*context)) {
|
||||
for _, f := range steps {
|
||||
f(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
func parseFlags(ctx *context) {
|
||||
flag.StringVar(&ctx.xedPath, "xedPath", "./xedpath",
|
||||
"XED datafiles location")
|
||||
|
||||
flag.Parse()
|
||||
}
|
||||
|
||||
func openDatabase(ctx *context) {
|
||||
db, err := xeddata.NewDatabase(ctx.xedPath)
|
||||
if err != nil {
|
||||
log.Fatalf("open database: %v", err)
|
||||
}
|
||||
ctx.db = db
|
||||
}
|
||||
|
||||
// mergeRegMem merges reg-only with mem-only instructions.
|
||||
// For example: {MOVQ reg, mem} + {MOVQ reg, reg} = {MOVQ reg, reg/mem}.
|
||||
func mergeRegMem(ctx *context) {
|
||||
mergeKey := func(inst *instruction) string {
|
||||
return strings.Join([]string{
|
||||
fmt.Sprint(len(inst.args)),
|
||||
inst.enc.opbyte,
|
||||
inst.enc.opdigit,
|
||||
inst.enc.vex.P,
|
||||
inst.enc.vex.L,
|
||||
inst.enc.vex.M,
|
||||
inst.enc.vex.W,
|
||||
}, " ")
|
||||
}
|
||||
|
||||
for _, g := range ctx.groups {
|
||||
regOnly := make(map[string]*instruction)
|
||||
memOnly := make(map[string]*instruction)
|
||||
list := g.list[:0]
|
||||
for _, inst := range g.list {
|
||||
switch {
|
||||
case inst.pset.Is("RegOnly"):
|
||||
regOnly[mergeKey(inst)] = inst
|
||||
case inst.pset.Is("MemOnly"):
|
||||
memOnly[mergeKey(inst)] = inst
|
||||
default:
|
||||
if len(inst.args) == 0 {
|
||||
list = append(list, inst)
|
||||
continue
|
||||
}
|
||||
log.Fatalf("%s: unexpected MOD value", inst)
|
||||
}
|
||||
}
|
||||
|
||||
for k, m := range memOnly {
|
||||
r := regOnly[k]
|
||||
if r != nil {
|
||||
index := m.ArgIndexByZkind("reg/mem")
|
||||
arg := m.args[index]
|
||||
switch ytype := r.args[index].ytype; ytype {
|
||||
case "Yrl":
|
||||
arg.ytype = "Yml"
|
||||
case "Yxr":
|
||||
arg.ytype = "Yxm"
|
||||
case "YxrEvex":
|
||||
arg.ytype = "YxmEvex"
|
||||
case "Yyr":
|
||||
arg.ytype = "Yym"
|
||||
case "YyrEvex":
|
||||
arg.ytype = "YymEvex"
|
||||
case "Yzr":
|
||||
arg.ytype = "Yzm"
|
||||
case "Yk":
|
||||
arg.ytype = "Ykm"
|
||||
default:
|
||||
log.Fatalf("%s: unexpected register type: %s", r, ytype)
|
||||
}
|
||||
// Merge EVEX flags into m.
|
||||
m.enc.evex.SAE = m.enc.evex.SAE || r.enc.evex.SAE
|
||||
m.enc.evex.Rounding = m.enc.evex.Rounding || r.enc.evex.Rounding
|
||||
m.enc.evex.Zeroing = m.enc.evex.Zeroing || r.enc.evex.Zeroing
|
||||
delete(regOnly, k)
|
||||
}
|
||||
list = append(list, m)
|
||||
}
|
||||
for _, r := range regOnly {
|
||||
list = append(list, r)
|
||||
}
|
||||
|
||||
g.list = list
|
||||
}
|
||||
}
|
||||
|
||||
// mergeWIG merges [E]VEX.W0 + [E]VEX.W1 into [E]VEX.WIG.
|
||||
func mergeWIG(ctx *context) {
|
||||
mergeKey := func(inst *instruction) string {
|
||||
return strings.Join([]string{
|
||||
fmt.Sprint(len(inst.args)),
|
||||
inst.enc.opbyte,
|
||||
inst.enc.opdigit,
|
||||
inst.enc.vex.P,
|
||||
inst.enc.vex.L,
|
||||
inst.enc.vex.M,
|
||||
}, " ")
|
||||
}
|
||||
|
||||
for _, g := range ctx.groups {
|
||||
w0map := make(map[string]*instruction)
|
||||
w1map := make(map[string]*instruction)
|
||||
list := g.list[:0]
|
||||
for _, inst := range g.list {
|
||||
switch w := inst.enc.vex.W; w {
|
||||
case "evexW0", "vexW0":
|
||||
w0map[mergeKey(inst)] = inst
|
||||
case "evexW1", "vexW1":
|
||||
w1map[mergeKey(inst)] = inst
|
||||
default:
|
||||
log.Fatalf("%s: unexpected vex.W: %s", inst, w)
|
||||
}
|
||||
}
|
||||
|
||||
for k, w0 := range w0map {
|
||||
w1 := w1map[k]
|
||||
if w1 != nil {
|
||||
w0.enc.vex.W = strings.Replace(w0.enc.vex.W, "W0", "WIG", 1)
|
||||
delete(w1map, k)
|
||||
}
|
||||
list = append(list, w0)
|
||||
}
|
||||
for _, w1 := range w1map {
|
||||
list = append(list, w1)
|
||||
}
|
||||
|
||||
g.list = list
|
||||
}
|
||||
}
|
||||
|
||||
// assignZforms initializes zform field of every instruction in ctx.
|
||||
func assignZforms(ctx *context) {
|
||||
for _, g := range ctx.groups {
|
||||
for _, inst := range g.list {
|
||||
var parts []string
|
||||
if inst.pset.Is("EVEX") {
|
||||
parts = append(parts, "evex")
|
||||
}
|
||||
for _, arg := range inst.args {
|
||||
parts = append(parts, arg.zkind)
|
||||
}
|
||||
if inst.enc.opdigit != "" {
|
||||
parts = append(parts, "opdigit")
|
||||
}
|
||||
inst.zform = strings.Join(parts, " ")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// sortGroups sorts each instruction group by opcode as well as instructions
|
||||
// inside groups by special rules (see below).
|
||||
//
|
||||
// The order of instructions inside group determine ytab
|
||||
// elements order inside ytabList.
|
||||
//
|
||||
// We want these rules to be satisfied:
|
||||
// - EVEX-encoded entries go after VEX-encoded entries.
|
||||
// This way, VEX forms are selected over EVEX variants.
|
||||
// - EVEX forms with SAE/RC must go before forms without them.
|
||||
// This helps to avoid problems with reg-reg instructions
|
||||
// that encode either of them in ModRM.R/M which causes
|
||||
// ambiguity in ytabList (more than 1 ytab can match args).
|
||||
// If first matching ytab has SAE/RC, problem will not occur.
|
||||
// - Memory argument position affects order.
|
||||
// Required to be in sync with XED encoder when there
|
||||
// are multiple choices of how to encode instruction.
|
||||
func sortGroups(ctx *context) {
|
||||
sort.SliceStable(ctx.groups, func(i, j int) bool {
|
||||
return ctx.groups[i].opcode < ctx.groups[j].opcode
|
||||
})
|
||||
|
||||
for _, g := range ctx.groups {
|
||||
sortInstList(g.list)
|
||||
}
|
||||
}
|
||||
|
||||
func sortInstList(insts []*instruction) {
|
||||
// Use strings for sorting to get reliable transitive "less".
|
||||
order := make(map[*instruction]string)
|
||||
for _, inst := range insts {
|
||||
encTag := 'a'
|
||||
if inst.pset.Is("EVEX") {
|
||||
encTag = 'b'
|
||||
}
|
||||
memTag := 'a'
|
||||
if index := inst.ArgIndexByZkind("reg/mem"); index != -1 {
|
||||
memTag = 'z' - rune(index)
|
||||
}
|
||||
rcsaeTag := 'a'
|
||||
if !(inst.enc.evex.SAE || inst.enc.evex.Rounding) {
|
||||
rcsaeTag = 'b'
|
||||
}
|
||||
order[inst] = fmt.Sprintf("%c%c%c %s",
|
||||
encTag, memTag, rcsaeTag, inst.YtypeListString())
|
||||
}
|
||||
|
||||
sort.SliceStable(insts, func(i, j int) bool {
|
||||
return order[insts[i]] < order[insts[j]]
|
||||
})
|
||||
}
|
||||
|
||||
// addGoSuffixes splits some groups into several groups by introducing a suffix.
|
||||
// For example, ANDN group becomes ANDNL and ANDNQ (ANDN becomes empty itself).
|
||||
// Empty groups are removed.
|
||||
func addGoSuffixes(ctx *context) {
|
||||
var opcodeSuffixMatchers map[string][]string
|
||||
{
|
||||
opXY := []string{"VL=0", "X", "VL=1", "Y"}
|
||||
opXYZ := []string{"VL=0", "X", "VL=1", "Y", "VL=2", "Z"}
|
||||
opQ := []string{"REXW=1", "Q"}
|
||||
opLQ := []string{"REXW=0", "L", "REXW=1", "Q"}
|
||||
|
||||
opcodeSuffixMatchers = map[string][]string{
|
||||
"VCVTPD2DQ": opXY,
|
||||
"VCVTPD2PS": opXY,
|
||||
"VCVTTPD2DQ": opXY,
|
||||
"VCVTQQ2PS": opXY,
|
||||
"VCVTUQQ2PS": opXY,
|
||||
"VCVTPD2UDQ": opXY,
|
||||
"VCVTTPD2UDQ": opXY,
|
||||
|
||||
"VFPCLASSPD": opXYZ,
|
||||
"VFPCLASSPS": opXYZ,
|
||||
|
||||
"VCVTSD2SI": opQ,
|
||||
"VCVTTSD2SI": opQ,
|
||||
"VCVTTSS2SI": opQ,
|
||||
"VCVTSS2SI": opQ,
|
||||
|
||||
"VCVTSD2USI": opLQ,
|
||||
"VCVTSS2USI": opLQ,
|
||||
"VCVTTSD2USI": opLQ,
|
||||
"VCVTTSS2USI": opLQ,
|
||||
"VCVTUSI2SD": opLQ,
|
||||
"VCVTUSI2SS": opLQ,
|
||||
"VCVTSI2SD": opLQ,
|
||||
"VCVTSI2SS": opLQ,
|
||||
"ANDN": opLQ,
|
||||
"BEXTR": opLQ,
|
||||
"BLSI": opLQ,
|
||||
"BLSMSK": opLQ,
|
||||
"BLSR": opLQ,
|
||||
"BZHI": opLQ,
|
||||
"MULX": opLQ,
|
||||
"PDEP": opLQ,
|
||||
"PEXT": opLQ,
|
||||
"RORX": opLQ,
|
||||
"SARX": opLQ,
|
||||
"SHLX": opLQ,
|
||||
"SHRX": opLQ,
|
||||
}
|
||||
}
|
||||
|
||||
newGroups := make(map[string][]*instruction)
|
||||
for _, g := range ctx.groups {
|
||||
kv := opcodeSuffixMatchers[g.opcode]
|
||||
if kv == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
list := g.list[:0]
|
||||
for _, inst := range g.list {
|
||||
newOp := inst.opcode + inst.pset.Match(kv...)
|
||||
if newOp != inst.opcode {
|
||||
inst.opcode = newOp
|
||||
newGroups[newOp] = append(newGroups[newOp], inst)
|
||||
} else {
|
||||
list = append(list, inst)
|
||||
}
|
||||
}
|
||||
g.list = list
|
||||
}
|
||||
groups := ctx.groups[:0] // Filled with non-empty groups
|
||||
// Some groups may become empty due to opcode split.
|
||||
for _, g := range ctx.groups {
|
||||
if len(g.list) != 0 {
|
||||
groups = append(groups, g)
|
||||
}
|
||||
}
|
||||
for op, insts := range newGroups {
|
||||
groups = append(groups, &instGroup{
|
||||
opcode: op,
|
||||
list: insts,
|
||||
})
|
||||
}
|
||||
ctx.groups = groups
|
||||
}
|
||||
|
||||
func printTables(ctx *context) {
|
||||
writeTables(os.Stdout, ctx)
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"go/format"
|
||||
"io"
|
||||
"log"
|
||||
"sort"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
var tablesTemplate = template.Must(template.New("avx_optabs").Parse(`
|
||||
// Code generated by x86avxgen. DO NOT EDIT.
|
||||
|
||||
package x86
|
||||
|
||||
// VEX instructions that come in two forms:
|
||||
// VTHING xmm2/m128, xmmV, xmm1
|
||||
// VTHING ymm2/m256, ymmV, ymm1
|
||||
//
|
||||
// The opcode array in the corresponding Optab entry
|
||||
// should contain the (VEX prefixes, opcode byte) pair
|
||||
// for each of the two forms.
|
||||
// For example, the entries for VPXOR are:
|
||||
//
|
||||
// VPXOR xmm2/m128, xmmV, xmm1
|
||||
// VEX.NDS.128.66.0F.WIG EF /r
|
||||
//
|
||||
// VPXOR ymm2/m256, ymmV, ymm1
|
||||
// VEX.NDS.256.66.0F.WIG EF /r
|
||||
//
|
||||
// Produce this optab entry:
|
||||
//
|
||||
// {AVPXOR, yvex_xy3, Pavx, opBytes{vex128|vex66|vex0F|vexWIG, 0xEF, vex256|vex66|vex0F|vexWIG, 0xEF}}
|
||||
//
|
||||
// VEX requires at least 2 bytes inside opBytes:
|
||||
// - VEX prefixes (vex-prefixed constants)
|
||||
// - Opcode byte
|
||||
//
|
||||
// EVEX instructions extend VEX form variety:
|
||||
// VTHING zmm2/m512, zmmV, zmm1 -- implicit K0 (merging)
|
||||
// VTHING zmm2/m512, zmmV, K, zmm1 -- explicit K mask (can't use K0)
|
||||
//
|
||||
// EVEX requires at least 3 bytes inside opBytes:
|
||||
// - EVEX prefixes (evex-prefixed constants); similar to VEX
|
||||
// - Displacement multiplier info (scale / broadcast scale)
|
||||
// - Opcode byte; similar to VEX
|
||||
//
|
||||
// Both VEX and EVEX instructions may have opdigit (opcode extension) byte
|
||||
// which follows the primary opcode byte.
|
||||
// Because it can only have value of 0-7, it is written in octal notation.
|
||||
//
|
||||
// x86.csv can be very useful for figuring out proper [E]VEX parts.
|
||||
|
||||
{{ range .Ylists }}
|
||||
var {{.Name}} = []ytab{
|
||||
{{- range .Ytabs }}
|
||||
{zcase: {{.Zcase}}, zoffset: {{.Zoffset}}, args: argList{ {{.ArgList}} }},
|
||||
{{- end }}
|
||||
}
|
||||
{{ end }}
|
||||
|
||||
var avxOptab = [...]Optab{
|
||||
{{- range .Optabs }}
|
||||
{as: {{.Opcode}}, ytab: {{.YtabList.Name}}, prefix: Pavx, op: opBytes{
|
||||
{{- range .OpLines }}
|
||||
{{.}},
|
||||
{{- end }}
|
||||
}},
|
||||
{{- end }}
|
||||
}
|
||||
`))
|
||||
|
||||
// writeTables writes avx optabs file contents to w.
|
||||
func writeTables(w io.Writer, ctx *context) {
|
||||
ylists := make([]*ytabList, 0, len(ctx.ytabLists))
|
||||
for _, ylist := range ctx.ytabLists {
|
||||
ylists = append(ylists, ylist)
|
||||
}
|
||||
sort.Slice(ylists, func(i, j int) bool {
|
||||
return ylists[i].Name < ylists[j].Name
|
||||
})
|
||||
optabs := make([]*optab, 0, len(ctx.optabs))
|
||||
for _, o := range ctx.optabs {
|
||||
optabs = append(optabs, o)
|
||||
}
|
||||
sort.Slice(optabs, func(i, j int) bool {
|
||||
return optabs[i].Opcode < optabs[j].Opcode
|
||||
})
|
||||
|
||||
var buf bytes.Buffer
|
||||
err := tablesTemplate.Execute(&buf, struct {
|
||||
Ylists []*ytabList
|
||||
Optabs []*optab
|
||||
}{
|
||||
Ylists: ylists,
|
||||
Optabs: optabs,
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("template execute error: %v", err)
|
||||
}
|
||||
|
||||
// TODO: invoke "go fmt" or format.Gofmt? #22695.
|
||||
prettyCode, err := format.Source(buf.Bytes())
|
||||
if err != nil {
|
||||
log.Fatalf("gofmt error: %v", err)
|
||||
}
|
||||
|
||||
if _, err := w.Write(prettyCode); err != nil {
|
||||
log.Fatalf("write output: %v", err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
var _yvmovsd = []ytab{
|
||||
{zcase: Zvex_r_v_rm, zoffset: 2, args: argList{Yxr, Yxr, Yxr}},
|
||||
{zcase: Zvex_r_v_rm, zoffset: 2, args: argList{Yxr, Ym}},
|
||||
{zcase: Zvex_rm_v_r, zoffset: 2, args: argList{Ym, Yxr}},
|
||||
{zcase: Zvex_rm_v_r, zoffset: 2, args: argList{Yxr, Yxr, Yxr}},
|
||||
{zcase: Zevex_r_v_rm, zoffset: 0, args: argList{YxrEvex, YxrEvex, YxrEvex}},
|
||||
{zcase: Zevex_r_v_k_rm, zoffset: 3, args: argList{YxrEvex, YxrEvex, Yknot0, YxrEvex}},
|
||||
{zcase: Zevex_r_v_rm, zoffset: 0, args: argList{YxrEvex, Ym}},
|
||||
{zcase: Zevex_r_k_rm, zoffset: 3, args: argList{YxrEvex, Yknot0, Ym}},
|
||||
{zcase: Zevex_rm_v_r, zoffset: 0, args: argList{Ym, YxrEvex}},
|
||||
{zcase: Zevex_rm_k_r, zoffset: 3, args: argList{Ym, Yknot0, YxrEvex}},
|
||||
{zcase: Zevex_rm_v_r, zoffset: 0, args: argList{YxrEvex, YxrEvex, YxrEvex}},
|
||||
{zcase: Zevex_rm_v_k_r, zoffset: 3, args: argList{YxrEvex, YxrEvex, Yknot0, YxrEvex}},
|
||||
}
|
||||
----
|
||||
{as: AVMOVSD, ytab: _yvmovsd, prefix: Pavx, op: opBytes{
|
||||
avxEscape | vex128 | vexF2 | vex0F | vexW0, 0x11,
|
||||
avxEscape | vex128 | vexF2 | vex0F | vexW0, 0x11,
|
||||
avxEscape | vex128 | vexF2 | vex0F | vexW0, 0x10,
|
||||
avxEscape | vex128 | vexF2 | vex0F | vexW0, 0x10,
|
||||
avxEscape | evex128 | evexF2 | evex0F | evexW1, evexZeroingEnabled, 0x11,
|
||||
avxEscape | evex128 | evexF2 | evex0F | evexW1, evexN8, 0x11,
|
||||
avxEscape | evex128 | evexF2 | evex0F | evexW1, evexN8 | evexZeroingEnabled, 0x10,
|
||||
avxEscape | evex128 | evexF2 | evex0F | evexW1, evexZeroingEnabled, 0x10,
|
||||
}}
|
||||
|
||||
======
|
||||
var _yvaddpd = []ytab{
|
||||
{zcase: Zvex_rm_v_r, zoffset: 2, args: argList{Yxm, Yxr, Yxr}},
|
||||
{zcase: Zvex_rm_v_r, zoffset: 2, args: argList{Yym, Yyr, Yyr}},
|
||||
{zcase: Zevex_rm_v_r, zoffset: 0, args: argList{Yzm, Yzr, Yzr}},
|
||||
{zcase: Zevex_rm_v_k_r, zoffset: 3, args: argList{Yzm, Yzr, Yknot0, Yzr}},
|
||||
{zcase: Zevex_rm_v_r, zoffset: 0, args: argList{YxmEvex, YxrEvex, YxrEvex}},
|
||||
{zcase: Zevex_rm_v_k_r, zoffset: 3, args: argList{YxmEvex, YxrEvex, Yknot0, YxrEvex}},
|
||||
{zcase: Zevex_rm_v_r, zoffset: 0, args: argList{YymEvex, YyrEvex, YyrEvex}},
|
||||
{zcase: Zevex_rm_v_k_r, zoffset: 3, args: argList{YymEvex, YyrEvex, Yknot0, YyrEvex}},
|
||||
}
|
||||
----
|
||||
{as: AVADDPD, ytab: _yvaddpd, prefix: Pavx, op: opBytes{
|
||||
avxEscape | vex128 | vex66 | vex0F | vexW0, 0x58,
|
||||
avxEscape | vex256 | vex66 | vex0F | vexW0, 0x58,
|
||||
avxEscape | evex512 | evex66 | evex0F | evexW1, evexN64 | evexBcstN8 | evexRoundingEnabled | evexZeroingEnabled, 0x58,
|
||||
avxEscape | evex128 | evex66 | evex0F | evexW1, evexN16 | evexBcstN8 | evexZeroingEnabled, 0x58,
|
||||
avxEscape | evex256 | evex66 | evex0F | evexW1, evexN32 | evexBcstN8 | evexZeroingEnabled, 0x58,
|
||||
}}
|
||||
|
||||
======
|
||||
var _yvcmppd = []ytab{
|
||||
{zcase: Zvex_i_rm_v_r, zoffset: 2, args: argList{Yu8, Yxm, Yxr, Yxr}},
|
||||
{zcase: Zvex_i_rm_v_r, zoffset: 2, args: argList{Yu8, Yym, Yyr, Yyr}},
|
||||
{zcase: Zevex_i_rm_v_r, zoffset: 0, args: argList{Yu8, Yzm, Yzr, Yk}},
|
||||
{zcase: Zevex_i_rm_v_k_r, zoffset: 3, args: argList{Yu8, Yzm, Yzr, Yknot0, Yk}},
|
||||
{zcase: Zevex_i_rm_v_r, zoffset: 0, args: argList{Yu8, YxmEvex, YxrEvex, Yk}},
|
||||
{zcase: Zevex_i_rm_v_k_r, zoffset: 3, args: argList{Yu8, YxmEvex, YxrEvex, Yknot0, Yk}},
|
||||
{zcase: Zevex_i_rm_v_r, zoffset: 0, args: argList{Yu8, YymEvex, YyrEvex, Yk}},
|
||||
{zcase: Zevex_i_rm_v_k_r, zoffset: 3, args: argList{Yu8, YymEvex, YyrEvex, Yknot0, Yk}},
|
||||
}
|
||||
----
|
||||
{as: AVCMPPD, ytab: _yvcmppd, prefix: Pavx, op: opBytes{
|
||||
avxEscape | vex128 | vex66 | vex0F | vexW0, 0xC2,
|
||||
avxEscape | vex256 | vex66 | vex0F | vexW0, 0xC2,
|
||||
avxEscape | evex512 | evex66 | evex0F | evexW1, evexN64 | evexBcstN8 | evexSaeEnabled, 0xC2,
|
||||
avxEscape | evex128 | evex66 | evex0F | evexW1, evexN16 | evexBcstN8, 0xC2,
|
||||
avxEscape | evex256 | evex66 | evex0F | evexW1, evexN32 | evexBcstN8, 0xC2,
|
||||
}}
|
||||
|
||||
======
|
||||
var _yvmovapd = []ytab{
|
||||
{zcase: Zvex_r_v_rm, zoffset: 2, args: argList{Yxr, Yxm}},
|
||||
{zcase: Zvex_r_v_rm, zoffset: 2, args: argList{Yyr, Yym}},
|
||||
{zcase: Zvex_rm_v_r, zoffset: 2, args: argList{Yxm, Yxr}},
|
||||
{zcase: Zvex_rm_v_r, zoffset: 2, args: argList{Yym, Yyr}},
|
||||
{zcase: Zevex_r_v_rm, zoffset: 0, args: argList{YxrEvex, YxmEvex}},
|
||||
{zcase: Zevex_r_k_rm, zoffset: 3, args: argList{YxrEvex, Yknot0, YxmEvex}},
|
||||
{zcase: Zevex_r_v_rm, zoffset: 0, args: argList{YyrEvex, YymEvex}},
|
||||
{zcase: Zevex_r_k_rm, zoffset: 3, args: argList{YyrEvex, Yknot0, YymEvex}},
|
||||
{zcase: Zevex_r_v_rm, zoffset: 0, args: argList{Yzr, Yzm}},
|
||||
{zcase: Zevex_r_k_rm, zoffset: 3, args: argList{Yzr, Yknot0, Yzm}},
|
||||
{zcase: Zevex_rm_v_r, zoffset: 0, args: argList{YxmEvex, YxrEvex}},
|
||||
{zcase: Zevex_rm_k_r, zoffset: 3, args: argList{YxmEvex, Yknot0, YxrEvex}},
|
||||
{zcase: Zevex_rm_v_r, zoffset: 0, args: argList{YymEvex, YyrEvex}},
|
||||
{zcase: Zevex_rm_k_r, zoffset: 3, args: argList{YymEvex, Yknot0, YyrEvex}},
|
||||
{zcase: Zevex_rm_v_r, zoffset: 0, args: argList{Yzm, Yzr}},
|
||||
{zcase: Zevex_rm_k_r, zoffset: 3, args: argList{Yzm, Yknot0, Yzr}},
|
||||
}
|
||||
----
|
||||
{as: AVMOVAPD, ytab: _yvmovapd, prefix: Pavx, op: opBytes{
|
||||
avxEscape | vex128 | vex66 | vex0F | vexW0, 0x29,
|
||||
avxEscape | vex256 | vex66 | vex0F | vexW0, 0x29,
|
||||
avxEscape | vex128 | vex66 | vex0F | vexW0, 0x28,
|
||||
avxEscape | vex256 | vex66 | vex0F | vexW0, 0x28,
|
||||
avxEscape | evex128 | evex66 | evex0F | evexW1, evexN16 | evexZeroingEnabled, 0x29,
|
||||
avxEscape | evex256 | evex66 | evex0F | evexW1, evexN32 | evexZeroingEnabled, 0x29,
|
||||
avxEscape | evex512 | evex66 | evex0F | evexW1, evexN64 | evexZeroingEnabled, 0x29,
|
||||
avxEscape | evex128 | evex66 | evex0F | evexW1, evexN16 | evexZeroingEnabled, 0x28,
|
||||
avxEscape | evex256 | evex66 | evex0F | evexW1, evexN32 | evexZeroingEnabled, 0x28,
|
||||
avxEscape | evex512 | evex66 | evex0F | evexW1, evexN64 | evexZeroingEnabled, 0x28,
|
||||
}}
|
||||
|
||||
======
|
||||
var _yvpslld = []ytab{
|
||||
{zcase: Zvex_i_rm_vo, zoffset: 3, args: argList{Yu8, Yxr, Yxr}},
|
||||
{zcase: Zvex_i_rm_vo, zoffset: 3, args: argList{Yu8, Yyr, Yyr}},
|
||||
{zcase: Zvex_rm_v_r, zoffset: 2, args: argList{Yxm, Yxr, Yxr}},
|
||||
{zcase: Zvex_rm_v_r, zoffset: 2, args: argList{Yxm, Yyr, Yyr}},
|
||||
{zcase: Zevex_i_rm_vo, zoffset: 0, args: argList{Yu8, YxmEvex, YxrEvex}},
|
||||
{zcase: Zevex_i_rm_k_vo, zoffset: 4, args: argList{Yu8, YxmEvex, Yknot0, YxrEvex}},
|
||||
{zcase: Zevex_i_rm_vo, zoffset: 0, args: argList{Yu8, YymEvex, YyrEvex}},
|
||||
{zcase: Zevex_i_rm_k_vo, zoffset: 4, args: argList{Yu8, YymEvex, Yknot0, YyrEvex}},
|
||||
{zcase: Zevex_i_rm_vo, zoffset: 0, args: argList{Yu8, Yzm, Yzr}},
|
||||
{zcase: Zevex_i_rm_k_vo, zoffset: 4, args: argList{Yu8, Yzm, Yknot0, Yzr}},
|
||||
{zcase: Zevex_rm_v_r, zoffset: 0, args: argList{YxmEvex, YxrEvex, YxrEvex}},
|
||||
{zcase: Zevex_rm_v_k_r, zoffset: 3, args: argList{YxmEvex, YxrEvex, Yknot0, YxrEvex}},
|
||||
{zcase: Zevex_rm_v_r, zoffset: 0, args: argList{YxmEvex, YyrEvex, YyrEvex}},
|
||||
{zcase: Zevex_rm_v_k_r, zoffset: 3, args: argList{YxmEvex, YyrEvex, Yknot0, YyrEvex}},
|
||||
{zcase: Zevex_rm_v_r, zoffset: 0, args: argList{YxmEvex, Yzr, Yzr}},
|
||||
{zcase: Zevex_rm_v_k_r, zoffset: 3, args: argList{YxmEvex, Yzr, Yknot0, Yzr}},
|
||||
}
|
||||
----
|
||||
{as: AVPSLLW, ytab: _yvpslld, prefix: Pavx, op: opBytes{
|
||||
avxEscape | vex128 | vex66 | vex0F | vexW0, 0x71, 06,
|
||||
avxEscape | vex256 | vex66 | vex0F | vexW0, 0x71, 06,
|
||||
avxEscape | vex128 | vex66 | vex0F | vexW0, 0xF1,
|
||||
avxEscape | vex256 | vex66 | vex0F | vexW0, 0xF1,
|
||||
avxEscape | evex128 | evex66 | evex0F | evexW0, evexN16 | evexZeroingEnabled, 0x71, 06,
|
||||
avxEscape | evex256 | evex66 | evex0F | evexW0, evexN32 | evexZeroingEnabled, 0x71, 06,
|
||||
avxEscape | evex512 | evex66 | evex0F | evexW0, evexN64 | evexZeroingEnabled, 0x71, 06,
|
||||
avxEscape | evex128 | evex66 | evex0F | evexW0, evexN16 | evexZeroingEnabled, 0xF1,
|
||||
avxEscape | evex256 | evex66 | evex0F | evexW0, evexN16 | evexZeroingEnabled, 0xF1,
|
||||
avxEscape | evex512 | evex66 | evex0F | evexW0, evexN16 | evexZeroingEnabled, 0xF1,
|
||||
}}
|
||||
|
||||
======
|
||||
var _yvzeroall = []ytab{
|
||||
{zcase: Zvex, zoffset: 2, args: argList{}},
|
||||
}
|
||||
----
|
||||
{as: AVZEROALL, ytab: _yvzeroall, prefix: Pavx, op: opBytes{
|
||||
avxEscape | vex256 | vex0F | vexW0, 0x77,
|
||||
}}
|
||||
|
||||
======
|
||||
var _yvzeroall = []ytab{
|
||||
{zcase: Zvex, zoffset: 2, args: argList{}},
|
||||
}
|
||||
----
|
||||
{as: AVZEROUPPER, ytab: _yvzeroall, prefix: Pavx, op: opBytes{
|
||||
avxEscape | vex128 | vex0F | vexW0, 0x77,
|
||||
}}
|
||||
|
||||
======
|
||||
var _yvcomisd = []ytab{
|
||||
{zcase: Zvex_rm_v_r, zoffset: 2, args: argList{Yxm, Yxr}},
|
||||
{zcase: Zevex_rm_v_r, zoffset: 3, args: argList{YxmEvex, YxrEvex}},
|
||||
}
|
||||
----
|
||||
{as: AVUCOMISD, ytab: _yvcomisd, prefix: Pavx, op: opBytes{
|
||||
avxEscape | vex128 | vex66 | vex0F | vexW0, 0x2E,
|
||||
avxEscape | evex128 | evex66 | evex0F | evexW1, evexN8 | evexSaeEnabled, 0x2E,
|
||||
}}
|
||||
Vendored
+57893
File diff suppressed because it is too large
Load Diff
+69
@@ -0,0 +1,69 @@
|
||||
|
||||
|
||||
###FILE: ./datafiles/xed-operand-types.txt
|
||||
|
||||
#BEGIN_LEGAL
|
||||
#
|
||||
#Copyright (c) 2016 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
#END_LEGAL
|
||||
#
|
||||
#
|
||||
#XTYPE TYPE BITS-PER-ELEM
|
||||
#
|
||||
var VARIABLE 0 # instruction must set NELEM and ELEMENT_SIZE
|
||||
struct STRUCT 0 # many elements of different widths
|
||||
int INT 0 # one element, all the bits, width varies
|
||||
uint UINT 0 # one element, all the bits, width varies
|
||||
#
|
||||
i1 INT 1
|
||||
i8 INT 8
|
||||
i16 INT 16
|
||||
i32 INT 32
|
||||
i64 INT 64
|
||||
u8 UINT 8
|
||||
u16 UINT 16
|
||||
u32 UINT 32
|
||||
u64 UINT 64
|
||||
u128 UINT 128
|
||||
u256 UINT 256
|
||||
f32 SINGLE 32
|
||||
f64 DOUBLE 64
|
||||
f80 LONGDOUBLE 80
|
||||
b80 LONGBCD 80
|
||||
|
||||
|
||||
###FILE: ./datafiles/ivbavx/fp16-operand-types.txt
|
||||
|
||||
#BEGIN_LEGAL
|
||||
#
|
||||
#Copyright (c) 2016 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
#END_LEGAL
|
||||
#XTYPE TYPE BITS-PER-ELEM
|
||||
f16 FLOAT16 16
|
||||
|
||||
+341
@@ -0,0 +1,341 @@
|
||||
|
||||
|
||||
###FILE: ./datafiles/xed-state-bits.txt
|
||||
|
||||
#BEGIN_LEGAL
|
||||
#
|
||||
#Copyright (c) 2016 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
#END_LEGAL
|
||||
###########################################################################
|
||||
## file: xed-state-bits.txt
|
||||
###########################################################################
|
||||
|
||||
# These are just shorthand for some conditions or captures.
|
||||
# Simple macro replacement
|
||||
#all_modes ALL_MODES=1
|
||||
not64 MODE!=2
|
||||
mode64 MODE=2
|
||||
mode32 MODE=1
|
||||
mode16 MODE=0
|
||||
|
||||
# effective addressing mode
|
||||
eanot16 EASZ!=1
|
||||
eamode16 EASZ=1
|
||||
eamode32 EASZ=2
|
||||
eamode64 EASZ=3
|
||||
|
||||
# stack addressing mode
|
||||
smode16 SMODE=0
|
||||
smode32 SMODE=1
|
||||
smode64 SMODE=2
|
||||
|
||||
eosz8 EOSZ=0
|
||||
eosz16 EOSZ=1
|
||||
not_eosz16 EOSZ!=1
|
||||
eosz32 EOSZ=2
|
||||
eosz64 EOSZ=3
|
||||
eosznot64 EOSZ!=3
|
||||
|
||||
|
||||
# for OD expansion in graph partitioning FIXME
|
||||
mod0 MOD=0
|
||||
mod1 MOD=1
|
||||
mod2 MOD=2
|
||||
mod3 MOD=3
|
||||
|
||||
rex_reqd REX=1
|
||||
no_rex REX=0
|
||||
reset_rex REX=0 REXW=0 REXB=0 REXR=0 REXX=0
|
||||
|
||||
rexb_prefix REXB=1
|
||||
rexx_prefix REXX=1
|
||||
rexr_prefix REXR=1
|
||||
|
||||
# 2013-09-25 FIXME: we were inconsistent. some things use W0/W1, some
|
||||
# use the more verbose form. We should converge on W0/W1.
|
||||
#
|
||||
rexw_prefix REXW=1 SKIP_OSZ=1
|
||||
norexw_prefix REXW=0 SKIP_OSZ=1
|
||||
W1 REXW=1 SKIP_OSZ=1
|
||||
W0 REXW=0 SKIP_OSZ=1
|
||||
|
||||
norexb_prefix REXB=0
|
||||
norexx_prefix REXX=0
|
||||
norexr_prefix REXR=0
|
||||
############################################################3333
|
||||
f2_prefix REP=2 # REPNZ, REPNE
|
||||
f3_prefix REP=3 # REPZ, REPE
|
||||
repne REP=2
|
||||
repe REP=3
|
||||
norep REP=0
|
||||
66_prefix OSZ=1
|
||||
nof3_prefix REP!=3
|
||||
no66_prefix OSZ=0
|
||||
not_refining REP=0 # dummy setting for state values 2007-08-06 FIXME
|
||||
refining_f2 REP=2
|
||||
refining_f3 REP=3
|
||||
not_refining_f3 REP!=3 # for pause vs xchg
|
||||
no_refining_prefix REP=0 OSZ=0 # critical:REP must be first for decoding partitioning
|
||||
osz_refining_prefix REP=0 OSZ=1
|
||||
f2_refining_prefix REP=2
|
||||
f3_refining_prefix REP=3
|
||||
|
||||
no67_prefix ASZ=0
|
||||
67_prefix ASZ=1
|
||||
|
||||
lock_prefix LOCK=1
|
||||
nolock_prefix LOCK=0
|
||||
|
||||
default_ds DEFAULT_SEG=0
|
||||
default_ss DEFAULT_SEG=1
|
||||
default_es DEFAULT_SEG=2 # for string ops
|
||||
no_seg_prefix SEG_OVD=0
|
||||
some_seg_prefix SEG_OVD!=0
|
||||
cs_prefix SEG_OVD=1
|
||||
ds_prefix SEG_OVD=2
|
||||
es_prefix SEG_OVD=3
|
||||
fs_prefix SEG_OVD=4
|
||||
gs_prefix SEG_OVD=5
|
||||
ss_prefix SEG_OVD=6
|
||||
|
||||
# default (or not) to 64b width in 64b mode
|
||||
nrmw DF64=0
|
||||
df64 DF64=1
|
||||
|
||||
# default choice for encoder when there are multiple choices for a
|
||||
# nonterminal. The ISA is not uniquely determined for encoding so we
|
||||
# must express preferences for certain forms!
|
||||
enc ENCODER_PREFERRED=1
|
||||
|
||||
# for the legacy prefix encoder, tell it to keep trying rules and not
|
||||
# return after successfully finding one that applies
|
||||
no_return NO_RETURN=1
|
||||
|
||||
# indicate an encoding or decoding error occurred
|
||||
error ERROR=XED_ERROR_GENERAL_ERROR
|
||||
|
||||
# dummy constraint which always satisfies
|
||||
true DUMMY=0
|
||||
|
||||
|
||||
###FILE: ./datafiles/amdxop/xop-state-bits.txt
|
||||
|
||||
#BEGIN_LEGAL
|
||||
#
|
||||
#Copyright (c) 2016 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
#END_LEGAL
|
||||
|
||||
XMAP8 MAP=8
|
||||
XMAP9 MAP=9
|
||||
XMAPA MAP=10
|
||||
|
||||
XOPV VEXVALID=3
|
||||
|
||||
|
||||
###FILE: ./datafiles/avx/avx-state-bits.txt
|
||||
|
||||
#BEGIN_LEGAL
|
||||
#
|
||||
#Copyright (c) 2016 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
#END_LEGAL
|
||||
VL128 VL=0
|
||||
VL256 VL=1
|
||||
|
||||
VV1 VEXVALID=1
|
||||
VV0 VEXVALID=0
|
||||
|
||||
VMAP0 MAP=0
|
||||
V0F MAP=1
|
||||
V0F38 MAP=2
|
||||
V0F3A MAP=3
|
||||
|
||||
VNP VEX_PREFIX=0
|
||||
V66 VEX_PREFIX=1
|
||||
VF2 VEX_PREFIX=2
|
||||
VF3 VEX_PREFIX=3
|
||||
|
||||
# No VEX-SPECIFIED-REGISTER
|
||||
NOVSR VEXDEST3=0b1 VEXDEST210=0b111
|
||||
|
||||
EMX_BROADCAST_1TO4_32 BCAST=10 # 128
|
||||
EMX_BROADCAST_1TO4_64 BCAST=13 # 256
|
||||
EMX_BROADCAST_1TO8_32 BCAST=3 # 256
|
||||
EMX_BROADCAST_2TO4_64 BCAST=20 # 256
|
||||
|
||||
|
||||
|
||||
###FILE: ./datafiles/avxhsw/hsw-state-bits.txt
|
||||
|
||||
#BEGIN_LEGAL
|
||||
#
|
||||
#Copyright (c) 2016 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
#END_LEGAL
|
||||
|
||||
|
||||
EMX_BROADCAST_1TO2_64 BCAST=11 # 128
|
||||
EMX_BROADCAST_1TO8_16 BCAST=14 # 128
|
||||
EMX_BROADCAST_1TO16_16 BCAST=15 # 256
|
||||
EMX_BROADCAST_1TO16_8 BCAST=17 # 128
|
||||
EMX_BROADCAST_1TO32_8 BCAST=18 # 256
|
||||
|
||||
|
||||
|
||||
|
||||
###FILE: /home/quasilyte/CODE/intel/xed/datafiles/knc/uisa-state-bits.txt
|
||||
|
||||
#BEGIN_LEGAL
|
||||
#
|
||||
#Copyright (c) 2016 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
#END_LEGAL
|
||||
|
||||
VL512 VL=2
|
||||
VLBAD VL=3 # unused VL setting to cause things not to decode.
|
||||
|
||||
# KNC EVEX is KVV
|
||||
#
|
||||
KVV VEXVALID=4
|
||||
|
||||
# No VEX-SPECIFIED-REGISTER
|
||||
NOEVSR VEXDEST3=0b1 VEXDEST210=0b111 VEXDEST4=0b0
|
||||
|
||||
# No VEX-SPECIFIED-REGISTER for GATHERS/SCATTERS -- index reg 5th bit is VEXTDEST4
|
||||
NO_SPARSE_EVSR VEXDEST3=0b1 VEXDEST210=0b111
|
||||
|
||||
# These conflict w/another chip ... so if you ever build a combo
|
||||
# model you'll have to remove these somehow.
|
||||
#
|
||||
EMX_BROADCAST_1TO16_32 BCAST=1 # 512
|
||||
EMX_BROADCAST_4TO16_32 BCAST=2 # 512
|
||||
EMX_BROADCAST_1TO8_64 BCAST=5 # 512
|
||||
EMX_BROADCAST_4TO8_64 BCAST=6 # 512
|
||||
|
||||
|
||||
|
||||
###FILE: ./datafiles/avx512f/avx512-state-bits.txt
|
||||
|
||||
#BEGIN_LEGAL
|
||||
#
|
||||
#Copyright (c) 2016 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
#END_LEGAL
|
||||
EVV VEXVALID=2
|
||||
|
||||
EMX_BROADCAST_1TO16_32 BCAST=1 # 512
|
||||
EMX_BROADCAST_4TO16_32 BCAST=2 # 512
|
||||
EMX_BROADCAST_1TO8_64 BCAST=5 # 512
|
||||
EMX_BROADCAST_4TO8_64 BCAST=6 # 512
|
||||
EMX_BROADCAST_2TO16_32 BCAST=7 # 512
|
||||
EMX_BROADCAST_2TO8_64 BCAST=8 # 512
|
||||
EMX_BROADCAST_8TO16_32 BCAST=9 # 512
|
||||
EMX_BROADCAST_1TO32_16 BCAST=16 # 512
|
||||
EMX_BROADCAST_1TO64_8 BCAST=19 # 512
|
||||
# these do not show up on earlier processors
|
||||
EMX_BROADCAST_4TO8_32 BCAST=4 # 256
|
||||
EMX_BROADCAST_2TO4_32 BCAST=12 # 128
|
||||
EMX_BROADCAST_2TO8_32 BCAST=21 # 256
|
||||
EMX_BROADCAST_1TO2_32 BCAST=22 # 128
|
||||
|
||||
|
||||
###FILE: ./datafiles/avx512-skx/skx-state-bits.txt
|
||||
|
||||
#BEGIN_LEGAL
|
||||
#
|
||||
#Copyright (c) 2016 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
#END_LEGAL
|
||||
|
||||
EMX_BROADCAST_1TO2_8 BCAST=23
|
||||
EMX_BROADCAST_1TO4_8 BCAST=24
|
||||
EMX_BROADCAST_1TO8_8 BCAST=25
|
||||
|
||||
EMX_BROADCAST_1TO2_16 BCAST=26
|
||||
EMX_BROADCAST_1TO4_16 BCAST=27
|
||||
+224
@@ -0,0 +1,224 @@
|
||||
|
||||
|
||||
###FILE: ./datafiles/xed-operand-width.txt
|
||||
|
||||
#BEGIN_LEGAL
|
||||
#
|
||||
#Copyright (c) 2016 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
#END_LEGAL
|
||||
# @file xed-operand-width.txt
|
||||
|
||||
# the default xtype can be overridden in each operand using a ":" followed by an explicit xtype
|
||||
##
|
||||
## the width defaults to bytes. But it can be bits if it has a "bits" suffix
|
||||
##
|
||||
#
|
||||
# default
|
||||
#oc2-code XTYPE width16 width32 width64 (if only one width is shown, it is for all widths)
|
||||
#
|
||||
INVALID INVALID 0
|
||||
#
|
||||
# 3 strange things:
|
||||
#
|
||||
asz int 2 4 8 # varies with the effective address width
|
||||
ssz int 2 4 8 # varies with the stack address width
|
||||
pseudo struct 0 # these are for unusual registers
|
||||
pseudox87 struct 0 # these are for unusual registers
|
||||
#
|
||||
#
|
||||
#
|
||||
#1 i1 1 # FIXME: this is not used...
|
||||
a16 i16 4 # bound
|
||||
a32 i32 8 # bound
|
||||
b u8 1
|
||||
d i32 4
|
||||
#
|
||||
i8 i8 1
|
||||
u8 u8 1
|
||||
i16 i16 2
|
||||
u16 u16 2
|
||||
i32 i32 4
|
||||
u32 u32 4
|
||||
i64 i64 8
|
||||
u64 u64 8
|
||||
f16 f16 2 # IVB converts
|
||||
f32 f32 4
|
||||
f64 f64 8
|
||||
#
|
||||
dq i32 16
|
||||
#
|
||||
xub u8 16
|
||||
xuw u16 16
|
||||
xud u32 16
|
||||
xuq u64 16
|
||||
x128 u128 16
|
||||
#
|
||||
xb i8 16
|
||||
xw i16 16
|
||||
xd i32 16
|
||||
xq i64 16
|
||||
#
|
||||
#
|
||||
mb i8 8
|
||||
mw i16 8
|
||||
md i32 8
|
||||
mq i64 8
|
||||
#
|
||||
m64int i64 8
|
||||
m64real f64 8
|
||||
mem108 struct 108
|
||||
mem14 struct 14
|
||||
mem16 struct 2
|
||||
mem16int i16 2
|
||||
mem28 struct 28
|
||||
mem32int i32 4
|
||||
mem32real f32 4
|
||||
mem80dec b80 10
|
||||
mem80real f80 10
|
||||
f80 f80 10 # for X87 registers:
|
||||
mem94 struct 94
|
||||
mfpxenv struct 512
|
||||
mxsave struct 576
|
||||
mprefetch i64 64 # made up width for prefetches
|
||||
p struct 4 6 6
|
||||
p2 struct 4 6 10
|
||||
pd f64 16
|
||||
ps f32 16
|
||||
pi i32 8
|
||||
q i64 8
|
||||
s struct 6 6 10
|
||||
s64 struct 10
|
||||
sd f64 8
|
||||
si i32 4
|
||||
ss f32 4
|
||||
v int 2 4 8
|
||||
y int 4 4 8
|
||||
w i16 2
|
||||
z int 2 4 4
|
||||
spw8 int 16 32 0 # varies (64b invalid) STACK POINTER WIDTH
|
||||
spw int 2 4 8 # varies STACK POINTER WIDTH
|
||||
spw5 int 10 20 40 # varies (IRET approx) STACK POINTER WIDTH
|
||||
spw3 int 6 12 24 # varies (IRET approx) STACK POINTER WIDTH
|
||||
spw2 int 4 8 16 # varies (FAR call/ret approx) STACK POINTER WIDTH
|
||||
i1 int 1bits
|
||||
i2 int 2bits
|
||||
i3 int 3bits
|
||||
i4 int 4bits
|
||||
i5 int 5bits
|
||||
i6 int 6bits
|
||||
i7 int 7bits
|
||||
i8 int 8bits
|
||||
var var 0 # relies on NELEM * ELEMENT_SIZE to get the number of bits.
|
||||
bnd32 u32 12 # MPX 32b BNDLDX/BNDSTX memop 3x4B
|
||||
bnd64 u64 24 # MPX 32b BNDLDX/BNDSTX memop 3x8B
|
||||
|
||||
|
||||
###FILE: ./datafiles/avx/avx-operand-width.txt
|
||||
|
||||
#BEGIN_LEGAL
|
||||
#
|
||||
#Copyright (c) 2016 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
#END_LEGAL
|
||||
#
|
||||
#code XTYPE width16 width32 width64 (if only one width is presented, it is for all widths)
|
||||
#
|
||||
qq i32 32
|
||||
yub u8 32
|
||||
yuw u16 32
|
||||
yud u32 32
|
||||
yuq u64 32
|
||||
y128 u128 32
|
||||
|
||||
yb i8 32
|
||||
yw i16 32
|
||||
yd i32 32
|
||||
yq i64 32
|
||||
|
||||
yps f32 32
|
||||
ypd f64 32
|
||||
|
||||
|
||||
|
||||
|
||||
###FILE: ./datafiles/avx512f/avx512-operand-widths.txt
|
||||
|
||||
#BEGIN_LEGAL
|
||||
#
|
||||
#Copyright (c) 2016 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
#END_LEGAL
|
||||
#
|
||||
#code XTYPE width16 width32 width64 (if only one width is presented, it is for all widths)
|
||||
#
|
||||
vv var 0 # relies on nelem * elem_size
|
||||
zv var 0 # relies on nelem * elem_size
|
||||
|
||||
wrd u16 16bits
|
||||
mskw i1 64bits # FIXME: bad name
|
||||
|
||||
zmskw i1 512bits
|
||||
|
||||
zf32 f32 512bits
|
||||
zf64 f64 512bits
|
||||
|
||||
zb i8 512bits
|
||||
zw i16 512bits
|
||||
zd i32 512bits
|
||||
zq i64 512bits
|
||||
|
||||
zub u8 512bits
|
||||
zuw u16 512bits
|
||||
zud u32 512bits
|
||||
zuq u64 512bits
|
||||
|
||||
# alternative names...
|
||||
zi8 i8 512bits
|
||||
zi16 i16 512bits
|
||||
zi32 i32 512bits
|
||||
zi64 i64 512bits
|
||||
|
||||
zu8 u8 512bits
|
||||
zu16 u16 512bits
|
||||
zu32 u32 512bits
|
||||
zu64 u64 512bits
|
||||
zu128 u128 512bits
|
||||
|
||||
|
||||
Reference in New Issue
Block a user