1
0
mirror of https://github.com/google/gops.git synced 2024-11-24 08:22:25 +02:00

Vendor all dependencies.

This commit is contained in:
Jaana Burcu Dogan 2017-05-12 16:49:31 -07:00
parent 467d918128
commit 0ac75a2ac5
92 changed files with 55304 additions and 0 deletions

19
Gopkg.lock generated Normal file
View File

@ -0,0 +1,19 @@
memo = "c464a3d83956b677421b9fc797a6c77aa6e94a28120ee71d2b19860a5ff39c20"
[[projects]]
branch = "master"
name = "github.com/kardianos/osext"
packages = ["."]
revision = "ae77be60afb1dcacde03767a8c37337fad28ac14"
[[projects]]
branch = "master"
name = "github.com/keybase/go-ps"
packages = [".","darwincgo"]
revision = "668c8856d9992f97248b3177d45743d2cc1068db"
[[projects]]
branch = "master"
name = "golang.org/x/arch"
packages = ["arm/armasm","ppc64/ppc64asm","x86/x86asm"]
revision = "9dd86654181264cc7c76c929f3df20d11251e23a"

64
Gopkg.toml Normal file
View File

@ -0,0 +1,64 @@
## Gopkg.toml example (these lines may be deleted)
## "required" lists a set of packages (not projects) that must be included in
## Gopkg.lock. This list is merged with the set of packages imported by the current
## project. Use it when your project needs a package it doesn't explicitly import -
## including "main" packages.
# required = ["github.com/user/thing/cmd/thing"]
## "ignored" lists a set of packages (not projects) that are ignored when
## dep statically analyzes source code. Ignored packages can be in this project,
## or in a dependency.
# ignored = ["github.com/user/project/badpkg"]
## Dependencies define constraints on dependent projects. They are respected by
## dep whether coming from the Gopkg.toml of the current project or a dependency.
# [[dependencies]]
## Required: the root import path of the project being constrained.
# name = "github.com/user/project"
#
## Recommended: the version constraint to enforce for the project.
## Only one of "branch", "version" or "revision" can be specified.
# version = "1.0.0"
# branch = "master"
# revision = "abc123"
#
## Optional: an alternate location (URL or import path) for the project's source.
# source = "https://github.com/myfork/package.git"
## Overrides have the same structure as [[dependencies]], but supercede all
## [[dependencies]] declarations from all projects. Only the current project's
## [[overrides]] are applied.
##
## Overrides are a sledgehammer. Use them only as a last resort.
# [[overrides]]
## Required: the root import path of the project being constrained.
# name = "github.com/user/project"
#
## Optional: specifying a version constraint override will cause all other
## constraints on this project to be ignored; only the overriden constraint
## need be satisfied.
## Again, only one of "branch", "version" or "revision" can be specified.
# version = "1.0.0"
# branch = "master"
# revision = "abc123"
#
## Optional: specifying an alternate source location as an override will
## enforce that the alternate location is used for that project, regardless of
## what source location any dependent projects specify.
# source = "https://github.com/myfork/package.git"
[[dependencies]]
branch = "master"
name = "github.com/kardianos/osext"
[[dependencies]]
branch = "master"
name = "github.com/keybase/go-ps"
[[dependencies]]
branch = "master"
name = "golang.org/x/arch"

27
vendor/github.com/kardianos/osext/LICENSE generated vendored Normal file
View File

@ -0,0 +1,27 @@
Copyright (c) 2012 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

21
vendor/github.com/kardianos/osext/README.md generated vendored Normal file
View File

@ -0,0 +1,21 @@
### Extensions to the "os" package.
[![GoDoc](https://godoc.org/github.com/kardianos/osext?status.svg)](https://godoc.org/github.com/kardianos/osext)
## Find the current Executable and ExecutableFolder.
As of go1.8 the Executable function may be found in `os`. The Executable function
in the std lib `os` package is used if available.
There is sometimes utility in finding the current executable file
that is running. This can be used for upgrading the current executable
or finding resources located relative to the executable file. Both
working directory and the os.Args[0] value are arbitrary and cannot
be relied on; os.Args[0] can be "faked".
Multi-platform and supports:
* Linux
* OS X
* Windows
* Plan 9
* BSDs.

33
vendor/github.com/kardianos/osext/osext.go generated vendored Normal file
View File

@ -0,0 +1,33 @@
// Copyright 2012 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.
// Extensions to the standard "os" package.
package osext // import "github.com/kardianos/osext"
import "path/filepath"
var cx, ce = executableClean()
func executableClean() (string, error) {
p, err := executable()
return filepath.Clean(p), err
}
// Executable returns an absolute path that can be used to
// re-invoke the current program.
// It may not be valid after the current program exits.
func Executable() (string, error) {
return cx, ce
}
// Returns same path as Executable, returns just the folder
// path. Excludes the executable name and any trailing slash.
func ExecutableFolder() (string, error) {
p, err := Executable()
if err != nil {
return "", err
}
return filepath.Dir(p), nil
}

9
vendor/github.com/kardianos/osext/osext_go18.go generated vendored Normal file
View File

@ -0,0 +1,9 @@
//+build go1.8,!openbsd
package osext
import "os"
func executable() (string, error) {
return os.Executable()
}

22
vendor/github.com/kardianos/osext/osext_plan9.go generated vendored Normal file
View File

@ -0,0 +1,22 @@
// Copyright 2012 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.
//+build !go1.8
package osext
import (
"os"
"strconv"
"syscall"
)
func executable() (string, error) {
f, err := os.Open("/proc/" + strconv.Itoa(os.Getpid()) + "/text")
if err != nil {
return "", err
}
defer f.Close()
return syscall.Fd2path(int(f.Fd()))
}

36
vendor/github.com/kardianos/osext/osext_procfs.go generated vendored Normal file
View File

@ -0,0 +1,36 @@
// Copyright 2012 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.
// +build !go1.8,android !go1.8,linux !go1.8,netbsd !go1.8,solaris !go1.8,dragonfly
package osext
import (
"errors"
"fmt"
"os"
"runtime"
"strings"
)
func executable() (string, error) {
switch runtime.GOOS {
case "linux", "android":
const deletedTag = " (deleted)"
execpath, err := os.Readlink("/proc/self/exe")
if err != nil {
return execpath, err
}
execpath = strings.TrimSuffix(execpath, deletedTag)
execpath = strings.TrimPrefix(execpath, deletedTag)
return execpath, nil
case "netbsd":
return os.Readlink("/proc/curproc/exe")
case "dragonfly":
return os.Readlink("/proc/curproc/file")
case "solaris":
return os.Readlink(fmt.Sprintf("/proc/%d/path/a.out", os.Getpid()))
}
return "", errors.New("ExecPath not implemented for " + runtime.GOOS)
}

126
vendor/github.com/kardianos/osext/osext_sysctl.go generated vendored Normal file
View File

@ -0,0 +1,126 @@
// Copyright 2012 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.
// +build !go1.8,darwin !go1.8,freebsd openbsd
package osext
import (
"os"
"os/exec"
"path/filepath"
"runtime"
"syscall"
"unsafe"
)
var initCwd, initCwdErr = os.Getwd()
func executable() (string, error) {
var mib [4]int32
switch runtime.GOOS {
case "freebsd":
mib = [4]int32{1 /* CTL_KERN */, 14 /* KERN_PROC */, 12 /* KERN_PROC_PATHNAME */, -1}
case "darwin":
mib = [4]int32{1 /* CTL_KERN */, 38 /* KERN_PROCARGS */, int32(os.Getpid()), -1}
case "openbsd":
mib = [4]int32{1 /* CTL_KERN */, 55 /* KERN_PROC_ARGS */, int32(os.Getpid()), 1 /* KERN_PROC_ARGV */}
}
n := uintptr(0)
// Get length.
_, _, errNum := syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 4, 0, uintptr(unsafe.Pointer(&n)), 0, 0)
if errNum != 0 {
return "", errNum
}
if n == 0 { // This shouldn't happen.
return "", nil
}
buf := make([]byte, n)
_, _, errNum = syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 4, uintptr(unsafe.Pointer(&buf[0])), uintptr(unsafe.Pointer(&n)), 0, 0)
if errNum != 0 {
return "", errNum
}
if n == 0 { // This shouldn't happen.
return "", nil
}
var execPath string
switch runtime.GOOS {
case "openbsd":
// buf now contains **argv, with pointers to each of the C-style
// NULL terminated arguments.
var args []string
argv := uintptr(unsafe.Pointer(&buf[0]))
Loop:
for {
argp := *(**[1 << 20]byte)(unsafe.Pointer(argv))
if argp == nil {
break
}
for i := 0; uintptr(i) < n; i++ {
// we don't want the full arguments list
if string(argp[i]) == " " {
break Loop
}
if argp[i] != 0 {
continue
}
args = append(args, string(argp[:i]))
n -= uintptr(i)
break
}
if n < unsafe.Sizeof(argv) {
break
}
argv += unsafe.Sizeof(argv)
n -= unsafe.Sizeof(argv)
}
execPath = args[0]
// There is no canonical way to get an executable path on
// OpenBSD, so check PATH in case we are called directly
if execPath[0] != '/' && execPath[0] != '.' {
execIsInPath, err := exec.LookPath(execPath)
if err == nil {
execPath = execIsInPath
}
}
default:
for i, v := range buf {
if v == 0 {
buf = buf[:i]
break
}
}
execPath = string(buf)
}
var err error
// execPath will not be empty due to above checks.
// Try to get the absolute path if the execPath is not rooted.
if execPath[0] != '/' {
execPath, err = getAbs(execPath)
if err != nil {
return execPath, err
}
}
// For darwin KERN_PROCARGS may return the path to a symlink rather than the
// actual executable.
if runtime.GOOS == "darwin" {
if execPath, err = filepath.EvalSymlinks(execPath); err != nil {
return execPath, err
}
}
return execPath, nil
}
func getAbs(execPath string) (string, error) {
if initCwdErr != nil {
return execPath, initCwdErr
}
// The execPath may begin with a "../" or a "./" so clean it first.
// Join the two paths, trailing and starting slashes undetermined, so use
// the generic Join function.
return filepath.Join(initCwd, filepath.Clean(execPath)), nil
}

203
vendor/github.com/kardianos/osext/osext_test.go generated vendored Normal file
View File

@ -0,0 +1,203 @@
// Copyright 2012 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.
// +build darwin linux freebsd netbsd windows openbsd
package osext
import (
"bytes"
"fmt"
"io"
"os"
"os/exec"
"path/filepath"
"runtime"
"testing"
)
const (
executableEnvVar = "OSTEST_OUTPUT_EXECUTABLE"
executableEnvValueMatch = "match"
executableEnvValueDelete = "delete"
)
func TestPrintExecutable(t *testing.T) {
ef, err := Executable()
if err != nil {
t.Fatalf("Executable failed: %v", err)
}
t.Log("Executable:", ef)
}
func TestPrintExecutableFolder(t *testing.T) {
ef, err := ExecutableFolder()
if err != nil {
t.Fatalf("ExecutableFolder failed: %v", err)
}
t.Log("Executable Folder:", ef)
}
func TestExecutableFolder(t *testing.T) {
ef, err := ExecutableFolder()
if err != nil {
t.Fatalf("ExecutableFolder failed: %v", err)
}
if ef[len(ef)-1] == filepath.Separator {
t.Fatal("ExecutableFolder ends with a trailing slash.")
}
}
func TestExecutableMatch(t *testing.T) {
ep, err := Executable()
if err != nil {
t.Fatalf("Executable failed: %v", err)
}
// fullpath to be of the form "dir/prog".
dir := filepath.Dir(filepath.Dir(ep))
fullpath, err := filepath.Rel(dir, ep)
if err != nil {
t.Fatalf("filepath.Rel: %v", err)
}
// Make child start with a relative program path.
// Alter argv[0] for child to verify getting real path without argv[0].
cmd := &exec.Cmd{
Dir: dir,
Path: fullpath,
Env: []string{fmt.Sprintf("%s=%s", executableEnvVar, executableEnvValueMatch)},
}
out, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("exec(self) failed: %v", err)
}
outs := string(out)
if !filepath.IsAbs(outs) {
t.Fatalf("Child returned %q, want an absolute path", out)
}
if !sameFile(outs, ep) {
t.Fatalf("Child returned %q, not the same file as %q", out, ep)
}
}
func TestExecutableDelete(t *testing.T) {
if runtime.GOOS != "linux" {
t.Skip()
}
fpath, err := Executable()
if err != nil {
t.Fatalf("Executable failed: %v", err)
}
r, w := io.Pipe()
stderrBuff := &bytes.Buffer{}
stdoutBuff := &bytes.Buffer{}
cmd := &exec.Cmd{
Path: fpath,
Env: []string{fmt.Sprintf("%s=%s", executableEnvVar, executableEnvValueDelete)},
Stdin: r,
Stderr: stderrBuff,
Stdout: stdoutBuff,
}
err = cmd.Start()
if err != nil {
t.Fatalf("exec(self) start failed: %v", err)
}
tempPath := fpath + "_copy"
_ = os.Remove(tempPath)
err = copyFile(tempPath, fpath)
if err != nil {
t.Fatalf("copy file failed: %v", err)
}
err = os.Remove(fpath)
if err != nil {
t.Fatalf("remove running test file failed: %v", err)
}
err = os.Rename(tempPath, fpath)
if err != nil {
t.Fatalf("rename copy to previous name failed: %v", err)
}
w.Write([]byte{0})
w.Close()
err = cmd.Wait()
if err != nil {
t.Fatalf("exec wait failed: %v", err)
}
childPath := stderrBuff.String()
if !filepath.IsAbs(childPath) {
t.Fatalf("Child returned %q, want an absolute path", childPath)
}
if !sameFile(childPath, fpath) {
t.Fatalf("Child returned %q, not the same file as %q", childPath, fpath)
}
}
func sameFile(fn1, fn2 string) bool {
fi1, err := os.Stat(fn1)
if err != nil {
return false
}
fi2, err := os.Stat(fn2)
if err != nil {
return false
}
return os.SameFile(fi1, fi2)
}
func copyFile(dest, src string) error {
df, err := os.Create(dest)
if err != nil {
return err
}
defer df.Close()
sf, err := os.Open(src)
if err != nil {
return err
}
defer sf.Close()
_, err = io.Copy(df, sf)
return err
}
func TestMain(m *testing.M) {
env := os.Getenv(executableEnvVar)
switch env {
case "":
os.Exit(m.Run())
case executableEnvValueMatch:
// First chdir to another path.
dir := "/"
if runtime.GOOS == "windows" {
dir = filepath.VolumeName(".")
}
os.Chdir(dir)
if ep, err := Executable(); err != nil {
fmt.Fprint(os.Stderr, "ERROR: ", err)
} else {
fmt.Fprint(os.Stderr, ep)
}
case executableEnvValueDelete:
bb := make([]byte, 1)
var err error
n, err := os.Stdin.Read(bb)
if err != nil {
fmt.Fprint(os.Stderr, "ERROR: ", err)
os.Exit(2)
}
if n != 1 {
fmt.Fprint(os.Stderr, "ERROR: n != 1, n == ", n)
os.Exit(2)
}
if ep, err := Executable(); err != nil {
fmt.Fprint(os.Stderr, "ERROR: ", err)
} else {
fmt.Fprint(os.Stderr, ep)
}
}
os.Exit(0)
}

36
vendor/github.com/kardianos/osext/osext_windows.go generated vendored Normal file
View File

@ -0,0 +1,36 @@
// Copyright 2012 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.
//+build !go1.8
package osext
import (
"syscall"
"unicode/utf16"
"unsafe"
)
var (
kernel = syscall.MustLoadDLL("kernel32.dll")
getModuleFileNameProc = kernel.MustFindProc("GetModuleFileNameW")
)
// GetModuleFileName() with hModule = NULL
func executable() (exePath string, err error) {
return getModuleFileName()
}
func getModuleFileName() (string, error) {
var n uint32
b := make([]uint16, syscall.MAX_PATH)
size := uint32(len(b))
r0, _, e1 := getModuleFileNameProc.Call(0, uintptr(unsafe.Pointer(&b[0])), uintptr(size))
n = uint32(r0)
if n == 0 {
return "", e1
}
return string(utf16.Decode(b[0:n])), nil
}

1
vendor/github.com/keybase/go-ps/.gitignore generated vendored Normal file
View File

@ -0,0 +1 @@
.vagrant/

View File

@ -0,0 +1,10 @@
- repo: https://github.com/gabriel/pre-commit-golang
sha: c02a81d85a5295886022b8106c367518e6c3760e
hooks:
- id: go-fmt
- id: go-metalinter
args:
- --deadline=60s
- --vendor
- --cyclo-over=20
- --dupl-threshold=100

11
vendor/github.com/keybase/go-ps/.travis.yml generated vendored Normal file
View File

@ -0,0 +1,11 @@
language: go
go:
- tip
os:
- linux
- osx
before_install:
- go get github.com/mattn/goveralls
- go get golang.org/x/tools/cmd/cover
script:
- $HOME/gopath/bin/goveralls -service=travis-ci

44
vendor/github.com/keybase/go-ps/LICENSE.md generated vendored Normal file
View File

@ -0,0 +1,44 @@
The MIT License (MIT)
Copyright (c) 2014 Mitchell Hashimoto
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
The MIT License (MIT)
Copyright (c) 2015 Keybase
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

31
vendor/github.com/keybase/go-ps/README.md generated vendored Normal file
View File

@ -0,0 +1,31 @@
# Process List Library for Go
[![Build Status](https://travis-ci.org/keybase/go-ps.svg?branch=master)](https://travis-ci.org/keybase/go-ps)
[![Build Status](https://ci.appveyor.com/api/projects/status/github/keybase/go-ps?branch=master&svg=true)](https://ci.appveyor.com/project/keybase/go-ps)
[![Coverage Status](https://coveralls.io/repos/github/keybase/go-ps/badge.svg?branch=master)](https://coveralls.io/github/keybase/go-ps?branch=master)
[![GoDoc](https://godoc.org/github.com/keybase/go-ps?status.svg)](https://godoc.org/github.com/keybase/go-ps)
go-ps is a library for Go that implements OS-specific APIs to list and
manipulate processes in a platform-safe way. The library can find and
list processes on Linux, Mac OS X, and Windows.
If you're new to Go, this library has a good amount of advanced Go educational
value as well. It uses some advanced features of Go: build tags, accessing
DLL methods for Windows, cgo for Darwin, etc.
How it works:
* **Darwin** uses `sysctl` and `proc_listpids` (for the path) to retrieve the process table, via cgo.
* **Unix** uses the procfs at `/proc` to inspect the process tree.
* **Windows** uses the Windows API, and methods such as
`CreateToolhelp32Snapshot` to get a point-in-time snapshot of
the process table.
## Installation
Install using standard `go get`:
```
$ go get github.com/keybase/go-ps
```

31
vendor/github.com/keybase/go-ps/appveyor.yml generated vendored Normal file
View File

@ -0,0 +1,31 @@
# environment variables
environment:
global:
GOPATH: c:\work\
# clone path
clone_folder: c:\work\src\github.com\keybase\go-ps
# build platform, i.e. x86, x64, Any CPU. This setting is optional.
#platform: Any CPU
# scripts to run before build
before_build:
# scripts to run after build
after_build:
# to run your custom scripts instead of automatic MSBuild
build_script:
- go version
- go build
- go get github.com/stretchr/testify/assert
- go get github.com/stretchr/testify/require
- go test -short -v
- go test -short -race -v
# to disable automatic tests
test: off
# to disable deployment
deploy: off

1
vendor/github.com/keybase/go-ps/darwincgo/empty.go generated vendored Normal file
View File

@ -0,0 +1 @@
package darwincgo

View File

@ -0,0 +1,87 @@
// +build darwin
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <strings.h>
#include <libproc.h>
#include <unistd.h>
#include <sys/sysctl.h>
// This is declared in process_darwin.go
extern void goDarwinAppendProc(pid_t, pid_t, char *);
extern void goDarwinSetPath(pid_t, char *);
// darwinProcesses loads the process table and calls the exported Go function to
// insert the data back into the Go space.
//
// This function is implemented in C because while it would technically
// be possible to do this all in Go, I didn't want to go spelunking through
// header files to get all the structures properly. It is much easier to just
// call it in C and be done with it.
int darwinProcesses() {
int err = 0;
int i = 0;
static const int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0 };
size_t length = 0;
struct kinfo_proc *result = NULL;
size_t resultCount = 0;
// Get the length first
err = sysctl((int*)name, (sizeof(name) / sizeof(*name)) - 1,
NULL, &length, NULL, 0);
if (err != 0) {
goto ERREXIT;
}
// Allocate the appropriate sized buffer to read the process list
result = malloc(length);
// Call sysctl again with our buffer to fill it with the process list
err = sysctl((int*)name, (sizeof(name) / sizeof(*name)) - 1,
result, &length,
NULL, 0);
if (err != 0) {
goto ERREXIT;
}
resultCount = length / sizeof(struct kinfo_proc);
for (i = 0; i < resultCount; i++) {
struct kinfo_proc *single = &result[i];
goDarwinAppendProc(
single->kp_proc.p_pid,
single->kp_eproc.e_ppid,
single->kp_proc.p_comm);
}
ERREXIT:
if (result != NULL) {
free(result);
}
if (err != 0) {
return errno;
}
return 0;
}
// darwinProcessPaths looks up paths for process pids
void darwinProcessPaths() {
int pid_buf_size = proc_listpids(PROC_ALL_PIDS, 0, NULL, 0);
int pid_count = pid_buf_size / sizeof(pid_t);
pid_t* pids = malloc(pid_buf_size);
bzero(pids, pid_buf_size);
proc_listpids(PROC_ALL_PIDS, 0, pids, pid_buf_size);
char path_buffer[PROC_PIDPATHINFO_MAXSIZE];
for (int i=0; i < pid_count; i++) {
if (pids[i] == 0) break;
bzero(path_buffer, PROC_PIDPATHINFO_MAXSIZE);
if (proc_pidpath(pids[i], path_buffer, sizeof(path_buffer)) > 0) {
goDarwinSetPath(pids[i], path_buffer);
}
}
free(pids);
}

View File

@ -0,0 +1,84 @@
// +build darwin
package darwincgo
/*
#include <stdio.h>
#include <errno.h>
#include <libproc.h>
extern int darwinProcesses();
extern void darwinProcessPaths();
*/
import "C"
import (
"path/filepath"
"sync"
)
// This lock is what verifies that C calling back into Go is only
// modifying data once at a time.
var darwinLock sync.Mutex
var darwinProcsByPID map[int]*DarwinProcess
// DarwinProcess is process definition for OS X
type DarwinProcess struct {
pid int
ppid int
path string
}
// Pid returns process id
func (p *DarwinProcess) Pid() int {
return p.pid
}
// PPid returns parent process id
func (p *DarwinProcess) PPid() int {
return p.ppid
}
// Executable returns process executable name
func (p *DarwinProcess) Executable() string {
path, _ := p.Path()
return filepath.Base(path)
}
// Path returns path to process executable
func (p *DarwinProcess) Path() (string, error) {
return p.path, nil
}
//export goDarwinAppendProc
func goDarwinAppendProc(pid C.pid_t, ppid C.pid_t, comm *C.char) {
proc := &DarwinProcess{
pid: int(pid),
ppid: int(ppid),
}
darwinProcsByPID[proc.pid] = proc
}
//export goDarwinSetPath
func goDarwinSetPath(pid C.pid_t, comm *C.char) {
if proc, ok := darwinProcsByPID[int(pid)]; ok && proc != nil {
proc.path = C.GoString(comm)
}
}
// ProcessMap returns a map of processes for the main library package.
func ProcessMap() (map[int]*DarwinProcess, error) {
darwinLock.Lock()
defer darwinLock.Unlock()
darwinProcsByPID = make(map[int]*DarwinProcess)
// To ignore deadcode warnings for exported functions
_ = goDarwinAppendProc
_ = goDarwinSetPath
// TODO: Investigate why darwinProcesses returns error even if process list
// succeeds
C.darwinProcesses()
C.darwinProcessPaths()
return darwinProcsByPID, nil
}

75
vendor/github.com/keybase/go-ps/process.go generated vendored Normal file
View File

@ -0,0 +1,75 @@
// Package ps provides an API for finding and listing processes in a
// platform-agnostic way.
//
// NOTE: If you're reading these docs online via GoDocs or some other system,
// you might only see the Unix docs. This project makes heavy use of
// platform-specific implementations. We recommend reading the source if you
// are interested.
package ps
import "fmt"
// Process is the generic interface that is implemented on every platform
// and provides common operations for processes.
type Process interface {
// Pid is the process ID for this process.
Pid() int
// PPid is the parent process ID for this process.
PPid() int
// Executable name running this process. This is not a path to the
// executable.
Executable() string
// Path is full path to the executable. The path may be unavailable if the
// exectuable was deleted from the system while it was still running.
Path() (string, error)
}
type processesFn func() ([]Process, error)
// Processes returns all processes.
//
// This of course will be a point-in-time snapshot of when this method was
// called. Some operating systems don't provide snapshot capability of the
// process table, in which case the process table returned might contain
// ephemeral entities that happened to be running when this was called.
func Processes() ([]Process, error) {
return processes()
}
// FindProcess looks up a single process by pid.
// This may require a full process listing depending on the platform, so
// consider using os.FindProcess instead.
// Process will be nil and error will be nil if a matching process is not found.
func FindProcess(pid int) (Process, error) {
return findProcess(pid)
}
type matchFn func(Process) bool
// findProcessesWithFn finds processes using match function.
// If max is != 0, then we will return that max number of processes.
func findProcessesWithFn(processesFn processesFn, matchFn matchFn, max int) ([]Process, error) {
processes, err := processesFn()
if err != nil {
return nil, fmt.Errorf("Error listing processes: %s", err)
}
if processes == nil {
return nil, nil
}
procs := []Process{}
for _, p := range processes {
if matchFn(p) {
procs = append(procs, p)
}
if max != 0 && len(procs) >= max {
break
}
}
return procs, nil
}
// Avoid linting error
var _ = findProcessesWithFn

31
vendor/github.com/keybase/go-ps/process_darwin.go generated vendored Normal file
View File

@ -0,0 +1,31 @@
// +build darwin
package ps
import (
"github.com/keybase/go-ps/darwincgo"
)
func findProcess(pid int) (Process, error) {
m, err := darwincgo.ProcessMap()
if err != nil {
return nil, err
}
p := m[pid]
if p == nil {
return nil, nil
}
return p, nil
}
func processes() ([]Process, error) {
m, err := darwincgo.ProcessMap()
if err != nil {
return nil, err
}
ps := make([]Process, 0, len(m))
for _, dp := range m {
ps = append(ps, dp)
}
return ps, nil
}

38
vendor/github.com/keybase/go-ps/process_darwin_test.go generated vendored Normal file
View File

@ -0,0 +1,38 @@
// +build darwin
package ps
import (
"os"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestFindProcessDarwin(t *testing.T) {
proc := testFindProcess(t, "go-ps.test")
assert.True(t, proc.PPid() > 0)
}
func TestProcessesDarwin(t *testing.T) {
testProcesses(t, "go")
}
func TestProcessesDarwinError(t *testing.T) {
proc, err := findProcess(-1)
assert.Nil(t, proc)
assert.Nil(t, err)
}
func TestProcessExecRemoved(t *testing.T) {
procPath, cmd, proc := testExecRun(t)
defer cleanup(cmd, procPath)
t.Logf("Ran with PID: %d", cmd.Process.Pid)
// Remove it while it is running
_ = os.Remove(procPath)
matchPath := func(p Process) bool { return p.Pid() == proc.Pid() }
procs, err := findProcessesWithFn(processes, matchPath, 1)
require.NoError(t, err)
t.Logf("Proc: %#v", procs[0])
}

269
vendor/github.com/keybase/go-ps/process_freebsd.go generated vendored Normal file
View File

@ -0,0 +1,269 @@
// +build freebsd,amd64
package ps
import (
"bytes"
"encoding/binary"
"fmt"
"syscall"
"unsafe"
)
// copied from sys/sysctl.h
const (
CTL_KERN = 1 // "high kernel": proc, limits
KERN_PROC = 14 // struct: process entries
KERN_PROC_PID = 1 // by process id
KERN_PROC_PROC = 8 // only return procs
KERN_PROC_PATHNAME = 12 // path to executable
)
// copied from sys/user.h
type Kinfo_proc struct {
Ki_structsize int32
Ki_layout int32
Ki_args int64
Ki_paddr int64
Ki_addr int64
Ki_tracep int64
Ki_textvp int64
Ki_fd int64
Ki_vmspace int64
Ki_wchan int64
Ki_pid int32
Ki_ppid int32
Ki_pgid int32
Ki_tpgid int32
Ki_sid int32
Ki_tsid int32
Ki_jobc [2]byte
Ki_spare_short1 [2]byte
Ki_tdev int32
Ki_siglist [16]byte
Ki_sigmask [16]byte
Ki_sigignore [16]byte
Ki_sigcatch [16]byte
Ki_uid int32
Ki_ruid int32
Ki_svuid int32
Ki_rgid int32
Ki_svgid int32
Ki_ngroups [2]byte
Ki_spare_short2 [2]byte
Ki_groups [64]byte
Ki_size int64
Ki_rssize int64
Ki_swrss int64
Ki_tsize int64
Ki_dsize int64
Ki_ssize int64
Ki_xstat [2]byte
Ki_acflag [2]byte
Ki_pctcpu int32
Ki_estcpu int32
Ki_slptime int32
Ki_swtime int32
Ki_cow int32
Ki_runtime int64
Ki_start [16]byte
Ki_childtime [16]byte
Ki_flag int64
Ki_kiflag int64
Ki_traceflag int32
Ki_stat [1]byte
Ki_nice [1]byte
Ki_lock [1]byte
Ki_rqindex [1]byte
Ki_oncpu [1]byte
Ki_lastcpu [1]byte
Ki_ocomm [17]byte
Ki_wmesg [9]byte
Ki_login [18]byte
Ki_lockname [9]byte
Ki_comm [20]byte
Ki_emul [17]byte
Ki_sparestrings [68]byte
Ki_spareints [36]byte
Ki_cr_flags int32
Ki_jid int32
Ki_numthreads int32
Ki_tid int32
Ki_pri int32
Ki_rusage [144]byte
Ki_rusage_ch [144]byte
Ki_pcb int64
Ki_kstack int64
Ki_udata int64
Ki_tdaddr int64
Ki_spareptrs [48]byte
Ki_spareint64s [96]byte
Ki_sflag int64
Ki_tdflags int64
}
// UnixProcess is an implementation of Process that contains Unix-specific
// fields and information.
type UnixProcess struct {
pid int
ppid int
state rune
pgrp int
sid int
binary string
}
// Pid returns process id
func (p *UnixProcess) Pid() int {
return p.pid
}
// PPid returns parent process id
func (p *UnixProcess) PPid() int {
return p.ppid
}
// Executable returns process executable name
func (p *UnixProcess) Executable() string {
return p.binary
}
// Path returns path to process executable
func (p *UnixProcess) Path() (string, error) {
return "", fmt.Errorf("Unsupported")
}
// Refresh reloads all the data associated with this process.
func (p *UnixProcess) Refresh() error {
mib := []int32{CTL_KERN, KERN_PROC, KERN_PROC_PID, int32(p.pid)}
buf, length, err := call_syscall(mib)
if err != nil {
return err
}
proc_k := Kinfo_proc{}
if length != uint64(unsafe.Sizeof(proc_k)) {
return err
}
k, err := parse_kinfo_proc(buf)
if err != nil {
return err
}
p.ppid, p.pgrp, p.sid, p.binary = copy_params(&k)
return nil
}
func copy_params(k *Kinfo_proc) (int, int, int, string) {
n := -1
for i, b := range k.Ki_comm {
if b == 0 {
break
}
n = i + 1
}
comm := string(k.Ki_comm[:n])
return int(k.Ki_ppid), int(k.Ki_pgid), int(k.Ki_sid), comm
}
func findProcess(pid int) (Process, error) {
mib := []int32{CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, int32(pid)}
_, _, err := call_syscall(mib)
if err != nil {
return nil, err
}
return newUnixProcess(pid)
}
func processes() ([]Process, error) {
results := make([]Process, 0, 50)
mib := []int32{CTL_KERN, KERN_PROC, KERN_PROC_PROC, 0}
buf, length, err := call_syscall(mib)
if err != nil {
return results, err
}
// get kinfo_proc size
k := Kinfo_proc{}
procinfo_len := int(unsafe.Sizeof(k))
count := int(length / uint64(procinfo_len))
// parse buf to procs
for i := 0; i < count; i++ {
b := buf[i*procinfo_len : i*procinfo_len+procinfo_len]
k, err := parse_kinfo_proc(b)
if err != nil {
continue
}
p, err := newUnixProcess(int(k.Ki_pid))
if err != nil {
continue
}
p.ppid, p.pgrp, p.sid, p.binary = copy_params(&k)
results = append(results, p)
}
return results, nil
}
func parse_kinfo_proc(buf []byte) (Kinfo_proc, error) {
var k Kinfo_proc
br := bytes.NewReader(buf)
err := binary.Read(br, binary.LittleEndian, &k)
if err != nil {
return k, err
}
return k, nil
}
func call_syscall(mib []int32) ([]byte, uint64, error) {
miblen := uint64(len(mib))
// get required buffer size
length := uint64(0)
_, _, err := syscall.RawSyscall6(
syscall.SYS___SYSCTL,
uintptr(unsafe.Pointer(&mib[0])),
uintptr(miblen),
0,
uintptr(unsafe.Pointer(&length)),
0,
0)
if err != 0 {
b := make([]byte, 0)
return b, length, err
}
if length == 0 {
b := make([]byte, 0)
return b, length, err
}
// get proc info itself
buf := make([]byte, length)
_, _, err = syscall.RawSyscall6(
syscall.SYS___SYSCTL,
uintptr(unsafe.Pointer(&mib[0])),
uintptr(miblen),
uintptr(unsafe.Pointer(&buf[0])),
uintptr(unsafe.Pointer(&length)),
0,
0)
if err != 0 {
return buf, length, err
}
return buf, length, nil
}
func newUnixProcess(pid int) (*UnixProcess, error) {
p := &UnixProcess{pid: pid}
return p, p.Refresh()
}

93
vendor/github.com/keybase/go-ps/process_nix_test.go generated vendored Normal file
View File

@ -0,0 +1,93 @@
// +build darwin linux
package ps
import (
"io"
"os"
"os/exec"
"path/filepath"
"testing"
"github.com/stretchr/testify/require"
)
func TestProcessExecRun(t *testing.T) {
procPath, cmd, _ := testExecRun(t)
defer cleanup(cmd, procPath)
}
func testProcessPath(t *testing.T, procPath string) Process {
matchPath := func(p Process) bool {
return matchPath(t, p, procPath)
}
procs, err := findProcessesWithFn(processes, matchPath, 1)
require.NoError(t, err)
require.Equal(t, 1, len(procs))
proc := procs[0]
path, err := proc.Path()
require.NoError(t, err)
require.Equal(t, procPath, path)
return proc
}
func cleanup(cmd *exec.Cmd, procPath string) {
if cmd != nil && cmd.Process != nil {
_ = cmd.Process.Kill()
}
_ = os.Remove(procPath)
}
func testExecPath(t *testing.T) string {
// Copy sleep executable to tmp
procPath := filepath.Join(os.TempDir(), "sleeptest")
err := copyFile("/bin/sleep", procPath, 0777)
require.NoError(t, err)
// Temp dir might have symlinks in which case we need the eval'ed path
procPath, err = filepath.EvalSymlinks(procPath)
require.NoError(t, err)
return procPath
}
func testExecRun(t *testing.T) (string, *exec.Cmd, Process) {
procPath := testExecPath(t)
cmd := exec.Command(procPath, "10")
err := cmd.Start()
require.NoError(t, err)
proc := testProcessPath(t, procPath)
return procPath, cmd, proc
}
func copyFile(sourcePath string, destinationPath string, mode os.FileMode) error {
in, err := os.Open(sourcePath)
if err != nil {
return err
}
defer func() { _ = in.Close() }()
out, err := os.Create(destinationPath)
if err != nil {
return err
}
defer func() { _ = out.Close() }()
_, err = io.Copy(out, in)
closeErr := out.Close()
if err != nil {
return err
}
err = os.Chmod(destinationPath, mode)
if err != nil {
return err
}
return closeErr
}
func matchPath(t *testing.T, p Process, match string) bool {
path, err := p.Path()
if err != nil {
t.Logf("Error trying to get path: %s", err)
return false
}
return path == match
}

302
vendor/github.com/keybase/go-ps/process_openbsd.go generated vendored Normal file
View File

@ -0,0 +1,302 @@
// +build openbsd
package ps
import (
"bytes"
"encoding/binary"
"fmt"
"syscall"
"unsafe"
)
// copied from sys/sysctl.h
const (
CTL_KERN = 1
KERN_PROC = 66
KERN_PROC_PID = 1
KERN_PROC_ARGS = 55
KERN_PROC_ARGV = 1
KERN_PROC_ALL = 0
)
/* Generated via cgo:
$ cat /tmp/gen_defs.go
// +build ignore
package ps
// #include <sys/types.h>
// #include <sys/sysctl.h>
import "C"
type Kinfo_proc C.struct_kinfo_proc
$ go tool cgo -godefs temp.go
*/
type Kinfo_proc struct {
Ki_forw uint64
Ki_back uint64
Ki_paddr uint64
Ki_addr uint64
Ki_fd uint64
Ki_stats uint64
Ki_limit uint64
Ki_vmspace uint64
Ki_sigacts uint64
Ki_sess uint64
Ki_tsess uint64
Ki_ru uint64
Ki_eflag int32
Ki_exitsig int32
Ki_flag int32
Ki_pid int32
Ki_ppid int32
Ki_sid int32
Ki_x_pgid int32
Ki_tpgid int32
Ki_uid uint32
Ki_ruid uint32
Ki_gid uint32
Ki_rgid uint32
Ki_groups [16]uint32
Ki_ngroups int16
Ki_jobc int16
Ki_tdev uint32
Ki_estcpu uint32
Ki_rtime_sec uint32
Ki_rtime_usec uint32
Ki_cpticks int32
Ki_pctcpu uint32
Ki_swtime uint32
Ki_slptime uint32
Ki_schedflags int32
Ki_uticks uint64
Ki_sticks uint64
Ki_iticks uint64
Ki_tracep uint64
Ki_traceflag int32
Ki_holdcnt int32
Ki_siglist int32
Ki_sigmask uint32
Ki_sigignore uint32
Ki_sigcatch uint32
Ki_stat int8
Ki_priority uint8
Ki_usrpri uint8
Ki_nice uint8
Ki_xstat uint16
Ki_acflag uint16
//Ki_comm [24]int8
Ki_comm [20]byte
Ki_wmesg [8]int8
Ki_wchan uint64
Ki_login [32]int8
Ki_vm_rssize int32
Ki_vm_tsize int32
Ki_vm_dsize int32
Ki_vm_ssize int32
Ki_uvalid int64
Ki_ustart_sec uint64
Ki_ustart_usec uint32
Ki_uutime_sec uint32
Ki_uutime_usec uint32
Ki_ustime_sec uint32
Ki_ustime_usec uint32
Ki_pad_cgo_0 [4]byte
Ki_uru_maxrss uint64
Ki_uru_ixrss uint64
Ki_uru_idrss uint64
Ki_uru_isrss uint64
Ki_uru_minflt uint64
Ki_uru_majflt uint64
Ki_uru_nswap uint64
Ki_uru_inblock uint64
Ki_uru_oublock uint64
Ki_uru_msgsnd uint64
Ki_uru_msgrcv uint64
Ki_uru_nsignals uint64
Ki_uru_nvcsw uint64
Ki_uru_nivcsw uint64
Ki_uctime_sec uint32
Ki_uctime_usec uint32
Ki_psflags int32
Ki_spare int32
Ki_svuid uint32
Ki_svgid uint32
Ki_emul [8]int8
Ki_rlim_rss_cur uint64
Ki_cpuid uint64
Ki_vm_map_size uint64
Ki_tid int32
Ki_rtableid uint32
}
var proc_k_size = unsafe.Sizeof(Kinfo_proc{})
// UnixProcess is an implementation of Process that contains Unix-specific
// fields and information.
type UnixProcess struct {
pid int
ppid int
state rune
pgrp int
sid int
binary string
}
// Pid returns process id
func (p *UnixProcess) Pid() int {
return p.pid
}
// PPid returns parent process id
func (p *UnixProcess) PPid() int {
return p.ppid
}
// Executable returns process executable name
func (p *UnixProcess) Executable() string {
return p.binary
}
// Path returns path to process executable
func (p *UnixProcess) Path() (string, error) {
// On OpenBSD we don't have the actual path of a binary, the next
// best thing we can do is walk $PATH to hopefully find the binary.
// More info here: https://github.com/kardianos/osext/commit/b4814f465fb1f92d46e37f7ef84d732ece7c3e3a
return "", fmt.Errorf("Unsupported")
}
// Refresh reloads all the data associated with this process.
func (p *UnixProcess) Refresh() error {
mib := []int32{CTL_KERN, KERN_PROC, KERN_PROC_PID, int32(p.pid), int32(proc_k_size), 1}
buf, length, err := call_syscall(mib)
if err != nil {
return err
}
if length != uint64(proc_k_size) {
return err
}
k, err := parse_kinfo_proc(buf)
if err != nil {
return err
}
p.ppid, p.pgrp, p.sid, p.binary = copy_params(&k)
return nil
}
func copy_params(k *Kinfo_proc) (int, int, int, string) {
n := -1
for i, b := range k.Ki_comm {
if b == 0 {
break
}
n = i + 1
}
comm := string(k.Ki_comm[:n])
return int(k.Ki_ppid), int(k.Ki_x_pgid), int(k.Ki_sid), comm
}
func findProcess(pid int) (Process, error) {
mib := []int32{CTL_KERN, KERN_PROC, KERN_PROC_PID, int32(pid), int32(proc_k_size), 1}
_, _, err := call_syscall(mib)
if err != nil {
return nil, err
}
return newUnixProcess(pid)
}
func processes() ([]Process, error) {
results := make([]Process, 0, 50)
mib := []int32{CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0, int32(proc_k_size), 400}
buf, length, err := call_syscall(mib)
if err != nil {
return results, err
}
// get kinfo_proc size
procinfo_len := int(proc_k_size)
count := int(length / uint64(proc_k_size))
// parse buf to procs
for i := 0; i < count; i++ {
b := buf[i*procinfo_len : i*procinfo_len+procinfo_len]
k, err := parse_kinfo_proc(b)
if err != nil {
continue
}
p, err := newUnixProcess(int(k.Ki_pid))
if err != nil {
continue
}
p.ppid, p.pgrp, p.sid, p.binary = copy_params(&k)
results = append(results, p)
}
return results, nil
}
func parse_kinfo_proc(buf []byte) (Kinfo_proc, error) {
var k Kinfo_proc
br := bytes.NewReader(buf)
err := binary.Read(br, binary.LittleEndian, &k)
if err != nil {
return k, err
}
return k, nil
}
func call_syscall(mib []int32) ([]byte, uint64, error) {
miblen := uint64(len(mib))
// get required buffer size
length := uint64(0)
_, _, err := syscall.RawSyscall6(
syscall.SYS___SYSCTL,
uintptr(unsafe.Pointer(&mib[0])),
uintptr(miblen),
0,
uintptr(unsafe.Pointer(&length)),
0,
0)
if err != 0 {
b := make([]byte, 0)
return b, length, err
}
if length == 0 {
b := make([]byte, 0)
return b, length, err
}
// get proc info itself
buf := make([]byte, length)
_, _, err = syscall.RawSyscall6(
syscall.SYS___SYSCTL,
uintptr(unsafe.Pointer(&mib[0])),
uintptr(miblen),
uintptr(unsafe.Pointer(&buf[0])),
uintptr(unsafe.Pointer(&length)),
0,
0)
if err != 0 {
return buf, length, err
}
return buf, length, nil
}
func newUnixProcess(pid int) (*UnixProcess, error) {
p := &UnixProcess{pid: pid}
return p, p.Refresh()
}

View File

@ -0,0 +1,28 @@
// +build openbsd
package ps
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestFindProcessOpenBSD(t *testing.T) {
proc := testFindProcess(t, "go-ps.test")
assert.True(t, proc.PPid() > 0)
}
func TestProcessesOpenBSD(t *testing.T) {
testProcesses(t, "go")
}
/*
// Currently querying for -1 will return -1 :P
func TestProcessesOpenBSDError(t *testing.T) {
proc, err := findProcess(-1)
assert.Nil(t, proc)
assert.Nil(t, err)
}
*/

72
vendor/github.com/keybase/go-ps/process_test.go generated vendored Normal file
View File

@ -0,0 +1,72 @@
package ps
import (
"errors"
"os"
"runtime"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func testFindProcess(t *testing.T, name string) Process {
proc, err := FindProcess(os.Getpid())
require.NoError(t, err)
require.NotNil(t, proc)
assert.Equal(t, os.Getpid(), proc.Pid())
if name != "" {
assert.Equal(t, name, proc.Executable())
path, err := proc.Path()
require.NoError(t, err)
t.Logf("Path: %s", path)
assert.True(t, strings.HasSuffix(path, string(os.PathSeparator)+name))
}
return proc
}
func testProcesses(t *testing.T, name string) {
// This test works because there will always be SOME processes running
procs, err := Processes()
require.NoError(t, err)
require.True(t, len(procs) > 0)
if name != "" {
found := false
for _, p := range procs {
if p.Executable() == name {
found = true
break
}
}
assert.True(t, found)
}
}
func TestFindProcess(t *testing.T) {
testFindProcess(t, "")
}
func TestFindProcessGo(t *testing.T) {
var exe = "go-ps.test"
if runtime.GOOS == "windows" {
exe += ".exe"
}
testFindProcess(t, exe)
}
func TestProcesses(t *testing.T) {
testProcesses(t, "")
}
func TestFindProcessesWithFnError(t *testing.T) {
ps, err := findProcessesWithFn(func() ([]Process, error) { return nil, errors.New("TestFindProcessesWithFn Error") }, nil, 0)
require.Nil(t, ps)
require.NotNil(t, err)
ps, err = findProcessesWithFn(func() ([]Process, error) { return nil, nil }, nil, 0)
require.Nil(t, ps)
require.Nil(t, err)
}

144
vendor/github.com/keybase/go-ps/process_unix.go generated vendored Normal file
View File

@ -0,0 +1,144 @@
// +build linux
package ps
import (
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"strconv"
"strings"
)
// UnixProcess is an implementation of Process that contains Unix-specific
// fields and information.
type UnixProcess struct {
pid int
ppid int
state rune
pgrp int
sid int
binary string // binary name might be truncated
}
// Pid returns process id
func (p *UnixProcess) Pid() int {
return p.pid
}
// PPid returns parent process id
func (p *UnixProcess) PPid() int {
return p.ppid
}
// Executable returns process executable name
func (p *UnixProcess) Executable() string {
path, err := p.Path()
if err != nil {
// Fall back to binary name which might be truncated
return p.binary
}
return filepath.Base(path)
}
// Path returns path to process executable
func (p *UnixProcess) Path() (string, error) {
return filepath.EvalSymlinks(fmt.Sprintf("/proc/%d/exe", p.pid))
}
// Refresh reloads all the data associated with this process.
func (p *UnixProcess) Refresh() error {
statPath := fmt.Sprintf("/proc/%d/stat", p.pid)
dataBytes, err := ioutil.ReadFile(statPath)
if err != nil {
return err
}
// First, parse out the image name
data := string(dataBytes)
binStart := strings.IndexRune(data, '(') + 1
binEnd := strings.IndexRune(data[binStart:], ')')
p.binary = data[binStart : binStart+binEnd]
// Move past the image name and start parsing the rest
// The name here might not be the full name
data = data[binStart+binEnd+2:]
_, err = fmt.Sscanf(data,
"%c %d %d %d",
&p.state,
&p.ppid,
&p.pgrp,
&p.sid)
return err
}
func findProcess(pid int) (Process, error) {
dir := fmt.Sprintf("/proc/%d", pid)
_, err := os.Stat(dir)
if err != nil {
if os.IsNotExist(err) {
return nil, nil
}
return nil, err
}
return newUnixProcess(pid)
}
func processes() ([]Process, error) {
d, err := os.Open("/proc")
if err != nil {
return nil, err
}
defer d.Close()
results := make([]Process, 0, 50)
for {
fis, err := d.Readdir(10)
if err == io.EOF {
break
}
if err != nil {
return nil, err
}
for _, fi := range fis {
// We only care about directories, since all pids are dirs
if !fi.IsDir() {
continue
}
// We only care if the name starts with a numeric
name := fi.Name()
if name[0] < '0' || name[0] > '9' {
continue
}
// From this point forward, any errors we just ignore, because
// it might simply be that the process doesn't exist anymore.
pid, err := strconv.ParseInt(name, 10, 0)
if err != nil {
continue
}
p, err := newUnixProcess(int(pid))
if err != nil {
continue
}
results = append(results, p)
}
}
return results, nil
}
func newUnixProcess(pid int) (*UnixProcess, error) {
p := &UnixProcess{pid: pid}
return p, p.Refresh()
}

29
vendor/github.com/keybase/go-ps/process_unix_test.go generated vendored Normal file
View File

@ -0,0 +1,29 @@
// +build linux
package ps
import (
"os"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestUnixProcess(t *testing.T) {
var _ Process = new(UnixProcess)
}
func TestProcessesUnixError(t *testing.T) {
proc, err := findProcess(-1)
assert.Nil(t, proc)
assert.Nil(t, err)
}
func TestProcessesUnixPPid(t *testing.T) {
proc, err := FindProcess(os.Getpid())
require.NoError(t, err)
require.NotNil(t, proc)
assert.Equal(t, os.Getpid(), proc.Pid())
assert.Equal(t, os.Getppid(), proc.PPid())
}

196
vendor/github.com/keybase/go-ps/process_windows.go generated vendored Normal file
View File

@ -0,0 +1,196 @@
// +build windows
package ps
import (
"fmt"
"syscall"
"unsafe"
)
// Windows API functions
var (
modKernel32 = syscall.NewLazyDLL("kernel32.dll")
procCloseHandle = modKernel32.NewProc("CloseHandle")
procCreateToolhelp32Snapshot = modKernel32.NewProc("CreateToolhelp32Snapshot")
procProcess32First = modKernel32.NewProc("Process32FirstW")
procProcess32Next = modKernel32.NewProc("Process32NextW")
procModule32First = modKernel32.NewProc("Module32FirstW")
procModule32Next = modKernel32.NewProc("Module32NextW")
)
// Some constants from the Windows API
const (
ERROR_NO_MORE_FILES = 0x12
MAX_PATH = 260
MAX_MODULE_NAME32 = 255
)
type PROCESSENTRY32 struct {
Size uint32
CntUsage uint32
ProcessID uint32
DefaultHeapID uintptr
ModuleID uint32
CntThreads uint32
ParentProcessID uint32
PriorityClassBase int32
Flags uint32
ExeFile [MAX_PATH]uint16
}
// WindowsProcess is an implementation of Process for Windows.
type WindowsProcess struct {
pid int
ppid int
exe string
}
// Pid returns process id
func (p *WindowsProcess) Pid() int {
return p.pid
}
// PPid returns parent process id
func (p *WindowsProcess) PPid() int {
return p.ppid
}
// Executable returns process executable name
func (p *WindowsProcess) Executable() string {
return p.exe
}
// Path returns path to process executable
func (p *WindowsProcess) Path() (string, error) {
processModules, err := modules(p.pid)
if err != nil {
return "", err
}
if len(processModules) == 0 {
return "", fmt.Errorf("No modules found for process")
}
return processModules[0].path, nil
}
func ptrToString(c []uint16) string {
i := 0
for {
if c[i] == 0 {
return syscall.UTF16ToString(c[:i])
}
i++
}
}
func newWindowsProcess(e *PROCESSENTRY32) *WindowsProcess {
return &WindowsProcess{
pid: int(e.ProcessID),
ppid: int(e.ParentProcessID),
exe: ptrToString(e.ExeFile[:]),
}
}
func findProcess(pid int) (Process, error) {
return findProcessWithFn(processes, pid)
}
func findProcessWithFn(processesFn processesFn, pid int) (Process, error) {
ps, err := processesFn()
if err != nil {
return nil, fmt.Errorf("Error listing processes: %s", err)
}
for _, p := range ps {
if p.Pid() == pid {
return p, nil
}
}
return nil, nil
}
func processes() ([]Process, error) {
handle, _, _ := procCreateToolhelp32Snapshot.Call(
0x00000002,
0)
if handle < 0 {
return nil, syscall.GetLastError()
}
defer procCloseHandle.Call(handle)
var entry PROCESSENTRY32
entry.Size = uint32(unsafe.Sizeof(entry))
ret, _, _ := procProcess32First.Call(handle, uintptr(unsafe.Pointer(&entry)))
if ret == 0 {
return nil, fmt.Errorf("Error retrieving process info.")
}
results := make([]Process, 0, 50)
for {
results = append(results, newWindowsProcess(&entry))
ret, _, _ := procProcess32Next.Call(handle, uintptr(unsafe.Pointer(&entry)))
if ret == 0 {
break
}
}
return results, nil
}
// MODULEENTRY32 is the Windows API structure that contains a modules's
// information.
type MODULEENTRY32 struct {
Size uint32
ModuleID uint32
ProcessID uint32
GlblcntUsage uint32
ProccntUsage uint32
ModBaseAddr *uint8
ModBaseSize uint32
HModule uintptr
SzModule [MAX_MODULE_NAME32 + 1]uint16
SzExePath [MAX_PATH]uint16
}
type windowsModule struct {
name string
path string
}
func newWindowsModule(e *MODULEENTRY32) windowsModule {
return windowsModule{
name: ptrToString(e.SzModule[:]),
path: ptrToString(e.SzExePath[:]),
}
}
func modules(pid int) ([]windowsModule, error) {
handle, _, _ := procCreateToolhelp32Snapshot.Call(
0x00000008, // TH32CS_SNAPMODULE
uintptr(uint32(pid)))
if handle < 0 {
return nil, syscall.GetLastError()
}
defer procCloseHandle.Call(handle)
var entry MODULEENTRY32
entry.Size = uint32(unsafe.Sizeof(entry))
ret, _, _ := procModule32First.Call(handle, uintptr(unsafe.Pointer(&entry)))
if ret == 0 {
return nil, fmt.Errorf("Error retrieving module info")
}
results := make([]windowsModule, 0, 50)
for {
results = append(results, newWindowsModule(&entry))
ret, _, _ := procModule32Next.Call(handle, uintptr(unsafe.Pointer(&entry)))
if ret == 0 {
break
}
}
return results, nil
}

View File

@ -0,0 +1,29 @@
// +build windows
package ps
import (
"fmt"
"os"
"testing"
"github.com/stretchr/testify/assert"
)
func TestFindProcessWindows(t *testing.T) {
proc := testFindProcess(t, "go-ps.test.exe")
assert.True(t, proc.PPid() > 0)
}
func TestProcessesWindows(t *testing.T) {
testProcesses(t, "go.exe")
}
func TestProcessesWindowsError(t *testing.T) {
errFn := func() ([]Process, error) {
return nil, fmt.Errorf("oops")
}
proc, err := findProcessWithFn(errFn, os.Getpid())
assert.Nil(t, proc)
assert.EqualError(t, err, "Error listing processes: oops")
}

3
vendor/golang.org/x/arch/AUTHORS generated vendored Normal file
View File

@ -0,0 +1,3 @@
# This source code refers to The Go Authors for copyright purposes.
# The master list of authors is in the main Go distribution,
# visible at https://tip.golang.org/AUTHORS.

31
vendor/golang.org/x/arch/CONTRIBUTING.md generated vendored Normal file
View File

@ -0,0 +1,31 @@
# Contributing to Go
Go is an open source project.
It is the work of hundreds of contributors. We appreciate your help!
## Filing issues
When [filing an issue](https://golang.org/issue/new), make sure to answer these five questions:
1. What version of Go are you using (`go version`)?
2. What operating system and processor architecture are you using?
3. What did you do?
4. What did you expect to see?
5. What did you see instead?
General questions should go to the [golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead of the issue tracker.
The gophers there will answer or ask you to file an issue if you've tripped over a bug.
## Contributing code
Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html)
before sending patches.
**We do not accept GitHub pull requests**
(we use [Gerrit](https://code.google.com/p/gerrit/) instead for code review).
Unless otherwise noted, the Go source files are distributed under
the BSD-style license found in the LICENSE file.

3
vendor/golang.org/x/arch/CONTRIBUTORS generated vendored Normal file
View File

@ -0,0 +1,3 @@
# This source code was written by the Go contributors.
# The master list of contributors is in the main Go distribution,
# visible at https://tip.golang.org/CONTRIBUTORS.

27
vendor/golang.org/x/arch/LICENSE generated vendored Normal file
View File

@ -0,0 +1,27 @@
Copyright (c) 2015 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

22
vendor/golang.org/x/arch/PATENTS generated vendored Normal file
View File

@ -0,0 +1,22 @@
Additional IP Rights Grant (Patents)
"This implementation" means the copyrightable works distributed by
Google as part of the Go project.
Google hereby grants to You a perpetual, worldwide, non-exclusive,
no-charge, royalty-free, irrevocable (except as stated in this section)
patent license to make, have made, use, offer to sell, sell, import,
transfer and otherwise run, modify and propagate the contents of this
implementation of Go, where such license applies only to those patent
claims, both currently owned or controlled by Google and acquired in
the future, licensable by Google that are necessarily infringed by this
implementation of Go. This grant does not include claims that would be
infringed only as a consequence of further modification of this
implementation. If you or your agent or exclusive licensee institute or
order or agree to the institution of patent litigation against any
entity (including a cross-claim or counterclaim in a lawsuit) alleging
that this implementation of Go or any code incorporated within this
implementation of Go constitutes direct or contributory patent
infringement, or inducement of patent infringement, then any patent
rights granted to you under this License for this implementation of Go
shall terminate as of the date such litigation is filed.

7
vendor/golang.org/x/arch/README generated vendored Normal file
View File

@ -0,0 +1,7 @@
This repository holds machine architecture information used by the Go toolchain.
The parts needed in the main Go repository are copied in.
This repository requires Go 1.6, or Go 1.5 with the vendor experiment enabled:
export GO15VENDOREXPERIMENT=1

454
vendor/golang.org/x/arch/arm/arm.csv generated vendored Normal file
View File

@ -0,0 +1,454 @@
# arm instruction description version 0.01.
# https://golang.org/x/arch/arm
#
# This file contains a block of comment lines, each beginning with #,
# followed by entries in CSV format. All the # comments are at the top
# of the file, so a reader can skip past the comments and hand the
# rest of the file to a standard CSV reader.
#
# Each line in the CSV section contains 5 fields:
#
# mask value mnemonic encoding tags
#
# The mnemonic and encoding correspond to the notation used in the
# ARM Architecture Reference Manual.
#
# A particular instruction word w matches a line if w&mask == value.
# The mask and value are computed from a combination of the encodings
# and the additional pseudocode restrictions given in the manual
# for each instruction.
#
# Multiple lines may match a particular instruction word.
# The tags specify which line takes priority in these cases,
# as a partial order. Eventually the plan is that a tag of the form
# 'name:x' marks a line with the name x, and a tag of the form
# 'except:x' says that the line on which the tag appears is of lower
# priority than the ones marked with name x.
# For now, however, a tag of the form 'SEE XXX' is taken from the
# manual and is like 'except:x' but without a rigorous resolution for
# the x. So far we've been able to just sort instructions into two classes:
# those with SEE and those without.
#
# The tag 'pseudo' indicates that this instruction is an alternate name
# for another encoding and should be ignored during disassembly.
#
# This file was generated by a program reading the PDF version of
# the manual, but it was then hand edited to make corrections.
# The eventual plan is for the generator to write the
# file directly, using the PDF and a list of modifications, but
# no hand editing. Then, when a new version of the manual comes out,
# updating the list should be as easy as downloading the new PDF
# and invoking the generator. However, we are not there yet.
#
"0x0fe00000","0x02a00000","ADC{S}<c> <Rd>,<Rn>,#<const>","cond:4|0|0|1|0|1|0|1|S|Rn:4|Rd:4|imm12:12","SEE SUBS PC, LR and related instructions"
"0x0fe00090","0x00a00010","ADC{S}<c> <Rd>,<Rn>,<Rm>,<type> <Rs>","cond:4|0|0|0|0|1|0|1|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4",""
"0x0fe00010","0x00a00000","ADC{S}<c> <Rd>,<Rn>,<Rm>{,<shift>}","cond:4|0|0|0|0|1|0|1|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4","SEE SUBS PC, LR and related instructions"
"0x0fe00000","0x02800000","ADD{S}<c> <Rd>,<Rn>,#<const>","cond:4|0|0|1|0|1|0|0|S|Rn:4|Rd:4|imm12:12","SEE ADR SEE ADD (SP plus immediate) SEE SUBS PC, LR and related instructions"
"0x0fe00090","0x00800010","ADD{S}<c> <Rd>,<Rn>,<Rm>,<type> <Rs>","cond:4|0|0|0|0|1|0|0|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4",""
"0x0fe00010","0x00800000","ADD{S}<c> <Rd>,<Rn>,<Rm>{,<shift>}","cond:4|0|0|0|0|1|0|0|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4","SEE SUBS PC, LR and related instructions SEE ADD (SP plus register)"
"0x0fef0000","0x028d0000","ADD{S}<c> <Rd>,SP,#<const>","cond:4|0|0|1|0|1|0|0|S|1|1|0|1|Rd:4|imm12:12","SEE SUBS PC, LR and related instructions"
"0x0fef0010","0x008d0000","ADD{S}<c> <Rd>,SP,<Rm>{,<shift>}","cond:4|0|0|0|0|1|0|0|S|1|1|0|1|Rd:4|imm5:5|type:2|0|Rm:4","SEE SUBS PC, LR and related instructions"
"0x0fff0000","0x028f0000","ADR<c> <Rd>,<label+12>","cond:4|0|0|1|0|1|0|0|0|1|1|1|1|Rd:4|imm12:12","pseudo"
"0x0fff0000","0x024f0000","ADR<c> <Rd>,<label-12>","cond:4|0|0|1|0|0|1|0|0|1|1|1|1|Rd:4|imm12:12","pseudo"
"0x0fe00000","0x02000000","AND{S}<c> <Rd>,<Rn>,#<const>","cond:4|0|0|1|0|0|0|0|S|Rn:4|Rd:4|imm12:12","SEE SUBS PC, LR and related instructions"
"0x0fe00090","0x00000010","AND{S}<c> <Rd>,<Rn>,<Rm>,<type> <Rs>","cond:4|0|0|0|0|0|0|0|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4",""
"0x0fe00010","0x00000000","AND{S}<c> <Rd>,<Rn>,<Rm>{,<shift>}","cond:4|0|0|0|0|0|0|0|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4","SEE SUBS PC, LR and related instructions"
"0x0fef0070","0x01a00040","ASR{S}<c> <Rd>,<Rm>,#<imm5_32>","cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|imm5:5|1|0|0|Rm:4",""
"0x0fef00f0","0x01a00050","ASR{S}<c> <Rd>,<Rn>,<Rm>","cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|Rm:4|0|1|0|1|Rn:4",""
"0x0f000000","0x0a000000","B<c> <label24>","cond:4|1|0|1|0|imm24:24",""
"0x0fe0007f","0x07c0001f","BFC<c> <Rd>,#<lsb>,#<width>","cond:4|0|1|1|1|1|1|0|msb:5|Rd:4|lsb:5|0|0|1|1|1|1|1",""
"0x0fe00070","0x07c00010","BFI<c> <Rd>,<Rn>,#<lsb>,#<width>","cond:4|0|1|1|1|1|1|0|msb:5|Rd:4|lsb:5|0|0|1|Rn:4","SEE BFC"
"0x0fe00000","0x03c00000","BIC{S}<c> <Rd>,<Rn>,#<const>","cond:4|0|0|1|1|1|1|0|S|Rn:4|Rd:4|imm12:12","SEE SUBS PC, LR and related instructions"
"0x0fe00090","0x01c00010","BIC{S}<c> <Rd>,<Rn>,<Rm>,<type> <Rs>","cond:4|0|0|0|1|1|1|0|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4",""
"0x0fe00010","0x01c00000","BIC{S}<c> <Rd>,<Rn>,<Rm>{,<shift>}","cond:4|0|0|0|1|1|1|0|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4","SEE SUBS PC, LR and related instructions"
"0x0ff000f0","0x01200070","BKPT<c> #<imm12+4>","cond:4|0|0|0|1|0|0|1|0|imm12:12|0|1|1|1|imm4:4",""
"0x0f000000","0x0b000000","BL<c> <label24>","cond:4|1|0|1|1|imm24:24",""
"0xfe000000","0xfa000000","BLX <label24H>","1|1|1|1|1|0|1|H|imm24:24",""
"0x0ffffff0","0x012fff30","BLX<c> <Rm>","cond:4|0|0|0|1|0|0|1|0|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4",""
"0x0ffffff0","0x012fff10","BX<c> <Rm>","cond:4|0|0|0|1|0|0|1|0|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4",""
"0x0ffffff0","0x012fff20","BXJ<c> <Rm>","cond:4|0|0|0|1|0|0|1|0|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|0|0|1|0|Rm:4",""
"0xffffffff","0xf57ff01f","CLREX","1|1|1|1|0|1|0|1|0|1|1|1|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|0|0|1|(1)|(1)|(1)|(1)",""
"0x0fff0ff0","0x016f0f10","CLZ<c> <Rd>,<Rm>","cond:4|0|0|0|1|0|1|1|0|(1)|(1)|(1)|(1)|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4",""
"0x0ff0f000","0x03700000","CMN<c> <Rn>,#<const>","cond:4|0|0|1|1|0|1|1|1|Rn:4|(0)|(0)|(0)|(0)|imm12:12",""
"0x0ff0f090","0x01700010","CMN<c> <Rn>,<Rm>,<type> <Rs>","cond:4|0|0|0|1|0|1|1|1|Rn:4|(0)|(0)|(0)|(0)|Rs:4|0|type:2|1|Rm:4",""
"0x0ff0f010","0x01700000","CMN<c> <Rn>,<Rm>{,<shift>}","cond:4|0|0|0|1|0|1|1|1|Rn:4|(0)|(0)|(0)|(0)|imm5:5|type:2|0|Rm:4",""
"0x0ff0f000","0x03500000","CMP<c> <Rn>,#<const>","cond:4|0|0|1|1|0|1|0|1|Rn:4|(0)|(0)|(0)|(0)|imm12:12",""
"0x0ff0f090","0x01500010","CMP<c> <Rn>,<Rm>,<type> <Rs>","cond:4|0|0|0|1|0|1|0|1|Rn:4|(0)|(0)|(0)|(0)|Rs:4|0|type:2|1|Rm:4",""
"0x0ff0f010","0x01500000","CMP<c> <Rn>,<Rm>{,<shift>}","cond:4|0|0|0|1|0|1|0|1|Rn:4|(0)|(0)|(0)|(0)|imm5:5|type:2|0|Rm:4",""
"0x0ffffff0","0x0320f0f0","DBG<c> #<option>","cond:4|0|0|1|1|0|0|1|0|0|0|0|0|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|1|1|1|1|option:4",""
"0xfffffff0","0xf57ff050","DMB #<option>","1|1|1|1|0|1|0|1|0|1|1|1|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|1|0|1|option:4",""
"0xfffffff0","0xf57ff040","DSB #<option>","1|1|1|1|0|1|0|1|0|1|1|1|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|1|0|0|option:4",""
"0x0fe00000","0x02200000","EOR{S}<c> <Rd>,<Rn>,#<const>","cond:4|0|0|1|0|0|0|1|S|Rn:4|Rd:4|imm12:12","SEE SUBS PC, LR and related instructions"
"0x0fe00090","0x00200010","EOR{S}<c> <Rd>,<Rn>,<Rm>,<type> <Rs>","cond:4|0|0|0|0|0|0|1|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4",""
"0x0fe00010","0x00200000","EOR{S}<c> <Rd>,<Rn>,<Rm>{,<shift>}","cond:4|0|0|0|0|0|0|1|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4","SEE SUBS PC, LR and related instructions"
"0xfffffff0","0xf57ff060","ISB #<option>","1|1|1|1|0|1|0|1|0|1|1|1|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|1|1|0|option:4",""
"0x0fd00000","0x08900000","LDM<c> <Rn>{!},<registers>","cond:4|1|0|0|0|1|0|W|1|Rn:4|register_list:16","SEE POP"
"0x0fd00000","0x08100000","LDMDA<c> <Rn>{!},<registers>","cond:4|1|0|0|0|0|0|W|1|Rn:4|register_list:16",""
"0x0fd00000","0x09100000","LDMDB<c> <Rn>{!},<registers>","cond:4|1|0|0|1|0|0|W|1|Rn:4|register_list:16",""
"0x0fd00000","0x09900000","LDMIB<c> <Rn>{!},<registers>","cond:4|1|0|0|1|1|0|W|1|Rn:4|register_list:16",""
"0x0f7f0000","0x051f0000","LDR<c> <Rt>,<label+/-12>","cond:4|0|1|0|(1)|U|0|(0)|1|1|1|1|1|Rt:4|imm12:12",""
"0x0e500010","0x06100000","LDR<c> <Rt>,[<Rn>,+/-<Rm>{, <shift>}]{!}","cond:4|0|1|1|P|U|0|W|1|Rn:4|Rt:4|imm5:5|type:2|0|Rm:4","SEE LDRT"
"0x0e500000","0x04100000","LDR<c> <Rt>,[<Rn>{,#+/-<imm12>}]{!}","cond:4|0|1|0|P|U|0|W|1|Rn:4|Rt:4|imm12:12","SEE LDR (literal) SEE LDRT SEE POP"
"0x0f7f0000","0x055f0000","LDRB<c> <Rt>,<label+/-12>","cond:4|0|1|0|(1)|U|1|(0)|1|1|1|1|1|Rt:4|imm12:12",""
"0x0e500010","0x06500000","LDRB<c> <Rt>,[<Rn>,+/-<Rm>{, <shift>}]{!}","cond:4|0|1|1|P|U|1|W|1|Rn:4|Rt:4|imm5:5|type:2|0|Rm:4","SEE LDRBT"
"0x0e500000","0x04500000","LDRB<c> <Rt>,[<Rn>{,#+/-<imm12>}]{!}","cond:4|0|1|0|P|U|1|W|1|Rn:4|Rt:4|imm12:12","SEE LDRB (literal) SEE LDRBT"
"0x0f700000","0x04700000","LDRBT<c> <Rt>,[<Rn>],#+/-<imm12>","cond:4|0|1|0|0|U|1|1|1|Rn:4|Rt:4|imm12:12",""
"0x0f700010","0x06700000","LDRBT<c> <Rt>,[<Rn>],+/-<Rm>{, <shift>}","cond:4|0|1|1|0|U|1|1|1|Rn:4|Rt:4|imm5:5|type:2|0|Rm:4",""
"0x0f7f10f0","0x014f00d0","LDRD<c> <Rt1>,<Rt2>,<label+/-4+4>","cond:4|0|0|0|(1)|U|1|(0)|0|1|1|1|1|Rt:4|imm4H:4|1|1|0|1|imm4L:4","pseudo"
"0x0e500ff0","0x000000d0","LDRD<c> <Rt1>,<Rt2>,[<Rn>,+/-<Rm>]{!}","cond:4|0|0|0|P|U|0|W|0|Rn:4|Rt:4|(0)|(0)|(0)|(0)|1|1|0|1|Rm:4",""
"0x0e5000f0","0x004000d0","LDRD<c> <Rt1>,<Rt2>,[<Rn>{,#+/-<imm8>}]{!}","cond:4|0|0|0|P|U|1|W|0|Rn:4|Rt:4|imm4H:4|1|1|0|1|imm4L:4","SEE LDRD (literal)"
"0x0ff00fff","0x01900f9f","LDREX<c> <Rt>,[<Rn>]","cond:4|0|0|0|1|1|0|0|1|Rn:4|Rt:4|(1)|(1)|(1)|(1)|1|0|0|1|(1)|(1)|(1)|(1)",""
"0x0ff00fff","0x01d00f9f","LDREXB<c> <Rt>, [<Rn>]","cond:4|0|0|0|1|1|1|0|1|Rn:4|Rt:4|(1)|(1)|(1)|(1)|1|0|0|1|(1)|(1)|(1)|(1)",""
"0x0ff00fff","0x01b00f9f","LDREXD<c> <Rt1>,<Rt2>,[<Rn>]","cond:4|0|0|0|1|1|0|1|1|Rn:4|Rt:4|(1)|(1)|(1)|(1)|1|0|0|1|(1)|(1)|(1)|(1)",""
"0x0ff00fff","0x01f00f9f","LDREXH<c> <Rt>, [<Rn>]","cond:4|0|0|0|1|1|1|1|1|Rn:4|Rt:4|(1)|(1)|(1)|(1)|1|0|0|1|(1)|(1)|(1)|(1)",""
"0x0f7f00f0","0x015f00b0","LDRH<c> <Rt>,<label+/-4+4>","cond:4|0|0|0|1|U|1|0|1|1|1|1|1|Rt:4|imm4H:4|1|0|1|1|imm4L:4","pseudo"
"0x0e500ff0","0x001000b0","LDRH<c> <Rt>,[<Rn>,+/-<Rm>]{!}","cond:4|0|0|0|P|U|0|W|1|Rn:4|Rt:4|0|0|0|0|1|0|1|1|Rm:4","SEE LDRHT"
"0x0e5000f0","0x005000b0","LDRH<c> <Rt>,[<Rn>{,#+/-<imm8>}]{!}","cond:4|0|0|0|P|U|1|W|1|Rn:4|Rt:4|imm4H:4|1|0|1|1|imm4L:4","SEE LDRH literal SEE LDRHT"
"0x0f7000f0","0x007000b0","LDRHT<c> <Rt>, [<Rn>] {,#+/-<imm8>}","cond:4|0|0|0|0|U|1|1|1|Rn:4|Rt:4|imm4H:4|1|0|1|1|imm4L:4",""
"0x0f700ff0","0x003000b0","LDRHT<c> <Rt>, [<Rn>], +/-<Rm>","cond:4|0|0|0|0|U|0|1|1|Rn:4|Rt:4|0|0|0|0|1|0|1|1|Rm:4",""
"0x0f7f00f0","0x015f00d0","LDRSB<c> <Rt>,<label+/-4+4>","cond:4|0|0|0|1|U|1|0|1|1|1|1|1|Rt:4|imm4H:4|1|1|0|1|imm4L:4","pseudo"
"0x0e500ff0","0x001000d0","LDRSB<c> <Rt>,[<Rn>,+/-<Rm>]{!}","cond:4|0|0|0|P|U|0|W|1|Rn:4|Rt:4|0|0|0|0|1|1|0|1|Rm:4","SEE LDRSBT"
"0x0e5000f0","0x005000d0","LDRSB<c> <Rt>,[<Rn>{,#+/-<imm8>}]{!}","cond:4|0|0|0|P|U|1|W|1|Rn:4|Rt:4|imm4H:4|1|1|0|1|imm4L:4","SEE LDRSB literal SEE LDRSBT"
"0x0f7000f0","0x007000d0","LDRSBT<c> <Rt>, [<Rn>] {,#+/-<imm8>}","cond:4|0|0|0|0|U|1|1|1|Rn:4|Rt:4|imm4H:4|1|1|0|1|imm4L:4",""
"0x0f700ff0","0x003000d0","LDRSBT<c> <Rt>, [<Rn>], +/-<Rm>","cond:4|0|0|0|0|U|0|1|1|Rn:4|Rt:4|0|0|0|0|1|1|0|1|Rm:4",""
"0x0f7f00f0","0x015f00f0","LDRSH<c> <Rt>,<label+/-4+4>","cond:4|0|0|0|1|U|1|0|1|1|1|1|1|Rt:4|imm4H:4|1|1|1|1|imm4L:4","pseudo"
"0x0e500ff0","0x001000f0","LDRSH<c> <Rt>,[<Rn>,+/-<Rm>]{!}","cond:4|0|0|0|P|U|0|W|1|Rn:4|Rt:4|0|0|0|0|1|1|1|1|Rm:4","SEE LDRSHT"
"0x0e5000f0","0x005000f0","LDRSH<c> <Rt>,[<Rn>{,#+/-<imm8>}]{!}","cond:4|0|0|0|P|U|1|W|1|Rn:4|Rt:4|imm4H:4|1|1|1|1|imm4L:4","SEE LDRSH literal SEE LDRSHT"
"0x0f7000f0","0x007000f0","LDRSHT<c> <Rt>, [<Rn>] {,#+/-<imm8>}","cond:4|0|0|0|0|U|1|1|1|Rn:4|Rt:4|imm4H:4|1|1|1|1|imm4L:4",""
"0x0f700ff0","0x003000f0","LDRSHT<c> <Rt>, [<Rn>], +/-<Rm>","cond:4|0|0|0|0|U|0|1|1|Rn:4|Rt:4|0|0|0|0|1|1|1|1|Rm:4",""
"0x0f700000","0x04300000","LDRT<c> <Rt>, [<Rn>] {,#+/-<imm12>}","cond:4|0|1|0|0|U|0|1|1|Rn:4|Rt:4|imm12:12",""
"0x0f700010","0x06300000","LDRT<c> <Rt>,[<Rn>],+/-<Rm>{, <shift>}","cond:4|0|1|1|0|U|0|1|1|Rn:4|Rt:4|imm5:5|type:2|0|Rm:4",""
"0x0fef0070","0x01a00000","LSL{S}<c> <Rd>,<Rm>,#<imm5_nz>","cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|imm5:5|0|0|0|Rm:4","SEE MOV register"
"0x0fef00f0","0x01a00010","LSL{S}<c> <Rd>,<Rn>,<Rm>","cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|Rm:4|0|0|0|1|Rn:4",""
"0x0fef0070","0x01a00020","LSR{S}<c> <Rd>,<Rm>,#<imm5_32>","cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|imm5:5|0|1|0|Rm:4",""
"0x0fef00f0","0x01a00030","LSR{S}<c> <Rd>,<Rn>,<Rm>","cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|Rm:4|0|0|1|1|Rn:4",""
"0x0fe000f0","0x00200090","MLA{S}<c> <Rd>,<Rn>,<Rm>,<Ra>","cond:4|0|0|0|0|0|0|1|S|Rd:4|Ra:4|Rm:4|1|0|0|1|Rn:4",""
"0x0ff000f0","0x00600090","MLS<c> <Rd>,<Rn>,<Rm>,<Ra>","cond:4|0|0|0|0|0|1|1|0|Rd:4|Ra:4|Rm:4|1|0|0|1|Rn:4",""
"0x0ff00000","0x03400000","MOVT<c> <Rd>,#<imm12+4>","cond:4|0|0|1|1|0|1|0|0|imm4:4|Rd:4|imm12:12",""
"0x0ff00000","0x03000000","MOVW<c> <Rd>,#<imm12+4>","cond:4|0|0|1|1|0|0|0|0|imm4:4|Rd:4|imm12:12",""
"0x0fef0000","0x03a00000","MOV{S}<c> <Rd>,#<const>","cond:4|0|0|1|1|1|0|1|S|0|0|0|0|Rd:4|imm12:12","SEE SUBS PC, LR and related instructions"
"0x0fef0ff0","0x01a00000","MOV{S}<c> <Rd>,<Rm>","cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|0|0|0|0|0|0|0|0|Rm:4","SEE SUBS PC, LR and related instructions"
"0x0fff0fff","0x010f0000","MRS<c> <Rd>,APSR","cond:4|0|0|0|1|0|0|0|0|(1)|(1)|(1)|(1)|Rd:4|(0)|(0)|(0)|(0)|0|0|0|0|(0)|(0)|(0)|(0)",""
"0x0fe0f0f0","0x00000090","MUL{S}<c> <Rd>,<Rn>,<Rm>","cond:4|0|0|0|0|0|0|0|S|Rd:4|(0)|(0)|(0)|(0)|Rm:4|1|0|0|1|Rn:4",""
"0x0fef0000","0x03e00000","MVN{S}<c> <Rd>,#<const>","cond:4|0|0|1|1|1|1|1|S|(0)|(0)|(0)|(0)|Rd:4|imm12:12","SEE SUBS PC, LR and related instructions"
"0x0fef0090","0x01e00010","MVN{S}<c> <Rd>,<Rm>,<type> <Rs>","cond:4|0|0|0|1|1|1|1|S|(0)|(0)|(0)|(0)|Rd:4|Rs:4|0|type:2|1|Rm:4",""
"0x0fef0010","0x01e00000","MVN{S}<c> <Rd>,<Rm>{,<shift>}","cond:4|0|0|0|1|1|1|1|S|(0)|(0)|(0)|(0)|Rd:4|imm5:5|type:2|0|Rm:4","SEE SUBS PC, LR and related instructions"
"0x0fffffff","0x0320f000","NOP<c>","cond:4|0|0|1|1|0|0|1|0|0|0|0|0|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|0|0|0|0|0|0|0",""
"0x0fe00000","0x03800000","ORR{S}<c> <Rd>,<Rn>,#<const>","cond:4|0|0|1|1|1|0|0|S|Rn:4|Rd:4|imm12:12","SEE SUBS PC, LR and related instructions"
"0x0fe00090","0x01800010","ORR{S}<c> <Rd>,<Rn>,<Rm>,<type> <Rs>","cond:4|0|0|0|1|1|0|0|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4",""
"0x0fe00010","0x01800000","ORR{S}<c> <Rd>,<Rn>,<Rm>{,<shift>}","cond:4|0|0|0|1|1|0|0|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4","SEE SUBS PC, LR and related instructions"
"0x0ff00030","0x06800010","PKH<BT,TB><c> <Rd>,<Rn>,<Rm>{,LSL #<imm5>}","cond:4|0|1|1|0|1|0|0|0|Rn:4|Rd:4|imm5:5|tb|0|1|Rm:4",""
"0xff7ff000","0xf55ff000","PLD <label+/-12>","1|1|1|1|0|1|0|1|U|(1)|0|1|1|1|1|1|(1)|(1)|(1)|(1)|imm12:12",""
"0xff30f000","0xf510f000","PLD{W} [<Rn>,#+/-<imm12>]","1|1|1|1|0|1|0|1|U|R|0|1|Rn:4|(1)|(1)|(1)|(1)|imm12:12","SEE PLD (literal)"
"0xff30f010","0xf710f000","PLD{W} [<Rn>,+/-<Rm>{, <shift>}]","1|1|1|1|0|1|1|1|U|R|0|1|Rn:4|(1)|(1)|(1)|(1)|imm5:5|type:2|0|Rm:4",""
"0xff70f000","0xf450f000","PLI [<Rn>,#+/-<imm12>]","1|1|1|1|0|1|0|0|U|1|0|1|Rn:4|(1)|(1)|(1)|(1)|imm12:12",""
"0xff70f010","0xf650f000","PLI [<Rn>,+/-<Rm>{, <shift>}]","1|1|1|1|0|1|1|0|U|1|0|1|Rn:4|(1)|(1)|(1)|(1)|imm5:5|type:2|0|Rm:4",""
"0x0fff0000","0x08bd0000","POP<c> <registers2>","cond:4|1|0|0|0|1|0|1|1|1|1|0|1|register_list:16",""
"0x0fff0fff","0x049d0004","POP<c> <registers1>","cond:4|0|1|0|0|1|0|0|1|1|1|0|1|Rt:4|0|0|0|0|0|0|0|0|0|1|0|0",""
"0x0fff0000","0x092d0000","PUSH<c> <registers2>","cond:4|1|0|0|1|0|0|1|0|1|1|0|1|register_list:16",""
"0x0fff0fff","0x052d0004","PUSH<c> <registers1>","cond:4|0|1|0|1|0|0|1|0|1|1|0|1|Rt:4|0|0|0|0|0|0|0|0|0|1|0|0",""
"0x0ff00ff0","0x06200f10","QADD16<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|0|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4",""
"0x0ff00ff0","0x06200f90","QADD8<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|0|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|0|0|1|Rm:4",""
"0x0ff00ff0","0x01000050","QADD<c> <Rd>,<Rm>,<Rn>","cond:4|0|0|0|1|0|0|0|0|Rn:4|Rd:4|(0)|(0)|(0)|(0)|0|1|0|1|Rm:4",""
"0x0ff00ff0","0x06200f30","QASX<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|0|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4",""
"0x0ff00ff0","0x01400050","QDADD<c> <Rd>,<Rm>,<Rn>","cond:4|0|0|0|1|0|1|0|0|Rn:4|Rd:4|(0)|(0)|(0)|(0)|0|1|0|1|Rm:4",""
"0x0ff00ff0","0x01600050","QDSUB<c> <Rd>,<Rm>,<Rn>","cond:4|0|0|0|1|0|1|1|0|Rn:4|Rd:4|0|0|0|0|0|1|0|1|Rm:4",""
"0x0ff00ff0","0x06200f50","QSAX<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|0|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|0|1|Rm:4",""
"0x0ff00ff0","0x06200f70","QSUB16<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|0|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|1|1|Rm:4",""
"0x0ff00ff0","0x06200ff0","QSUB8<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|0|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|1|1|1|Rm:4",""
"0x0ff00ff0","0x01200050","QSUB<c> <Rd>,<Rm>,<Rn>","cond:4|0|0|0|1|0|0|1|0|Rn:4|Rd:4|0|0|0|0|0|1|0|1|Rm:4",""
"0x0fff0ff0","0x06ff0f30","RBIT<c> <Rd>,<Rm>","cond:4|0|1|1|0|1|1|1|1|(1)|(1)|(1)|(1)|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4",""
"0x0fff0ff0","0x06bf0fb0","REV16<c> <Rd>,<Rm>","cond:4|0|1|1|0|1|0|1|1|(1)|(1)|(1)|(1)|Rd:4|(1)|(1)|(1)|(1)|1|0|1|1|Rm:4",""
"0x0fff0ff0","0x06bf0f30","REV<c> <Rd>,<Rm>","cond:4|0|1|1|0|1|0|1|1|(1)|(1)|(1)|(1)|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4",""
"0x0fff0ff0","0x06ff0fb0","REVSH<c> <Rd>,<Rm>","cond:4|0|1|1|0|1|1|1|1|(1)|(1)|(1)|(1)|Rd:4|(1)|(1)|(1)|(1)|1|0|1|1|Rm:4",""
"0x0fef0070","0x01a00060","ROR{S}<c> <Rd>,<Rm>,#<imm5>","cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|imm5:5|1|1|0|Rm:4","SEE RRX"
"0x0fef00f0","0x01a00070","ROR{S}<c> <Rd>,<Rn>,<Rm>","cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|Rm:4|0|1|1|1|Rn:4",""
"0x0fef0ff0","0x01a00060","RRX{S}<c> <Rd>,<Rm>","cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|0|0|0|0|0|1|1|0|Rm:4",""
"0x0fe00000","0x02600000","RSB{S}<c> <Rd>,<Rn>,#<const>","cond:4|0|0|1|0|0|1|1|S|Rn:4|Rd:4|imm12:12","SEE SUBS PC, LR and related instructions"
"0x0fe00090","0x00600010","RSB{S}<c> <Rd>,<Rn>,<Rm>,<type> <Rs>","cond:4|0|0|0|0|0|1|1|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4",""
"0x0fe00010","0x00600000","RSB{S}<c> <Rd>,<Rn>,<Rm>{,<shift>}","cond:4|0|0|0|0|0|1|1|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4","SEE SUBS PC, LR and related instructions"
"0x0fe00000","0x02e00000","RSC{S}<c> <Rd>,<Rn>,#<const>","cond:4|0|0|1|0|1|1|1|S|Rn:4|Rd:4|imm12:12","SEE SUBS PC, LR and related instructions"
"0x0fe00090","0x00e00010","RSC{S}<c> <Rd>,<Rn>,<Rm>,<type> <Rs>","cond:4|0|0|0|0|1|1|1|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4",""
"0x0fe00010","0x00e00000","RSC{S}<c> <Rd>,<Rn>,<Rm>{,<shift>}","cond:4|0|0|0|0|1|1|1|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4","SEE SUBS PC, LR and related instructions"
"0x0ff00ff0","0x06100f10","SADD16<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|0|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4",""
"0x0ff00ff0","0x06100f90","SADD8<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|0|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|0|0|1|Rm:4",""
"0x0ff00ff0","0x06100f30","SASX<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|0|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4",""
"0x0fe00000","0x02c00000","SBC{S}<c> <Rd>,<Rn>,#<const>","cond:4|0|0|1|0|1|1|0|S|Rn:4|Rd:4|imm12:12","SEE SUBS PC, LR and related instructions"
"0x0fe00090","0x00c00010","SBC{S}<c> <Rd>,<Rn>,<Rm>,<type> <Rs>","cond:4|0|0|0|0|1|1|0|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4",""
"0x0fe00010","0x00c00000","SBC{S}<c> <Rd>,<Rn>,<Rm>{,<shift>}","cond:4|0|0|0|0|1|1|0|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4","SEE SUBS PC, LR and related instructions"
"0x0fe00070","0x07a00050","SBFX<c> <Rd>,<Rn>,#<lsb>,#<widthm1>","cond:4|0|1|1|1|1|0|1|widthm1:5|Rd:4|lsb:5|1|0|1|Rn:4",""
"0x0ff00ff0","0x06800fb0","SEL<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|1|0|0|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|0|1|1|Rm:4",""
"0xfffffdff","0xf1010000","SETEND <endian_specifier>","1|1|1|1|0|0|0|1|0|0|0|0|0|0|0|1|0|0|0|0|0|0|E|(0)|(0)|(0)|(0)|(0)|(0)|(0)|(0)|(0)",""
"0x0fffffff","0x0320f004","SEV<c>","cond:4|0|0|1|1|0|0|1|0|0|0|0|0|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|0|0|0|0|1|0|0",""
"0x0ff00ff0","0x06300f10","SHADD16<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|0|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4",""
"0x0ff00ff0","0x06300f90","SHADD8<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|0|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|0|0|1|Rm:4",""
"0x0ff00ff0","0x06300f30","SHASX<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|0|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4",""
"0x0ff00ff0","0x06300f50","SHSAX<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|0|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|0|1|Rm:4",""
"0x0ff00ff0","0x06300f70","SHSUB16<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|0|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|1|1|Rm:4",""
"0x0ff00ff0","0x06300ff0","SHSUB8<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|0|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|1|1|1|Rm:4",""
"0x0ff00090","0x01000080","SMLA<x><y><c> <Rd>,<Rn>,<Rm>,<Ra>","cond:4|0|0|0|1|0|0|0|0|Rd:4|Ra:4|Rm:4|1|M|N|0|Rn:4",""
"0x0ff000d0","0x07000010","SMLAD{X}<c> <Rd>,<Rn>,<Rm>,<Ra>","cond:4|0|1|1|1|0|0|0|0|Rd:4|Ra:4|Rm:4|0|0|M|1|Rn:4","SEE SMUAD"
"0x0ff00090","0x01400080","SMLAL<x><y><c> <RdLo>,<RdHi>,<Rn>,<Rm>","cond:4|0|0|0|1|0|1|0|0|RdHi:4|RdLo:4|Rm:4|1|M|N|0|Rn:4",""
"0x0ff000d0","0x07400010","SMLALD{X}<c> <RdLo>,<RdHi>,<Rn>,<Rm>","cond:4|0|1|1|1|0|1|0|0|RdHi:4|RdLo:4|Rm:4|0|0|M|1|Rn:4",""
"0x0fe000f0","0x00e00090","SMLAL{S}<c> <RdLo>,<RdHi>,<Rn>,<Rm>","cond:4|0|0|0|0|1|1|1|S|RdHi:4|RdLo:4|Rm:4|1|0|0|1|Rn:4",""
"0x0ff000b0","0x01200080","SMLAW<y><c> <Rd>,<Rn>,<Rm>,<Ra>","cond:4|0|0|0|1|0|0|1|0|Rd:4|Ra:4|Rm:4|1|M|0|0|Rn:4",""
"0x0ff000d0","0x07000050","SMLSD{X}<c> <Rd>,<Rn>,<Rm>,<Ra>","cond:4|0|1|1|1|0|0|0|0|Rd:4|Ra:4|Rm:4|0|1|M|1|Rn:4","SEE SMUSD"
"0x0ff000d0","0x07400050","SMLSLD{X}<c> <RdLo>,<RdHi>,<Rn>,<Rm>","cond:4|0|1|1|1|0|1|0|0|RdHi:4|RdLo:4|Rm:4|0|1|M|1|Rn:4",""
"0x0ff000d0","0x07500010","SMMLA{R}<c> <Rd>,<Rn>,<Rm>,<Ra>","cond:4|0|1|1|1|0|1|0|1|Rd:4|Ra:4|Rm:4|0|0|R|1|Rn:4","SEE SMMUL"
"0x0ff000d0","0x075000d0","SMMLS{R}<c> <Rd>,<Rn>,<Rm>,<Ra>","cond:4|0|1|1|1|0|1|0|1|Rd:4|Ra:4|Rm:4|1|1|R|1|Rn:4",""
"0x0ff0f0d0","0x0750f010","SMMUL{R}<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|1|0|1|0|1|Rd:4|1|1|1|1|Rm:4|0|0|R|1|Rn:4",""
"0x0ff0f0d0","0x0700f010","SMUAD{X}<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|1|0|0|0|0|Rd:4|1|1|1|1|Rm:4|0|0|M|1|Rn:4",""
"0x0ff0f090","0x01600080","SMUL<x><y><c> <Rd>,<Rn>,<Rm>","cond:4|0|0|0|1|0|1|1|0|Rd:4|0|0|0|0|Rm:4|1|M|N|0|Rn:4",""
"0x0fe000f0","0x00c00090","SMULL{S}<c> <RdLo>,<RdHi>,<Rn>,<Rm>","cond:4|0|0|0|0|1|1|0|S|RdHi:4|RdLo:4|Rm:4|1|0|0|1|Rn:4",""
"0x0ff0f0b0","0x012000a0","SMULW<y><c> <Rd>,<Rn>,<Rm>","cond:4|0|0|0|1|0|0|1|0|Rd:4|0|0|0|0|Rm:4|1|M|1|0|Rn:4",""
"0x0ff0f0d0","0x0700f050","SMUSD{X}<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|1|0|0|0|0|Rd:4|1|1|1|1|Rm:4|0|1|M|1|Rn:4",""
"0x0ff00ff0","0x06a00f30","SSAT16<c> <Rd>,#<sat_imm4m1>,<Rn>","cond:4|0|1|1|0|1|0|1|0|sat_imm:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rn:4",""
"0x0fe00030","0x06a00010","SSAT<c> <Rd>,#<sat_imm5m1>,<Rn>{,<shift>}","cond:4|0|1|1|0|1|0|1|sat_imm:5|Rd:4|imm5:5|sh|0|1|Rn:4",""
"0x0ff00ff0","0x06100f50","SSAX<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|0|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|0|1|Rm:4",""
"0x0ff00ff0","0x06100f70","SSUB16<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|0|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|1|1|Rm:4",""
"0x0ff00ff0","0x06100ff0","SSUB8<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|0|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|1|1|1|Rm:4",""
"0x0fd00000","0x08800000","STM<c> <Rn>{!},<registers>","cond:4|1|0|0|0|1|0|W|0|Rn:4|register_list:16",""
"0x0fd00000","0x08000000","STMDA<c> <Rn>{!},<registers>","cond:4|1|0|0|0|0|0|W|0|Rn:4|register_list:16",""
"0x0fd00000","0x09000000","STMDB<c> <Rn>{!},<registers>","cond:4|1|0|0|1|0|0|W|0|Rn:4|register_list:16","SEE PUSH"
"0x0fd00000","0x09800000","STMIB<c> <Rn>{!},<registers>","cond:4|1|0|0|1|1|0|W|0|Rn:4|register_list:16",""
"0x0e500018","0x06000000","STR<c> <Rt>,[<Rn>,+/-<Rm>{, <shift>}]{!}","cond:4|0|1|1|P|U|0|W|0|Rn:4|Rt:4|imm5:5|type:2|0|Rm:4","SEE STRT"
"0x0e500000","0x04000000","STR<c> <Rt>,[<Rn>{,#+/-<imm12>}]{!}","cond:4|0|1|0|P|U|0|W|0|Rn:4|Rt:4|imm12:12","SEE STRT SEE PUSH"
"0x0e500010","0x06400000","STRB<c> <Rt>,[<Rn>,+/-<Rm>{, <shift>}]{!}","cond:4|0|1|1|P|U|1|W|0|Rn:4|Rt:4|imm5:5|type:2|0|Rm:4","SEE STRBT"
"0x0e500000","0x04400000","STRB<c> <Rt>,[<Rn>{,#+/-<imm12>}]{!}","cond:4|0|1|0|P|U|1|W|0|Rn:4|Rt:4|imm12:12","SEE STRBT"
"0x0f700000","0x04600000","STRBT<c> <Rt>,[<Rn>],#+/-<imm12>","cond:4|0|1|0|0|U|1|1|0|Rn:4|Rt:4|imm12:12",""
"0x0f700010","0x06600000","STRBT<c> <Rt>,[<Rn>],+/-<Rm>{, <shift>}","cond:4|0|1|1|0|U|1|1|0|Rn:4|Rt:4|imm5:5|type:2|0|Rm:4",""
"0x0e500ff0","0x000000f0","STRD<c> <Rt1>,<Rt2>,[<Rn>,+/-<Rm>]{!}","cond:4|0|0|0|P|U|0|W|0|Rn:4|Rt:4|(0)|(0)|(0)|(0)|1|1|1|1|Rm:4",""
"0x0e5000f0","0x004000f0","STRD<c> <Rt1>,<Rt2>,[<Rn>{,#+/-<imm8>}]{!}","cond:4|0|0|0|P|U|1|W|0|Rn:4|Rt:4|imm4H:4|1|1|1|1|imm4L:4",""
"0x0ff00ff0","0x01800f90","STREX<c> <Rd>,<Rt>,[<Rn>]","cond:4|0|0|0|1|1|0|0|0|Rn:4|Rd:4|1|1|1|1|1|0|0|1|Rt:4",""
"0x0ff00ff0","0x01c00f90","STREXB<c> <Rd>,<Rt>,[<Rn>]","cond:4|0|0|0|1|1|1|0|0|Rn:4|Rd:4|1|1|1|1|1|0|0|1|Rt:4",""
"0x0ff00ff0","0x01a00f90","STREXD<c> <Rd>,<Rt1>,<Rt2>,[<Rn>]","cond:4|0|0|0|1|1|0|1|0|Rn:4|Rd:4|1|1|1|1|1|0|0|1|Rt:4",""
"0x0ff00ff0","0x01e00f90","STREXH<c> <Rd>,<Rt>,[<Rn>]","cond:4|0|0|0|1|1|1|1|0|Rn:4|Rd:4|1|1|1|1|1|0|0|1|Rt:4",""
"0x0e500ff0","0x000000b0","STRH<c> <Rt>,[<Rn>,+/-<Rm>]{!}","cond:4|0|0|0|P|U|0|W|0|Rn:4|Rt:4|0|0|0|0|1|0|1|1|Rm:4","SEE STRHT"
"0x0e5000f0","0x004000b0","STRH<c> <Rt>,[<Rn>{,#+/-<imm8>}]{!}","cond:4|0|0|0|P|U|1|W|0|Rn:4|Rt:4|imm4H:4|1|0|1|1|imm4L:4","SEE STRHT"
"0x0f7000f0","0x006000b0","STRHT<c> <Rt>, [<Rn>] {,#+/-<imm8>}","cond:4|0|0|0|0|U|1|1|0|Rn:4|Rt:4|imm4H:4|1|0|1|1|imm4L:4",""
"0x0f700ff0","0x002000b0","STRHT<c> <Rt>, [<Rn>], +/-<Rm>","cond:4|0|0|0|0|U|0|1|0|Rn:4|Rt:4|0|0|0|0|1|0|1|1|Rm:4",""
"0x0f700000","0x04200000","STRT<c> <Rt>, [<Rn>] {,#+/-<imm12>}","cond:4|0|1|0|0|U|0|1|0|Rn:4|Rt:4|imm12:12",""
"0x0f700010","0x06200000","STRT<c> <Rt>,[<Rn>],+/-<Rm>{, <shift>}","cond:4|0|1|1|0|U|0|1|0|Rn:4|Rt:4|imm5:5|type:2|0|Rm:4",""
"0x0fe00000","0x02400000","SUB{S}<c> <Rd>,<Rn>,#<const>","cond:4|0|0|1|0|0|1|0|S|Rn:4|Rd:4|imm12:12","SEE ADR SEE SUB (SP minus immediate) SEE SUBS PC, LR and related instructions"
"0x0fe00090","0x00400010","SUB{S}<c> <Rd>,<Rn>,<Rm>,<type> <Rs>","cond:4|0|0|0|0|0|1|0|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4",""
"0x0fe00010","0x00400000","SUB{S}<c> <Rd>,<Rn>,<Rm>{,<shift>}","cond:4|0|0|0|0|0|1|0|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4","SEE SUBS PC, LR and related instructions SEE SUB (SP minus register)"
"0x0fef0000","0x024d0000","SUB{S}<c> <Rd>,SP,#<const>","cond:4|0|0|1|0|0|1|0|S|1|1|0|1|Rd:4|imm12:12","SEE SUBS PC, LR and related instructions"
"0x0fef0010","0x004d0000","SUB{S}<c> <Rd>,SP,<Rm>{,<shift>}","cond:4|0|0|0|0|0|1|0|S|1|1|0|1|Rd:4|imm5:5|type:2|0|Rm:4","SEE SUBS PC, LR and related instructions"
"0x0f000000","0x0f000000","SVC<c> #<imm24>","cond:4|1|1|1|1|imm24:24",""
"0x0fb00ff0","0x01000090","SWP{B}<c> <Rt>,<Rm>,[<Rn>]","cond:4|0|0|0|1|0|B|0|0|Rn:4|Rt:4|0|0|0|0|1|0|0|1|Rm:4",""
"0x0ff003f0","0x06800070","SXTAB16<c> <Rd>,<Rn>,<Rm>{,<rotation>}","cond:4|0|1|1|0|1|0|0|0|Rn:4|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4","SEE SXTB16"
"0x0ff003f0","0x06a00070","SXTAB<c> <Rd>,<Rn>,<Rm>{,<rotation>}","cond:4|0|1|1|0|1|0|1|0|Rn:4|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4","SEE SXTB"
"0x0ff003f0","0x06b00070","SXTAH<c> <Rd>,<Rn>,<Rm>{,<rotation>}","cond:4|0|1|1|0|1|0|1|1|Rn:4|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4","SEE SXTH"
"0x0fff03f0","0x068f0070","SXTB16<c> <Rd>,<Rm>{,<rotation>}","cond:4|0|1|1|0|1|0|0|0|1|1|1|1|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4",""
"0x0fff03f0","0x06af0070","SXTB<c> <Rd>,<Rm>{,<rotation>}","cond:4|0|1|1|0|1|0|1|0|1|1|1|1|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4",""
"0x0fff03f0","0x06bf0070","SXTH<c> <Rd>,<Rm>{,<rotation>}","cond:4|0|1|1|0|1|0|1|1|1|1|1|1|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4",""
"0x0ff0f000","0x03300000","TEQ<c> <Rn>,#<const>","cond:4|0|0|1|1|0|0|1|1|Rn:4|(0)|(0)|(0)|(0)|imm12:12",""
"0x0ff0f090","0x01300010","TEQ<c> <Rn>,<Rm>,<type> <Rs>","cond:4|0|0|0|1|0|0|1|1|Rn:4|(0)|(0)|(0)|(0)|Rs:4|0|type:2|1|Rm:4",""
"0x0ff0f010","0x01300000","TEQ<c> <Rn>,<Rm>{,<shift>}","cond:4|0|0|0|1|0|0|1|1|Rn:4|(0)|(0)|(0)|(0)|imm5:5|type:2|0|Rm:4",""
"0x0ff0f000","0x03100000","TST<c> <Rn>,#<const>","cond:4|0|0|1|1|0|0|0|1|Rn:4|(0)|(0)|(0)|(0)|imm12:12",""
"0x0ff0f090","0x01100010","TST<c> <Rn>,<Rm>,<type> <Rs>","cond:4|0|0|0|1|0|0|0|1|Rn:4|(0)|(0)|(0)|(0)|Rs:4|0|type:2|1|Rm:4",""
"0x0ff0f010","0x01100000","TST<c> <Rn>,<Rm>{,<shift>}","cond:4|0|0|0|1|0|0|0|1|Rn:4|(0)|(0)|(0)|(0)|imm5:5|type:2|0|Rm:4",""
"0x0ff00ff0","0x06500f10","UADD16<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|1|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4",""
"0x0ff00ff0","0x06500f90","UADD8<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|1|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|0|0|1|Rm:4",""
"0x0ff00ff0","0x06500f30","UASX<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|1|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4",""
"0x0fe00070","0x07e00050","UBFX<c> <Rd>,<Rn>,#<lsb>,#<widthm1>","cond:4|0|1|1|1|1|1|1|widthm1:5|Rd:4|lsb:5|1|0|1|Rn:4",""
"0x0ff00ff0","0x06700f10","UHADD16<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|1|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4",""
"0x0ff00ff0","0x06700f90","UHADD8<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|1|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|0|0|1|Rm:4",""
"0x0ff00ff0","0x06700f30","UHASX<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|1|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4",""
"0x0ff00ff0","0x06700f50","UHSAX<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|1|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|0|1|Rm:4",""
"0x0ff00ff0","0x06700f70","UHSUB16<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|1|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|1|1|Rm:4",""
"0x0ff00ff0","0x06700ff0","UHSUB8<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|1|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|1|1|1|Rm:4",""
"0x0ff000f0","0x00400090","UMAAL<c> <RdLo>,<RdHi>,<Rn>,<Rm>","cond:4|0|0|0|0|0|1|0|0|RdHi:4|RdLo:4|Rm:4|1|0|0|1|Rn:4",""
"0x0fe000f0","0x00a00090","UMLAL{S}<c> <RdLo>,<RdHi>,<Rn>,<Rm>","cond:4|0|0|0|0|1|0|1|S|RdHi:4|RdLo:4|Rm:4|1|0|0|1|Rn:4",""
"0x0fe000f0","0x00800090","UMULL{S}<c> <RdLo>,<RdHi>,<Rn>,<Rm>","cond:4|0|0|0|0|1|0|0|S|RdHi:4|RdLo:4|Rm:4|1|0|0|1|Rn:4",""
"0x0ff00ff0","0x06600f10","UQADD16<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|1|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4",""
"0x0ff00ff0","0x06600f90","UQADD8<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|1|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|0|0|1|Rm:4",""
"0x0ff00ff0","0x06600f30","UQASX<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|1|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4",""
"0x0ff00ff0","0x06600f50","UQSAX<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|1|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|0|1|Rm:4",""
"0x0ff00ff0","0x06600f70","UQSUB16<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|1|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|1|1|Rm:4",""
"0x0ff00ff0","0x06600ff0","UQSUB8<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|1|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|1|1|1|Rm:4",""
"0x0ff0f0f0","0x0780f010","USAD8<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|1|1|0|0|0|Rd:4|1|1|1|1|Rm:4|0|0|0|1|Rn:4",""
"0x0ff000f0","0x07800010","USADA8<c> <Rd>,<Rn>,<Rm>,<Ra>","cond:4|0|1|1|1|1|0|0|0|Rd:4|Ra:4|Rm:4|0|0|0|1|Rn:4","SEE USAD8"
"0x0ff00ff0","0x06e00f30","USAT16<c> <Rd>,#<sat_imm4>,<Rn>","cond:4|0|1|1|0|1|1|1|0|sat_imm:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rn:4",""
"0x0fe00030","0x06e00010","USAT<c> <Rd>,#<sat_imm5>,<Rn>{,<shift>}","cond:4|0|1|1|0|1|1|1|sat_imm:5|Rd:4|imm5:5|sh|0|1|Rn:4",""
"0x0ff00ff0","0x06500f50","USAX<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|1|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|0|1|Rm:4",""
"0x0ff00ff0","0x06500f70","USUB16<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|1|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|1|1|Rm:4",""
"0x0ff00ff0","0x06500ff0","USUB8<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|1|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|1|1|1|Rm:4",""
"0x0ff003f0","0x06c00070","UXTAB16<c> <Rd>,<Rn>,<Rm>{,<rotation>}","cond:4|0|1|1|0|1|1|0|0|Rn:4|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4","SEE UXTB16"
"0x0ff003f0","0x06e00070","UXTAB<c> <Rd>,<Rn>,<Rm>{,<rotation>}","cond:4|0|1|1|0|1|1|1|0|Rn:4|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4","SEE UXTB"
"0x0ff003f0","0x06f00070","UXTAH<c> <Rd>,<Rn>,<Rm>{,<rotation>}","cond:4|0|1|1|0|1|1|1|1|Rn:4|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4","SEE UXTH"
"0x0fff03f0","0x06cf0070","UXTB16<c> <Rd>,<Rm>{,<rotation>}","cond:4|0|1|1|0|1|1|0|0|1|1|1|1|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4",""
"0x0fff03f0","0x06ef0070","UXTB<c> <Rd>,<Rm>{,<rotation>}","cond:4|0|1|1|0|1|1|1|0|1|1|1|1|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4",""
"0x0fff03f0","0x06ff0070","UXTH<c> <Rd>,<Rm>{,<rotation>}","cond:4|0|1|1|0|1|1|1|1|1|1|1|1|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4",""
"0xff800f10","0xf3000110","V<BIF,BIT,BSL> <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|1|0|D|op:2|Vn:4|Vd:4|0|0|0|1|N|Q|M|1|Vm:4","SEE VEOR"
"0xffb00c10","0xf3b00800","V<TBL,TBX>.8 <Dd>, <list_len>, <Dm>","1|1|1|1|0|0|1|1|1|D|1|1|Vn:4|Vd:4|1|0|len:2|N|op|M|0|Vm:4",""
"0xfe800a50","0xf2800040","V<MLA,MLS>.<dt> <Qd>, <Qn>, <Dm[x]>","1|1|1|1|0|0|1|Q|1|D|size:2|Vn:4|Vd:4|0|op|0|F|N|1|M|0|Vm:4","SEE “Related encodings”"
"0xfe800f00","0xf2000600","V<MAX,MIN>.<dt> <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|U|0|D|size:2|Vn:4|Vd:4|0|1|1|0|N|Q|M|op|Vm:4",""
"0xfe800f10","0xf2000900","V<MLA,MLS>.<dt> <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|op|0|D|size:2|Vn:4|Vd:4|1|0|0|1|N|Q|M|0|Vm:4",""
"0xff800f10","0xf2000d10","V<MLA,MLS>.F32 <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|0|0|D|op|sz|Vn:4|Vd:4|1|1|0|1|N|Q|M|1|Vm:4",""
"0xff800f10","0xf2000f00","V<MAX,MIN>.F32 <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|0|0|D|op|sz|Vn:4|Vd:4|1|1|1|1|N|Q|M|0|Vm:4",""
"0xff800f10","0xf3000e10","VAC<GE,GT>.F32 <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|1|0|D|op|sz|Vn:4|Vd:4|1|1|1|0|N|Q|M|1|Vm:4",""
"0x0fb00e10","0x0e000a00","V<MLA,MLS><c>.F<32,64> <Sd,Dd>, <Sn,Dn>, <Sm,Dm>","cond:4|1|1|1|0|0|D|0|0|Vn:4|Vd:4|1|0|1|sz|N|op|M|0|Vm:4","vfp"
"0xfe801d50","0xf2800800","V<MLA,MLS>L.<dt> <Qd>, <Dn>, <Dm>","1|1|1|1|0|0|1|U|1|D|size:2|Vn:4|Vd:4|1|0|op|0|N|0|M|0|Vm:4","SEE “Related encodings”"
"0xfe801b50","0xf2800240","V<MLA,MLS>L.<dt> <Qd>, <Dn>, <Dm[x]>","1|1|1|1|0|0|1|U|1|D|size:2|Vn:4|Vd:4|0|op|1|0|N|1|M|0|Vm:4","SEE “Related encodings”"
"0xfe800f10","0xf2000710","VABA.<dt_Usize> <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|U|0|D|size:2|Vn:4|Vd:4|0|1|1|1|N|Q|M|1|Vm:4",""
"0xfe801f50","0xf2800500","VABAL.<dt_Usize> <Qd>, <Dn>, <Dm>","1|1|1|1|0|0|1|U|1|D|size:2|Vn:4|Vd:4|0|1|0|1|N|0|M|0|Vm:4","SEE “Related encodings”"
"0xfe800f10","0xf2000700","VABD.<dt_Usize> <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|U|0|D|size:2|Vn:4|Vd:4|0|1|1|1|N|Q|M|0|Vm:4",""
"0xffa00f10","0xf3200d00","VABD.F32 <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|1|0|D|1|sz|Vn:4|Vd:4|1|1|0|1|N|Q|M|0|Vm:4",""
"0xfe801f50","0xf2800700","VABDL.<dt_Usize> <Qd>, <Dn>, <Dm>","1|1|1|1|0|0|1|U|1|D|size:2|Vn:4|Vd:4|0|1|1|1|N|0|M|0|Vm:4","SEE “Related encodings”"
"0xffb30b90","0xf3b10300","VABS.<dt_Fsize> <Qd>, <Qm>","1|1|1|1|0|0|1|1|1|D|1|1|size:2|0|1|Vd:4|0|F|1|1|0|Q|M|0|Vm:4",""
"0x0fbf0ed0","0x0eb00ac0","VABS<c>.F<32,64> <Sd,Dd>, <Sm,Dm>","cond:4|1|1|1|0|1|D|1|1|0|0|0|0|Vd:4|1|0|1|sz|1|1|M|0|Vm:4","vfp"
"0xff800f10","0xf2000800","VADD.<dt_Isize> <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|0|0|D|size:2|Vn:4|Vd:4|1|0|0|0|N|Q|M|0|Vm:4",""
"0xffa00f10","0xf2000d00","VADD.F32 <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|0|0|D|0|sz|Vn:4|Vd:4|1|1|0|1|N|Q|M|0|Vm:4",""
"0x0fb00e50","0x0e300a00","VADD<c>.F<32,64> <Sd,Dd>, <Sn,Dn>, <Sm,Dm>","cond:4|1|1|1|0|0|D|1|1|Vn:4|Vd:4|1|0|1|sz|N|0|M|0|Vm:4","vfp"
"0xff810f51","0xf2800400","VADDHN.<dt_Isize> <Dd>, <Qn>, <Qm>","1|1|1|1|0|0|1|0|1|D|size:2|Vn:4|Vd:4|0|1|0|0|N|0|M|0|Vm:4","SEE “Related encodings”"
"0xfe801e50","0xf2800000","VADDL.<dt_Usize> <Qd>, <Dn>, <Dm>","1|1|1|1|0|0|1|U|1|D|size:2|Vn:4|Vd:4|0|0|0|op|N|0|M|0|Vm:4","SEE “Related encodings”"
"0xffb00f10","0xf2000110","VAND <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|0|0|D|0|0|Vn:4|Vd:4|0|0|0|1|N|Q|M|1|Vm:4",""
"0xffb00f10","0xf2100110","VBIC <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|0|0|D|0|1|Vn:4|Vd:4|0|0|0|1|N|Q|M|1|Vm:4",""
"0xfeb800b0","0xf2800030","VBIC.<dt_simd> <Qd>, #<imm_simd1>","1|1|1|1|0|0|1|i|1|D|0|0|0|imm3:3|Vd:4|cmode:4|0|Q|1|1|imm4:4","SEE “Related encodings”"
"0xffb30b90","0xf3b10100","VCEQ.<dt_Fsize> <Qd>, <Qm>, #0","1|1|1|1|0|0|1|1|1|D|1|1|size:2|0|1|Vd:4|0|F|0|1|0|Q|M|0|Vm:4",""
"0xff800f10","0xf3000810","VCEQ.<dt_Isize> <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|1|0|D|size:2|Vn:4|Vd:4|1|0|0|0|N|Q|M|1|Vm:4",""
"0xffa00f10","0xf2000e00","VCEQ.F32 <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|0|0|D|0|sz|Vn:4|Vd:4|1|1|1|0|N|Q|M|0|Vm:4",""
"0xffb30b90","0xf3b10080","VCGE.<dt_Fsize> <Qd>, <Qm>, #0","1|1|1|1|0|0|1|1|1|D|1|1|size:2|0|1|Vd:4|0|F|0|0|1|Q|M|0|Vm:4",""
"0xfe800f10","0xf2000310","VCGE.<dt_Isize> <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|U|0|D|size:2|Vn:4|Vd:4|0|0|1|1|N|Q|M|1|Vm:4",""
"0xffa00f10","0xf3000e00","VCGE.F32 <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|1|0|D|0|sz|Vn:4|Vd:4|1|1|1|0|N|Q|M|0|Vm:4",""
"0xffb30b90","0xf3b10000","VCGT.<dt_Fsize> <Qd>, <Qm>, #0","1|1|1|1|0|0|1|1|1|D|1|1|size:2|0|1|Vd:4|0|F|0|0|0|Q|M|0|Vm:4",""
"0xfe800f10","0xf2000300","VCGT.<dt_Isize> <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|U|0|D|size:2|Vn:4|Vd:4|0|0|1|1|N|Q|M|0|Vm:4",""
"0xffa00f10","0xf3200e00","VCGT.F32 <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|1|0|D|1|sz|Vn:4|Vd:4|1|1|1|0|N|Q|M|0|Vm:4",""
"0xffb30b90","0xf3b10180","VCLE.<dt_Fsize> <Qd>, <Qm>, #0","1|1|1|1|0|0|1|1|1|D|1|1|size:2|0|1|Vd:4|0|F|0|1|1|Q|M|0|Vm:4",""
"0xffb30f90","0xf3b00400","VCLS.<dt_Isize> <Qd>, <Qm>","1|1|1|1|0|0|1|1|1|D|1|1|size:2|0|0|Vd:4|0|1|0|0|0|Q|M|0|Vm:4",""
"0xffb30b90","0xf3b10200","VCLT.<dt_Fsize> <Qd>, <Qm>, #0","1|1|1|1|0|0|1|1|1|D|1|1|size:2|0|1|Vd:4|0|F|1|0|0|Q|M|0|Vm:4",""
"0xffb30f90","0xf3b00480","VCLZ.<dt_Isize> <Qd>, <Qm>","1|1|1|1|0|0|1|1|1|D|1|1|size:2|0|0|Vd:4|0|1|0|0|1|Q|M|0|Vm:4",""
"0x0fbf0e7f","0x0eb50a40","VCMP{E}<c>.F<32,64> <Sd,Dd>, #0.0","cond:4|1|1|1|0|1|D|1|1|0|1|0|1|Vd:4|1|0|1|sz|E|1|0|0|(0)|(0)|(0)|(0)","vfp"
"0x0fbf0e50","0x0eb40a40","VCMP{E}<c>.F<32,64> <Sd,Dd>, <Sm,Dm>","cond:4|1|1|1|0|1|D|1|1|0|1|0|0|Vd:4|1|0|1|sz|E|1|M|0|Vm:4","vfp"
"0xffbf0f90","0xf3b00500","VCNT.8 <Qd>, <Qm>","1|1|1|1|0|0|1|1|1|D|1|1|size:2|0|0|Vd:4|0|1|0|1|0|Q|M|0|Vm:4",""
"0xffbf0e10","0xf3bb0600","VCVT.<Td>.<Tm_1> <Qd>, <Qm>","1|1|1|1|0|0|1|1|1|D|1|1|size:2|1|1|Vd:4|0|1|1|op:2|Q|M|0|Vm:4",""
"0xfea00e90","0xf2a00e10","VCVT.<Td>.<Tm_2> <Qd>, <Qm>, #<fbits>","1|1|1|1|0|0|1|U|1|D|imm6:6|Vd:4|1|1|1|op|0|Q|M|1|Vm:4","SEE “Related encodings”"
"0x0fbe0e50","0x0eba0a40","VCVT<c>.F<32,64>.FX<S,U><16,32> <Sd,Dd>, <Sd,Dd>, #<fbits>","cond:4|1|1|1|0|1|D|1|1|1|0|1|U|Vd:4|1|0|1|sz|sx|1|i|0|imm4:4","vfp"
"0x0fbe0e50","0x0ebe0a40","VCVT<c>.FX<S,U><16,32>.F<32,64> <Sd,Dd>, <Sd,Dd>, #<fbits>","cond:4|1|1|1|0|1|D|1|1|1|1|1|U|Vd:4|1|0|1|sz|sx|1|i|0|imm4:4","vfp"
"0xffbf0ed0","0xf3b60600","VCVT.F32.F16 <Qd>, <Dm>","1|1|1|1|0|0|1|1|1|D|1|1|size:2|1|0|Vd:4|0|1|1|op|0|0|M|0|Vm:4",""
"0x0fbf0ed0","0x0eb70ac0","VCVT<c>.<F64.F32,F32.F64> <Dd,Sd>, <Sm,Dm>","cond:4|1|1|1|0|1|D|1|1|0|1|1|1|Vd:4|1|0|1|sz|1|1|M|0|Vm:4","vfp"
"0x0fbe0f50","0x0eb20a40","VCVT<B,T><c>.<F32.F16,F16.F32> <Sd>, <Sm>","cond:4|1|1|1|0|1|D|1|1|0|0|1|op|Vd:4|1|0|1|0|T|1|M|0|Vm:4","vfp"
"0x0fbf0e50","0x0eb80a40","VCVT<c>.F<32,64>.<U,S>32 <Sd,Dd>, <Sm>","cond:4|1|1|1|0|1|D|1|1|1|0|0|0|Vd:4|1|0|1|sz|op|1|M|0|Vm:4","vfp"
"0x0fbe0e50","0x0ebc0a40","VCVT<R,><c>.<U,S>32.F<32,64> <Sd>, <Sm,Dm>","cond:4|1|1|1|0|1|D|1|1|1|1|0|signed|Vd:4|1|0|1|sz|op|1|M|0|Vm:4","vfp"
"0x0fb00e50","0x0e800a00","VDIV<c>.F<32,64> <Sd,Dd>, <Sn,Dn>, <Sm,Dm>","cond:4|1|1|1|0|1|D|0|0|Vn:4|Vd:4|1|0|1|sz|N|0|M|0|Vm:4","vfp"
"0xffb00f90","0xf3b00c00","VDUP.<size_x> <Qd>, <Dm[size_x]>","1|1|1|1|0|0|1|1|1|D|1|1|imm4:4|Vd:4|1|1|0|0|0|Q|M|0|Vm:4",""
"0x0f900f5f","0x0e800b10","VDUP<c>.<size_be> <Qd>, <Rt>","cond:4|1|1|1|0|1|b|Q|0|Vd:4|Rt:4|1|0|1|1|D|0|e|1|(0)|(0)|(0)|(0)",""
"0xffb00f10","0xf3000110","VEOR <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|1|0|D|0|0|Vn:4|Vd:4|0|0|0|1|N|Q|M|1|Vm:4",""
"0xffb00010","0xf2b00000","VEXT.8 <Qd>, <Qn>, <Qm>, #<imm4>","1|1|1|1|0|0|1|0|1|D|1|1|Vn:4|Vd:4|imm4:4|N|Q|M|0|Vm:4",""
"0xfe800d10","0xf2000000","VH<ADD,SUB> <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|U|0|D|size:2|Vn:4|Vd:4|0|0|op|0|N|Q|M|0|Vm:4",""
"0xffb00200","0xf4200200","VLD1.<size> <list4>, [<Rn>{@<align>}]{!}","1|1|1|1|0|1|0|0|0|D|1|0|Rn:4|Vd:4|type:4|size:2|align:2|Rm:4","SEE “Related encodings”"
"0xffb00f00","0xf4a00c00","VLD1.<size> <list1>, [<Rn>{@<align>}]{!}","1|1|1|1|0|1|0|0|1|D|1|0|Rn:4|Vd:4|1|1|0|0|size:2|T|a|Rm:4",""
"0xffb00300","0xf4a00000","VLD1.<size> <list1>, [<Rn>{@<align>}]{!}","1|1|1|1|0|1|0|0|1|D|1|0|Rn:4|Vd:4|size:2|0|0|index_align:4|Rm:4","SEE VLD1 (single element to all lanes)"
"0xffb00400","0xf4200000","VLD2.<size> <list4>, [<Rn>{@<align>}]{!}","1|1|1|1|0|1|0|0|0|D|1|0|Rn:4|Vd:4|type:4|size:2|align:2|Rm:4","SEE “Related encodings”"
"0xffb00f00","0xf4a00d00","VLD2.<size> <list1>, [<Rn>{@<align>}]{!}","1|1|1|1|0|1|0|0|1|D|1|0|Rn:4|Vd:4|1|1|0|1|size:2|T|a|Rm:4",""
"0xffb00300","0xf4a00100","VLD2.<size> <list1>, [<Rn>{@<align>}]{!}","1|1|1|1|0|1|0|0|1|D|1|0|Rn:4|Vd:4|size:2|0|1|index_align:4|Rm:4","SEE VLD2 (single 2-element structure to all lanes)"
"0xffb00f10","0xf4a00e00","VLD3.<size> <list3t>, [<Rn>]{!}","1|1|1|1|0|1|0|0|1|D|1|0|Rn:4|Vd:4|1|1|1|0|size:2|T|a|Rm:4",""
"0xffb00310","0xf4a00200","VLD3.<size> <list3>, [<Rn>]{!}","1|1|1|1|0|1|0|0|1|D|1|0|Rn:4|Vd:4|size:2|1|0|index_align:4|Rm:4","SEE VLD3 (single 3-element structure to all lanes)"
"0xffb00e20","0xf4200400","VLD3.<size> <list4>, [<Rn>{@<align>}]{!}","1|1|1|1|0|1|0|0|0|D|1|0|Rn:4|Vd:4|type:4|size:2|align:2|Rm:4","SEE “Related encodings”"
"0xffb00f00","0xf4a00f00","VLD4.<size> <list4>, [<Rn>{@<align>}]{!}","1|1|1|1|0|1|0|0|1|D|1|0|Rn:4|Vd:4|1|1|1|1|size:2|T|a|Rm:4",""
"0xffb00e00","0xf4200000","VLD4.<size> <list1>, [<Rn>{@<align>}]{!}","1|1|1|1|0|1|0|0|0|D|1|0|Rn:4|Vd:4|type:4|size:2|align:2|Rm:4","SEE “Related encodings”"
"0xffb00300","0xf4a00300","VLD4.<size> <list1>, [<Rn>{@<align>}]{!}","1|1|1|1|0|1|0|0|1|D|1|0|Rn:4|Vd:4|size:2|1|1|index_align:4|Rm:4","SEE VLD4 (single 4-element structure to all lanes)"
"0x0f300e00","0x0d100a00","VLDR<c> <Sd,Dd>, [<Rn>{,#+/-<imm8>}]","cond:4|1|1|0|1|U|D|0|1|Rn:4|Vd:4|1|0|1|sz|imm8:8","vfp"
"0x0fe00fd0","0x0c400b10","VMOV<c> <Dm>, <Rt>, <Rt2>","cond:4|1|1|0|0|0|1|0|op|Rt2:4|Rt:4|1|0|1|1|0|0|M|1|Vm:4",""
"0xffb00f10","0xf2200110","VMOV <Qd>, <Qm>","1|1|1|1|0|0|1|0|0|D|1|0|Vm:4|Vd:4|0|0|0|1|M|Q|M|1|Vm:4","SEE VORR (register)"
"0x0fe00fd0","0x0c400a10","VMOV<c> <Sm>, <Sm1>, <Rt>, <Rt2>","cond:4|1|1|0|0|0|1|0|op|Rt2:4|Rt:4|1|0|1|0|0|0|M|1|Vm:4",""
"0x0ff00f7f","0x0e000a10","VMOV<c> <Sn>, <Rt>","cond:4|1|1|1|0|0|0|0|0|Vn:4|Rt:4|1|0|1|0|N|0|0|1|0|0|0|0","vfp"
"0x0ff00f7f","0x0e100a10","VMOV<c> <Rt>, <Sn>","cond:4|1|1|1|0|0|0|0|1|Vn:4|Rt:4|1|0|1|0|N|0|0|1|0|0|0|0","vfp"
"0xfeb80090","0xf2800010","VMOV.<dt_simd> <Qd>, #<imm_simd>","1|1|1|1|0|0|1|i|1|D|0|0|0|imm3:3|Vd:4|cmode:4|0|Q|op|1|imm4:4","SEE VORR (immediate) SEE “Related encodings”"
"0x0fd00f7f","0x0e100b10","VMOV<c>.32 <Rt>, <Dn[x]>","cond:4|1|1|1|0|0|0|opc1|1|Vn:4|Rt:4|1|0|1|1|N|0|0|1|0|0|0|0","vfp"
"0x0fd00f7f","0x0e000b10","VMOV<c>.32 <Dd[x]>, <Rt>","cond:4|1|1|1|0|0|0|opc1|0|Vd:4|Rt:4|1|0|1|1|D|0|0|1|0|0|0|0","vfp"
"0x0fb00ef0","0x0eb00a00","VMOV<c>.F<32,64> <Sd,Dd>, #<imm_vfp>","cond:4|1|1|1|0|1|D|1|1|imm4H:4|Vd:4|1|0|1|sz|0|0|0|0|imm4L:4","vfp"
"0x0fbf0ed0","0x0eb00a40","VMOV<c>.F<32,64> <Sd,Dd>, <Sm,Dm>","cond:4|1|1|1|0|1|D|1|1|0|0|0|0|Vd:4|1|0|1|sz|0|1|M|0|Vm:4","vfp"
"0xfe871fd0","0xf2800a10","VMOVL.<dt> <Qd>, <Dm>","1|1|1|1|0|0|1|U|1|D|imm3:3|0|0|0|Vd:4|1|0|1|0|0|0|M|1|Vm:4","SEE “Related encodings” SEE VSHLL"
"0xffb30fd1","0xf3b20200","VMOVN.<dt> <Dd>, <Qm>","1|1|1|1|0|0|1|1|1|D|1|1|size:2|1|0|Vd:4|0|0|1|0|0|0|M|0|Vm:4",""
"0x0fff0fff","0x0ef10a10","VMRS<c> <Rt_nzcv>, FPSCR","cond:4|1|1|1|0|1|1|1|1|0|0|0|1|Rt:4|1|0|1|0|0|0|0|1|0|0|0|0","vfp"
"0x0fff0fff","0x0ee10a10","VMSR<c> FPSCR, <Rt>","cond:4|1|1|1|0|1|1|1|0|0|0|0|1|Rt:4|1|0|1|0|0|0|0|1|0|0|0|0","vfp"
"0xfe800e50","0xf2800840","VMUL.<dt> <Qd>, <Qn>, <Dm[x]>","1|1|1|1|0|0|1|Q|1|D|size:2|Vn:4|Vd:4|1|0|0|F|N|1|M|0|Vm:4","SEE “Related encodings”"
"0xfe800f10","0xf2000910","VMUL.<dt> <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|op|0|D|size:2|Vn:4|Vd:4|1|0|0|1|N|Q|M|1|Vm:4",""
"0xffa00f10","0xf3000d10","VMUL.F32 <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|1|0|D|0|sz|Vn:4|Vd:4|1|1|0|1|N|Q|M|1|Vm:4",""
"0x0fb00e50","0x0e200a00","VMUL<c>.F<32,64> <Sd,Dd>, <Sn,Dn>, <Sm,Dm>","cond:4|1|1|1|0|0|D|1|0|Vn:4|Vd:4|1|0|1|sz|N|0|M|0|Vm:4","vfp"
"0xfe801d50","0xf2800c00","VMULL.<dt> <Qd>, <Dn>, <Dm>","1|1|1|1|0|0|1|U|1|D|size:2|Vn:4|Vd:4|1|1|op|0|N|0|M|0|Vm:4","SEE “Related encodings”"
"0xfe801f50","0xf2800a40","VMULL.<dt> <Qd>, <Dn>, <Dm[x]>","1|1|1|1|0|0|1|U|1|D|size:2|Vn:4|Vd:4|1|0|1|0|N|1|M|0|Vm:4","SEE “Related encodings”"
"0xffbf0f90","0xf3b00580","VMVN <Qd>, <Qm>","1|1|1|1|0|0|1|1|1|D|1|1|size:2|0|0|Vd:4|0|1|0|1|1|Q|M|0|Vm:4",""
"0xfeb800b0","0xf2800030","VMVN.<dt> <Qd>, #<imm3>","1|1|1|1|0|0|1|i|1|D|0|0|0|imm3:3|Vd:4|cmode:4|0|Q|1|1|imm4:4","SEE “Related encodings”"
"0xffb30b90","0xf3b10380","VNEG.<dt> <Qd>, <Qm>","1|1|1|1|0|0|1|1|1|D|1|1|size:2|0|1|Vd:4|0|F|1|1|1|Q|M|0|Vm:4",""
"0x0fbf0ed0","0x0eb10a40","VNEG<c>.F<32,64> <Sd,Dd>, <Sm,Dm>","cond:4|1|1|1|0|1|D|1|1|0|0|0|1|Vd:4|1|0|1|sz|0|1|M|0|Vm:4","vfp"
"0x0fb00e10","0x0e100a00","VN<MLS,MLA><c>.F<32,64> <Sd,Dd>, <Sn,Dn>, <Sm,Dm>","cond:4|1|1|1|0|0|D|0|1|Vn:4|Vd:4|1|0|1|sz|N|op|M|0|Vm:4","vfp"
"0x0fb00e50","0x0e200a40","VNMUL<c>.F<32,64> <Sd,Dd>, <Sn,Dn>, <Sm,Dm>","cond:4|1|1|1|0|0|D|1|0|Vn:4|Vd:4|1|0|1|sz|N|1|M|0|Vm:4","vfp"
"0xffb00f10","0xf2300110","VORN <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|0|0|D|1|1|Vn:4|Vd:4|0|0|0|1|N|Q|M|1|Vm:4",""
"0xffb00f10","0xf2200110","VORR <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|0|0|D|1|0|Vn:4|Vd:4|0|0|0|1|N|Q|M|1|Vm:4","SEE VMOV (register)"
"0xfeb800b0","0xf2800010","VORR.<dt> <Qd>, #<imm3>","1|1|1|1|0|0|1|i|1|D|0|0|0|imm3:3|Vd:4|cmode:4|0|Q|0|1|imm4:4","SEE VMOV (immediate)"
"0xfe800f00","0xf2000a00","VP<MIN,MAX>.<dt> <Dd>, <Dn>, <Dm>","1|1|1|1|0|0|1|U|0|D|size:2|Vn:4|Vd:4|1|0|1|0|N|Q|M|op|Vm:4",""
"0xff800f10","0xf3000f00","VP<MIN,MAX>.F32 <Dd>, <Dn>, <Dm>","1|1|1|1|0|0|1|1|0|D|op|sz|Vn:4|Vd:4|1|1|1|1|N|Q|M|0|Vm:4",""
"0xffb30f10","0xf3b00600","VPADAL.<dt> <Qd>, <Qm>","1|1|1|1|0|0|1|1|1|D|1|1|size:2|0|0|Vd:4|0|1|1|0|op|Q|M|0|Vm:4",""
"0xff800f10","0xf2000b10","VPADD.<dt> <Dd>, <Dn>, <Dm>","1|1|1|1|0|0|1|0|0|D|size:2|Vn:4|Vd:4|1|0|1|1|N|Q|M|1|Vm:4",""
"0xffa00f10","0xf3000d00","VPADD.F32 <Dd>, <Dn>, <Dm>","1|1|1|1|0|0|1|1|0|D|0|sz|Vn:4|Vd:4|1|1|0|1|N|Q|M|0|Vm:4",""
"0xffb30f10","0xf3b00200","VPADDL.<dt> <Qd>, <Qm>","1|1|1|1|0|0|1|1|1|D|1|1|size:2|0|0|Vd:4|0|0|1|0|op|Q|M|0|Vm:4",""
"0x0fbf0f00","0x0cbd0a00","VPOP <vlist32>","cond:4|1|1|0|0|1|D|1|1|1|1|0|1|Vd:4|1|0|1|0|imm8:8",""
"0x0fbf0f00","0x0cbd0b00","VPOP <vlist64>","cond:4|1|1|0|0|1|D|1|1|1|1|0|1|Vd:4|1|0|1|1|imm8:8",""
"0x0fbf0f00","0x0d2d0a00","VPUSH<c> <vlist32>","cond:4|1|1|0|1|0|D|1|0|1|1|0|1|Vd:4|1|0|1|0|imm8:8",""
"0x0fbf0f00","0x0d2d0b00","VPUSH<c> <vlist64>","cond:4|1|1|0|1|0|D|1|0|1|1|0|1|Vd:4|1|0|1|1|imm8:8",""
"0xffb30f90","0xf3b00700","VQABS.<dt> <Qd>,<Qm>","1|1|1|1|0|0|1|1|1|D|1|1|size:2|0|0|Vd:4|0|1|1|1|0|Q|M|0|Vm:4",""
"0xfe800f10","0xf2000010","VQADD.<dt> <Qd>,<Qn>,<Qm>","1|1|1|1|0|0|1|U|0|D|size:2|Vn:4|Vd:4|0|0|0|0|N|Q|M|1|Vm:4",""
"0xff801d50","0xf2800900","VQD<MLAL,MLSL>.<dt> <Qd>,<Dn>,<Dm>","1|1|1|1|0|0|1|0|1|D|size:2|Vn:4|Vd:4|1|0|op|1|N|0|M|0|Vm:4","SEE “Related encodings”"
"0xff801b50","0xf2800340","VQD<MLAL,MLSL>.<dt> <Qd>,<Dn>,<Dm[x]>","1|1|1|1|0|0|1|0|1|D|size:2|Vn:4|Vd:4|0|op|1|1|N|1|M|0|Vm:4","SEE “Related encodings”"
"0xfe800f50","0xf2800c40","VQDMULH.<dt> <Qd>,<Qn>,<Dm[x]>","1|1|1|1|0|0|1|Q|1|D|size:2|Vn:4|Vd:4|1|1|0|0|N|1|M|0|Vm:4",""
"0xff800f10","0xf2000b00","VQDMULH.<dt> <Qd>,<Qn>,<Qm>","1|1|1|1|0|0|1|0|0|D|size:2|Vn:4|Vd:4|1|0|1|1|N|Q|M|0|Vm:4",""
"0xff801f50","0xf2800d00","VQDMULL.<dt> <Qd>,<Dn>,<Dm>","1|1|1|1|0|0|1|0|1|D|size:2|Vn:4|Vd:4|1|1|0|1|N|0|M|0|Vm:4","SEE “Related encodings”"
"0xff801f50","0xf2800b40","VQDMULL.<dt> <Qd>,<Dn>,<Dm[x]>","1|1|1|1|0|0|1|0|1|D|size:2|Vn:4|Vd:4|1|0|1|1|N|1|M|0|Vm:4","SEE “Related encodings”"
"0xffb30f11","0xf3b20200","VQMOV{U}N.<type><size> <Dd>, <Qm>","1|1|1|1|0|0|1|1|1|D|1|1|size:2|1|0|Vd:4|0|0|1|0|op:2|M|0|Vm:4","SEE VMOVN"
"0xffb30f90","0xf3b00780","VQNEG.<dt> <Qd>,<Qm>","1|1|1|1|0|0|1|1|1|D|1|1|size:2|0|0|Vd:4|0|1|1|1|1|Q|M|0|Vm:4",""
"0xfe800f50","0xf2800d40","VQRDMULH.<dt> <Qd>,<Qn>,<Dm[x]>","1|1|1|1|0|0|1|Q|1|D|size:2|Vn:4|Vd:4|1|1|0|1|N|1|M|0|Vm:4",""
"0xff800f10","0xf3000b00","VQRDMULH.<dt> <Qd>,<Qn>,<Qm>","1|1|1|1|0|0|1|1|0|D|size:2|Vn:4|Vd:4|1|0|1|1|N|Q|M|0|Vm:4",""
"0xfe800f10","0xf2000510","VQRSHL.<type><size> <Qd>,<Qm>,<Qn>","1|1|1|1|0|0|1|U|0|D|size:2|Vn:4|Vd:4|0|1|0|1|N|Q|M|1|Vm:4",""
"0xfe800ed1","0xf2800850","VQRSHR{U}N.<type><size> <Dd>,<Qm>,#<imm6>","1|1|1|1|0|0|1|U|1|D|imm6:6|Vd:4|1|0|0|op|0|1|M|1|Vm:4","SEE “Related encodings” SEE VRSHRN"
"0xfe800f10","0xf2000410","VQSHL.<type><size> <Qd>,<Qm>,<Qn>","1|1|1|1|0|0|1|U|0|D|size:2|Vn:4|Vd:4|0|1|0|0|N|Q|M|1|Vm:4",""
"0xfe800e90","0xf2800690","VQSHL{U}.<type><size> <Qd>,<Qm>,#<imm6>","1|1|1|1|0|0|1|U|1|D|imm6:6|Vd:4|0|1|1|op|L|Q|M|1|Vm:4","SEE “Related encodings”"
"0xfe800ed1","0xf2800810","VQSHR{U}N.<type><size> <Dd>,<Qm>,#<imm6>","1|1|1|1|0|0|1|U|1|D|imm6:6|Vd:4|1|0|0|op|0|0|M|1|Vm:4","SEE “Related encodings” SEE VSHRN"
"0xfe800f10","0xf2000210","VQSUB.<type><size> <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|U|0|D|size:2|Vn:4|Vd:4|0|0|1|0|N|Q|M|1|Vm:4",""
"0xff810f51","0xf3800400","VRADDHN.<dt> <Dd>, <Qn>, <Qm>","1|1|1|1|0|0|1|1|1|D|size:2|Vn:4|Vd:4|0|1|0|0|N|0|M|0|Vm:4","SEE “Related encodings”"
"0xffbf0e90","0xf3bb0400","VRECPE.<dt> <Qd>, <Qm>","1|1|1|1|0|0|1|1|1|D|1|1|size:2|1|1|Vd:4|0|1|0|F|0|Q|M|0|Vm:4",""
"0xffa00f10","0xf2000f10","VRECPS.F32 <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|0|0|D|0|sz|Vn:4|Vd:4|1|1|1|1|N|Q|M|1|Vm:4",""
"0xffb30e10","0xf3b00000","VREV<n>.<size> <Qd>, <Qm>","1|1|1|1|0|0|1|1|1|D|1|1|size:2|0|0|Vd:4|0|0|0|op:2|Q|M|0|Vm:4",""
"0xfe800f10","0xf2000100","VRHADD <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|U|0|D|size:2|Vn:4|Vd:4|0|0|0|1|N|Q|M|0|Vm:4",""
"0xfe800f10","0xf2000500","VRSHL.<type><size> <Qd>, <Qm>, <Qn>","1|1|1|1|0|0|1|U|0|D|size:2|Vn:4|Vd:4|0|1|0|1|N|Q|M|0|Vm:4",""
"0xfe800f90","0xf2800290","VRSHR.<type><size> <Qd>, <Qm>, #<imm6>","1|1|1|1|0|0|1|U|1|D|imm6:6|Vd:4|0|0|1|0|L|Q|M|1|Vm:4","SEE “Related encodings”"
"0xff800fd1","0xf2800850","VRSHRN.I<size> <Dd>, <Qm>, #<imm6>","1|1|1|1|0|0|1|0|1|D|imm6:6|Vd:4|1|0|0|0|0|1|M|1|Vm:4","SEE “Related encodings”"
"0xffbf0e90","0xf3bb0480","VRSQRTE.<dt> <Qd>, <Qm>","1|1|1|1|0|0|1|1|1|D|1|1|size:2|1|1|Vd:4|0|1|0|F|1|Q|M|0|Vm:4",""
"0xffa00f10","0xf2200f10","VRSQRTS.F32 <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|0|0|D|1|sz|Vn:4|Vd:4|1|1|1|1|N|Q|M|1|Vm:4",""
"0xfe800f90","0xf2800390","VRSRA.<type><size> <Qd>, <Qm>, #<imm6>","1|1|1|1|0|0|1|U|1|D|imm6:6|Vd:4|0|0|1|1|L|Q|M|1|Vm:4","SEE “Related encodings”"
"0xff810f51","0xf3800600","VRSUBHN.<dt> <Dd>, <Qn>, <Qm>","1|1|1|1|0|0|1|1|1|D|size:2|Vn:4|Vd:4|0|1|1|0|N|0|M|0|Vm:4","SEE “Related encodings”"
"0xff800f90","0xf2800590","VSHL.I<size> <Qd>, <Qm>, #<imm6>","1|1|1|1|0|0|1|0|1|D|imm6:6|Vd:4|0|1|0|1|L|Q|M|1|Vm:4","SEE “Related encodings”"
"0xfe800f10","0xf2000400","VSHL.I<size> <Qd>, <Qm>, <Qn>","1|1|1|1|0|0|1|U|0|D|size:2|Vn:4|Vd:4|0|1|0|0|N|Q|M|0|Vm:4",""
"0xffb31fd0","0xf3b20300","VSHLL.<type><size> <Qd>, <Dm>, #<immsize>","1|1|1|1|0|0|1|1|1|D|1|1|size:2|1|0|Vd:4|0|0|1|1|0|0|M|0|Vm:4",""
"0xfe801fd0","0xf2800a10","VSHLL.<type><size> <Qd>, <Dm>, #<imm6>","1|1|1|1|0|0|1|U|1|D|imm6:6|Vd:4|1|0|1|0|0|0|M|1|Vm:4","SEE “Related encodings” SEE VMOVL"
"0xfe800f90","0xf2800090","VSHR.<type><size_vs> <Qd>, <Qm>, #<imm_vs>","1|1|1|1|0|0|1|U|1|D|imm6:6|Vd:4|0|0|0|0|L|Q|M|1|Vm:4","SEE “Related encodings”"
"0xff800fd1","0xf2800810","VSHRN.I<size_vsn> <Dd>, <Qm>, #<imm_vsn>","1|1|1|1|0|0|1|0|1|D|imm6:6|Vd:4|1|0|0|0|0|0|M|1|Vm:4","SEE “Related encodings”"
"0xff800f90","0xf3800590","VSLI.<size_vs> <Qd>, <Qm>, #<imm_vs>","1|1|1|1|0|0|1|1|1|D|imm6:6|Vd:4|0|1|0|1|L|Q|M|1|Vm:4","SEE “Related encodings”"
"0x0fbf0ed0","0x0eb10ac0","VSQRT<c>.F<32,64> <Sd,Dd>, <Sm,Dm>","cond:4|1|1|1|0|1|D|1|1|0|0|0|1|Vd:4|1|0|1|sz|1|1|M|0|Vm:4","vfp"
"0xfe800f90","0xf2800190","VSRA.<type_U><size_vs> <Qd>, <Qm>, #<imm_vs>","1|1|1|1|0|0|1|U|1|D|imm6:6|Vd:4|0|0|0|1|L|Q|M|1|Vm:4","SEE “Related encodings”"
"0xff800f90","0xf3800490","VSRI.<size_vs> <Qd>, <Qm>, #<imm_vs>","1|1|1|1|0|0|1|1|1|D|imm6:6|Vd:4|0|1|0|0|L|Q|M|1|Vm:4","SEE “Related encodings”"
"0xffb00200","0xf4000200","VST1.<size> <list4>, [<Rn>{@<align>}]{!}","1|1|1|1|0|1|0|0|0|D|0|0|Rn:4|Vd:4|type:4|size:2|align:2|Rm:4","SEE “Related encodings”"
"0xffb00300","0xf4800000","VST1.<size> <list1>, [<Rn>{@<align>}]{!}","1|1|1|1|0|1|0|0|1|D|0|0|Rn:4|Vd:4|size:2|0|0|index_align:4|Rm:4",""
"0xffb00400","0xf4000000","VST2.<size> <list4>, [<Rn>{@<align>}]{!}","1|1|1|1|0|1|0|0|0|D|0|0|Rn:4|Vd:4|type:4|size:2|align:2|Rm:4","SEE “Related encodings”"
"0xffb00300","0xf4800100","VST2.<size> <list1>, [<Rn>{@<align>}]{!}","1|1|1|1|0|1|0|0|1|D|0|0|Rn:4|Vd:4|size:2|0|1|index_align:4|Rm:4",""
"0xffb00300","0xf4800200","VST3.<size> <list4>, [<Rn>]{!}","1|1|1|1|0|1|0|0|1|D|0|0|Rn:4|Vd:4|size:2|1|0|index_align:4|Rm:4",""
"0xffb00e20","0xf4000400","VST3.<size> <list1>, [<Rn>{@<align>}]{!}","1|1|1|1|0|1|0|0|0|D|0|0|Rn:4|Vd:4|type:4|size:2|align:2|Rm:4","SEE “Related encodings”"
"0xffb00e00","0xf4000000","VST4.<size> <list4>, [<Rn>{@<align>}]{!}","1|1|1|1|0|1|0|0|0|D|0|0|Rn:4|Vd:4|type:4|size:2|align:2|Rm:4","SEE “Related encodings”"
"0xffb00300","0xf4800300","VST4.<size> <list1>, [<Rn>{@<align>}]{!}","1|1|1|1|0|1|0|0|1|D|0|0|Rn:4|Vd:4|size:2|1|1|index_align:4|Rm:4",""
"0x0f300e00","0x0d000a00","VSTR<c> <Sd,Dd>, [<Rn>{,#+/-<imm8>}]","cond:4|1|1|0|1|U|D|0|0|Rn:4|Vd:4|1|0|1|sz|imm8:8","vfp"
"0xff800f10","0xf3000800","VSUB.<dt_Isize> <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|1|0|D|size:2|Vn:4|Vd:4|1|0|0|0|N|Q|M|0|Vm:4",""
"0xffa00f10","0xf2200d00","VSUB.F32 <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|0|0|D|1|sz|Vn:4|Vd:4|1|1|0|1|N|Q|M|0|Vm:4",""
"0x0fb00e50","0x0e300a40","VSUB<c>.F<32,64> <Sd,Dd>, <Sn,Dn>, <Sm,Dm>","cond:4|1|1|1|0|0|D|1|1|Vn:4|Vd:4|1|0|1|sz|N|1|M|0|Vm:4","vfp"
"0xff810f51","0xf2800600","VSUBHN.<dt_Isize> <Dd>, <Qn>, <Qm>","1|1|1|1|0|0|1|0|1|D|size:2|Vn:4|Vd:4|0|1|1|0|N|0|M|0|Vm:4","SEE “Related encodings”"
"0xfe801e50","0xf2800200","VSUBL.<dt_Usize> <Qd>, <Dn>, <Dm>","1|1|1|1|0|0|1|U|1|D|size:2|Vn:4|Vd:4|0|0|1|op|N|0|M|0|Vm:4","SEE “Related encodings”"
"0xffbf0f90","0xf3b20000","VSWP <Qd>, <Qm>","1|1|1|1|0|0|1|1|1|D|1|1|size:2|1|0|Vd:4|0|0|0|0|0|Q|M|0|Vm:4",""
"0xffb30f90","0xf3b20080","VTRN.<size_n> <Qd>, <Qm>","1|1|1|1|0|0|1|1|1|D|1|1|size:2|1|0|Vd:4|0|0|0|0|1|Q|M|0|Vm:4",""
"0xff800f10","0xf2000810","VTST.<size_n> <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|0|0|D|size:2|Vn:4|Vd:4|1|0|0|0|N|Q|M|1|Vm:4",""
"0xffb30f90","0xf3b20100","VUZP.<size_n> <Qd>, <Qm>","1|1|1|1|0|0|1|1|1|D|1|1|size:2|1|0|Vd:4|0|0|0|1|0|Q|M|0|Vm:4",""
"0xffb30f90","0xf3b20180","VZIP.<size_n> <Qd>, <Qm>","1|1|1|1|0|0|1|1|1|D|1|1|size:2|1|0|Vd:4|0|0|0|1|1|Q|M|0|Vm:4",""
"0x0fffffff","0x0320f002","WFE<c>","cond:4|0|0|1|1|0|0|1|0|0|0|0|0|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|0|0|0|0|0|1|0",""
"0x0fffffff","0x0320f003","WFI<c>","cond:4|0|0|1|1|0|0|1|0|0|0|0|0|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|0|0|0|0|0|1|1",""
"0x0fffffff","0x0320f001","YIELD<c>","cond:4|0|0|1|1|0|0|1|0|0|0|0|0|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|0|0|0|0|0|0|1",""
"0xffffffff","0xf7fabcfd","UNDEF","1|1|1|1|0|1|1|1|1|1|1|1|1|0|1|0|1|0|1|1|1|1|0|0|1|1|1|1|1|1|0|1",""
Can't render this file because it has a wrong number of fields in line 4.

2
vendor/golang.org/x/arch/arm/armasm/Makefile generated vendored Normal file
View File

@ -0,0 +1,2 @@
tables.go: ../armmap/map.go ../arm.csv
go run ../armmap/map.go -fmt=decoder ../arm.csv >_tables.go && gofmt _tables.go >tables.go && rm _tables.go

567
vendor/golang.org/x/arch/arm/armasm/decode.go generated vendored Normal file
View File

@ -0,0 +1,567 @@
// Copyright 2014 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 armasm
import (
"encoding/binary"
"fmt"
)
// An instFormat describes the format of an instruction encoding.
// An instruction with 32-bit value x matches the format if x&mask == value
// and the condition matches.
// The condition matches if x>>28 == 0xF && value>>28==0xF
// or if x>>28 != 0xF and value>>28 == 0.
// If x matches the format, then the rest of the fields describe how to interpret x.
// The opBits describe bits that should be extracted from x and added to the opcode.
// For example opBits = 0x1234 means that the value
// (2 bits at offset 1) followed by (4 bits at offset 3)
// should be added to op.
// Finally the args describe how to decode the instruction arguments.
// args is stored as a fixed-size array; if there are fewer than len(args) arguments,
// args[i] == 0 marks the end of the argument list.
type instFormat struct {
mask uint32
value uint32
priority int8
op Op
opBits uint64
args instArgs
}
type instArgs [4]instArg
var (
errMode = fmt.Errorf("unsupported execution mode")
errShort = fmt.Errorf("truncated instruction")
errUnknown = fmt.Errorf("unknown instruction")
)
var decoderCover []bool
// Decode decodes the leading bytes in src as a single instruction.
func Decode(src []byte, mode Mode) (inst Inst, err error) {
if mode != ModeARM {
return Inst{}, errMode
}
if len(src) < 4 {
return Inst{}, errShort
}
if decoderCover == nil {
decoderCover = make([]bool, len(instFormats))
}
x := binary.LittleEndian.Uint32(src)
// The instFormat table contains both conditional and unconditional instructions.
// Considering only the top 4 bits, the conditional instructions use mask=0, value=0,
// while the unconditional instructions use mask=f, value=f.
// Prepare a version of x with the condition cleared to 0 in conditional instructions
// and then assume mask=f during matching.
const condMask = 0xf0000000
xNoCond := x
if x&condMask != condMask {
xNoCond &^= condMask
}
var priority int8
Search:
for i := range instFormats {
f := &instFormats[i]
if xNoCond&(f.mask|condMask) != f.value || f.priority <= priority {
continue
}
delta := uint32(0)
deltaShift := uint(0)
for opBits := f.opBits; opBits != 0; opBits >>= 16 {
n := uint(opBits & 0xFF)
off := uint((opBits >> 8) & 0xFF)
delta |= (x >> off) & (1<<n - 1) << deltaShift
deltaShift += n
}
op := f.op + Op(delta)
// Special case: BKPT encodes with condition but cannot have one.
if op&^15 == BKPT_EQ && op != BKPT {
continue Search
}
var args Args
for j, aop := range f.args {
if aop == 0 {
break
}
arg := decodeArg(aop, x)
if arg == nil { // cannot decode argument
continue Search
}
args[j] = arg
}
decoderCover[i] = true
inst = Inst{
Op: op,
Args: args,
Enc: x,
Len: 4,
}
priority = f.priority
continue Search
}
if inst.Op != 0 {
return inst, nil
}
return Inst{}, errUnknown
}
// An instArg describes the encoding of a single argument.
// In the names used for arguments, _p_ means +, _m_ means -,
// _pm_ means ± (usually keyed by the U bit).
// The _W suffix indicates a general addressing mode based on the P and W bits.
// The _offset and _postindex suffixes force the given addressing mode.
// The rest should be somewhat self-explanatory, at least given
// the decodeArg function.
type instArg uint8
const (
_ instArg = iota
arg_APSR
arg_FPSCR
arg_Dn_half
arg_R1_0
arg_R1_12
arg_R2_0
arg_R2_12
arg_R_0
arg_R_12
arg_R_12_nzcv
arg_R_16
arg_R_16_WB
arg_R_8
arg_R_rotate
arg_R_shift_R
arg_R_shift_imm
arg_SP
arg_Sd
arg_Sd_Dd
arg_Dd_Sd
arg_Sm
arg_Sm_Dm
arg_Sn
arg_Sn_Dn
arg_const
arg_endian
arg_fbits
arg_fp_0
arg_imm24
arg_imm5
arg_imm5_32
arg_imm5_nz
arg_imm_12at8_4at0
arg_imm_4at16_12at0
arg_imm_vfp
arg_label24
arg_label24H
arg_label_m_12
arg_label_p_12
arg_label_pm_12
arg_label_pm_4_4
arg_lsb_width
arg_mem_R
arg_mem_R_pm_R_W
arg_mem_R_pm_R_postindex
arg_mem_R_pm_R_shift_imm_W
arg_mem_R_pm_R_shift_imm_offset
arg_mem_R_pm_R_shift_imm_postindex
arg_mem_R_pm_imm12_W
arg_mem_R_pm_imm12_offset
arg_mem_R_pm_imm12_postindex
arg_mem_R_pm_imm8_W
arg_mem_R_pm_imm8_postindex
arg_mem_R_pm_imm8at0_offset
arg_option
arg_registers
arg_registers1
arg_registers2
arg_satimm4
arg_satimm5
arg_satimm4m1
arg_satimm5m1
arg_widthm1
)
// decodeArg decodes the arg described by aop from the instruction bits x.
// It returns nil if x cannot be decoded according to aop.
func decodeArg(aop instArg, x uint32) Arg {
switch aop {
default:
return nil
case arg_APSR:
return APSR
case arg_FPSCR:
return FPSCR
case arg_R_0:
return Reg(x & (1<<4 - 1))
case arg_R_8:
return Reg((x >> 8) & (1<<4 - 1))
case arg_R_12:
return Reg((x >> 12) & (1<<4 - 1))
case arg_R_16:
return Reg((x >> 16) & (1<<4 - 1))
case arg_R_12_nzcv:
r := Reg((x >> 12) & (1<<4 - 1))
if r == R15 {
return APSR_nzcv
}
return r
case arg_R_16_WB:
mode := AddrLDM
if (x>>21)&1 != 0 {
mode = AddrLDM_WB
}
return Mem{Base: Reg((x >> 16) & (1<<4 - 1)), Mode: mode}
case arg_R_rotate:
Rm := Reg(x & (1<<4 - 1))
typ, count := decodeShift(x)
// ROR #0 here means ROR #0, but decodeShift rewrites to RRX #1.
if typ == RotateRightExt {
return Reg(Rm)
}
return RegShift{Rm, typ, uint8(count)}
case arg_R_shift_R:
Rm := Reg(x & (1<<4 - 1))
Rs := Reg((x >> 8) & (1<<4 - 1))
typ := Shift((x >> 5) & (1<<2 - 1))
return RegShiftReg{Rm, typ, Rs}
case arg_R_shift_imm:
Rm := Reg(x & (1<<4 - 1))
typ, count := decodeShift(x)
if typ == ShiftLeft && count == 0 {
return Reg(Rm)
}
return RegShift{Rm, typ, uint8(count)}
case arg_R1_0:
return Reg((x & (1<<4 - 1)))
case arg_R1_12:
return Reg(((x >> 12) & (1<<4 - 1)))
case arg_R2_0:
return Reg((x & (1<<4 - 1)) | 1)
case arg_R2_12:
return Reg(((x >> 12) & (1<<4 - 1)) | 1)
case arg_SP:
return SP
case arg_Sd_Dd:
v := (x >> 12) & (1<<4 - 1)
vx := (x >> 22) & 1
sz := (x >> 8) & 1
if sz != 0 {
return D0 + Reg(vx<<4+v)
} else {
return S0 + Reg(v<<1+vx)
}
case arg_Dd_Sd:
return decodeArg(arg_Sd_Dd, x^(1<<8))
case arg_Sd:
v := (x >> 12) & (1<<4 - 1)
vx := (x >> 22) & 1
return S0 + Reg(v<<1+vx)
case arg_Sm_Dm:
v := (x >> 0) & (1<<4 - 1)
vx := (x >> 5) & 1
sz := (x >> 8) & 1
if sz != 0 {
return D0 + Reg(vx<<4+v)
} else {
return S0 + Reg(v<<1+vx)
}
case arg_Sm:
v := (x >> 0) & (1<<4 - 1)
vx := (x >> 5) & 1
return S0 + Reg(v<<1+vx)
case arg_Dn_half:
v := (x >> 16) & (1<<4 - 1)
vx := (x >> 7) & 1
return RegX{D0 + Reg(vx<<4+v), int((x >> 21) & 1)}
case arg_Sn_Dn:
v := (x >> 16) & (1<<4 - 1)
vx := (x >> 7) & 1
sz := (x >> 8) & 1
if sz != 0 {
return D0 + Reg(vx<<4+v)
} else {
return S0 + Reg(v<<1+vx)
}
case arg_Sn:
v := (x >> 16) & (1<<4 - 1)
vx := (x >> 7) & 1
return S0 + Reg(v<<1+vx)
case arg_const:
v := x & (1<<8 - 1)
rot := (x >> 8) & (1<<4 - 1) * 2
if rot > 0 && v&3 == 0 {
// could rotate less
return ImmAlt{uint8(v), uint8(rot)}
}
if rot >= 24 && ((v<<(32-rot))&0xFF)>>(32-rot) == v {
// could wrap around to rot==0.
return ImmAlt{uint8(v), uint8(rot)}
}
return Imm(v>>rot | v<<(32-rot))
case arg_endian:
return Endian((x >> 9) & 1)
case arg_fbits:
return Imm((16 << ((x >> 7) & 1)) - ((x&(1<<4-1))<<1 | (x>>5)&1))
case arg_fp_0:
return Imm(0)
case arg_imm24:
return Imm(x & (1<<24 - 1))
case arg_imm5:
return Imm((x >> 7) & (1<<5 - 1))
case arg_imm5_32:
x = (x >> 7) & (1<<5 - 1)
if x == 0 {
x = 32
}
return Imm(x)
case arg_imm5_nz:
x = (x >> 7) & (1<<5 - 1)
if x == 0 {
return nil
}
return Imm(x)
case arg_imm_4at16_12at0:
return Imm((x>>16)&(1<<4-1)<<12 | x&(1<<12-1))
case arg_imm_12at8_4at0:
return Imm((x>>8)&(1<<12-1)<<4 | x&(1<<4-1))
case arg_imm_vfp:
x = (x>>16)&(1<<4-1)<<4 | x&(1<<4-1)
return Imm(x)
case arg_label24:
imm := (x & (1<<24 - 1)) << 2
return PCRel(int32(imm<<6) >> 6)
case arg_label24H:
h := (x >> 24) & 1
imm := (x&(1<<24-1))<<2 | h<<1
return PCRel(int32(imm<<6) >> 6)
case arg_label_m_12:
d := int32(x & (1<<12 - 1))
return Mem{Base: PC, Mode: AddrOffset, Offset: int16(-d)}
case arg_label_p_12:
d := int32(x & (1<<12 - 1))
return Mem{Base: PC, Mode: AddrOffset, Offset: int16(d)}
case arg_label_pm_12:
d := int32(x & (1<<12 - 1))
u := (x >> 23) & 1
if u == 0 {
d = -d
}
return Mem{Base: PC, Mode: AddrOffset, Offset: int16(d)}
case arg_label_pm_4_4:
d := int32((x>>8)&(1<<4-1)<<4 | x&(1<<4-1))
u := (x >> 23) & 1
if u == 0 {
d = -d
}
return PCRel(d)
case arg_lsb_width:
lsb := (x >> 7) & (1<<5 - 1)
msb := (x >> 16) & (1<<5 - 1)
if msb < lsb || msb >= 32 {
return nil
}
return Imm(msb + 1 - lsb)
case arg_mem_R:
Rn := Reg((x >> 16) & (1<<4 - 1))
return Mem{Base: Rn, Mode: AddrOffset}
case arg_mem_R_pm_R_postindex:
// Treat [<Rn>],+/-<Rm> like [<Rn>,+/-<Rm>{,<shift>}]{!}
// by forcing shift bits to <<0 and P=0, W=0 (postindex=true).
return decodeArg(arg_mem_R_pm_R_shift_imm_W, x&^((1<<7-1)<<5|1<<24|1<<21))
case arg_mem_R_pm_R_W:
// Treat [<Rn>,+/-<Rm>]{!} like [<Rn>,+/-<Rm>{,<shift>}]{!}
// by forcing shift bits to <<0.
return decodeArg(arg_mem_R_pm_R_shift_imm_W, x&^((1<<7-1)<<5))
case arg_mem_R_pm_R_shift_imm_offset:
// Treat [<Rn>],+/-<Rm>{,<shift>} like [<Rn>,+/-<Rm>{,<shift>}]{!}
// by forcing P=1, W=0 (index=false, wback=false).
return decodeArg(arg_mem_R_pm_R_shift_imm_W, x&^(1<<21)|1<<24)
case arg_mem_R_pm_R_shift_imm_postindex:
// Treat [<Rn>],+/-<Rm>{,<shift>} like [<Rn>,+/-<Rm>{,<shift>}]{!}
// by forcing P=0, W=0 (postindex=true).
return decodeArg(arg_mem_R_pm_R_shift_imm_W, x&^(1<<24|1<<21))
case arg_mem_R_pm_R_shift_imm_W:
Rn := Reg((x >> 16) & (1<<4 - 1))
Rm := Reg(x & (1<<4 - 1))
typ, count := decodeShift(x)
u := (x >> 23) & 1
w := (x >> 21) & 1
p := (x >> 24) & 1
if p == 0 && w == 1 {
return nil
}
sign := int8(+1)
if u == 0 {
sign = -1
}
mode := AddrMode(uint8(p<<1) | uint8(w^1))
return Mem{Base: Rn, Mode: mode, Sign: sign, Index: Rm, Shift: typ, Count: count}
case arg_mem_R_pm_imm12_offset:
// Treat [<Rn>,#+/-<imm12>] like [<Rn>{,#+/-<imm12>}]{!}
// by forcing P=1, W=0 (index=false, wback=false).
return decodeArg(arg_mem_R_pm_imm12_W, x&^(1<<21)|1<<24)
case arg_mem_R_pm_imm12_postindex:
// Treat [<Rn>],#+/-<imm12> like [<Rn>{,#+/-<imm12>}]{!}
// by forcing P=0, W=0 (postindex=true).
return decodeArg(arg_mem_R_pm_imm12_W, x&^(1<<24|1<<21))
case arg_mem_R_pm_imm12_W:
Rn := Reg((x >> 16) & (1<<4 - 1))
u := (x >> 23) & 1
w := (x >> 21) & 1
p := (x >> 24) & 1
if p == 0 && w == 1 {
return nil
}
sign := int8(+1)
if u == 0 {
sign = -1
}
imm := int16(x & (1<<12 - 1))
mode := AddrMode(uint8(p<<1) | uint8(w^1))
return Mem{Base: Rn, Mode: mode, Offset: int16(sign) * imm}
case arg_mem_R_pm_imm8_postindex:
// Treat [<Rn>],#+/-<imm8> like [<Rn>{,#+/-<imm8>}]{!}
// by forcing P=0, W=0 (postindex=true).
return decodeArg(arg_mem_R_pm_imm8_W, x&^(1<<24|1<<21))
case arg_mem_R_pm_imm8_W:
Rn := Reg((x >> 16) & (1<<4 - 1))
u := (x >> 23) & 1
w := (x >> 21) & 1
p := (x >> 24) & 1
if p == 0 && w == 1 {
return nil
}
sign := int8(+1)
if u == 0 {
sign = -1
}
imm := int16((x>>8)&(1<<4-1)<<4 | x&(1<<4-1))
mode := AddrMode(uint8(p<<1) | uint8(w^1))
return Mem{Base: Rn, Mode: mode, Offset: int16(sign) * imm}
case arg_mem_R_pm_imm8at0_offset:
Rn := Reg((x >> 16) & (1<<4 - 1))
u := (x >> 23) & 1
sign := int8(+1)
if u == 0 {
sign = -1
}
imm := int16(x&(1<<8-1)) << 2
return Mem{Base: Rn, Mode: AddrOffset, Offset: int16(sign) * imm}
case arg_option:
return Imm(x & (1<<4 - 1))
case arg_registers:
return RegList(x & (1<<16 - 1))
case arg_registers2:
x &= 1<<16 - 1
n := 0
for i := 0; i < 16; i++ {
if x>>uint(i)&1 != 0 {
n++
}
}
if n < 2 {
return nil
}
return RegList(x)
case arg_registers1:
Rt := (x >> 12) & (1<<4 - 1)
return RegList(1 << Rt)
case arg_satimm4:
return Imm((x >> 16) & (1<<4 - 1))
case arg_satimm5:
return Imm((x >> 16) & (1<<5 - 1))
case arg_satimm4m1:
return Imm((x>>16)&(1<<4-1) + 1)
case arg_satimm5m1:
return Imm((x>>16)&(1<<5-1) + 1)
case arg_widthm1:
return Imm((x>>16)&(1<<5-1) + 1)
}
}
// decodeShift decodes the shift-by-immediate encoded in x.
func decodeShift(x uint32) (Shift, uint8) {
count := (x >> 7) & (1<<5 - 1)
typ := Shift((x >> 5) & (1<<2 - 1))
switch typ {
case ShiftRight, ShiftRightSigned:
if count == 0 {
count = 32
}
case RotateRight:
if count == 0 {
typ = RotateRightExt
count = 1
}
}
return typ, uint8(count)
}

69
vendor/golang.org/x/arch/arm/armasm/decode_test.go generated vendored Normal file
View File

@ -0,0 +1,69 @@
// Copyright 2014 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 armasm
import (
"encoding/hex"
"io/ioutil"
"strconv"
"strings"
"testing"
)
func TestDecode(t *testing.T) {
data, err := ioutil.ReadFile("testdata/decode.txt")
if err != nil {
t.Fatal(err)
}
all := string(data)
for strings.Contains(all, "\t\t") {
all = strings.Replace(all, "\t\t", "\t", -1)
}
for _, line := range strings.Split(all, "\n") {
line = strings.TrimSpace(line)
if line == "" || strings.HasPrefix(line, "#") {
continue
}
f := strings.SplitN(line, "\t", 4)
i := strings.Index(f[0], "|")
if i < 0 {
t.Errorf("parsing %q: missing | separator", f[0])
continue
}
if i%2 != 0 {
t.Errorf("parsing %q: misaligned | separator", f[0])
}
size := i / 2
code, err := hex.DecodeString(f[0][:i] + f[0][i+1:])
if err != nil {
t.Errorf("parsing %q: %v", f[0], err)
continue
}
mode, err := strconv.Atoi(f[1])
if err != nil {
t.Errorf("invalid mode %q in: %s", f[1], line)
continue
}
syntax, asm := f[2], f[3]
inst, err := Decode(code, Mode(mode))
var out string
if err != nil {
out = "error: " + err.Error()
} else {
switch syntax {
case "gnu":
out = GNUSyntax(inst)
case "plan9": // [sic]
out = GoSyntax(inst, 0, nil, nil)
default:
t.Errorf("unknown syntax %q", syntax)
continue
}
}
if out != asm || inst.Len != size {
t.Errorf("Decode(%s) [%s] = %s, %d, want %s, %d", f[0], syntax, out, inst.Len, asm, size)
}
}
}

614
vendor/golang.org/x/arch/arm/armasm/ext_test.go generated vendored Normal file
View File

@ -0,0 +1,614 @@
// Copyright 2014 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.
// Support for testing against external disassembler program.
// Copied and simplified from ../../x86/x86asm/ext_test.go.
package armasm
import (
"bufio"
"bytes"
"encoding/hex"
"flag"
"fmt"
"io/ioutil"
"log"
"math/rand"
"os"
"os/exec"
"regexp"
"runtime"
"strings"
"testing"
"time"
)
var (
printTests = flag.Bool("printtests", false, "print test cases that exercise new code paths")
dumpTest = flag.Bool("dump", false, "dump all encodings")
mismatch = flag.Bool("mismatch", false, "log allowed mismatches")
longTest = flag.Bool("long", false, "long test")
keep = flag.Bool("keep", false, "keep object files around")
debug = false
)
// A ExtInst represents a single decoded instruction parsed
// from an external disassembler's output.
type ExtInst struct {
addr uint32
enc [4]byte
nenc int
text string
}
func (r ExtInst) String() string {
return fmt.Sprintf("%#x: % x: %s", r.addr, r.enc, r.text)
}
// An ExtDis is a connection between an external disassembler and a test.
type ExtDis struct {
Arch Mode
Dec chan ExtInst
File *os.File
Size int
KeepFile bool
Cmd *exec.Cmd
}
// Run runs the given command - the external disassembler - and returns
// a buffered reader of its standard output.
func (ext *ExtDis) Run(cmd ...string) (*bufio.Reader, error) {
if *keep {
log.Printf("%s\n", strings.Join(cmd, " "))
}
ext.Cmd = exec.Command(cmd[0], cmd[1:]...)
out, err := ext.Cmd.StdoutPipe()
if err != nil {
return nil, fmt.Errorf("stdoutpipe: %v", err)
}
if err := ext.Cmd.Start(); err != nil {
return nil, fmt.Errorf("exec: %v", err)
}
b := bufio.NewReaderSize(out, 1<<20)
return b, nil
}
// Wait waits for the command started with Run to exit.
func (ext *ExtDis) Wait() error {
return ext.Cmd.Wait()
}
// testExtDis tests a set of byte sequences against an external disassembler.
// The disassembler is expected to produce the given syntax and be run
// in the given architecture mode (16, 32, or 64-bit).
// The extdis function must start the external disassembler
// and then parse its output, sending the parsed instructions on ext.Dec.
// The generate function calls its argument f once for each byte sequence
// to be tested. The generate function itself will be called twice, and it must
// make the same sequence of calls to f each time.
// When a disassembly does not match the internal decoding,
// allowedMismatch determines whether this mismatch should be
// allowed, or else considered an error.
func testExtDis(
t *testing.T,
syntax string,
arch Mode,
extdis func(ext *ExtDis) error,
generate func(f func([]byte)),
allowedMismatch func(text string, size int, inst *Inst, dec ExtInst) bool,
) {
start := time.Now()
ext := &ExtDis{
Dec: make(chan ExtInst),
Arch: arch,
}
errc := make(chan error)
// First pass: write instructions to input file for external disassembler.
file, f, size, err := writeInst(generate)
if err != nil {
t.Fatal(err)
}
ext.Size = size
ext.File = f
defer func() {
f.Close()
if !*keep {
os.Remove(file)
}
}()
// Second pass: compare disassembly against our decodings.
var (
totalTests = 0
totalSkips = 0
totalErrors = 0
errors = make([]string, 0, 100) // sampled errors, at most cap
)
go func() {
errc <- extdis(ext)
}()
generate(func(enc []byte) {
dec, ok := <-ext.Dec
if !ok {
t.Errorf("decoding stream ended early")
return
}
inst, text := disasm(syntax, arch, pad(enc))
totalTests++
if *dumpTest {
fmt.Printf("%x -> %s [%d]\n", enc[:len(enc)], dec.text, dec.nenc)
}
if text != dec.text || inst.Len != dec.nenc {
suffix := ""
if allowedMismatch(text, size, &inst, dec) {
totalSkips++
if !*mismatch {
return
}
suffix += " (allowed mismatch)"
}
totalErrors++
if len(errors) >= cap(errors) {
j := rand.Intn(totalErrors)
if j >= cap(errors) {
return
}
errors = append(errors[:j], errors[j+1:]...)
}
errors = append(errors, fmt.Sprintf("decode(%x) = %q, %d, want %q, %d%s", enc, text, inst.Len, dec.text, dec.nenc, suffix))
}
})
if *mismatch {
totalErrors -= totalSkips
}
for _, b := range errors {
t.Log(b)
}
if totalErrors > 0 {
t.Fail()
}
t.Logf("%d test cases, %d expected mismatches, %d failures; %.0f cases/second", totalTests, totalSkips, totalErrors, float64(totalTests)/time.Since(start).Seconds())
if err := <-errc; err != nil {
t.Fatalf("external disassembler: %v", err)
}
}
const start = 0x8000 // start address of text
// writeInst writes the generated byte sequences to a new file
// starting at offset start. That file is intended to be the input to
// the external disassembler.
func writeInst(generate func(func([]byte))) (file string, f *os.File, size int, err error) {
f, err = ioutil.TempFile("", "armasm")
if err != nil {
return
}
file = f.Name()
f.Seek(start, 0)
w := bufio.NewWriter(f)
defer w.Flush()
size = 0
generate(func(x []byte) {
if len(x) > 4 {
x = x[:4]
}
if debug {
fmt.Printf("%#x: %x%x\n", start+size, x, zeros[len(x):])
}
w.Write(x)
w.Write(zeros[len(x):])
size += len(zeros)
})
return file, f, size, nil
}
var zeros = []byte{0, 0, 0, 0}
// pad pads the code sequence with pops.
func pad(enc []byte) []byte {
if len(enc) < 4 {
enc = append(enc[:len(enc):len(enc)], zeros[:4-len(enc)]...)
}
return enc
}
// disasm returns the decoded instruction and text
// for the given source bytes, using the given syntax and mode.
func disasm(syntax string, mode Mode, src []byte) (inst Inst, text string) {
// If printTests is set, we record the coverage value
// before and after, and we write out the inputs for which
// coverage went up, in the format expected in testdata/decode.text.
// This produces a fairly small set of test cases that exercise nearly
// all the code.
var cover float64
if *printTests {
cover -= coverage()
}
inst, err := Decode(src, mode)
if err != nil {
text = "error: " + err.Error()
} else {
text = inst.String()
switch syntax {
//case "arm":
// text = ARMSyntax(inst)
case "gnu":
text = GNUSyntax(inst)
//case "plan9": // [sic]
// text = GoSyntax(inst, 0, nil)
default:
text = "error: unknown syntax " + syntax
}
}
if *printTests {
cover += coverage()
if cover > 0 {
max := len(src)
if max > 4 && inst.Len <= 4 {
max = 4
}
fmt.Printf("%x|%x\t%d\t%s\t%s\n", src[:inst.Len], src[inst.Len:max], mode, syntax, text)
}
}
return
}
// coverage returns a floating point number denoting the
// test coverage until now. The number increases when new code paths are exercised,
// both in the Go program and in the decoder byte code.
func coverage() float64 {
/*
testing.Coverage is not in the main distribution.
The implementation, which must go in package testing, is:
// Coverage reports the current code coverage as a fraction in the range [0, 1].
func Coverage() float64 {
var n, d int64
for _, counters := range cover.Counters {
for _, c := range counters {
if c > 0 {
n++
}
d++
}
}
if d == 0 {
return 0
}
return float64(n) / float64(d)
}
*/
var f float64
f += testing.Coverage()
f += decodeCoverage()
return f
}
func decodeCoverage() float64 {
n := 0
for _, t := range decoderCover {
if t {
n++
}
}
return float64(1+n) / float64(1+len(decoderCover))
}
// Helpers for writing disassembler output parsers.
// hasPrefix reports whether any of the space-separated words in the text s
// begins with any of the given prefixes.
func hasPrefix(s string, prefixes ...string) bool {
for _, prefix := range prefixes {
for s := s; s != ""; {
if strings.HasPrefix(s, prefix) {
return true
}
i := strings.Index(s, " ")
if i < 0 {
break
}
s = s[i+1:]
}
}
return false
}
// contains reports whether the text s contains any of the given substrings.
func contains(s string, substrings ...string) bool {
for _, sub := range substrings {
if strings.Contains(s, sub) {
return true
}
}
return false
}
// isHex reports whether b is a hexadecimal character (0-9A-Fa-f).
func isHex(b byte) bool { return b == '0' || unhex[b] > 0 }
// parseHex parses the hexadecimal byte dump in hex,
// appending the parsed bytes to raw and returning the updated slice.
// The returned bool signals whether any invalid hex was found.
// Spaces and tabs between bytes are okay but any other non-hex is not.
func parseHex(hex []byte, raw []byte) ([]byte, bool) {
hex = trimSpace(hex)
for j := 0; j < len(hex); {
for hex[j] == ' ' || hex[j] == '\t' {
j++
}
if j >= len(hex) {
break
}
if j+2 > len(hex) || !isHex(hex[j]) || !isHex(hex[j+1]) {
return nil, false
}
raw = append(raw, unhex[hex[j]]<<4|unhex[hex[j+1]])
j += 2
}
return raw, true
}
var unhex = [256]byte{
'0': 0,
'1': 1,
'2': 2,
'3': 3,
'4': 4,
'5': 5,
'6': 6,
'7': 7,
'8': 8,
'9': 9,
'A': 10,
'B': 11,
'C': 12,
'D': 13,
'E': 14,
'F': 15,
'a': 10,
'b': 11,
'c': 12,
'd': 13,
'e': 14,
'f': 15,
}
// index is like bytes.Index(s, []byte(t)) but avoids the allocation.
func index(s []byte, t string) int {
i := 0
for {
j := bytes.IndexByte(s[i:], t[0])
if j < 0 {
return -1
}
i = i + j
if i+len(t) > len(s) {
return -1
}
for k := 1; k < len(t); k++ {
if s[i+k] != t[k] {
goto nomatch
}
}
return i
nomatch:
i++
}
}
// fixSpace rewrites runs of spaces, tabs, and newline characters into single spaces in s.
// If s must be rewritten, it is rewritten in place.
func fixSpace(s []byte) []byte {
s = trimSpace(s)
for i := 0; i < len(s); i++ {
if s[i] == '\t' || s[i] == '\n' || i > 0 && s[i] == ' ' && s[i-1] == ' ' {
goto Fix
}
}
return s
Fix:
b := s
w := 0
for i := 0; i < len(s); i++ {
c := s[i]
if c == '\t' || c == '\n' {
c = ' '
}
if c == ' ' && w > 0 && b[w-1] == ' ' {
continue
}
b[w] = c
w++
}
if w > 0 && b[w-1] == ' ' {
w--
}
return b[:w]
}
// trimSpace trims leading and trailing space from s, returning a subslice of s.
func trimSpace(s []byte) []byte {
j := len(s)
for j > 0 && (s[j-1] == ' ' || s[j-1] == '\t' || s[j-1] == '\n') {
j--
}
i := 0
for i < j && (s[i] == ' ' || s[i] == '\t') {
i++
}
return s[i:j]
}
// pcrel matches instructions using relative addressing mode.
var (
pcrel = regexp.MustCompile(`^((?:.* )?(?:b|bl)x?(?:eq|ne|cs|cc|mi|pl|vs|vc|hi|ls|ge|lt|gt|le)?) 0x([0-9a-f]+)$`)
)
// Generators.
//
// The test cases are described as functions that invoke a callback repeatedly,
// with a new input sequence each time. These helpers make writing those
// a little easier.
// condCases generates conditional instructions.
func condCases(t *testing.T) func(func([]byte)) {
return func(try func([]byte)) {
// All the strides are relatively prime to 2 and therefore to 2²⁸,
// so we will not repeat any instructions until we have tried all 2²⁸.
// Using a stride other than 1 is meant to visit the instructions in a
// pseudorandom order, which gives better variety in the set of
// test cases chosen by -printtests.
stride := uint32(10007)
n := 1 << 28 / 7
if testing.Short() {
stride = 100003
n = 1 << 28 / 1001
} else if *longTest {
stride = 200000033
n = 1 << 28
}
x := uint32(0)
for i := 0; i < n; i++ {
enc := (x%15)<<28 | x&(1<<28-1)
try([]byte{byte(enc), byte(enc >> 8), byte(enc >> 16), byte(enc >> 24)})
x += stride
}
}
}
// uncondCases generates unconditional instructions.
func uncondCases(t *testing.T) func(func([]byte)) {
return func(try func([]byte)) {
condCases(t)(func(enc []byte) {
enc[3] |= 0xF0
try(enc)
})
}
}
func countBits(x uint32) int {
n := 0
for ; x != 0; x >>= 1 {
n += int(x & 1)
}
return n
}
func expandBits(x, m uint32) uint32 {
var out uint32
for i := uint(0); i < 32; i++ {
out >>= 1
if m&1 != 0 {
out |= (x & 1) << 31
x >>= 1
}
m >>= 1
}
return out
}
func tryCondMask(mask, val uint32, try func([]byte)) {
n := countBits(^mask)
bits := uint32(0)
for i := 0; i < 1<<uint(n); i++ {
bits += 848251 // arbitrary prime
x := val | expandBits(bits, ^mask) | uint32(i)%15<<28
try([]byte{byte(x), byte(x >> 8), byte(x >> 16), byte(x >> 24)})
}
}
// vfpCases generates VFP instructions.
func vfpCases(t *testing.T) func(func([]byte)) {
const (
vfpmask uint32 = 0xFF00FE10
vfp uint32 = 0x0E009A00
)
return func(try func([]byte)) {
tryCondMask(0xff00fe10, 0x0e009a00, try) // standard VFP instruction space
tryCondMask(0xffc00f7f, 0x0e000b10, try) // VFP MOV core reg to/from float64 half
tryCondMask(0xffe00f7f, 0x0e000a10, try) // VFP MOV core reg to/from float32
tryCondMask(0xffef0fff, 0x0ee10a10, try) // VFP MOV core reg to/from cond codes
}
}
// hexCases generates the cases written in hexadecimal in the encoded string.
// Spaces in 'encoded' separate entire test cases, not individual bytes.
func hexCases(t *testing.T, encoded string) func(func([]byte)) {
return func(try func([]byte)) {
for _, x := range strings.Fields(encoded) {
src, err := hex.DecodeString(x)
if err != nil {
t.Errorf("parsing %q: %v", x, err)
}
try(src)
}
}
}
// testdataCases generates the test cases recorded in testdata/decode.txt.
// It only uses the inputs; it ignores the answers recorded in that file.
func testdataCases(t *testing.T) func(func([]byte)) {
var codes [][]byte
data, err := ioutil.ReadFile("testdata/decode.txt")
if err != nil {
t.Fatal(err)
}
for _, line := range strings.Split(string(data), "\n") {
line = strings.TrimSpace(line)
if line == "" || strings.HasPrefix(line, "#") {
continue
}
f := strings.Fields(line)[0]
i := strings.Index(f, "|")
if i < 0 {
t.Errorf("parsing %q: missing | separator", f)
continue
}
if i%2 != 0 {
t.Errorf("parsing %q: misaligned | separator", f)
}
code, err := hex.DecodeString(f[:i] + f[i+1:])
if err != nil {
t.Errorf("parsing %q: %v", f, err)
continue
}
codes = append(codes, code)
}
return func(try func([]byte)) {
for _, code := range codes {
try(code)
}
}
}
func caller(skip int) string {
pc, _, _, _ := runtime.Caller(skip)
f := runtime.FuncForPC(pc)
name := "?"
if f != nil {
name = f.Name()
if i := strings.LastIndex(name, "."); i >= 0 {
name = name[i+1:]
}
}
return name
}

164
vendor/golang.org/x/arch/arm/armasm/gnu.go generated vendored Normal file
View File

@ -0,0 +1,164 @@
// Copyright 2014 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 armasm
import (
"bytes"
"fmt"
"strings"
)
var saveDot = strings.NewReplacer(
".F16", "_dot_F16",
".F32", "_dot_F32",
".F64", "_dot_F64",
".S32", "_dot_S32",
".U32", "_dot_U32",
".FXS", "_dot_S",
".FXU", "_dot_U",
".32", "_dot_32",
)
// GNUSyntax returns the GNU assembler syntax for the instruction, as defined by GNU binutils.
// This form typically matches the syntax defined in the ARM Reference Manual.
func GNUSyntax(inst Inst) string {
var buf bytes.Buffer
op := inst.Op.String()
op = saveDot.Replace(op)
op = strings.Replace(op, ".", "", -1)
op = strings.Replace(op, "_dot_", ".", -1)
op = strings.ToLower(op)
buf.WriteString(op)
sep := " "
for i, arg := range inst.Args {
if arg == nil {
break
}
text := gnuArg(&inst, i, arg)
if text == "" {
continue
}
buf.WriteString(sep)
sep = ", "
buf.WriteString(text)
}
return buf.String()
}
func gnuArg(inst *Inst, argIndex int, arg Arg) string {
switch inst.Op &^ 15 {
case LDRD_EQ, LDREXD_EQ, STRD_EQ:
if argIndex == 1 {
// second argument in consecutive pair not printed
return ""
}
case STREXD_EQ:
if argIndex == 2 {
// second argument in consecutive pair not printed
return ""
}
}
switch arg := arg.(type) {
case Imm:
switch inst.Op &^ 15 {
case BKPT_EQ:
return fmt.Sprintf("%#04x", uint32(arg))
case SVC_EQ:
return fmt.Sprintf("%#08x", uint32(arg))
}
return fmt.Sprintf("#%d", int32(arg))
case ImmAlt:
return fmt.Sprintf("#%d, %d", arg.Val, arg.Rot)
case Mem:
R := gnuArg(inst, -1, arg.Base)
X := ""
if arg.Sign != 0 {
X = ""
if arg.Sign < 0 {
X = "-"
}
X += gnuArg(inst, -1, arg.Index)
if arg.Shift == ShiftLeft && arg.Count == 0 {
// nothing
} else if arg.Shift == RotateRightExt {
X += ", rrx"
} else {
X += fmt.Sprintf(", %s #%d", strings.ToLower(arg.Shift.String()), arg.Count)
}
} else {
X = fmt.Sprintf("#%d", arg.Offset)
}
switch arg.Mode {
case AddrOffset:
if X == "#0" {
return fmt.Sprintf("[%s]", R)
}
return fmt.Sprintf("[%s, %s]", R, X)
case AddrPreIndex:
return fmt.Sprintf("[%s, %s]!", R, X)
case AddrPostIndex:
return fmt.Sprintf("[%s], %s", R, X)
case AddrLDM:
if X == "#0" {
return R
}
case AddrLDM_WB:
if X == "#0" {
return R + "!"
}
}
return fmt.Sprintf("[%s Mode(%d) %s]", R, int(arg.Mode), X)
case PCRel:
return fmt.Sprintf(".%+#x", int32(arg)+4)
case Reg:
switch inst.Op &^ 15 {
case LDREX_EQ:
if argIndex == 0 {
return fmt.Sprintf("r%d", int32(arg))
}
}
switch arg {
case R10:
return "sl"
case R11:
return "fp"
case R12:
return "ip"
}
case RegList:
var buf bytes.Buffer
fmt.Fprintf(&buf, "{")
sep := ""
for i := 0; i < 16; i++ {
if arg&(1<<uint(i)) != 0 {
fmt.Fprintf(&buf, "%s%s", sep, gnuArg(inst, -1, Reg(i)))
sep = ", "
}
}
fmt.Fprintf(&buf, "}")
return buf.String()
case RegShift:
if arg.Shift == ShiftLeft && arg.Count == 0 {
return gnuArg(inst, -1, arg.Reg)
}
if arg.Shift == RotateRightExt {
return gnuArg(inst, -1, arg.Reg) + ", rrx"
}
return fmt.Sprintf("%s, %s #%d", gnuArg(inst, -1, arg.Reg), strings.ToLower(arg.Shift.String()), arg.Count)
case RegShiftReg:
return fmt.Sprintf("%s, %s %s", gnuArg(inst, -1, arg.Reg), strings.ToLower(arg.Shift.String()), gnuArg(inst, -1, arg.RegCount))
}
return strings.ToLower(arg.String())
}

438
vendor/golang.org/x/arch/arm/armasm/inst.go generated vendored Normal file
View File

@ -0,0 +1,438 @@
// Copyright 2014 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 armasm
import (
"bytes"
"fmt"
)
// A Mode is an instruction execution mode.
type Mode int
const (
_ Mode = iota
ModeARM
ModeThumb
)
func (m Mode) String() string {
switch m {
case ModeARM:
return "ARM"
case ModeThumb:
return "Thumb"
}
return fmt.Sprintf("Mode(%d)", int(m))
}
// An Op is an ARM opcode.
type Op uint16
// NOTE: The actual Op values are defined in tables.go.
// They are chosen to simplify instruction decoding and
// are not a dense packing from 0 to N, although the
// density is high, probably at least 90%.
func (op Op) String() string {
if op >= Op(len(opstr)) || opstr[op] == "" {
return fmt.Sprintf("Op(%d)", int(op))
}
return opstr[op]
}
// An Inst is a single instruction.
type Inst struct {
Op Op // Opcode mnemonic
Enc uint32 // Raw encoding bits.
Len int // Length of encoding in bytes.
Args Args // Instruction arguments, in ARM manual order.
}
func (i Inst) String() string {
var buf bytes.Buffer
buf.WriteString(i.Op.String())
for j, arg := range i.Args {
if arg == nil {
break
}
if j == 0 {
buf.WriteString(" ")
} else {
buf.WriteString(", ")
}
buf.WriteString(arg.String())
}
return buf.String()
}
// An Args holds the instruction arguments.
// If an instruction has fewer than 4 arguments,
// the final elements in the array are nil.
type Args [4]Arg
// An Arg is a single instruction argument, one of these types:
// Endian, Imm, Mem, PCRel, Reg, RegList, RegShift, RegShiftReg.
type Arg interface {
IsArg()
String() string
}
type Float32Imm float32
func (Float32Imm) IsArg() {}
func (f Float32Imm) String() string {
return fmt.Sprintf("#%v", float32(f))
}
type Float64Imm float32
func (Float64Imm) IsArg() {}
func (f Float64Imm) String() string {
return fmt.Sprintf("#%v", float64(f))
}
// An Imm is an integer constant.
type Imm uint32
func (Imm) IsArg() {}
func (i Imm) String() string {
return fmt.Sprintf("#%#x", uint32(i))
}
// A ImmAlt is an alternate encoding of an integer constant.
type ImmAlt struct {
Val uint8
Rot uint8
}
func (ImmAlt) IsArg() {}
func (i ImmAlt) Imm() Imm {
v := uint32(i.Val)
r := uint(i.Rot)
return Imm(v>>r | v<<(32-r))
}
func (i ImmAlt) String() string {
return fmt.Sprintf("#%#x, %d", i.Val, i.Rot)
}
// A Label is a text (code) address.
type Label uint32
func (Label) IsArg() {}
func (i Label) String() string {
return fmt.Sprintf("%#x", uint32(i))
}
// A Reg is a single register.
// The zero value denotes R0, not the absence of a register.
type Reg uint8
const (
R0 Reg = iota
R1
R2
R3
R4
R5
R6
R7
R8
R9
R10
R11
R12
R13
R14
R15
S0
S1
S2
S3
S4
S5
S6
S7
S8
S9
S10
S11
S12
S13
S14
S15
S16
S17
S18
S19
S20
S21
S22
S23
S24
S25
S26
S27
S28
S29
S30
S31
D0
D1
D2
D3
D4
D5
D6
D7
D8
D9
D10
D11
D12
D13
D14
D15
D16
D17
D18
D19
D20
D21
D22
D23
D24
D25
D26
D27
D28
D29
D30
D31
APSR
APSR_nzcv
FPSCR
SP = R13
LR = R14
PC = R15
)
func (Reg) IsArg() {}
func (r Reg) String() string {
switch r {
case APSR:
return "APSR"
case APSR_nzcv:
return "APSR_nzcv"
case FPSCR:
return "FPSCR"
case SP:
return "SP"
case PC:
return "PC"
case LR:
return "LR"
}
if R0 <= r && r <= R15 {
return fmt.Sprintf("R%d", int(r-R0))
}
if S0 <= r && r <= S31 {
return fmt.Sprintf("S%d", int(r-S0))
}
if D0 <= r && r <= D31 {
return fmt.Sprintf("D%d", int(r-D0))
}
return fmt.Sprintf("Reg(%d)", int(r))
}
// A RegX represents a fraction of a multi-value register.
// The Index field specifies the index number,
// but the size of the fraction is not specified.
// It must be inferred from the instruction and the register type.
// For example, in a VMOV instruction, RegX{D5, 1} represents
// the top 32 bits of the 64-bit D5 register.
type RegX struct {
Reg Reg
Index int
}
func (RegX) IsArg() {}
func (r RegX) String() string {
return fmt.Sprintf("%s[%d]", r.Reg, r.Index)
}
// A RegList is a register list.
// Bits at indexes x = 0 through 15 indicate whether the corresponding Rx register is in the list.
type RegList uint16
func (RegList) IsArg() {}
func (r RegList) String() string {
var buf bytes.Buffer
fmt.Fprintf(&buf, "{")
sep := ""
for i := 0; i < 16; i++ {
if r&(1<<uint(i)) != 0 {
fmt.Fprintf(&buf, "%s%s", sep, Reg(i).String())
sep = ","
}
}
fmt.Fprintf(&buf, "}")
return buf.String()
}
// An Endian is the argument to the SETEND instruction.
type Endian uint8
const (
LittleEndian Endian = 0
BigEndian Endian = 1
)
func (Endian) IsArg() {}
func (e Endian) String() string {
if e != 0 {
return "BE"
}
return "LE"
}
// A Shift describes an ARM shift operation.
type Shift uint8
const (
ShiftLeft Shift = 0 // left shift
ShiftRight Shift = 1 // logical (unsigned) right shift
ShiftRightSigned Shift = 2 // arithmetic (signed) right shift
RotateRight Shift = 3 // right rotate
RotateRightExt Shift = 4 // right rotate through carry (Count will always be 1)
)
var shiftName = [...]string{
"LSL", "LSR", "ASR", "ROR", "RRX",
}
func (s Shift) String() string {
if s < 5 {
return shiftName[s]
}
return fmt.Sprintf("Shift(%d)", int(s))
}
// A RegShift is a register shifted by a constant.
type RegShift struct {
Reg Reg
Shift Shift
Count uint8
}
func (RegShift) IsArg() {}
func (r RegShift) String() string {
return fmt.Sprintf("%s %s #%d", r.Reg, r.Shift, r.Count)
}
// A RegShiftReg is a register shifted by a register.
type RegShiftReg struct {
Reg Reg
Shift Shift
RegCount Reg
}
func (RegShiftReg) IsArg() {}
func (r RegShiftReg) String() string {
return fmt.Sprintf("%s %s %s", r.Reg, r.Shift, r.RegCount)
}
// A PCRel describes a memory address (usually a code label)
// as a distance relative to the program counter.
// TODO(rsc): Define which program counter (PC+4? PC+8? PC?).
type PCRel int32
func (PCRel) IsArg() {}
func (r PCRel) String() string {
return fmt.Sprintf("PC%+#x", int32(r))
}
// An AddrMode is an ARM addressing mode.
type AddrMode uint8
const (
_ AddrMode = iota
AddrPostIndex // [R], X – use address R, set R = R + X
AddrPreIndex // [R, X]! – use address R + X, set R = R + X
AddrOffset // [R, X] – use address R + X
AddrLDM // R – [R] but formats as R, for LDM/STM only
AddrLDM_WB // R! - [R], X where X is instruction-specific amount, for LDM/STM only
)
// A Mem is a memory reference made up of a base R and index expression X.
// The effective memory address is R or R+X depending on AddrMode.
// The index expression is X = Sign*(Index Shift Count) + Offset,
// but in any instruction either Sign = 0 or Offset = 0.
type Mem struct {
Base Reg
Mode AddrMode
Sign int8
Index Reg
Shift Shift
Count uint8
Offset int16
}
func (Mem) IsArg() {}
func (m Mem) String() string {
R := m.Base.String()
X := ""
if m.Sign != 0 {
X = "+"
if m.Sign < 0 {
X = "-"
}
X += m.Index.String()
if m.Shift != ShiftLeft || m.Count != 0 {
X += fmt.Sprintf(", %s #%d", m.Shift, m.Count)
}
} else {
X = fmt.Sprintf("#%d", m.Offset)
}
switch m.Mode {
case AddrOffset:
if X == "#0" {
return fmt.Sprintf("[%s]", R)
}
return fmt.Sprintf("[%s, %s]", R, X)
case AddrPreIndex:
return fmt.Sprintf("[%s, %s]!", R, X)
case AddrPostIndex:
return fmt.Sprintf("[%s], %s", R, X)
case AddrLDM:
if X == "#0" {
return R
}
case AddrLDM_WB:
if X == "#0" {
return R + "!"
}
}
return fmt.Sprintf("[%s Mode(%d) %s]", R, int(m.Mode), X)
}

268
vendor/golang.org/x/arch/arm/armasm/objdump_test.go generated vendored Normal file
View File

@ -0,0 +1,268 @@
// Copyright 2014 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 armasm
import (
"encoding/binary"
"strings"
"testing"
)
func TestObjdumpARMTestdata(t *testing.T) { testObjdumpARM(t, testdataCases(t)) }
func TestObjdumpARMManual(t *testing.T) { testObjdumpARM(t, hexCases(t, objdumpManualTests)) }
func TestObjdumpARMCond(t *testing.T) { testObjdumpARM(t, condCases(t)) }
func TestObjdumpARMUncond(t *testing.T) { testObjdumpARM(t, uncondCases(t)) }
func TestObjdumpARMVFP(t *testing.T) { testObjdumpARM(t, vfpCases(t)) }
// objdumpManualTests holds test cases that will be run by TestObjdumpARMManual.
// If you are debugging a few cases that turned up in a longer run, it can be useful
// to list them here and then use -run=Manual, particularly with tracing enabled.
// Note that these are byte sequences, so they must be reversed from the usual
// word presentation.
var objdumpManualTests = `
002a9b1d
001b9bed
020b8ded
003a9b1d
060b8ded
fcde1100
b4de1100
bc480000
0b008de7
0b00ade7
fdbcfaf7
`
// allowedMismatchObjdump reports whether the mismatch between text and dec
// should be allowed by the test.
func allowedMismatchObjdump(text string, size int, inst *Inst, dec ExtInst) bool {
if hasPrefix(text, "error:") {
if hasPrefix(dec.text, unsupported...) || strings.Contains(dec.text, "invalid:") || strings.HasSuffix(dec.text, "^") || strings.Contains(dec.text, "f16.f64") || strings.Contains(dec.text, "f64.f16") {
return true
}
// word 4320F02C: libopcodes says 'nopmi {44}'.
if hasPrefix(dec.text, "nop") && strings.Contains(dec.text, "{") {
return true
}
}
if hasPrefix(dec.text, "error:") && text == "undef" && inst.Enc == 0xf7fabcfd {
return true
}
// word 00f02053: libopcodes says 'noppl {0}'.
if hasPrefix(dec.text, "nop") && hasPrefix(text, "nop") && dec.text == text+" {0}" {
return true
}
// word F57FF04F. we say 'dsb #15', libopcodes says 'dsb sy'.
if hasPrefix(text, "dsb") && hasPrefix(dec.text, "dsb") {
return true
}
// word F57FF06F. we say 'isb #15', libopcodes says 'isb sy'.
if hasPrefix(text, "isb") && hasPrefix(dec.text, "isb") {
return true
}
// word F57FF053. we say 'dmb #3', libopcodes says 'dmb osh'.
if hasPrefix(text, "dmb") && hasPrefix(dec.text, "dmb") {
return true
}
// word 992D0000. push/stmdb with no registers (undefined).
// we say 'stmdbls sp!, {}', libopcodes says 'pushls {}'.
if hasPrefix(text, "stmdb") && hasPrefix(dec.text, "push") && strings.Contains(text, "{}") && strings.Contains(dec.text, "{}") {
return true
}
// word 28BD0000. pop/ldm with no registers (undefined).
// we say 'ldmcs sp!, {}', libopcodes says 'popcs {}'.
if hasPrefix(text, "ldm") && hasPrefix(dec.text, "pop") && strings.Contains(text, "{}") && strings.Contains(dec.text, "{}") {
return true
}
// word 014640F0.
// libopcodes emits #-0 for negative zero; we don't.
if strings.Replace(dec.text, "#-0", "#0", -1) == text || strings.Replace(dec.text, ", #-0", "", -1) == text {
return true
}
// word 91EF90F0. we say 'strdls r9, [pc, #0]!' but libopcodes says 'strdls r9, [pc]'.
// word D16F60F0. we say 'strdle r6, [pc, #0]!' but libopcodes says 'strdle r6, [pc, #-0]'.
if strings.Replace(text, ", #0]!", "]", -1) == strings.Replace(dec.text, ", #-0]", "]", -1) {
return true
}
// word 510F4000. we say apsr, libopcodes says CPSR.
if strings.Replace(dec.text, "CPSR", "apsr", -1) == text {
return true
}
// word 06A4B059.
// for ssat and usat, libopcodes decodes asr #0 as asr #0 but the manual seems to say it should be asr #32.
// There is never an asr #0.
if strings.Replace(dec.text, ", asr #0", ", asr #32", -1) == text {
return true
}
if len(dec.enc) >= 4 {
raw := binary.LittleEndian.Uint32(dec.enc[:4])
// word 21FFF0B5.
// the manual is clear that this is pre-indexed mode (with !) but libopcodes generates post-index (without !).
if raw&0x01200000 == 0x01200000 && strings.Replace(text, "!", "", -1) == dec.text {
return true
}
// word C100543E: libopcodes says tst, but no evidence for that.
if strings.HasPrefix(dec.text, "tst") && raw&0x0ff00000 != 0x03100000 && raw&0x0ff00000 != 0x01100000 {
return true
}
// word C3203CE8: libopcodes says teq, but no evidence for that.
if strings.HasPrefix(dec.text, "teq") && raw&0x0ff00000 != 0x03300000 && raw&0x0ff00000 != 0x01300000 {
return true
}
// word D14C552E: libopcodes says cmp but no evidence for that.
if strings.HasPrefix(dec.text, "cmp") && raw&0x0ff00000 != 0x03500000 && raw&0x0ff00000 != 0x01500000 {
return true
}
// word 2166AA4A: libopcodes says cmn but no evidence for that.
if strings.HasPrefix(dec.text, "cmn") && raw&0x0ff00000 != 0x03700000 && raw&0x0ff00000 != 0x01700000 {
return true
}
// word E70AEEEF: libopcodes says str but no evidence for that.
if strings.HasPrefix(dec.text, "str") && len(dec.text) >= 5 && (dec.text[3] == ' ' || dec.text[5] == ' ') && raw&0x0e500018 != 0x06000000 && raw&0x0e500000 != 0x0400000 {
return true
}
// word B0AF48F4: libopcodes says strd but P=0,W=1 which is unpredictable.
if hasPrefix(dec.text, "ldr", "str") && raw&0x01200000 == 0x00200000 {
return true
}
// word B6CC1C76: libopcodes inexplicably says 'uxtab16lt r1, ip, r6, ROR #24' instead of 'uxtab16lt r1, ip, r6, ror #24'
if strings.ToLower(dec.text) == text {
return true
}
// word F410FDA1: libopcodes says PLDW but the manual is clear that PLDW is F5/F7, not F4.
// word F7D0FB17: libopcodes says PLDW but the manual is clear that PLDW has 0x10 clear
if hasPrefix(dec.text, "pld") && raw&0xfd000010 != 0xf5000000 {
return true
}
// word F650FE14: libopcodes says PLI but the manual is clear that PLI has 0x10 clear
if hasPrefix(dec.text, "pli") && raw&0xff000010 != 0xf6000000 {
return true
}
}
return false
}
// Instructions known to libopcodes (or xed) but not to us.
// Most of these are floating point coprocessor instructions.
var unsupported = strings.Fields(`
abs
acs
adf
aes
asn
atn
cdp
cf
cmf
cnf
cos
cps
crc32
dvf
eret
exp
fadd
fcmp
fcpy
fcvt
fdiv
fdv
fix
fld
flt
fmac
fmd
fml
fmr
fms
fmul
fmx
fneg
fnm
frd
fsit
fsq
fst
fsu
fto
fui
hlt
hvc
lda
ldc
ldf
lfm
lgn
log
mar
mcr
mcrr
mia
mnf
mra
mrc
mrrc
mrs
msr
msr
muf
mvf
nrm
pol
pow
rdf
rfc
rfe
rfs
rmf
rnd
rpw
rsf
sdiv
sev
sfm
sha1
sha256
sin
smc
sqt
srs
stc
stf
stl
suf
tan
udf
udiv
urd
vfma
vfms
vfnma
vfnms
vrint
wfc
wfs
`)

259
vendor/golang.org/x/arch/arm/armasm/objdumpext_test.go generated vendored Normal file
View File

@ -0,0 +1,259 @@
// Copyright 2014 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.
// Copied and simplified from ../../x86/x86asm/objdumpext_test.go.
package armasm
import (
"bytes"
"debug/elf"
"encoding/binary"
"fmt"
"io"
"log"
"os"
"strconv"
"strings"
"testing"
)
const objdumpPath = "/usr/local/bin/arm-linux-elf-objdump"
func testObjdumpARM(t *testing.T, generate func(func([]byte))) {
testObjdumpArch(t, generate, ModeARM)
}
func testObjdumpArch(t *testing.T, generate func(func([]byte)), arch Mode) {
if testing.Short() {
t.Skip("skipping objdump test in short mode")
}
if _, err := os.Stat(objdumpPath); err != nil {
t.Skip(err)
}
testExtDis(t, "gnu", arch, objdump, generate, allowedMismatchObjdump)
}
func objdump(ext *ExtDis) error {
// File already written with instructions; add ELF header.
if ext.Arch == ModeARM {
if err := writeELF32(ext.File, ext.Size); err != nil {
return err
}
} else {
panic("unknown arch")
}
b, err := ext.Run(objdumpPath, "-d", "-z", ext.File.Name())
if err != nil {
return err
}
var (
nmatch int
reading bool
next uint32 = start
addr uint32
encbuf [4]byte
enc []byte
text string
)
flush := func() {
if addr == next {
if m := pcrel.FindStringSubmatch(text); m != nil {
targ, _ := strconv.ParseUint(m[2], 16, 64)
text = fmt.Sprintf("%s .%+#x", m[1], int32(uint32(targ)-addr-uint32(len(enc))))
}
if strings.HasPrefix(text, "stmia") {
text = "stm" + text[5:]
}
if strings.HasPrefix(text, "stmfd") {
text = "stmdb" + text[5:]
}
if strings.HasPrefix(text, "ldmfd") {
text = "ldm" + text[5:]
}
text = strings.Replace(text, "#0.0", "#0", -1)
if text == "undefined" && len(enc) == 4 {
text = "error: unknown instruction"
enc = nil
}
if len(enc) == 4 {
// prints as word but we want to record bytes
enc[0], enc[3] = enc[3], enc[0]
enc[1], enc[2] = enc[2], enc[1]
}
ext.Dec <- ExtInst{addr, encbuf, len(enc), text}
encbuf = [4]byte{}
enc = nil
next += 4
}
}
var textangle = []byte("<.text>:")
for {
line, err := b.ReadSlice('\n')
if err != nil {
if err == io.EOF {
break
}
return fmt.Errorf("reading objdump output: %v", err)
}
if bytes.Contains(line, textangle) {
reading = true
continue
}
if !reading {
continue
}
if debug {
os.Stdout.Write(line)
}
if enc1 := parseContinuation(line, encbuf[:len(enc)]); enc1 != nil {
enc = enc1
continue
}
flush()
nmatch++
addr, enc, text = parseLine(line, encbuf[:0])
if addr > next {
return fmt.Errorf("address out of sync expected <= %#x at %q in:\n%s", next, line, line)
}
}
flush()
if next != start+uint32(ext.Size) {
return fmt.Errorf("not enough results found [%d %d]", next, start+ext.Size)
}
if err := ext.Wait(); err != nil {
return fmt.Errorf("exec: %v", err)
}
return nil
}
var (
undefined = []byte("<UNDEFINED>")
unpredictable = []byte("<UNPREDICTABLE>")
illegalShifter = []byte("<illegal shifter operand>")
)
func parseLine(line []byte, encstart []byte) (addr uint32, enc []byte, text string) {
oline := line
i := index(line, ":\t")
if i < 0 {
log.Fatalf("cannot parse disassembly: %q", oline)
}
x, err := strconv.ParseUint(string(trimSpace(line[:i])), 16, 32)
if err != nil {
log.Fatalf("cannot parse disassembly: %q", oline)
}
addr = uint32(x)
line = line[i+2:]
i = bytes.IndexByte(line, '\t')
if i < 0 {
log.Fatalf("cannot parse disassembly: %q", oline)
}
enc, ok := parseHex(line[:i], encstart)
if !ok {
log.Fatalf("cannot parse disassembly: %q", oline)
}
line = trimSpace(line[i:])
if bytes.Contains(line, undefined) {
text = "undefined"
return
}
if bytes.Contains(line, illegalShifter) {
text = "undefined"
return
}
if false && bytes.Contains(line, unpredictable) {
text = "unpredictable"
return
}
if i := bytes.IndexByte(line, ';'); i >= 0 {
line = trimSpace(line[:i])
}
text = string(fixSpace(line))
return
}
func parseContinuation(line []byte, enc []byte) []byte {
i := index(line, ":\t")
if i < 0 {
return nil
}
line = line[i+1:]
enc, _ = parseHex(line, enc)
return enc
}
// writeELF32 writes an ELF32 header to the file,
// describing a text segment that starts at start
// and extends for size bytes.
func writeELF32(f *os.File, size int) error {
f.Seek(0, 0)
var hdr elf.Header32
var prog elf.Prog32
var sect elf.Section32
var buf bytes.Buffer
binary.Write(&buf, binary.LittleEndian, &hdr)
off1 := buf.Len()
binary.Write(&buf, binary.LittleEndian, &prog)
off2 := buf.Len()
binary.Write(&buf, binary.LittleEndian, &sect)
off3 := buf.Len()
buf.Reset()
data := byte(elf.ELFDATA2LSB)
hdr = elf.Header32{
Ident: [16]byte{0x7F, 'E', 'L', 'F', 1, data, 1},
Type: 2,
Machine: uint16(elf.EM_ARM),
Version: 1,
Entry: start,
Phoff: uint32(off1),
Shoff: uint32(off2),
Flags: 0x05000002,
Ehsize: uint16(off1),
Phentsize: uint16(off2 - off1),
Phnum: 1,
Shentsize: uint16(off3 - off2),
Shnum: 3,
Shstrndx: 2,
}
binary.Write(&buf, binary.LittleEndian, &hdr)
prog = elf.Prog32{
Type: 1,
Off: start,
Vaddr: start,
Paddr: start,
Filesz: uint32(size),
Memsz: uint32(size),
Flags: 5,
Align: start,
}
binary.Write(&buf, binary.LittleEndian, &prog)
binary.Write(&buf, binary.LittleEndian, &sect) // NULL section
sect = elf.Section32{
Name: 1,
Type: uint32(elf.SHT_PROGBITS),
Addr: start,
Off: start,
Size: uint32(size),
Flags: uint32(elf.SHF_ALLOC | elf.SHF_EXECINSTR),
Addralign: 4,
}
binary.Write(&buf, binary.LittleEndian, &sect) // .text
sect = elf.Section32{
Name: uint32(len("\x00.text\x00")),
Type: uint32(elf.SHT_STRTAB),
Addr: 0,
Off: uint32(off2 + (off3-off2)*3),
Size: uint32(len("\x00.text\x00.shstrtab\x00")),
Addralign: 1,
}
binary.Write(&buf, binary.LittleEndian, &sect)
buf.WriteString("\x00.text\x00.shstrtab\x00")
f.Write(buf.Bytes())
return nil
}

220
vendor/golang.org/x/arch/arm/armasm/plan9x.go generated vendored Normal file
View File

@ -0,0 +1,220 @@
// Copyright 2014 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 armasm
import (
"bytes"
"encoding/binary"
"fmt"
"io"
"strings"
)
// GoSyntax returns the Go assembler syntax for the instruction.
// The syntax was originally defined by Plan 9.
// The pc is the program counter of the instruction, used for expanding
// PC-relative addresses into absolute ones.
// The symname function queries the symbol table for the program
// being disassembled. Given a target address it returns the name and base
// address of the symbol containing the target, if any; otherwise it returns "", 0.
// The reader r should read from the text segment using text addresses
// as offsets; it is used to display pc-relative loads as constant loads.
func GoSyntax(inst Inst, pc uint64, symname func(uint64) (string, uint64), text io.ReaderAt) string {
if symname == nil {
symname = func(uint64) (string, uint64) { return "", 0 }
}
var args []string
for _, a := range inst.Args {
if a == nil {
break
}
args = append(args, plan9Arg(&inst, pc, symname, a))
}
op := inst.Op.String()
switch inst.Op &^ 15 {
case LDR_EQ, LDRB_EQ, LDRH_EQ:
// Check for RET
reg, _ := inst.Args[0].(Reg)
mem, _ := inst.Args[1].(Mem)
if inst.Op&^15 == LDR_EQ && reg == R15 && mem.Base == SP && mem.Sign == 0 && mem.Mode == AddrPostIndex {
return fmt.Sprintf("RET%s #%d", op[3:], mem.Offset)
}
// Check for PC-relative load.
if mem.Base == PC && mem.Sign == 0 && mem.Mode == AddrOffset && text != nil {
addr := uint32(pc) + 8 + uint32(mem.Offset)
buf := make([]byte, 4)
switch inst.Op &^ 15 {
case LDRB_EQ:
if _, err := text.ReadAt(buf[:1], int64(addr)); err != nil {
break
}
args[1] = fmt.Sprintf("$%#x", buf[0])
case LDRH_EQ:
if _, err := text.ReadAt(buf[:2], int64(addr)); err != nil {
break
}
args[1] = fmt.Sprintf("$%#x", binary.LittleEndian.Uint16(buf))
case LDR_EQ:
if _, err := text.ReadAt(buf, int64(addr)); err != nil {
break
}
x := binary.LittleEndian.Uint32(buf)
if s, base := symname(uint64(x)); s != "" && uint64(x) == base {
args[1] = fmt.Sprintf("$%s(SB)", s)
} else {
args[1] = fmt.Sprintf("$%#x", x)
}
}
}
}
// Move addressing mode into opcode suffix.
suffix := ""
switch inst.Op &^ 15 {
case LDR_EQ, LDRB_EQ, LDRH_EQ, STR_EQ, STRB_EQ, STRH_EQ:
mem, _ := inst.Args[1].(Mem)
switch mem.Mode {
case AddrOffset, AddrLDM:
// no suffix
case AddrPreIndex, AddrLDM_WB:
suffix = ".W"
case AddrPostIndex:
suffix = ".P"
}
off := ""
if mem.Offset != 0 {
off = fmt.Sprintf("%#x", mem.Offset)
}
base := fmt.Sprintf("(R%d)", int(mem.Base))
index := ""
if mem.Sign != 0 {
sign := ""
if mem.Sign < 0 {
sign = ""
}
shift := ""
if mem.Count != 0 {
shift = fmt.Sprintf("%s%d", plan9Shift[mem.Shift], mem.Count)
}
index = fmt.Sprintf("(%sR%d%s)", sign, int(mem.Index), shift)
}
args[1] = off + base + index
}
// Reverse args, placing dest last.
for i, j := 0, len(args)-1; i < j; i, j = i+1, j-1 {
args[i], args[j] = args[j], args[i]
}
// For MLA-like instructions, the addend is the third operand.
switch inst.Op &^ 15 {
case SMLAWT_EQ, SMLAWB_EQ, MLA_EQ, MLS_EQ, SMMLA_EQ, SMMLS_EQ, SMLABB_EQ:
args = []string{args[1], args[2], args[0], args[3]}
}
switch inst.Op &^ 15 {
case MOV_EQ:
op = "MOVW" + op[3:]
case LDR_EQ:
op = "MOVW" + op[3:] + suffix
case LDRB_EQ:
op = "MOVB" + op[4:] + suffix
case LDRH_EQ:
op = "MOVH" + op[4:] + suffix
case STR_EQ:
op = "MOVW" + op[3:] + suffix
args[0], args[1] = args[1], args[0]
case STRB_EQ:
op = "MOVB" + op[4:] + suffix
args[0], args[1] = args[1], args[0]
case STRH_EQ:
op = "MOVH" + op[4:] + suffix
args[0], args[1] = args[1], args[0]
}
if args != nil {
op += " " + strings.Join(args, ", ")
}
return op
}
// assembler syntax for the various shifts.
// @x> is a lie; the assembler uses @> 0
// instead of @x> 1, but i wanted to be clear that it
// was a different operation (rotate right extended, not rotate right).
var plan9Shift = []string{"<<", ">>", "->", "@>", "@x>"}
func plan9Arg(inst *Inst, pc uint64, symname func(uint64) (string, uint64), arg Arg) string {
switch a := arg.(type) {
case Endian:
case Imm:
return fmt.Sprintf("$%d", int(a))
case Mem:
case PCRel:
addr := uint32(pc) + 8 + uint32(a)
if s, base := symname(uint64(addr)); s != "" && uint64(addr) == base {
return fmt.Sprintf("%s(SB)", s)
}
return fmt.Sprintf("%#x", addr)
case Reg:
if a < 16 {
return fmt.Sprintf("R%d", int(a))
}
case RegList:
var buf bytes.Buffer
start := -2
end := -2
fmt.Fprintf(&buf, "[")
flush := func() {
if start >= 0 {
if buf.Len() > 1 {
fmt.Fprintf(&buf, ",")
}
if start == end {
fmt.Fprintf(&buf, "R%d", start)
} else {
fmt.Fprintf(&buf, "R%d-R%d", start, end)
}
start = -2
end = -2
}
}
for i := 0; i < 16; i++ {
if a&(1<<uint(i)) != 0 {
if i == end+1 {
end++
continue
}
start = i
end = i
} else {
flush()
}
}
flush()
fmt.Fprintf(&buf, "]")
return buf.String()
case RegShift:
return fmt.Sprintf("R%d%s$%d", int(a.Reg), plan9Shift[a.Shift], int(a.Count))
case RegShiftReg:
return fmt.Sprintf("R%d%sR%d", int(a.Reg), plan9Shift[a.Shift], int(a.RegCount))
}
return strings.ToUpper(arg.String())
}

9448
vendor/golang.org/x/arch/arm/armasm/tables.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,5 @@
newdecode.txt:
cd ..; go test -cover -run 'ObjdumpARMCond' -v -timeout 10h -printtests -long 2>&1 | tee log
cd ..; go test -cover -run 'ObjdumpARMUncond' -v -timeout 10h -printtests -long 2>&1 | tee -a log
egrep ' (gnu|plan9) ' ../log |sort >newdecode.txt

309
vendor/golang.org/x/arch/arm/armasm/testdata/decode.txt generated vendored Normal file
View File

@ -0,0 +1,309 @@
000001f1| 1 gnu setend le
00100f61| 1 gnu mrsvs r1, apsr
00f02053| 1 gnu noppl
00f0d4f4| 1 gnu pli [r4]
01f020d3| 1 gnu yieldle
02002d59| 1 gnu stmdbpl sp!, {r1}
021da9d8| 1 gnu stmle r9!, {r1, r8, sl, fp, ip}
02c0b071| 1 gnu movsvc ip, r2
02f02073| 1 gnu wfevc
03f02013| 1 gnu wfine
03f05df7| 1 gnu pld [sp, -r3]
04009d34| 1 gnu popcc {r0}
043a52b1| 1 gnu cmplt r2, r4, lsl #20
04402de5| 1 gnu push {r4}
045b148d| 1 gnu vldrhi d5, [r4, #-16]
04f02093| 1 gnu sevls
0793eab0| 1 gnu rsclt r9, sl, r7, lsl #6
079bfb9e| 1 gnu vmovls.f64 d25, #183
0a4fc9d3| 1 gnu bicle r4, r9, #10, 30
0bac7ab6| 1 gnu ldrbtlt sl, [sl], -fp, lsl #24
0c2aee44| 1 gnu strbtmi r2, [lr], #2572
0c4bb000| 1 gnu adcseq r4, r0, ip, lsl #22
0e26d561| 1 gnu bicsvs r2, r5, lr, lsl #12
0f0fa011| 1 gnu lslne r0, pc, #30
0fa448e0| 1 gnu sub sl, r8, pc, lsl #8
101af1de| 1 gnu vmrsle r1, fpscr
108a0cee| 1 gnu vmov s24, r8
108a1dae| 1 gnu vmovge r8, s26
108ae14e| 1 gnu vmsrmi fpscr, r8
10faf1ae| 1 gnu vmrsge apsr_nzcv, fpscr
10fb052e| 1 gnu vmovcs.32 d5[0], pc
11c902b7| 1 gnu smladlt r2, r1, r9, ip
11ef5b16| 1 gnu uadd16ne lr, fp, r1
12fa87a7| 1 gnu usad8ge r7, r2, sl
135f2956| 1 gnu qadd16pl r5, r9, r3
13de9aa1| 1 gnu orrsge sp, sl, r3, lsl lr
145c0e40| 1 gnu andmi r5, lr, r4, lsl ip
150f7fd6| 1 gnu uhadd16le r0, pc, r5
15b9bf12| 1 gnu adcsne fp, pc, #344064
16373391| 1 gnu teqls r3, r6, lsl r7
19ef1966| 1 gnu sadd16vs lr, r9, r9
1ab0b091| 1 gnu lslsls fp, sl, r0
1b9f6fe6| 1 gnu uqadd16 r9, pc, fp
1bb58557| 1 gnu usada8pl r5, fp, r5, fp
1beff8e0| 1 gnu rscs lr, r8, fp, lsl pc
1caff0e6| 1 gnu usat sl, #16, ip, lsl #30
1d0f3d36| 1 gnu shadd16cc r0, sp, sp
1dca1d52| 1 gnu andspl ip, sp, #118784
1e4891d0| 1 gnu addsle r4, r1, lr, lsl r8
1f0889e6| 1 gnu pkhbt r0, r9, pc, lsl #16
1f1f6fe1| 1 gnu clz r1, pc
1f26d157| 1 gnu bfcpl r2, #12, #6
1ff07ff5| 1 gnu clrex
1fff2fd1| 1 gnu bxle pc
20f153f6| 1 gnu pli [r3, -r0, lsr #2]
21047013| 1 gnu cmnne r0, #553648128
21c2eb8b| 1 gnu blhi .-0x50f778
21c2ebfb| 1 gnu blx .-0x50f776
21fa62ee| 1 gnu vmul.f32 s31, s4, s3
23005720| 1 gnu subscs r0, r7, r3, lsr #32
236a303e| 1 gnu vaddcc.f32 s12, s0, s7
23f055f6| 1 gnu pli [r5, -r3, lsr #32]
2430a031| 1 gnu lsrcc r3, r4, #32
245d0803| 1 gnu movweq r5, #36132
251a86be| 1 gnu vdivlt.f32 s2, s12, s11
25db7b81| 1 gnu cmnhi fp, r5, lsr #22
26bc3553| 1 gnu teqpl r5, #9728
277c2d69| 1 gnu pushvs {r0, r1, r2, r5, sl, fp, ip, sp, lr}
29fc1cf5| 1 gnu pldw [ip, #-3113]
29ff2fc1| 1 gnu bxjgt r9
2decd9c0| 1 gnu sbcsgt lr, r9, sp, lsr #24
30fa5e47| 1 gnu smmulrmi lr, r0, sl
316f64d6| 1 gnu uqasxle r6, r4, r1
323f5da6| 1 gnu uasxge r3, sp, r2
327fe5e6| 1 gnu usat16 r7, #5, r2
330151e3| 1 gnu cmp r1, #-1073741812
34af2ae6| 1 gnu qasx sl, sl, r4
35fd3710| 1 gnu eorsne pc, r7, r5, lsr sp
36def1c1| 1 gnu mvnsgt sp, r6, lsr lr
3801b061| 1 gnu lsrsvs r0, r8, r1
38985477| 1 gnu smmlarvc r4, r8, r8, r9
3a2fbfa6| 1 gnu revge r2, sl
3a3f1b06| 1 gnu sasxeq r3, fp, sl
3a7fa346| 1 gnu ssat16mi r7, #4, sl
3a943b94| 1 gnu ldrtls r9, [fp], #-1082
3bf505e7| 1 gnu smuadx r5, fp, r5
3cef7086| 1 gnu uhasxhi lr, r0, ip
3e5f3ec6| 1 gnu shasxgt r5, lr, lr
3f4fff86| 1 gnu rbithi r4, pc
3faf4717| 1 gnu smlaldxne sl, r7, pc, pc
3fff2fc1| 1 gnu blxgt pc
402bbf7e| 1 gnu vcvtvc.u16.f64 d2, d2, #16
403ab5de| 1 gnu vcmple.f32 s6, #0
40eb363e| 1 gnu vsubcc.f64 d14, d6, d0
420f73d1| 1 gnu cmnle r3, r2, asr #30
424a648e| 1 gnu vnmulhi.f32 s9, s8, s4
4284d717| 1 gnu ldrbne r8, [r7, r2, asr #8]
42a599c3| 1 gnu orrsgt sl, r9, #276824064
42abf0be| 1 gnu vmovlt.f64 d26, d2
446ea031| 1 gnu asrcc r6, r4, #28
4a953557| 1 gnu ldrpl r9, [r5, -sl, asr #10]!
4ab6f712| 1 gnu rscsne fp, r7, #77594624
4af07ff5| 1 gnu dsb #10
4df6def4| 1 gnu pli [lr, #1613]
4efbf52e| 1 gnu vcmpcs.f64 d31, #0
50aaac79| 1 gnu stmibvc ip!, {r4, r6, r9, fp, sp, pc}
50caf011| 1 gnu mvnsne ip, r0, asr sl
50f04961| 1 gnu qdaddvs pc, r0, r9
51282008| 1 gnu stmdaeq r0!, {r0, r4, r6, fp, sp}
52bf6576| 1 gnu uqsaxvc fp, r5, r2
5345c9d0| 1 gnu sbcle r4, r9, r3, asr r5
538f5e46| 1 gnu usaxmi r8, lr, r3
54106d31| 1 gnu qdsubcc r1, r4, sp
56e0e557| 1 gnu ubfxpl lr, r6, #0, #6
57073d11| 1 gnu teqne sp, r7, asr r7
58bb0aa9| 1 gnu stmdbge sl, {r3, r4, r6, r8, r9, fp, ip, sp, pc}
58f007b1| 1 gnu qaddlt pc, r8, r7
59fd0e77| 1 gnu smusdvc lr, r9, sp
5ab7f1c5| 1 gnu ldrbgt fp, [r1, #1882]!
5abf23c6| 1 gnu qsaxgt fp, r3, sl
5b8f1c96| 1 gnu ssaxls r8, ip, fp
5b98ab97| 1 gnu sbfxls r9, fp, #16, #12
5bc9b041| 1 gnu asrsmi ip, fp, r9
5bf07ff5| 1 gnu dmb #11
5c102b81| 1 gnu qsubhi r1, ip, fp
5caa49e1| 1 gnu qdadd sl, ip, r9
5d3f7226| 1 gnu uhsaxcs r3, r2, sp
5db55470| 1 gnu subsvc fp, r4, sp, asr r5
5ef14387| 1 gnu smlsldhi pc, r3, lr, r1
5f540a11| 1 gnu qaddne r5, pc, sl
5f9079d1| 1 gnu cmnle r9, pc, asr r0
5faf3f66| 1 gnu shsaxvs sl, pc, pc
605071d7| 1 gnu ldrble r5, [r1, -r0, rrx]!
614adc76| 1 gnu ldrbvc r4, [ip], r1, ror #20
616b9e42| 1 gnu addsmi r6, lr, #99328
62c84f15| 1 gnu strbne ip, [pc, #-2146]
62f051f7| 1 gnu pld [r1, -r2, rrx]
6346c393| 1 gnu bicls r4, r3, #103809024
654abbae| 1 gnu vcvtge.f32.u16 s8, s8, #5
65a5f0e3| 1 gnu mvns sl, #423624704
65f796f7| 1 gnu pldw [r6, r5, ror #14]
670bb12e| 1 gnu vnegcs.f64 d0, d23
67903731| 1 gnu teqcc r7, r7, rrx
68ddc637| 1 gnu strbcc sp, [r6, r8, ror #26]
695b3ab6| 1 gnu ldrtlt r5, [sl], -r9, ror #22
697cfc71| 1 gnu mvnsvc r7, r9, ror #24
6a0ab3ee| 1 gnu vcvtb.f16.f32 s0, s21
6ad9ad54| 1 gnu strtpl sp, [sp], #2410
6af07ff5| 1 gnu isb #10
6afa6f10| 1 gnu rsbne pc, pc, sl, ror #20
6d5b19ee| 1 gnu vnmla.f64 d5, d9, d29
6d60b071| 1 gnu rrxsvc r6, sp
6df754f7| 1 gnu pld [r4, -sp, ror #14]
70065821| 1 gnu cmpcs r8, r0, ror r6
7050ed86| 1 gnu uxtabhi r5, sp, r0
715f1186| 1 gnu ssub16hi r5, r1, r1
716c9805| 1 gnu ldreq r6, [r8, #3185]
718d5ab1| 1 gnu cmplt sl, r1, ror sp
71c8cfb6| 1 gnu uxtb16lt ip, r1, ror #16
7294af06| 1 gnu sxtbeq r9, r2, ror #8
72c0bac6| 1 gnu sxtahgt ip, sl, r2
730f6716| 1 gnu uqsub16ne r0, r7, r3
73608f46| 1 gnu sxtb16mi r6, r3
73687f22| 1 gnu rsbscs r6, pc, #7536640
74308816| 1 gnu sxtab16ne r3, r8, r4
757f3456| 1 gnu shsub16pl r7, r4, r5
77788016| 1 gnu sxtab16ne r7, r0, r7, ror #16
78061671| 1 gnu tstvc r6, r8, ror r6
780a2fe1| 1 gnu bkpt 0xf0a8
7850abd6| 1 gnu sxtable r5, fp, r8
792cef26| 1 gnu uxtbcs r2, r9, ror #24
799eb8e0| 1 gnu adcs r9, r8, r9, ror lr
799f5726| 1 gnu usub16cs r9, r7, r9
79d0bf16| 1 gnu sxthne sp, r9
7a037ba1| 1 gnu cmnge fp, sl, ror r3
7b0f2566| 1 gnu qsub16vs r0, r5, fp
7b79dd51| 1 gnu bicspl r7, sp, fp, ror r9
7b9a9f1d| 1 gnu vldrne s18, [pc, #492]
7c70cea6| 1 gnu uxtab16ge r7, lr, ip
7d48f966| 1 gnu uxtahvs r4, r9, sp, ror #16
7d5c13a1| 1 gnu tstge r3, sp, ror ip
7e0001f1| 1 gnu setend le
7e1c0ba7| 1 gnu smlsdxge fp, lr, ip, r1
7e567e40| 1 gnu rsbsmi r5, lr, lr, ror r6
7e8f73b6| 1 gnu uhsub16lt r8, r3, lr
7ef0ffd6| 1 gnu uxthle pc, lr
7faaa011| 1 gnu rorne sl, pc, sl
81f19af7| 1 gnu pldw [sl, r1, lsl #3]
82033901| 1 gnu teqeq r9, r2, lsl #7
82f316f5| 1 gnu pldw [r6, #-898]
830201f1| 1 gnu setend be
838a3b91| 1 gnu teqls fp, r3, lsl #21
8408af2f| 1 gnu svccs 0x00af0884
884201d1| 1 gnu smlabble r1, r8, r2, r4
8aa12e31| 1 gnu smlawbcc lr, sl, r1, sl
8b9b99c0| 1 gnu addsgt r9, r9, fp, lsl #23
8c005c81| 1 gnu cmphi ip, ip, lsl #1
8fb429c6| 1 gnu strtgt fp, [r9], -pc, lsl #9
907b1f9e| 1 gnu vmovls.32 r7, d31[0]
91975f25| 1 gnu ldrbcs r9, [pc, #-1937]
91b010e3| 1 gnu tst r0, #145
927facb1| 1 gnu strexdlt r7, r2, [ip]
92904c91| 1 gnu swpbls r9, r2, [ip]
92af1226| 1 gnu sadd8cs sl, r2, r2
92b28c70| 1 gnu umullvc fp, ip, r2, r2
945f68a6| 1 gnu uqadd8ge r5, r8, r4
950b2560| 1 gnu mlavs r5, r5, fp, r0
969fcf71| 1 gnu strexbvc r9, r6, [pc]
96cf35e6| 1 gnu shadd8 ip, r5, r6
98060eb0| 1 gnu mullt lr, r8, r6
9843fb93| 1 gnu mvnsls r4, #152, 6
9a3fe2b0| 1 gnu smlallt r3, r2, sl, pc
9aef58b6| 1 gnu uadd8lt lr, r8, sl
9afcdff5| 1 gnu pld [pc, #3226]
9c221810| 1 gnu mulsne r8, ip, r2
9c3bc9dd| 1 gnu vstrle d19, [r9, #624]
9c5f2606| 1 gnu qadd8eq r5, r6, ip
9d87dac0| 1 gnu smullsgt r8, sl, sp, r7
9e0f7c86| 1 gnu uhadd8hi r0, ip, lr
9e814560| 1 gnu umaalvs r8, r5, lr, r1
9e9f8dc1| 1 gnu strexgt r9, lr, [sp]
9ec3c9d7| 1 gnu bfile ip, lr, #7, #3
9ed26d90| 1 gnu mlsls sp, lr, r2, sp
9f7fd9c1| 1 gnu ldrexbgt r7, [r9]
9f7fea91| 1 gnu strexhls r7, pc, [sl]
9f9f9921| 1 gnu ldrexcs r9, [r9]
9faffd21| 1 gnu ldrexhcs sl, [sp]
9fcfbd61| 1 gnu ldrexdvs ip, [sp]
9ff7a710| 1 gnu umlalne pc, r7, pc, r7
a05459d3| 1 gnu cmple r9, #160, 8
a3062be1| 1 gnu smulwb fp, r3, r6
a68a92b1| 1 gnu orrslt r8, r2, r6, lsr #21
abff55f6| 1 gnu pli [r5, -fp, lsr #31]
addbf8ea| 1 gnu b .-0x1c9148
ae79b021| 1 gnu lsrscs r7, lr, #19
b590a3b1| 1 gnu strhlt r9, [r3, r5]!
b5b2e390| 1 gnu strhtls fp, [r3], #37
b6ac4e30| 1 gnu strhcc sl, [lr], #-198
b73fff86| 1 gnu revshhi r3, r7
b75fbfc6| 1 gnu rev16gt r5, r7
b80b7c80| 1 gnu ldrhthi r0, [ip], #-184
b82035e0| 1 gnu ldrht r2, [r5], -r8
b8877391| 1 gnu ldrhls r8, [r3, #-120]!
b9703e41| 1 gnu ldrhmi r7, [lr, -r9]!
b9cf8c16| 1 gnu selne ip, ip, r9
bd81bd58| 1 gnu poppl {r0, r2, r3, r4, r5, r7, r8, pc}
bdfdb469| 1 gnu ldmibvs r4!, {r0, r2, r3, r4, r5, r7, r8, sl, fp, ip, sp, lr, pc}
beb02500| 1 gnu strhteq fp, [r5], -lr
bf1a5e42| 1 gnu subsmi r1, lr, #782336
c19a4d5e| 1 gnu vmlspl.f32 s19, s27, s2
c1aab15e| 1 gnu vsqrtpl.f32 s20, s2
c354b003| 1 gnu movseq r5, #-1023410176
c4091dc1| 1 gnu tstgt sp, r4, asr #19
c50e13a9| 1 gnu ldmdbge r3, {r0, r2, r6, r7, r9, sl, fp}
c68c8637| 1 gnu strcc r8, [r6, r6, asr #25]
c6ad48e3| 1 gnu movt sl, #36294
c6f65ff5| 1 gnu pld [pc, #-1734]
c8a92f10| 1 gnu eorne sl, pc, r8, asr #19
c9016b61| 1 gnu smulbtvs fp, r9, r1
cadbf49e| 1 gnu vcmpels.f64 d29, d10
ce9de476| 1 gnu strbtvc r9, [r4], lr, asr #27
cf3c1ab1| 1 gnu tstlt sl, pc, asr #25
d355aab6| 1 gnu ssatlt r5, #11, r3, asr #11
d4f4df10| 1 gnu ldrsbne pc, [pc], #68
d6530d61| 1 gnu ldrdvs r5, [sp, -r6]
d74d7800| 1 gnu ldrsbteq r4, [r8], #-215
d9703680| 1 gnu ldrsbthi r7, [r6], -r9
dbe003c0| 1 gnu ldrdgt lr, [r3], -fp
dc709561| 1 gnu ldrsbvs r7, [r5, ip]
dcc3b9c8| 1 gnu ldmgt r9!, {r2, r3, r4, r6, r7, r8, r9, lr, pc}
debfa0e5| 1 gnu str fp, [r0, #4062]!
dee062a1| 1 gnu ldrdge lr, [r2, #-14]!
dfa05ab7| 1 gnu smmlslt sl, pc, r0, sl
e02ef011| 1 gnu mvnsne r2, r0, ror #29
e4d41718| 1 gnu ldmdane r7, {r2, r5, r6, r7, sl, ip, lr, pc}
e6d0fe34| 1 gnu ldrbtcc sp, [lr], #230
e73bf7be| 1 gnu vcvtlt.f32.f64 s7, d23
e74e72b3| 1 gnu cmnlt r2, #3696
e80bf07e| 1 gnu vabsvc.f64 d16, d24
e9b5b001| 1 gnu rorseq fp, r9, #11
ea7bbdbe| 1 gnu vcvtlt.s32.f64 s14, d26
ec063813| 1 gnu teqne r8, #236, 12
ec0e49e1| 1 gnu smlaltt r0, r9, ip, lr
ee4ab85e| 1 gnu vcvtpl.f32.s32 s8, s29
ef461f25| 1 gnu ldrcs r4, [pc, #-1775]
ef5fd002| 1 gnu sbcseq r5, r0, #956
f4cf1d36| 1 gnu ssub8cc ip, sp, r4
f67f73b6| 1 gnu uhsub8lt r7, r3, r6
f6e09ca0| 1 gnu ldrshge lr, [ip], r6
f7702e32| 1 gnu eorcc r7, lr, #247
fa4dcf20| 1 gnu strdcs r4, [pc], #218
fac03720| 1 gnu ldrshtcs ip, [r7], -sl
fc0f64c6| 1 gnu uqsub8gt r0, r4, ip
fc28f481| 1 gnu ldrshhi r2, [r4, #140]!
fc300560| 1 gnu strdvs r3, [r5], -ip
fcacfc70| 1 gnu ldrshtvc sl, [ip], #204
fdbcfaf7| 1 gnu undef
fddf5c86| 1 gnu usub8hi sp, ip, sp
fdf02013| 1 gnu dbgne #13
fe0319e3| 1 gnu tst r9, #-134217725
fe7f3116| 1 gnu shsub8ne r7, r1, lr
ff4f2ac6| 1 gnu qsub8gt r4, sl, pc
ff818c71| 1 gnu strdvc r8, [ip, pc]
|6b5721d3 1 gnu error: unknown instruction
|76452001 1 gnu error: unknown instruction
|97acd647 1 gnu error: unknown instruction
ed003be9| 1 plan9 LDMDB [R0,R2-R3,R5-R7], R11!
923124e0| 1 plan9 MLA R1, R2, R3, R4
923164e0| 1 plan9 MLS R1, R2, R3, R4

756
vendor/golang.org/x/arch/arm/armmap/map.go generated vendored Normal file
View File

@ -0,0 +1,756 @@
// Copyright 2014 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.
// Armmap constructs the ARM opcode map from the instruction set CSV file.
//
// Usage:
// armmap [-fmt=format] arm.csv
//
// The known output formats are:
//
// text (default) - print decoding tree in text form
// decoder - print decoding tables for the armasm package
package main
import (
"bufio"
"encoding/csv"
"flag"
"fmt"
"log"
"os"
"sort"
"strconv"
"strings"
)
var format = flag.String("fmt", "text", "output format: text, decoder")
var inputFile string
func usage() {
fmt.Fprintf(os.Stderr, "usage: armmap [-fmt=format] x86.csv\n")
os.Exit(2)
}
func main() {
log.SetFlags(0)
log.SetPrefix("armmap: ")
flag.Usage = usage
flag.Parse()
if flag.NArg() != 1 {
usage()
}
inputFile = flag.Arg(0)
var print func(*Prog)
switch *format {
default:
log.Fatalf("unknown output format %q", *format)
case "text":
print = printText
case "decoder":
print = printDecoder
}
p, err := readCSV(flag.Arg(0))
if err != nil {
log.Fatal(err)
}
print(p)
}
// readCSV reads the CSV file and returns the corresponding Prog.
// It may print details about problems to standard error using the log package.
func readCSV(file string) (*Prog, error) {
// Read input.
// Skip leading blank and # comment lines.
f, err := os.Open(file)
if err != nil {
return nil, err
}
b := bufio.NewReader(f)
for {
c, err := b.ReadByte()
if err != nil {
break
}
if c == '\n' {
continue
}
if c == '#' {
b.ReadBytes('\n')
continue
}
b.UnreadByte()
break
}
table, err := csv.NewReader(b).ReadAll()
if err != nil {
return nil, fmt.Errorf("parsing %s: %v", file, err)
}
if len(table) == 0 {
return nil, fmt.Errorf("empty csv input")
}
if len(table[0]) < 5 {
return nil, fmt.Errorf("csv too narrow: need at least five columns")
}
p := &Prog{}
for _, row := range table {
add(p, row[0], row[1], row[2], row[3], row[4])
}
return p, nil
}
type Prog struct {
Inst []Inst
OpRanges map[string]string
}
type Inst struct {
Text string
Encoding string
Mask uint32
Value uint32
Priority int
OpBase string
OpBits uint64
Args []string
}
type Arg struct {
Name string
Bits uint64
}
// add adds the entry from the CSV described by maskstr, valuestr, text, encoding, tags
// to the program p.
func add(p *Prog, maskstr, valuestr, text, encoding, tags string) {
if strings.Contains(tags, "pseudo") {
return
}
// For now, ignore the VFP floating point instructions.
if strings.HasPrefix(text, "V") && !strings.Contains(tags, "vfp") {
// TODO
return
}
mask, err := strconv.ParseUint(maskstr, 0, 32)
if err != nil {
log.Printf("invalid mask %q", maskstr)
return
}
value, err := strconv.ParseUint(valuestr, 0, 32)
if err != nil {
log.Printf("invalid value %q", valuestr)
return
}
// Parse encoding, building size and offset of each field.
// The first field in the encoding is the largest offset.
fuzzy := uint32(0) // mask of 'should be' bits
fieldOffset := map[string]int{}
fieldWidth := map[string]int{}
off := 32
for _, f := range strings.Split(encoding, "|") {
n := 1
if i := strings.Index(f, ":"); i >= 0 {
n, _ = strconv.Atoi(f[i+1:])
}
off -= n
fieldOffset[f] = off
fieldWidth[f] = n
if f == "(0)" || f == "(1)" {
fuzzy |= 1 << uint(off)
}
}
if off != 0 {
fmt.Fprintf(os.Stderr, "%s: counted %d bits in %s\n", text, 32-off, encoding)
}
// Track which encoding fields we found uses for.
// If we do not find a use for a field, that's an error in the input tables.
fieldUsed := map[string]bool{}
// Split text into opcode and arguments.
var op, argstr string
if i := strings.Index(text, " "); i >= 0 {
op = text[:i]
argstr = text[i:]
} else {
op = text
}
op = strings.TrimSpace(op)
argstr = strings.TrimSpace(argstr)
// Parse opcode suffixes.
i := strings.Index(op, "<")
if i < 0 {
i = len(op)
}
if j := strings.Index(op, "{"); j >= 0 && j < i {
i = j
}
op, suffix := op[:i], op[i:]
if suffix != "" && opSuffix[suffix] == "" {
fmt.Fprintf(os.Stderr, "%s: invalid op suffix %q in %s\n", text, suffix, op+suffix)
}
// Make sure fields needed by opcode suffix are available.
for _, f := range strings.Split(opSuffix[suffix], ",") {
if f != "" && fieldWidth[f] == 0 {
fmt.Fprintf(os.Stderr, "%s: opsuffix %s missing %s in encoding %s\n", text, suffix, f, encoding)
}
fieldUsed[f] = true
}
// Build list of opcodes that can be generated by this suffix.
// For example, the opcodes generated by ADD<c> are ADD.EQ, ADD.NE, etc.
// To simplify the decoding of instruction opcodes, we arrange that this
// sequence aligns with the encoding, so that decoding amounts to extracting
// the right bits, concatenating them, and adding them to the first opcode in
// the sequence. If the condition code is present, we always place it in the
// low order bits, so that x&^15 == FOO_EQ tests whether x is any of the
// conditional FOO instructions.
ops := []string{op}
opBits := uint64(0) // record of bits to extract and add to opcode base
opFields := strings.Split(opSuffix[suffix], ",")
// First the optional elements, like {S} meaning "" or ".S".
for strings.HasPrefix(suffix, "{") {
i := strings.Index(suffix, "}")
var f, option string
option, suffix = suffix[1:i], suffix[i+1:]
f, opFields = opFields[0], opFields[1:]
if option == "W" {
// The {W} option on PLD{W} uses the R bit which is !W.
ops = cross(ops, "."+option, "")
} else {
ops = cross(ops, "", "."+option)
}
if fieldWidth[f] != 1 {
fmt.Fprintf(os.Stderr, "%s: have %d bits for {%s}\n", text, fieldWidth[f], option)
}
// opBits is a sequence of 16-bit chunks describing contiguous bit sections.
// Each chunk is 8-bit offset followed by 8-bit size.
opBits = opBits<<16 | uint64(fieldOffset[f])<<8 | 1
}
// Then the true field substitutions.
haveCond := false
for strings.Contains(suffix, "<") {
var f, literal, x string
if len(opFields) == 0 {
fmt.Fprintf(os.Stderr, "%s: ran out of suffix fields for <%s>\n", text, x)
break
}
f, opFields = opFields[0], opFields[1:]
i := strings.Index(suffix, "<")
j := strings.Index(suffix, ">")
literal, x, suffix = suffix[:i], suffix[i+1:j], suffix[j+1:]
// Add leading literal text to all opcodes.
ops = cross(ops, literal)
// The <c> condition can happen anywhere in the opcode text
// but we want to generate the actual variation in the low bits
// of the list index. Remember when and where we've seen <c> and apply
// it after the loop has finished.
if x == "c" && f == "cond:4" {
haveCond = true
ops = cross(ops, "_COND_")
continue
}
// Otherwise, choices[x] lists the possible expansions of <x>.
// If <x> is of the form <A,B,C> the choices are A, B, and C.
expand := choices[x]
if expand == nil && strings.Contains(x, ",") {
expand = strings.Split(x, ",")
}
if expand == nil {
fmt.Fprintf(os.Stderr, "%s: unknown choices for <%s>\n", text, x)
expand = []string{x}
} else if len(expand) != 1<<uint(fieldWidth[f]) {
fmt.Fprintf(os.Stderr, "%s: have %d choices for <%s> but %d bits\n", text, len(expand), x, fieldWidth[f])
}
opBits = opBits<<16 | uint64(fieldOffset[f])<<8 | uint64(fieldWidth[f])
ops = cross(ops, expand...)
}
if haveCond {
// Apply condtional suffix last.
opBits = opBits<<16 | 28<<8 | 4
ops = crossCond(ops)
}
ops = cross(ops, suffix)
// Now ops is a list of opcodes generated by this opcode pattern.
// We want to make sure that we can arrange for those opcodes to
// happen consecutively in the final opcode numbering.
// Record in p.OpRanges[op] the required consecutive sequence of
// opcode that includes op. To make searches easier, we record
// the sequence as a comma-separated list of strings with commas
// on both ends: [A, B] encodes as ",A,B,".
if p.OpRanges == nil {
p.OpRanges = make(map[string]string)
}
opstr := "," + strings.Join(ops, ",") + ","
for _, op := range ops {
if old := p.OpRanges[op]; old != "" && old != opstr {
if strings.Contains(old, opstr) {
opstr = old
} else if strings.Contains(opstr, old) {
// great, do nothing
} else {
// It would also be okay if there is some subsequence s such that
// old = x+s and opstr = s+y (or vice versa), in which case we should
// record opstr = x+s+y. However, this has not come up in practice.
// Failing that, we can't satisfy the sequencing requirements.
fmt.Fprintf(os.Stderr, "%s: %s appears in both %s and %s\n", text, op, old, opstr)
}
}
}
for _, op := range strings.Split(opstr, ",") {
if op != "" {
p.OpRanges[op] = opstr
}
}
// Process the arguments, building a list of argument descriptions.
// Each argument description has the form <argument>|field@off|field@off...
// where the |field@off suffixes give the name and location of the fields
// needed by the argument. Each such string maps to a different decoding
// type in the generated table, according to the argOps map.
var args []string
for argstr != "" {
// Find longest match among argSuffixes pieces.
best := 0
for a := range argSuffixes {
if argstr == a || strings.HasPrefix(argstr, a+",") {
if best < len(a) {
best = len(a)
}
}
}
if best == 0 {
fmt.Fprintf(os.Stderr, "%s: unknown arg %s\n", text, argstr)
break
}
var arg, desc string
arg, argstr = argstr[:best], strings.TrimSpace(strings.TrimLeft(argstr[best:], ","))
desc = arg
for _, f := range strings.Split(argSuffixes[desc], ",") {
if f == "" {
continue
}
if fieldWidth[f] == 0 {
fmt.Fprintf(os.Stderr, "%s: arg %s missing %s in encoding %s\n", text, arg, f, encoding)
}
fieldUsed[f] = true
desc += fmt.Sprintf("|%s@%d", f, fieldOffset[f])
}
args = append(args, desc)
}
// Check that all encoding fields were used by suffix or argument decoding.
for f := range fieldWidth {
switch f {
case "0", "1", "(0)", "(1)":
// ok
default:
if !fieldUsed[f] {
fmt.Fprintf(os.Stderr, "%s: encoding field %s not used in %s\n", text, f, encoding)
}
}
}
// Determine decoding priority. Instructions that say 'SEE X' in the tag
// are considered lower priority than ones that don't. In theory the
// structure described by the SEE tags might be richer than that, but
// in practice it only has those two levels.
// We leave space for two more priorities according to whether the
// fuzzy bits are set correctly. The full set of priorities then is:
//
// 4 - no SEE tag, fuzzy bits all match
// 3 - no SEE tag, some fuzzy bits don't match
// 2 - SEE tag, fuzzy bits all match
// 1 - SEE tag, some fuzzy bits don't match
//
// You could argue for swapping the middle two levels but so far
// it has not been an issue.
pri := 4
if strings.Contains(tags, "SEE") {
pri = 2
}
inst := Inst{
Text: text,
Encoding: encoding,
Mask: uint32(mask),
Value: uint32(value),
Priority: pri,
OpBase: ops[0],
OpBits: opBits,
Args: args,
}
p.Inst = append(p.Inst, inst)
if fuzzy != 0 {
inst.Mask &^= fuzzy
inst.Priority--
p.Inst = append(p.Inst, inst)
}
}
// opSuffix describes the encoding fields used to resolve a given opcode suffix.
var opSuffix = map[string]string{
"<ADD,SUB>": "op",
"<BIF,BIT,BSL>": "op:2",
"<MLA,MLS><c>.F<32,64>": "op,cond:4,sz",
"<MLS,MLA><c>.F<32,64>": "op,cond:4,sz",
"<BT,TB><c>": "tb,cond:4",
"<TBL,TBX>.8": "op",
"<c>": "cond:4",
"<c>.32": "cond:4",
"<c>.F<32,64>": "cond:4,sz",
"<x><y><c>": "N,M,cond:4",
"<y><c>": "M,cond:4",
"{B}<c>": "B,cond:4",
"{E}<c>.F<32,64>": "E,cond:4,sz",
"{R}<c>": "R,cond:4",
"<c>.F<32,64>.<U,S>32": "cond:4,sz,op",
"<R,><c>.<U,S>32.F<32,64>": "op,cond:4,signed,sz",
"{S}<c>": "S,cond:4",
"{W}": "R",
"{X}<c>": "M,cond:4",
"<B,T><c>.<F32.F16,F16.F32>": "T,cond:4,op",
"<c>.<F64.F32,F32.F64>": "cond:4,sz",
"<c>.FX<S,U><16,32>.F<32,64>": "cond:4,U,sx,sz",
"<c>.F<32,64>.FX<S,U><16,32>": "cond:4,sz,U,sx",
}
// choices[x] describes the choices for filling in "<"+x+">" in an opcode suffix.
// Opcodes that end up containing ZZ take up a numeric sequence value but are
// not exported in the package API.
var choices = map[string][]string{
"c": {".EQ", ".NE", ".CS", ".CC", ".MI", ".PL", ".VS", ".VC", ".HI", ".LS", ".GE", ".LT", ".GT", ".LE", "", ".ZZ"},
"x": {"B", "T"},
"y": {"B", "T"},
}
// argOps maps from argument descriptions to internal decoder name.
var argOps = map[string]string{
// 4-bit register encodings
"<Rm>|Rm:4@0": "arg_R_0",
"<Rn>|Rn:4@0": "arg_R_0",
"<Rt>|Rt:4@0": "arg_R_0",
"<Rm>|Rm:4@8": "arg_R_8",
"<Ra>|Ra:4@12": "arg_R_12",
"<Rd>|Rd:4@12": "arg_R_12",
"<RdLo>|RdLo:4@12": "arg_R_12",
"<Rt>|Rt:4@12": "arg_R_12",
"<Rt_nzcv>|Rt:4@12": "arg_R_12_nzcv",
"<Rd>|Rd:4@16": "arg_R_16",
"<RdHi>|RdHi:4@16": "arg_R_16",
"<Rn>|Rn:4@16": "arg_R_16",
// first and second of consecutive register pair
"<Rt1>|Rt:4@0": "arg_R1_0",
"<Rt1>|Rt:4@12": "arg_R1_12",
"<Rt2>|Rt:4@0": "arg_R2_0",
"<Rt2>|Rt:4@12": "arg_R2_12",
// register arithmetic
"<Rm>,<type> <Rs>|Rm:4@0|Rs:4@8|type:2@5": "arg_R_shift_R",
"<Rm>{,<shift>}|Rm:4@0|imm5:5@7|type:2@5": "arg_R_shift_imm",
"<Rn>{,<shift>}|Rn:4@0|imm5:5@7|sh@6": "arg_R_shift_imm",
"<Rm>{,LSL #<imm5>}|Rm:4@0|imm5:5@7": "arg_R_shift_imm",
"<Rm>{,<rotation>}|Rm:4@0|rotate:2@10": "arg_R_rotate",
// memory references
"<Rn>{!}|Rn:4@16|W@21": "arg_R_16_WB",
"[<Rn>]|Rn:4@16": "arg_mem_R",
"[<Rn>,+/-<Rm>{, <shift>}]{!}|Rn:4@16|U@23|Rm:4@0|type:2@5|imm5:5@7|P@24|W@21": "arg_mem_R_pm_R_shift_imm_W",
"[<Rn>{,#+/-<imm8>}]{!}|Rn:4@16|P@24|U@23|W@21|imm4H:4@8|imm4L:4@0": "arg_mem_R_pm_imm8_W",
"[<Rn>] {,#+/-<imm8>}|Rn:4@16|U@23|imm4H:4@8|imm4L:4@0": "arg_mem_R_pm_imm8_postindex",
"[<Rn>{,#+/-<imm12>}]{!}|Rn:4@16|P@24|U@23|W@21|imm12:12@0": "arg_mem_R_pm_imm12_W",
"[<Rn>],#+/-<imm12>|Rn:4@16|imm12:12@0|U@23": "arg_mem_R_pm_imm12_postindex",
"[<Rn>,#+/-<imm12>]|Rn:4@16|U@23|imm12:12@0": "arg_mem_R_pm_imm12_offset",
"[<Rn>] {,#+/-<imm12>}|Rn:4@16|U@23|imm12:12@0": "arg_mem_R_pm_imm12_postindex",
"[<Rn>], +/-<Rm>|Rn:4@16|U@23|Rm:4@0": "arg_mem_R_pm_R_postindex",
"[<Rn>,+/-<Rm>]{!}|Rn:4@16|U@23|Rm:4@0|P@24|W@21": "arg_mem_R_pm_R_W",
"[<Rn>],+/-<Rm>{, <shift>}|Rn:4@16|Rm:4@0|imm5:5@7|type:2@5|U@23": "arg_mem_R_pm_R_shift_imm_postindex",
"[<Rn>,+/-<Rm>{, <shift>}]|Rn:4@16|U@23|Rm:4@0|type:2@5|imm5:5@7": "arg_mem_R_pm_R_shift_imm_offset",
"[<Rn>{,#+/-<imm8>}]|Rn:4@16|U@23|imm8:8@0": "arg_mem_R_pm_imm8at0_offset",
// pc-relative constants
"<label+12>|imm12:12@0": "arg_label_p_12",
"<label-12>|imm12:12@0": "arg_label_m_12",
"<label+/-12>|imm12:12@0|U@23": "arg_label_pm_12",
"<label+/-4+4>|imm4H:4@8|imm4L:4@0|U@23": "arg_label_pm_4_4",
// constants
"#<const>|imm12:12@0": "arg_const",
"#<imm5>|imm5:5@7": "arg_imm5",
"#<imm5_nz>|imm5:5@7": "arg_imm5_nz",
"#<imm5_32>|imm5:5@7": "arg_imm5_32",
"<label24>|imm24:24@0": "arg_label24",
"#<lsb>|lsb:5@7": "arg_imm5",
"#<width>|lsb:5@7|msb:5@16": "arg_lsb_width",
"#<imm12+4>|imm12:12@8|imm4:4@0": "arg_imm_12at8_4at0",
"#<imm12+4>|imm12:12@0|imm4:4@16": "arg_imm_4at16_12at0",
"<label24H>|imm24:24@0|H@24": "arg_label24H",
"#<option>|option:4@0": "arg_option",
"#<widthm1>|widthm1:5@16": "arg_widthm1",
"#<sat_imm4>|sat_imm:4@16": "arg_satimm4",
"#<sat_imm5>|sat_imm:5@16": "arg_satimm5",
"#<sat_imm4m1>|sat_imm:4@16": "arg_satimm4m1",
"#<sat_imm5m1>|sat_imm:5@16": "arg_satimm5m1",
"#<imm24>|imm24:24@0": "arg_imm24",
// special
"<registers>|register_list:16@0": "arg_registers",
"<registers2>|register_list:16@0": "arg_registers2",
"<registers1>|Rt:4@12": "arg_registers1",
"<endian_specifier>|E@9": "arg_endian",
"SP": "arg_SP",
"APSR": "arg_APSR",
"FPSCR": "arg_FPSCR",
// VFP floating point registers
"<Sd>|Vd:4@12|D@22": "arg_Sd",
"<Sd,Dd>|Vd:4@12|D@22|sz@8": "arg_Sd_Dd",
"<Dd,Sd>|Vd:4@12|D@22|sz@8": "arg_Dd_Sd",
"<Sn>|Vn:4@16|N@7": "arg_Sn",
"<Sn,Dn>|Vn:4@16|N@7|sz@8": "arg_Sn_Dn",
"<Sm>|Vm:4@0|M@5": "arg_Sm",
"<Sm,Dm>|Vm:4@0|M@5|sz@8": "arg_Sm_Dm",
"#0.0": "arg_fp_0",
"#<imm_vfp>|imm4H:4@16|imm4L:4@0|sz@8": "arg_imm_vfp",
"#<fbits>|sx@7|imm4:4@0|i@5": "arg_fbits",
"<Dn[x]>|N@7|Vn:4@16|opc1@21": "arg_Dn_half",
"<Dd[x]>|D@7|Vd:4@16|opc1@21": "arg_Dn_half",
}
// argSuffixes describes the encoding fields needed for a particular suffix.
// The set of keys in argSuffixes also drives the identification of suffix pieces.
// For example, <Rm> and <Rm>{, <type> <Rs>} are both keys in the map
// and matching is done 'longest first', so "<Rm>, <Rm>{, <type> <Rs>}" is
// parsed as just two arguments despite the extra ", ".
// The field order in the map values must match the order expected in
// the argument descriptions in argOps.
var argSuffixes = map[string]string{
"#0": "",
"#0.0": "",
"#<const>": "imm12:12",
"#<fbits>": "sx,imm4:4,i",
"#<imm12+4>": "imm12:12,imm4:4",
"#<imm24>": "imm24:24",
"#<imm3>": "imm3:3",
"#<imm4>": "imm4:4",
"#<imm5>": "imm5:5",
"#<imm5_nz>": "imm5:5",
"#<imm5_32>": "imm5:5",
"#<imm6>": "imm6:6",
"#<immsize>": "size:2",
"#<imm_vfp>": "imm4H:4,imm4L:4,sz",
"#<sat_imm4>": "sat_imm:4",
"#<sat_imm5>": "sat_imm:5",
"#<sat_imm4m1>": "sat_imm:4",
"#<sat_imm5m1>": "sat_imm:5",
"#<lsb>": "lsb:5",
"#<option>": "option:4",
"#<width>": "lsb:5,msb:5",
"#<widthm1>": "widthm1:5",
"+/-<Rm>": "Rm:4,U",
"<Dd>": "D,Vd:4",
"<Dd[x]>": "D,Vd:4,opc1",
"<Dm>": "M,Vm:4",
"<Dm[x]>": "M,Vm:4,size:2",
"<Dn>": "N,Vn:4",
"<Dn[x]>": "N,Vn:4,opc1",
"<Dm[size_x]>": "imm4:4",
"<Qd>": "D,Vd:4",
"<Qm>": "M,Vm:4",
"<Qn>": "N,Vn:4",
"<Ra>": "Ra:4",
"<Rd>": "Rd:4",
"<RdHi>": "RdHi:4",
"<RdLo>": "RdLo:4",
"<Rm>": "Rm:4",
"<Rm>{,<rotation>}": "Rm:4,rotate:2",
"<Rm>{,<shift>}": "Rm:4,imm5:5,type:2",
"<Rm>{,LSL #<imm5>}": "Rm:4,imm5:5",
"<Rn>": "Rn:4",
"<Rn>{!}": "Rn:4,W",
"<Rn>{,<shift>}": "Rn:4,imm5:5,sh",
"<Rs>": "Rs:4",
"<Rt1>": "Rt:4",
"<Rt2>": "Rt:4",
"<Rt>": "Rt:4",
"<Rt_nzcv>": "Rt:4",
"<Sd>": "Vd:4,D",
"<Sm1>": "Vm:4,M",
"<Sm>": "Vm:4,M",
"<Sn>": "Vn:4,N",
"<Sd,Dd>": "Vd:4,D,sz",
"<Dd,Sd>": "Vd:4,D,sz",
"<Sn,Dn>": "Vn:4,N,sz",
"<Sm,Dm>": "Vm:4,M,sz",
"<endian_specifier>": "E",
"<label+/-12>": "imm12:12,U",
"<label+12>": "imm12:12",
"<label-12>": "imm12:12",
"<label24>": "imm24:24",
"<label24H>": "imm24:24,H",
"<label+/-4+4>": "imm4H:4,imm4L:4,U",
"<list4>": "D,Vd:4,type:4",
"<list3>": "D,Vd:4,index_align:4",
"<list3t>": "D,Vd:4,T",
"<list1>": "D,Vd:4",
"<list_len>": "N,Vn:4,len:2",
"<vlist32>": "D,Vd:4,imm8:8",
"<vlist64>": "D,Vd:4,imm8:8",
"<registers>": "register_list:16",
"<registers2>": "register_list:16",
"<registers1>": "Rt:4",
"APSR": "",
"<Rm>,<type> <Rs>": "Rm:4,Rs:4,type:2",
"FPSCR": "",
"SP": "",
"[<Rn>,#+/-<imm12>]": "Rn:4,U,imm12:12",
"[<Rn>,+/-<Rm>]{!}": "Rn:4,U,Rm:4,P,W",
"[<Rn>,+/-<Rm>{, <shift>}]": "Rn:4,U,Rm:4,type:2,imm5:5",
"[<Rn>,+/-<Rm>{, <shift>}]{!}": "Rn:4,U,Rm:4,type:2,imm5:5,P,W",
"[<Rn>] {,#+/-<imm12>}": "Rn:4,U,imm12:12",
"[<Rn>] {,#+/-<imm8>}": "Rn:4,U,imm4H:4,imm4L:4",
"[<Rn>]": "Rn:4",
"[<Rn>],#+/-<imm12>": "Rn:4,imm12:12,U",
"[<Rn>],+/-<Rm>{, <shift>}": "Rn:4,Rm:4,imm5:5,type:2,U",
"[<Rn>]{!}": "Rn:4,Rm:4",
"[<Rn>{@<align>}]{!}": "XXX",
"[<Rn>{,#+/-<imm12>}]{!}": "Rn:4,P,U,W,imm12:12",
"[<Rn>{,#+/-<imm8>}]{!}": "Rn:4,P,U,W,imm4H:4,imm4L:4",
"[<Rn>{,#+/-<imm8>}]": "Rn:4,U,imm8:8",
"[<Rn>], +/-<Rm>": "Rn:4,U,Rm:4",
"#<imm_simd1>": "i,imm3:3,imm4:4,cmode:4",
"#<imm_simd>": "op,i,imm3:3,imm4:4,cmode:4",
"#<imm_vs>": "L,imm6:6",
"#<imm_vsn>": "imm6:6",
}
// cross returns the string concatenation cross product of xs and ys.
func cross(xs []string, ys ...string) []string {
var xys []string
for _, x := range xs {
for _, y := range ys {
xys = append(xys, x+y)
}
}
return xys
}
// crossCond returns the cross product of xs with all the possible
// conditional execution suffixes. It is assumed that each string x in xs
// contains a substring _COND_ marking where the conditional suffix
// should be placed.
func crossCond(xs []string) []string {
ys := choices["c"]
var xys []string
for _, x := range xs {
i := strings.Index(x, "_COND_")
pre, post := x[:i], x[i+6:]
for _, y := range ys {
xys = append(xys, pre+y+post)
}
}
return xys
}
// printText implements the -fmt=text mode, which is not implemented (yet?).
func printText(p *Prog) {
log.Fatal("-fmt=text not implemented")
}
// printDecoder implements the -fmt=decoder mode.
// It emits the tables.go for package armasm's decoder.
func printDecoder(p *Prog) {
fmt.Printf("package armasm\n\n")
// Build list of opcodes sorted by name
// but preserving the sequential ranges needed for opcode decoding.
haveRange := make(map[string]string)
for _, r := range p.OpRanges {
haveRange[r] = r
}
var ranges []string
for _, r := range haveRange {
ranges = append(ranges, r)
}
sort.Strings(ranges)
// Emit const definitions for opcodes.
fmt.Printf("const (\n")
iota := 0
fmt.Printf("\t_ Op = iota\n")
iota++
for _, r := range ranges {
for _, op := range strings.Split(r, ",") {
if op == "" {
continue
}
// Assume if opcode says .EQ it is the start of a 16-wide
// iteration through the conditional suffixes. If so, emit
// blank names until the assigned value is 16-aligned.
if strings.Contains(op, ".EQ") {
for iota&15 != 0 {
fmt.Printf("\t_\n")
iota++
}
}
fmt.Printf("\t%s\n", strings.Replace(op, ".", "_", -1))
iota++
}
}
fmt.Printf(")\n")
// Emit slice mapping opcode number to name string.
fmt.Printf("\nvar opstr = [...]string{\n")
for _, r := range ranges {
for _, op := range strings.Split(r, ",") {
if op == "" {
continue
}
fmt.Printf("\t%s: %q,\n", strings.Replace(op, ".", "_", -1), op)
}
}
fmt.Printf("}\n")
// Emit decoding table.
unknown := map[string]bool{}
fmt.Printf("\nvar instFormats = [...]instFormat{\n")
for _, inst := range p.Inst {
fmt.Printf("\t{%#08x, %#08x, %d, %s, %#x, instArgs{", inst.Mask, inst.Value, inst.Priority, strings.Replace(inst.OpBase, ".", "_", -1), inst.OpBits)
for i, a := range inst.Args {
if i > 0 {
fmt.Printf(", ")
}
str := argOps[a]
if str == "" && !unknown[a] {
fmt.Fprintf(os.Stderr, "%s: unknown arg %s\n", inst.Text, a)
unknown[a] = true
}
fmt.Printf("%s", str)
}
fmt.Printf("}}, // %s %s\n", inst.Text, inst.Encoding)
}
fmt.Printf("}\n")
}

615
vendor/golang.org/x/arch/arm/armspec/spec.go generated vendored Normal file
View File

@ -0,0 +1,615 @@
// Copyright 2014 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.
// +build go1.6
// +build !386 go1.8
// ... see golang.org/issue/12840
// Armspec reads the ``ARM Architecture Reference Manual''
// to collect instruction encoding details and writes those details to standard output
// in JSON format.
//
// Warning Warning Warning
//
// This program is unfinished. It is being published in this incomplete form
// for interested readers, but do not expect it to be runnable or useful.
//
package main
import (
"bufio"
"bytes"
"encoding/json"
"fmt"
"log"
"math"
"os"
"regexp"
"sort"
"strconv"
"strings"
"rsc.io/pdf"
)
type Inst struct {
Name string
ID string
Bits string
Arch string
Syntax []string
Code string
}
const debugPage = 0
var stdout *bufio.Writer
func main() {
log.SetFlags(0)
log.SetPrefix("armspec: ")
if len(os.Args) != 2 {
fmt.Fprintf(os.Stderr, "usage: armspec file.pdf\n")
os.Exit(2)
}
f, err := pdf.Open(os.Args[1])
if err != nil {
log.Fatal(err)
}
// Find instruction set reference in outline, to build instruction list.
instList := instHeadings(f.Outline())
if len(instList) < 200 {
log.Fatalf("only found %d instructions in table of contents", len(instList))
}
stdout = bufio.NewWriter(os.Stdout)
fmt.Fprintf(stdout, "[")
numTable := 0
defer stdout.Flush()
// Scan document looking for instructions.
// Must find exactly the ones in the outline.
n := f.NumPage()
PageLoop:
for pageNum := 1; pageNum <= n; pageNum++ {
if debugPage > 0 && pageNum != debugPage {
continue
}
if pageNum > 1127 {
break
}
p := f.Page(pageNum)
name, table := parsePage(pageNum, p)
if name == "" {
continue
}
if len(table) < 1 {
if false {
fmt.Fprintf(os.Stderr, "no encodings for instruction %q (page %d)\n", name, pageNum)
}
continue
}
for _, inst := range table {
if numTable > 0 {
fmt.Fprintf(stdout, ",")
}
numTable++
js, _ := json.Marshal(inst)
fmt.Fprintf(stdout, "\n%s", jsFix.Replace(string(js)))
}
for j, headline := range instList {
if name == headline {
instList[j] = ""
continue PageLoop
}
}
fmt.Fprintf(os.Stderr, "unexpected instruction %q (page %d)\n", name, pageNum)
}
fmt.Fprintf(stdout, "\n]\n")
stdout.Flush()
if debugPage == 0 {
for _, headline := range instList {
if headline != "" {
switch headline {
default:
fmt.Fprintf(os.Stderr, "missing instruction %q\n", headline)
case "CHKA": // ThumbEE
case "CPS": // system instruction
case "CPY": // synonym for MOV
case "ENTERX": // ThumbEE
case "F* (former VFP instruction mnemonics)": // synonyms
case "HB, HBL, HBLP, HBP": // ThumbEE
case "LEAVEX": // ThumbEE
case "MOV (shifted register)": // pseudo instruction for ASR, LSL, LSR, ROR, and RRX
case "NEG": // synonym for RSB
case "RFE": // system instruction
case "SMC (previously SMI)": // system instruction
case "SRS": // system instruction
case "SUBS PC, LR and related instructions": // system instruction
case "VAND (immediate)": // pseudo instruction
case "VCLE (register)": // pseudo instruction
case "VCLT (register)": // pseudo instruction
case "VORN (immediate)": // pseudo instruction
}
}
}
}
}
func instHeadings(outline pdf.Outline) []string {
return appendInstHeadings(outline, nil)
}
var instRE = regexp.MustCompile(`A[\d.]+ Alphabetical list of instructions`)
var childRE = regexp.MustCompile(`A[\d.]+ (.+)`)
var sectionRE = regexp.MustCompile(`^A[\d.]+$`)
var bitRE = regexp.MustCompile(`^( |[01]|\([01]\))*$`)
func appendInstHeadings(outline pdf.Outline, list []string) []string {
if instRE.MatchString(outline.Title) {
for _, child := range outline.Child {
m := childRE.FindStringSubmatch(child.Title)
if m == nil {
fmt.Fprintf(os.Stderr, "cannot parse section title: %s\n", child.Title)
continue
}
list = append(list, m[1])
}
}
for _, child := range outline.Child {
list = appendInstHeadings(child, list)
}
return list
}
const inch = 72.0
func parsePage(num int, p pdf.Page) (name string, table []Inst) {
content := p.Content()
var text []pdf.Text
for _, t := range content.Text {
if match(t, "Times-Roman", 7.2, "") {
t.FontSize = 9
}
if match(t, "Times-Roman", 6.72, "") && '0' <= t.S[0] && t.S[0] <= '9' {
t.S = string([]rune("⁰¹²³⁴⁵⁶⁷⁸⁹")[t.S[0]-'0'])
t.FontSize = 9
t.Y -= 2.28
}
if t.Font == "Gen_Arial" {
continue
}
text = append(text, t)
}
text = findWords(text)
for i, t := range text {
if t.Font == "Times" {
t.Font = "Times-Roman"
text[i] = t
}
}
if debugPage > 0 {
for _, t := range text {
fmt.Println(t)
}
for _, r := range content.Rect {
fmt.Println(r)
}
}
// Remove text we should ignore.
out := text[:0]
skip := false
for _, t := range text {
// skip page footer
if match(t, "Helvetica", 8, "A") || match(t, "Helvetica", 8, "ARM DDI") || match(t, "Helvetica-Oblique", 8, "Copyright") {
continue
}
// skip section header and body text
if match(t, "Helvetica-Bold", 12, "") && (sectionRE.MatchString(t.S) || t.S == "Alphabetical list of instructions") {
skip = true
continue
}
if skip && match(t, "Times-Roman", 9, "") {
continue
}
skip = false
out = append(out, t)
}
text = out
// Page header must say Instruction Details.
if len(text) == 0 || !match(text[0], "Helvetica-Oblique", 8, "Instruction Details") && !match(text[0], "Times-Roman", 9, "Instruction Details") {
return "", nil
}
text = text[1:]
isSection := func(text []pdf.Text, i int) int {
if i+2 <= len(text) && match(text[i], "Helvetica-Bold", 10, "") && sectionRE.MatchString(text[i].S) && match(text[i+1], "Helvetica-Bold", 10, "") {
return 2
}
if i+1 <= len(text) && match(text[i], "Helvetica-Bold", 10, "") && childRE.MatchString(text[i].S) {
return 1
}
return 0
}
// Skip dummy headlines and sections.
for d := isSection(text, 0); d != 0; d = isSection(text, 0) {
i := d
for i < len(text) && !match(text[i], "Helvetica-Bold", 9, "Encoding") && !match(text[i], "Helvetica-Bold", 10, "") {
i++
}
if isSection(text, i) == 0 {
break
}
text = text[i:]
}
// Next line is headline. Can wrap to multiple lines.
d := isSection(text, 0)
if d == 0 {
if debugPage > 0 {
fmt.Printf("non-inst-headline: %v\n", text[0])
}
checkNoEncodings(num, text)
return "", nil
}
if d == 2 {
name = text[1].S
text = text[2:]
} else if d == 1 {
m := childRE.FindStringSubmatch(text[0].S)
name = m[1]
text = text[1:]
}
for len(text) > 0 && match(text[0], "Helvetica-Bold", 10, "") {
name += " " + text[0].S
text = text[1:]
}
// Skip description.
for len(text) > 0 && (match(text[0], "Times-Roman", 9, "") || match(text[0], "LucidaSansTypewriteX", 6.48, "") || match(text[0], "Times-Bold", 10, "Note")) {
text = text[1:]
}
// Encodings follow.
warned := false
for i := 0; i < len(text); {
if match(text[i], "Helvetica-Bold", 10, "Assembler syntax") ||
match(text[i], "Helvetica-Bold", 9, "Modified operation in ThumbEE") ||
match(text[i], "Helvetica-Bold", 9, "Unallocated memory hints") ||
match(text[i], "Helvetica-Bold", 9, "Related encodings") ||
match(text[i], "Times-Roman", 9, "Figure A") ||
match(text[i], "Helvetica-Bold", 9, "Table A") ||
match(text[i], "Helvetica-Bold", 9, "VFP Instructions") ||
match(text[i], "Helvetica-Bold", 9, "VFP instructions") ||
match(text[i], "Helvetica-Bold", 9, "VFP vectors") ||
match(text[i], "Helvetica-Bold", 9, "FLDMX") ||
match(text[i], "Helvetica-Bold", 9, "FSTMX") ||
match(text[i], "Helvetica-Bold", 9, "Advanced SIMD and VFP") {
checkNoEncodings(num, text[i:])
break
}
if match(text[i], "Helvetica-Bold", 9, "Figure A") {
y := text[i].Y
i++
for i < len(text) && math.Abs(text[i].Y-y) < 2 {
i++
}
continue
}
if !match(text[i], "Helvetica-Bold", 9, "Encoding") {
if !warned {
warned = true
fmt.Fprintln(os.Stderr, "page", num, ": unexpected:", text[i])
}
i++
continue
}
inst := Inst{
Name: name,
}
enc := text[i].S
x := text[i].X
i++
// Possible subarchitecture notes.
for i < len(text) && text[i].X > x+36 {
if inst.Arch != "" {
inst.Arch += " "
}
inst.Arch += text[i].S
i++
}
// Encoding syntaxes.
for i < len(text) && (match(text[i], "LucidaSansTypewriteX", 6.48, "") || text[i].X > x+36) {
if text[i].X < x+0.25*inch {
inst.Syntax = append(inst.Syntax, text[i].S)
} else {
s := inst.Syntax[len(inst.Syntax)-1]
if !strings.Contains(s, "\t") {
s += "\t"
} else {
s += " "
}
s += text[i].S
inst.Syntax[len(inst.Syntax)-1] = s
}
i++
}
var bits, abits, aenc string
bits, i = readBitBox(inst.Name, inst.Syntax, content, text, i)
if strings.Contains(enc, " / ") {
if i < len(text) && match(text[i], "Times-Roman", 8, "") {
abits, i = readBitBox(inst.Name, inst.Syntax, content, text, i)
} else {
abits = bits
}
slash := strings.Index(enc, " / ")
aenc = "Encoding " + enc[slash+len(" / "):]
enc = enc[:slash]
}
// pseudocode
y0 := -1 * inch
tab := 0.0
for i < len(text) && match(text[i], "LucidaSansTypewriteX", 6.48, "") {
t := text[i]
i++
if math.Abs(t.Y-y0) < 3 {
// same line as last fragment, probably just two spaces
inst.Code += " " + t.S
continue
}
if inst.Code != "" {
inst.Code += "\n"
}
if t.X > x+0.1*inch {
if tab == 0 {
tab = t.X - x
}
inst.Code += strings.Repeat("\t", int((t.X-x)/tab+0.5))
} else {
tab = 0
}
inst.Code += t.S
y0 = t.Y
}
inst.ID = strings.TrimPrefix(enc, "Encoding ")
inst.Bits = bits
table = append(table, inst)
if abits != "" {
inst.ID = strings.TrimPrefix(aenc, "Encoding ")
inst.Bits = abits
table = append(table, inst)
}
}
return name, table
}
func readBitBox(name string, syntax []string, content pdf.Content, text []pdf.Text, i int) (string, int) {
// bit headings
y2 := 0.0
x1 := 0.0
x2 := 0.0
for i < len(text) && match(text[i], "Times-Roman", 8, "") {
if y2 == 0 {
y2 = text[i].Y
}
if x1 == 0 {
x1 = text[i].X
}
i++
}
// bit fields in box
y1 := 0.0
dy1 := 0.0
for i < len(text) && match(text[i], "Times-Roman", 9, "") {
if x2 < text[i].X+text[i].W {
x2 = text[i].X + text[i].W
}
y1 = text[i].Y
dy1 = text[i].FontSize
i++
}
if debugPage > 0 {
fmt.Println("encoding box", x1, y1, x2, y2)
}
// Find lines (thin rectangles) separating bit fields.
var bottom, top pdf.Rect
const (
yMargin = 0.25 * 72
xMargin = 2 * 72
)
for _, r := range content.Rect {
if r.Max.Y-r.Min.Y < 2 && x1-xMargin < r.Min.X && r.Min.X < x1 && x2 < r.Max.X && r.Max.X < x2+xMargin {
if y1-yMargin < r.Min.Y && r.Min.Y < y1 {
bottom = r
}
if y1+dy1 < r.Min.Y && r.Min.Y < y2 {
top = r
}
}
}
if debugPage > 0 {
fmt.Println("top", top, "bottom", bottom)
}
const ε = 0.1 * 72
var bars []pdf.Rect
for _, r := range content.Rect {
if r.Max.X-r.Min.X < 2 && math.Abs(r.Min.Y-bottom.Min.Y) < ε && math.Abs(r.Max.Y-top.Min.Y) < ε {
bars = append(bars, r)
}
}
sort.Sort(RectHorizontal(bars))
// There are 16-bit and 32-bit encodings.
// In practice, they are about 2.65 and 5.3 inches wide, respectively.
// Use 4 inches as a cutoff.
nbit := 32
dx := top.Max.X - top.Min.X
if top.Max.X-top.Min.X < 4*72 {
nbit = 16
}
total := 0
var buf bytes.Buffer
for i := 0; i < len(bars)-1; i++ {
if i > 0 {
fmt.Fprintf(&buf, "|")
}
var sub []pdf.Text
x1, x2 := bars[i].Min.X, bars[i+1].Min.X
for _, t := range content.Text {
tx := t.X + t.W/2
ty := t.Y + t.FontSize/2
if x1 < tx && tx < x2 && y1 < ty && ty < y2 {
sub = append(sub, t)
}
}
var str []string
for _, t := range findWords(sub) {
str = append(str, t.S)
}
s := strings.Join(str, " ")
s = strings.Replace(s, ")(", ") (", -1)
n := len(strings.Fields(s))
b := int(float64(nbit)*(x2-x1)/dx + 0.5)
if n == b {
for j, f := range strings.Fields(s) {
if j > 0 {
fmt.Fprintf(&buf, "|")
}
fmt.Fprintf(&buf, "%s", f)
}
} else {
if n != 1 {
fmt.Fprintf(os.Stderr, "%s - %s - multi-field %d-bit encoding: %s\n", name, syntax, n, s)
}
fmt.Fprintf(&buf, "%s:%d", s, b)
}
total += b
}
if total != nbit || total == 0 {
fmt.Fprintf(os.Stderr, "%s - %s - %d-bit encoding\n", name, syntax, total)
}
return buf.String(), i
}
type RectHorizontal []pdf.Rect
func (x RectHorizontal) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
func (x RectHorizontal) Less(i, j int) bool { return x[i].Min.X < x[j].Min.X }
func (x RectHorizontal) Len() int { return len(x) }
func checkNoEncodings(num int, text []pdf.Text) {
for _, t := range text {
if match(t, "Helvetica-Bold", 9, "Encoding") {
fmt.Fprintf(os.Stderr, "page %d: unexpected encoding: %s\n", num, t.S)
}
}
}
func match(t pdf.Text, font string, size float64, substr string) bool {
return t.Font == font && math.Abs(t.FontSize-size) < 0.1 && strings.Contains(t.S, substr)
}
func findWords(chars []pdf.Text) (words []pdf.Text) {
// Sort by Y coordinate and normalize.
const nudge = 1
sort.Sort(pdf.TextVertical(chars))
old := -100000.0
for i, c := range chars {
if c.Y != old && math.Abs(old-c.Y) < nudge {
chars[i].Y = old
} else {
old = c.Y
}
}
// Sort by Y coordinate, breaking ties with X.
// This will bring letters in a single word together.
sort.Sort(pdf.TextVertical(chars))
// Loop over chars.
for i := 0; i < len(chars); {
// Find all chars on line.
j := i + 1
for j < len(chars) && chars[j].Y == chars[i].Y {
j++
}
var end float64
// Split line into words (really, phrases).
for k := i; k < j; {
ck := &chars[k]
s := ck.S
end = ck.X + ck.W
charSpace := ck.FontSize / 6
wordSpace := ck.FontSize * 2 / 3
l := k + 1
for l < j {
// Grow word.
cl := &chars[l]
if sameFont(cl.Font, ck.Font) && math.Abs(cl.FontSize-ck.FontSize) < 0.1 && cl.X <= end+charSpace {
s += cl.S
end = cl.X + cl.W
l++
continue
}
// Add space to phrase before next word.
if sameFont(cl.Font, ck.Font) && math.Abs(cl.FontSize-ck.FontSize) < 0.1 && cl.X <= end+wordSpace {
s += " " + cl.S
end = cl.X + cl.W
l++
continue
}
break
}
f := ck.Font
f = strings.TrimSuffix(f, ",Italic")
f = strings.TrimSuffix(f, "-Italic")
words = append(words, pdf.Text{f, ck.FontSize, ck.X, ck.Y, end - ck.X, s})
k = l
}
i = j
}
return words
}
func sameFont(f1, f2 string) bool {
f1 = strings.TrimSuffix(f1, ",Italic")
f1 = strings.TrimSuffix(f1, "-Italic")
f2 = strings.TrimSuffix(f1, ",Italic")
f2 = strings.TrimSuffix(f1, "-Italic")
return strings.TrimSuffix(f1, ",Italic") == strings.TrimSuffix(f2, ",Italic") || f1 == "Symbol" || f2 == "Symbol" || f1 == "TimesNewRoman" || f2 == "TimesNewRoman"
}
var jsFix = strings.NewReplacer(
// `\u003c`, `<`,
// `\u003e`, `>`,
// `\u0026`, `&`,
// `\u0009`, `\t`,
)
func printTable(name string, table []Inst) {
_ = strconv.Atoi
}

223
vendor/golang.org/x/arch/arm/armspec/specmap.go generated vendored Normal file
View File

@ -0,0 +1,223 @@
// Copyright 2014 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.
// +build ignore
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"os"
"regexp"
"strconv"
"strings"
)
var _ = os.Stdout
var _ = fmt.Sprintf
type Inst struct {
Name string
ID string
Bits string
Arch string
Syntax []string
Code string
Base uint32
Mask uint32
Prog []*Stmt
}
func main() {
data, err := ioutil.ReadFile("spec.json")
if err != nil {
log.Fatal(err)
}
var insts []Inst
if err := json.Unmarshal(data, &insts); err != nil {
log.Fatal(err)
}
var out []Inst
for _, inst := range insts {
inst.Prog = parse(inst.Name+" "+inst.ID, inst.Code)
if inst.ID[0] == 'A' && !strings.HasPrefix(inst.Syntax[0], "MSR<c>") && !strings.Contains(inst.Syntax[0], "<coproc>") && !strings.Contains(inst.Syntax[0], "VLDM") && !strings.Contains(inst.Syntax[0], "VSTM") {
out = append(out, inst)
}
}
insts = out
for i := range insts {
dosize(&insts[i])
}
var cond, special []Inst
for _, inst := range insts {
if inst.Base>>28 == 0xF {
special = append(special, inst)
} else {
cond = append(cond, inst)
}
}
fmt.Printf("special:\n")
split(special, 0xF0000000, 1)
fmt.Printf("cond:\n")
split(cond, 0xF0000000, 1)
}
func dosize(inst *Inst) {
var base, mask uint32
off := 0
for _, f := range strings.Split(inst.Bits, "|") {
if i := strings.Index(f, ":"); i >= 0 {
n, _ := strconv.Atoi(f[i+1:])
off += n
continue
}
for _, bit := range strings.Fields(f) {
switch bit {
case "0", "(0)":
mask |= 1 << uint(31-off)
case "1", "(1)":
base |= 1 << uint(31-off)
}
off++
}
}
if off != 16 && off != 32 {
log.Printf("incorrect bit count for %s %s: have %d", inst.Name, inst.Bits, off)
}
if off == 16 {
mask >>= 16
base >>= 16
}
mask |= base
inst.Mask = mask
inst.Base = base
}
func split(insts []Inst, used uint32, depth int) {
Again:
if len(insts) <= 1 {
for _, inst := range insts {
fmt.Printf("%*s%#08x %#08x %s %s %v\n", depth*2+2, "", inst.Mask, inst.Base, inst.Syntax[0], inst.Bits, seeRE.FindAllString(inst.Code, -1))
}
return
}
m := ^used
for _, inst := range insts {
m &= inst.Mask
}
if m == 0 {
fmt.Printf("«%*s%#08x masked out (%d)\n", depth*2, "", used, len(insts))
for _, inst := range insts {
fmt.Printf("%*s%#08x %#08x %s %s %v\n", depth*2+2, "", inst.Mask, inst.Base, inst.Syntax[0], inst.Bits, seeRE.FindAllString(inst.Code, -1))
}
updated := false
for i := range insts {
if updateMask(&insts[i]) {
updated = true
}
}
fmt.Printf("»\n")
if updated {
goto Again
}
fmt.Printf("%*s%#08x masked out (%d)\n", depth*2, "", used, len(insts))
for _, inst := range insts {
fmt.Printf("%*s%#08x %#08x %s %s %v\n", depth*2+2, "", inst.Mask, inst.Base, inst.Syntax[0], inst.Bits, seeRE.FindAllString(inst.Code, -1))
}
//checkOverlap(used, insts)
return
}
for i := 31; i >= 0; i-- {
if m&(1<<uint(i)) != 0 {
m = 1 << uint(i)
break
}
}
var bit [2][]Inst
for _, inst := range insts {
b := (inst.Base / m) & 1
bit[b] = append(bit[b], inst)
}
for b, list := range bit {
if len(list) > 0 {
suffix := ""
if len(bit[1-b]) == 0 {
suffix = " (only)"
}
fmt.Printf("%*sbit %#08x = %d%s\n", depth*2, "", m, b, suffix)
split(list, used|m, depth+1)
}
}
}
var seeRE = regexp.MustCompile(`SEE ([^;\n]+)`)
func updateMask(inst *Inst) bool {
defer func() {
if err := recover(); err != nil {
fmt.Println("PANIC:", err)
return
}
}()
print(".")
println(inst.Name, inst.ID, inst.Bits)
println(inst.Code)
wiggle := ^inst.Mask &^ 0xF0000000
n := countbits(wiggle)
m1 := ^uint32(0)
m2 := ^uint32(0)
for i := uint32(0); i < 1<<uint(n); i++ {
w := inst.Base | expand(i, wiggle)
if !isValid(inst, w) {
continue
}
m1 &= w
m2 &= ^w
}
m := m1 | m2
m &^= 0xF0000000
m |= 0xF0000000 & inst.Mask
if m&^inst.Mask != 0 {
fmt.Printf("%s %s: mask=%#x but decided %#x\n", inst.Name, inst.ID, inst.Mask, m)
inst.Mask = m
inst.Base = m1
return true
}
if inst.Mask&^m != 0 {
fmt.Printf("%s %s: mask=%#x but got %#x\n", inst.Name, inst.ID, inst.Mask, m)
panic("bad updateMask")
}
return false
}
func countbits(x uint32) int {
n := 0
for ; x != 0; x >>= 1 {
n += int(x & 1)
}
return n
}
func expand(x, m uint32) uint32 {
var out uint32
for i := uint(0); i < 32; i++ {
out >>= 1
if m&1 != 0 {
out |= (x & 1) << 31
x >>= 1
}
m >>= 1
}
return out
}

1
vendor/golang.org/x/arch/codereview.cfg generated vendored Normal file
View File

@ -0,0 +1 @@
issuerepo: golang/go

1200
vendor/golang.org/x/arch/ppc64/pp64.csv generated vendored Normal file

File diff suppressed because it is too large Load Diff

179
vendor/golang.org/x/arch/ppc64/ppc64asm/decode.go generated vendored Normal file
View File

@ -0,0 +1,179 @@
// Copyright 2014 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 ppc64asm
import (
"encoding/binary"
"fmt"
"log"
)
const debugDecode = false
// instFormat is a decoding rule for one specific instruction form.
// a uint32 instruction ins matches the rule if ins&Mask == Value
// DontCare bits should be zero, but the machine might not reject
// ones in those bits, they are mainly reserved for future expansion
// of the instruction set.
// The Args are stored in the same order as the instruction manual.
type instFormat struct {
Op Op
Mask uint32
Value uint32
DontCare uint32
Args [5]*argField
}
// argField indicate how to decode an argument to an instruction.
// First parse the value from the BitFields, shift it left by Shift
// bits to get the actual numerical value.
type argField struct {
Type ArgType
Shift uint8
BitFields
}
// Parse parses the Arg out from the given binary instruction i.
func (a argField) Parse(i uint32) Arg {
switch a.Type {
default:
return nil
case TypeUnknown:
return nil
case TypeReg:
return R0 + Reg(a.BitFields.Parse(i))
case TypeCondRegBit:
return Cond0LT + CondReg(a.BitFields.Parse(i))
case TypeCondRegField:
return CR0 + CondReg(a.BitFields.Parse(i))
case TypeFPReg:
return F0 + Reg(a.BitFields.Parse(i))
case TypeVecReg:
return V0 + Reg(a.BitFields.Parse(i))
case TypeVecSReg:
return VS0 + Reg(a.BitFields.Parse(i))
case TypeSpReg:
return SpReg(a.BitFields.Parse(i))
case TypeImmSigned:
return Imm(a.BitFields.ParseSigned(i) << a.Shift)
case TypeImmUnsigned:
return Imm(a.BitFields.Parse(i) << a.Shift)
case TypePCRel:
return PCRel(a.BitFields.ParseSigned(i) << a.Shift)
case TypeLabel:
return Label(a.BitFields.ParseSigned(i) << a.Shift)
case TypeOffset:
return Offset(a.BitFields.ParseSigned(i) << a.Shift)
}
}
type ArgType int8
const (
TypeUnknown ArgType = iota
TypePCRel // PC-relative address
TypeLabel // absolute address
TypeReg // integer register
TypeCondRegBit // conditional register bit (0-31)
TypeCondRegField // conditional register field (0-7)
TypeFPReg // floating point register
TypeVecReg // vector register
TypeVecSReg // VSX register
TypeSpReg // special register (depends on Op)
TypeImmSigned // signed immediate
TypeImmUnsigned // unsigned immediate/flag/mask, this is the catch-all type
TypeOffset // signed offset in load/store
TypeLast // must be the last one
)
func (t ArgType) String() string {
switch t {
default:
return fmt.Sprintf("ArgType(%d)", int(t))
case TypeUnknown:
return "Unknown"
case TypeReg:
return "Reg"
case TypeCondRegBit:
return "CondRegBit"
case TypeCondRegField:
return "CondRegField"
case TypeFPReg:
return "FPReg"
case TypeVecReg:
return "VecReg"
case TypeVecSReg:
return "VecSReg"
case TypeSpReg:
return "SpReg"
case TypeImmSigned:
return "ImmSigned"
case TypeImmUnsigned:
return "ImmUnsigned"
case TypePCRel:
return "PCRel"
case TypeLabel:
return "Label"
case TypeOffset:
return "Offset"
}
}
func (t ArgType) GoString() string {
s := t.String()
if t > 0 && t < TypeLast {
return "Type" + s
}
return s
}
var (
// Errors
errShort = fmt.Errorf("truncated instruction")
errUnknown = fmt.Errorf("unknown instruction")
)
var decoderCover []bool
// Decode decodes the leading bytes in src as a single instruction using
// byte order ord.
func Decode(src []byte, ord binary.ByteOrder) (inst Inst, err error) {
if len(src) < 4 {
return inst, errShort
}
if decoderCover == nil {
decoderCover = make([]bool, len(instFormats))
}
inst.Len = 4 // only 4-byte instructions are supported
ui := ord.Uint32(src[:inst.Len])
inst.Enc = ui
for i, iform := range instFormats {
if ui&iform.Mask != iform.Value {
continue
}
if ui&iform.DontCare != 0 {
if debugDecode {
log.Printf("Decode(%#x): unused bit is 1 for Op %s", ui, iform.Op)
}
// to match GNU objdump (libopcodes), we ignore don't care bits
}
for i, argfield := range iform.Args {
if argfield == nil {
break
}
inst.Args[i] = argfield.Parse(ui)
}
inst.Op = iform.Op
if debugDecode {
log.Printf("%#x: search entry %d", ui, i)
continue
}
break
}
if inst.Op == 0 {
return inst, errUnknown
}
return inst, nil
}

64
vendor/golang.org/x/arch/ppc64/ppc64asm/decode_test.go generated vendored Normal file
View File

@ -0,0 +1,64 @@
// Copyright 2014 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 ppc64asm
import (
"encoding/binary"
"encoding/hex"
"io/ioutil"
"strings"
"testing"
)
func TestDecode(t *testing.T) {
data, err := ioutil.ReadFile("testdata/decode.txt")
if err != nil {
t.Fatal(err)
}
all := string(data)
for strings.Contains(all, "\t\t") {
all = strings.Replace(all, "\t\t", "\t", -1)
}
for _, line := range strings.Split(all, "\n") {
line = strings.TrimSpace(line)
if line == "" || strings.HasPrefix(line, "#") {
continue
}
f := strings.SplitN(line, "\t", 3)
i := strings.Index(f[0], "|")
if i < 0 {
t.Errorf("parsing %q: missing | separator", f[0])
continue
}
if i%2 != 0 {
t.Errorf("parsing %q: misaligned | separator", f[0])
}
size := i / 2
code, err := hex.DecodeString(f[0][:i] + f[0][i+1:])
if err != nil {
t.Errorf("parsing %q: %v", f[0], err)
continue
}
syntax, asm := f[1], f[2]
inst, err := Decode(code, binary.BigEndian)
var out string
if err != nil {
out = "error: " + err.Error()
} else {
switch syntax {
case "gnu":
out = GNUSyntax(inst)
//case "plan9":
// out = GoSyntax(inst, 0, nil, nil)
default:
t.Errorf("unknown syntax %q", syntax)
continue
}
}
if out != asm || inst.Len != size {
t.Errorf("Decode(%s) [%s] = %s want %s", f[0], syntax, out, asm)
}
}
}

6
vendor/golang.org/x/arch/ppc64/ppc64asm/doc.go generated vendored Normal file
View File

@ -0,0 +1,6 @@
// Copyright 2014 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 ppc64asm implements decoding of 64-bit PowerPC machine code.
package ppc64asm

535
vendor/golang.org/x/arch/ppc64/ppc64asm/ext_test.go generated vendored Normal file
View File

@ -0,0 +1,535 @@
// Copyright 2014 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.
// Support for testing against external disassembler program.
// Copied and simplified from rsc.io/arm/armasm/ext_test.go.
package ppc64asm
import (
"bufio"
"bytes"
"encoding/binary"
"encoding/hex"
"flag"
"fmt"
"io/ioutil"
"log"
"math/rand"
"os"
"os/exec"
"regexp"
"runtime"
"strings"
"testing"
"time"
)
var (
printTests = flag.Bool("printtests", false, "print test cases that exercise new code paths")
dumpTest = flag.Bool("dump", false, "dump all encodings")
mismatch = flag.Bool("mismatch", false, "log allowed mismatches")
longTest = flag.Bool("long", false, "long test")
keep = flag.Bool("keep", false, "keep object files around")
debug = false
)
// A ExtInst represents a single decoded instruction parsed
// from an external disassembler's output.
type ExtInst struct {
addr uint32
enc [4]byte
nenc int
text string
}
func (r ExtInst) String() string {
return fmt.Sprintf("%#x: % x: %s", r.addr, r.enc, r.text)
}
// An ExtDis is a connection between an external disassembler and a test.
type ExtDis struct {
Dec chan ExtInst
File *os.File
Size int
KeepFile bool
Cmd *exec.Cmd
}
// Run runs the given command - the external disassembler - and returns
// a buffered reader of its standard output.
func (ext *ExtDis) Run(cmd ...string) (*bufio.Reader, error) {
if *keep {
log.Printf("%s\n", strings.Join(cmd, " "))
}
ext.Cmd = exec.Command(cmd[0], cmd[1:]...)
out, err := ext.Cmd.StdoutPipe()
if err != nil {
return nil, fmt.Errorf("stdoutpipe: %v", err)
}
if err := ext.Cmd.Start(); err != nil {
return nil, fmt.Errorf("exec: %v", err)
}
b := bufio.NewReaderSize(out, 1<<20)
return b, nil
}
// Wait waits for the command started with Run to exit.
func (ext *ExtDis) Wait() error {
return ext.Cmd.Wait()
}
// testExtDis tests a set of byte sequences against an external disassembler.
// The disassembler is expected to produce the given syntax and be run
// in the given architecture mode (16, 32, or 64-bit).
// The extdis function must start the external disassembler
// and then parse its output, sending the parsed instructions on ext.Dec.
// The generate function calls its argument f once for each byte sequence
// to be tested. The generate function itself will be called twice, and it must
// make the same sequence of calls to f each time.
// When a disassembly does not match the internal decoding,
// allowedMismatch determines whether this mismatch should be
// allowed, or else considered an error.
func testExtDis(
t *testing.T,
syntax string,
extdis func(ext *ExtDis) error,
generate func(f func([]byte)),
allowedMismatch func(text string, size int, inst *Inst, dec ExtInst) bool,
) {
start := time.Now()
ext := &ExtDis{
Dec: make(chan ExtInst),
}
errc := make(chan error)
// First pass: write instructions to input file for external disassembler.
file, f, size, err := writeInst(generate)
if err != nil {
t.Fatal(err)
}
ext.Size = size
ext.File = f
defer func() {
f.Close()
if !*keep {
os.Remove(file)
}
}()
// Second pass: compare disassembly against our decodings.
var (
totalTests = 0
totalSkips = 0
totalErrors = 0
errors = make([]string, 0, 100) // sampled errors, at most cap
)
go func() {
errc <- extdis(ext)
}()
generate(func(enc []byte) {
dec, ok := <-ext.Dec
if !ok {
t.Errorf("decoding stream ended early")
return
}
inst, text := disasm(syntax, pad(enc))
totalTests++
if *dumpTest {
fmt.Printf("%x -> %s [%d]\n", enc[:len(enc)], dec.text, dec.nenc)
}
if text != dec.text || inst.Len != dec.nenc {
suffix := ""
if allowedMismatch(text, size, &inst, dec) {
totalSkips++
if !*mismatch {
return
}
suffix += " (allowed mismatch)"
}
totalErrors++
if len(errors) >= cap(errors) {
j := rand.Intn(totalErrors)
if j >= cap(errors) {
return
}
errors = append(errors[:j], errors[j+1:]...)
}
errors = append(errors, fmt.Sprintf("decode(%x) = %q, %d, want %q, %d%s", enc, text, inst.Len, dec.text, dec.nenc, suffix))
}
})
if *mismatch {
totalErrors -= totalSkips
}
for _, b := range errors {
t.Log(b)
}
if totalErrors > 0 {
t.Fail()
}
t.Logf("%d test cases, %d expected mismatches, %d failures; %.0f cases/second", totalTests, totalSkips, totalErrors, float64(totalTests)/time.Since(start).Seconds())
if err := <-errc; err != nil {
t.Fatalf("external disassembler: %v", err)
}
}
const start = 0x8000 // start address of text
// writeInst writes the generated byte sequences to a new file
// starting at offset start. That file is intended to be the input to
// the external disassembler.
func writeInst(generate func(func([]byte))) (file string, f *os.File, size int, err error) {
f, err = ioutil.TempFile("", "ppc64asm")
if err != nil {
return
}
file = f.Name()
f.Seek(start, 0)
w := bufio.NewWriter(f)
defer w.Flush()
size = 0
generate(func(x []byte) {
if len(x) > 4 {
x = x[:4]
}
if debug {
fmt.Printf("%#x: %x%x\n", start+size, x, zeros[len(x):])
}
w.Write(x)
w.Write(zeros[len(x):])
size += len(zeros)
})
return file, f, size, nil
}
var zeros = []byte{0, 0, 0, 0}
// pad pads the code sequence with pops.
func pad(enc []byte) []byte {
if len(enc) < 4 {
enc = append(enc[:len(enc):len(enc)], zeros[:4-len(enc)]...)
}
return enc
}
// disasm returns the decoded instruction and text
// for the given source bytes, using the given syntax and mode.
func disasm(syntax string, src []byte) (inst Inst, text string) {
// If printTests is set, we record the coverage value
// before and after, and we write out the inputs for which
// coverage went up, in the format expected in testdata/decode.text.
// This produces a fairly small set of test cases that exercise nearly
// all the code.
var cover float64
if *printTests {
cover -= coverage()
}
inst, err := Decode(src, binary.BigEndian)
if err != nil {
text = "error: " + err.Error()
} else {
text = inst.String()
switch syntax {
//case "arm":
// text = ARMSyntax(inst)
case "gnu":
text = GNUSyntax(inst)
//case "plan9":
// text = GoSyntax(inst, 0, nil)
default:
text = "error: unknown syntax " + syntax
}
}
if *printTests {
cover += coverage()
if cover > 0 {
max := len(src)
if max > 4 && inst.Len <= 4 {
max = 4
}
fmt.Printf("%x|%x\t%s\t%s\n", src[:inst.Len], src[inst.Len:max], syntax, text)
}
}
return
}
// coverage returns a floating point number denoting the
// test coverage until now. The number increases when new code paths are exercised,
// both in the Go program and in the decoder byte code.
func coverage() float64 {
var f float64
f += testing.Coverage()
f += decodeCoverage()
return f
}
func decodeCoverage() float64 {
n := 0
for _, t := range decoderCover {
if t {
n++
}
}
return float64(1+n) / float64(1+len(decoderCover))
}
// Helpers for writing disassembler output parsers.
// hasPrefix reports whether any of the space-separated words in the text s
// begins with any of the given prefixes.
func hasPrefix(s string, prefixes ...string) bool {
for _, prefix := range prefixes {
for s := s; s != ""; {
if strings.HasPrefix(s, prefix) {
return true
}
i := strings.Index(s, " ")
if i < 0 {
break
}
s = s[i+1:]
}
}
return false
}
// contains reports whether the text s contains any of the given substrings.
func contains(s string, substrings ...string) bool {
for _, sub := range substrings {
if strings.Contains(s, sub) {
return true
}
}
return false
}
// isHex reports whether b is a hexadecimal character (0-9A-Fa-f).
func isHex(b byte) bool { return b == '0' || unhex[b] > 0 }
// parseHex parses the hexadecimal byte dump in hex,
// appending the parsed bytes to raw and returning the updated slice.
// The returned bool signals whether any invalid hex was found.
// Spaces and tabs between bytes are okay but any other non-hex is not.
func parseHex(hex []byte, raw []byte) ([]byte, bool) {
hex = trimSpace(hex)
for j := 0; j < len(hex); {
for hex[j] == ' ' || hex[j] == '\t' {
j++
}
if j >= len(hex) {
break
}
if j+2 > len(hex) || !isHex(hex[j]) || !isHex(hex[j+1]) {
return nil, false
}
raw = append(raw, unhex[hex[j]]<<4|unhex[hex[j+1]])
j += 2
}
return raw, true
}
var unhex = [256]byte{
'0': 0,
'1': 1,
'2': 2,
'3': 3,
'4': 4,
'5': 5,
'6': 6,
'7': 7,
'8': 8,
'9': 9,
'A': 10,
'B': 11,
'C': 12,
'D': 13,
'E': 14,
'F': 15,
'a': 10,
'b': 11,
'c': 12,
'd': 13,
'e': 14,
'f': 15,
}
// index is like bytes.Index(s, []byte(t)) but avoids the allocation.
func index(s []byte, t string) int {
i := 0
for {
j := bytes.IndexByte(s[i:], t[0])
if j < 0 {
return -1
}
i = i + j
if i+len(t) > len(s) {
return -1
}
for k := 1; k < len(t); k++ {
if s[i+k] != t[k] {
goto nomatch
}
}
return i
nomatch:
i++
}
}
// fixSpace rewrites runs of spaces, tabs, and newline characters into single spaces in s.
// If s must be rewritten, it is rewritten in place.
func fixSpace(s []byte) []byte {
s = trimSpace(s)
for i := 0; i < len(s); i++ {
if s[i] == '\t' || s[i] == '\n' || i > 0 && s[i] == ' ' && s[i-1] == ' ' {
goto Fix
}
}
return s
Fix:
b := s
w := 0
for i := 0; i < len(s); i++ {
c := s[i]
if c == '\t' || c == '\n' {
c = ' '
}
if c == ' ' && w > 0 && b[w-1] == ' ' {
continue
}
b[w] = c
w++
}
if w > 0 && b[w-1] == ' ' {
w--
}
return b[:w]
}
// trimSpace trims leading and trailing space from s, returning a subslice of s.
func trimSpace(s []byte) []byte {
j := len(s)
for j > 0 && (s[j-1] == ' ' || s[j-1] == '\t' || s[j-1] == '\n') {
j--
}
i := 0
for i < j && (s[i] == ' ' || s[i] == '\t') {
i++
}
return s[i:j]
}
// pcrel matches instructions using relative addressing mode.
var (
pcrel = regexp.MustCompile(`^((?:.* )?(?:b|bc)[^ac ]* (?:(?:[0-9]{1,2},)|(?:[0-7]\*)|\+|lt|gt|eq|so|cr[0-7]|,)*)0x([0-9a-f]+)$`)
)
// Generators.
//
// The test cases are described as functions that invoke a callback repeatedly,
// with a new input sequence each time. These helpers make writing those
// a little easier.
// randomCases generates random instructions.
func randomCases(t *testing.T) func(func([]byte)) {
return func(try func([]byte)) {
// All the strides are relatively prime to 2 and therefore to 2²⁸,
// so we will not repeat any instructions until we have tried all 2²⁸.
// Using a stride other than 1 is meant to visit the instructions in a
// pseudorandom order, which gives better variety in the set of
// test cases chosen by -printtests.
stride := uint32(10007)
n := 1 << 28 / 7
if testing.Short() {
stride = 100003
n = 1 << 28 / 1001
} else if *longTest {
stride = 2000033
n = 1 << 29
}
x := uint32(0)
for i := 0; i < n; i++ {
enc := (x%15)<<28 | x&(1<<28-1)
try([]byte{byte(enc), byte(enc >> 8), byte(enc >> 16), byte(enc >> 24)})
x += stride
}
}
}
// hexCases generates the cases written in hexadecimal in the encoded string.
// Spaces in 'encoded' separate entire test cases, not individual bytes.
func hexCases(t *testing.T, encoded string) func(func([]byte)) {
return func(try func([]byte)) {
for _, x := range strings.Fields(encoded) {
src, err := hex.DecodeString(x)
if err != nil {
t.Errorf("parsing %q: %v", x, err)
}
try(src)
}
}
}
// testdataCases generates the test cases recorded in testdata/decode.txt.
// It only uses the inputs; it ignores the answers recorded in that file.
func testdataCases(t *testing.T) func(func([]byte)) {
var codes [][]byte
data, err := ioutil.ReadFile("testdata/decode.txt")
if err != nil {
t.Fatal(err)
}
for _, line := range strings.Split(string(data), "\n") {
line = strings.TrimSpace(line)
if line == "" || strings.HasPrefix(line, "#") {
continue
}
f := strings.Fields(line)[0]
i := strings.Index(f, "|")
if i < 0 {
t.Errorf("parsing %q: missing | separator", f)
continue
}
if i%2 != 0 {
t.Errorf("parsing %q: misaligned | separator", f)
}
code, err := hex.DecodeString(f[:i] + f[i+1:])
if err != nil {
t.Errorf("parsing %q: %v", f, err)
continue
}
codes = append(codes, code)
}
return func(try func([]byte)) {
for _, code := range codes {
try(code)
}
}
}
func caller(skip int) string {
pc, _, _, _ := runtime.Caller(skip)
f := runtime.FuncForPC(pc)
name := "?"
if f != nil {
name = f.Name()
if i := strings.LastIndex(name, "."); i >= 0 {
name = name[i+1:]
}
}
return name
}

84
vendor/golang.org/x/arch/ppc64/ppc64asm/field.go generated vendored Normal file
View File

@ -0,0 +1,84 @@
// Copyright 2014 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 ppc64asm
import (
"fmt"
"strings"
)
// A BitField is a bit-field in a 32-bit word.
// Bits are counted from 0 from the MSB to 31 as the LSB.
type BitField struct {
Offs uint8 // the offset of the left-most bit.
Bits uint8 // length in bits.
}
func (b BitField) String() string {
if b.Bits > 1 {
return fmt.Sprintf("[%d:%d]", b.Offs, int(b.Offs+b.Bits)-1)
} else if b.Bits == 1 {
return fmt.Sprintf("[%d]", b.Offs)
} else {
return fmt.Sprintf("[%d, len=0]", b.Offs)
}
}
// Parse extracts the bitfield b from i, and return it as an unsigned integer.
// Parse will panic if b is invalid.
func (b BitField) Parse(i uint32) uint32 {
if b.Bits > 32 || b.Bits == 0 || b.Offs > 31 || b.Offs+b.Bits > 32 {
panic(fmt.Sprintf("invalid bitfiled %v", b))
}
return (i >> (32 - b.Offs - b.Bits)) & ((1 << b.Bits) - 1)
}
// ParseSigned extracts the bitfield b from i, and return it as a signed integer.
// ParseSigned will panic if b is invalid.
func (b BitField) ParseSigned(i uint32) int32 {
u := int32(b.Parse(i))
return u << (32 - b.Bits) >> (32 - b.Bits)
}
// BitFields is a series of BitFields representing a single number.
type BitFields []BitField
func (bs BitFields) String() string {
ss := make([]string, len(bs))
for i, bf := range bs {
ss[i] = bf.String()
}
return fmt.Sprintf("<%s>", strings.Join(ss, "|"))
}
func (bs *BitFields) Append(b BitField) {
*bs = append(*bs, b)
}
// parse extracts the bitfields from i, concatenate them and return the result
// as an unsigned integer and the total length of all the bitfields.
// parse will panic if any bitfield in b is invalid, but it doesn't check if
// the sequence of bitfields is reasonable.
func (bs BitFields) parse(i uint32) (u uint32, Bits uint8) {
for _, b := range bs {
u = (u << b.Bits) | b.Parse(i)
Bits += b.Bits
}
return u, Bits
}
// Parse extracts the bitfields from i, concatenate them and return the result
// as an unsigned integer. Parse will panic if any bitfield in b is invalid.
func (bs BitFields) Parse(i uint32) uint32 {
u, _ := bs.parse(i)
return u
}
// Parse extracts the bitfields from i, concatenate them and return the result
// as a signed integer. Parse will panic if any bitfield in b is invalid.
func (bs BitFields) ParseSigned(i uint32) int32 {
u, l := bs.parse(i)
return int32(u) << (32 - l) >> (32 - l)
}

60
vendor/golang.org/x/arch/ppc64/ppc64asm/field_test.go generated vendored Normal file
View File

@ -0,0 +1,60 @@
// Copyright 2014 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 ppc64asm
import (
"testing"
)
func panicOrNot(f func()) (panicked bool) {
defer func() {
if err := recover(); err != nil {
panicked = true
}
}()
f()
return false
}
func TestBitField(t *testing.T) {
var tests = []struct {
b BitField
i uint32 // input
u uint32 // unsigned output
s int32 // signed output
fail bool // if the check should panic
}{
{BitField{0, 0}, 0, 0, 0, true},
{BitField{31, 2}, 0, 0, 0, true},
{BitField{31, 1}, 1, 1, -1, false},
{BitField{29, 2}, 0 << 1, 0, 0, false},
{BitField{29, 2}, 1 << 1, 1, 1, false},
{BitField{29, 2}, 2 << 1, 2, -2, false},
{BitField{29, 2}, 3 << 1, 3, -1, false},
{BitField{0, 32}, 1<<32 - 1, 1<<32 - 1, -1, false},
{BitField{16, 3}, 1 << 15, 4, -4, false},
}
for i, tst := range tests {
var (
ou uint32
os int32
)
failed := panicOrNot(func() {
ou = tst.b.Parse(tst.i)
os = tst.b.ParseSigned(tst.i)
})
if failed != tst.fail {
t.Errorf("case %d: %v: fail test failed, got %v, expected %v", i, tst.b, failed, tst.fail)
continue
}
if ou != tst.u {
t.Errorf("case %d: %v.Parse(%d) returned %d, expected %d", i, tst.b, tst.i, ou, tst.u)
continue
}
if os != tst.s {
t.Errorf("case %d: %v.ParseSigned(%d) returned %d, expected %d", i, tst.b, tst.i, os, tst.s)
}
}
}

125
vendor/golang.org/x/arch/ppc64/ppc64asm/gnu.go generated vendored Normal file
View File

@ -0,0 +1,125 @@
// Copyright 2014 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 ppc64asm
import (
"bytes"
"fmt"
"strings"
)
// GNUSyntax returns the GNU assembler syntax for the instruction, as defined by GNU binutils.
// This form typically matches the syntax defined in the Power ISA Reference Manual.
func GNUSyntax(inst Inst) string {
var buf bytes.Buffer
if inst.Op == 0 {
return "error: unkown instruction"
}
buf.WriteString(inst.Op.String())
sep := " "
for i, arg := range inst.Args[:] {
if arg == nil {
break
}
text := gnuArg(&inst, i, arg)
if text == "" {
continue
}
buf.WriteString(sep)
sep = ","
buf.WriteString(text)
}
return buf.String()
}
// gnuArg formats arg (which is the argIndex's arg in inst) according to GNU rules.
// NOTE: because GNUSyntax is the only caller of this func, and it receives a copy
// of inst, it's ok to modify inst.Args here.
func gnuArg(inst *Inst, argIndex int, arg Arg) string {
// special cases for load/store instructions
if _, ok := arg.(Offset); ok {
if argIndex+1 == len(inst.Args) || inst.Args[argIndex+1] == nil {
panic(fmt.Errorf("wrong table: offset not followed by register"))
}
}
switch arg := arg.(type) {
case Reg:
if isLoadStoreOp(inst.Op) && argIndex == 1 && arg == R0 {
return "0"
}
return arg.String()
case CondReg:
if arg == CR0 && strings.HasPrefix(inst.Op.String(), "cmp") {
return "" // don't show cr0 for cmp instructions
} else if arg >= CR0 {
return fmt.Sprintf("cr%d", int(arg-CR0))
}
bit := [4]string{"lt", "gt", "eq", "so"}[(arg-Cond0LT)%4]
if arg <= Cond0SO {
return bit
}
return fmt.Sprintf("4*cr%d+%s", int(arg-Cond0LT)/4, bit)
case Imm:
return fmt.Sprintf("%d", arg)
case SpReg:
return fmt.Sprintf("%d", int(arg))
case PCRel:
return fmt.Sprintf(".%+#x", int(arg))
case Label:
return fmt.Sprintf("%#x", uint32(arg))
case Offset:
reg := inst.Args[argIndex+1].(Reg)
removeArg(inst, argIndex+1)
if reg == R0 {
return fmt.Sprintf("%d(0)", int(arg))
}
return fmt.Sprintf("%d(r%d)", int(arg), reg-R0)
}
return fmt.Sprintf("???(%v)", arg)
}
// removeArg removes the arg in inst.Args[index].
func removeArg(inst *Inst, index int) {
for i := index; i < len(inst.Args); i++ {
if i+1 < len(inst.Args) {
inst.Args[i] = inst.Args[i+1]
} else {
inst.Args[i] = nil
}
}
}
// isLoadStoreOp returns true if op is a load or store instruction
func isLoadStoreOp(op Op) bool {
switch op {
case LBZ, LBZU, LBZX, LBZUX:
return true
case LHZ, LHZU, LHZX, LHZUX:
return true
case LHA, LHAU, LHAX, LHAUX:
return true
case LWZ, LWZU, LWZX, LWZUX:
return true
case LWA, LWAX, LWAUX:
return true
case LD, LDU, LDX, LDUX:
return true
case LQ:
return true
case STB, STBU, STBX, STBUX:
return true
case STH, STHU, STHX, STHUX:
return true
case STW, STWU, STWX, STWUX:
return true
case STD, STDU, STDX, STDUX:
return true
case STQ:
return true
case LHBRX, LWBRX, STHBRX, STWBRX:
return true
}
return false
}

344
vendor/golang.org/x/arch/ppc64/ppc64asm/inst.go generated vendored Normal file
View File

@ -0,0 +1,344 @@
// Copyright 2014 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 ppc64asm
import (
"bytes"
"fmt"
)
type Inst struct {
Op Op // Opcode mnemonic
Enc uint32 // Raw encoding bits
Len int // Length of encoding in bytes.
Args Args // Instruction arguments, in Power ISA manual order.
}
func (i Inst) String() string {
var buf bytes.Buffer
buf.WriteString(i.Op.String())
for j, arg := range i.Args {
if arg == nil {
break
}
if j == 0 {
buf.WriteString(" ")
} else {
buf.WriteString(", ")
}
buf.WriteString(arg.String())
}
return buf.String()
}
// An Op is an instruction operation.
type Op uint16
func (o Op) String() string {
if int(o) >= len(opstr) || opstr[o] == "" {
return fmt.Sprintf("Op(%d)", int(o))
}
return opstr[o]
}
// An Arg is a single instruction argument, one of these types: Reg, CondReg, SpReg, Imm, PCRel, Label, or Offset.
type Arg interface {
IsArg()
String() string
}
// An Args holds the instruction arguments.
// If an instruction has fewer than 4 arguments,
// the final elements in the array are nil.
type Args [5]Arg
// A Reg is a single register. The zero value means R0, not the absence of a register.
// It also includes special registers.
type Reg uint16
const (
_ Reg = iota
R0
R1
R2
R3
R4
R5
R6
R7
R8
R9
R10
R11
R12
R13
R14
R15
R16
R17
R18
R19
R20
R21
R22
R23
R24
R25
R26
R27
R28
R29
R30
R31
F0
F1
F2
F3
F4
F5
F6
F7
F8
F9
F10
F11
F12
F13
F14
F15
F16
F17
F18
F19
F20
F21
F22
F23
F24
F25
F26
F27
F28
F29
F30
F31
V0 // VSX extension, F0 is V0[0:63].
V1
V2
V3
V4
V5
V6
V7
V8
V9
V10
V11
V12
V13
V14
V15
V16
V17
V18
V19
V20
V21
V22
V23
V24
V25
V26
V27
V28
V29
V30
V31
VS0
VS1
VS2
VS3
VS4
VS5
VS6
VS7
VS8
VS9
VS10
VS11
VS12
VS13
VS14
VS15
VS16
VS17
VS18
VS19
VS20
VS21
VS22
VS23
VS24
VS25
VS26
VS27
VS28
VS29
VS30
VS31
VS32
VS33
VS34
VS35
VS36
VS37
VS38
VS39
VS40
VS41
VS42
VS43
VS44
VS45
VS46
VS47
VS48
VS49
VS50
VS51
VS52
VS53
VS54
VS55
VS56
VS57
VS58
VS59
VS60
VS61
VS62
VS63
)
func (Reg) IsArg() {}
func (r Reg) String() string {
switch {
case R0 <= r && r <= R31:
return fmt.Sprintf("r%d", int(r-R0))
case F0 <= r && r <= F31:
return fmt.Sprintf("f%d", int(r-F0))
case V0 <= r && r <= V31:
return fmt.Sprintf("v%d", int(r-V0))
case VS0 <= r && r <= VS63:
return fmt.Sprintf("vs%d", int(r-VS0))
default:
return fmt.Sprintf("Reg(%d)", int(r))
}
}
// CondReg is a bit or field in the conditon register.
type CondReg int8
const (
_ CondReg = iota
// Condition Regster bits
Cond0LT
Cond0GT
Cond0EQ
Cond0SO
Cond1LT
Cond1GT
Cond1EQ
Cond1SO
Cond2LT
Cond2GT
Cond2EQ
Cond2SO
Cond3LT
Cond3GT
Cond3EQ
Cond3SO
Cond4LT
Cond4GT
Cond4EQ
Cond4SO
Cond5LT
Cond5GT
Cond5EQ
Cond5SO
Cond6LT
Cond6GT
Cond6EQ
Cond6SO
Cond7LT
Cond7GT
Cond7EQ
Cond7SO
// Condition Register Fields
CR0
CR1
CR2
CR3
CR4
CR5
CR6
CR7
)
func (CondReg) IsArg() {}
func (c CondReg) String() string {
switch {
default:
return fmt.Sprintf("CondReg(%d)", int(c))
case c >= CR0:
return fmt.Sprintf("CR%d", int(c-CR0))
case c >= Cond0LT && c < CR0:
return fmt.Sprintf("Cond%d%s", int((c-Cond0LT)/4), [4]string{"LT", "GT", "EQ", "SO"}[(c-Cond0LT)%4])
}
}
// SpReg is a special register, its meaning depends on Op.
type SpReg uint16
const (
SpRegZero SpReg = 0
)
func (SpReg) IsArg() {}
func (s SpReg) String() string {
return fmt.Sprintf("SpReg(%d)", int(s))
}
// PCRel is a PC-relative offset, used only in branch instructions.
type PCRel int32
func (PCRel) IsArg() {}
func (r PCRel) String() string {
return fmt.Sprintf("PC%+#x", int32(r))
}
// A Label is a code (text) address, used only in absolute branch instructions.
type Label uint32
func (Label) IsArg() {}
func (l Label) String() string {
return fmt.Sprintf("%#x", uint32(l))
}
// Imm represents an immediate number.
type Imm int32
func (Imm) IsArg() {}
func (i Imm) String() string {
return fmt.Sprintf("%d", int32(i))
}
// Offset represents a memory offset immediate.
type Offset int32
func (Offset) IsArg() {}
func (o Offset) String() string {
return fmt.Sprintf("%+d", int32(o))
}

133
vendor/golang.org/x/arch/ppc64/ppc64asm/objdump_test.go generated vendored Normal file
View File

@ -0,0 +1,133 @@
// Copyright 2014 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 ppc64asm
import (
"encoding/binary"
"strings"
"testing"
)
func TestObjdumpPowerTestdata(t *testing.T) { testObjdump(t, testdataCases(t)) }
func TestObjdumpPowerManual(t *testing.T) { testObjdump(t, hexCases(t, objdumpManualTests)) }
// Disable this for now since generating all possible bit combinations within a word
// generates lots of ppc64x instructions not possible with golang so not worth supporting..
//func TestObjdumpPowerRandom(t *testing.T) { testObjdump(t, randomCases(t)) }
// objdumpManualTests holds test cases that will be run by TestObjdumpARMManual.
// If you are debugging a few cases that turned up in a longer run, it can be useful
// to list them here and then use -run=Manual, particularly with tracing enabled.
// Note that these are byte sequences, so they must be reversed from the usual
// word presentation.
var objdumpManualTests = `
6d746162
4c040000
88000017
`
// allowedMismatchObjdump reports whether the mismatch between text and dec
// should be allowed by the test.
func allowedMismatchObjdump(text string, size int, inst *Inst, dec ExtInst) bool {
if hasPrefix(dec.text, deleted...) {
return true
}
// we support more instructions than binutils
if strings.Contains(dec.text, ".long") {
return true
}
if hasPrefix(text, "error:") {
if hasPrefix(dec.text, unsupported...) {
return true
}
}
switch inst.Op {
case BC, BCA, BL, BLA, BCL, BCLA, TDI, TWI, TW, TD:
return true // TODO(minux): we lack the support for extended opcodes here
case RLWNM, RLWNM_, RLDICL, RLDICL_, RLWINM, RLWINM_, RLDCL, RLDCL_:
return true // TODO(minux): we lack the support for extended opcodes here
case DCBTST, DCBT:
return true // objdump uses the embedded argument order, we use the server argument order
case MTFSF, MTFSF_: // objdump doesn't show the last two arguments
return true
case VSPLTB, VSPLTH, VSPLTW: // objdump generates unreasonable result "vspltw v6,v19,4" for 10c49a8c, the last 4 should be 0.
return true
}
if hasPrefix(text, "evm", "evl", "efs") { // objdump will disassemble them wrong (e.g. evmhoumia as vsldoi)
return true
}
if len(dec.enc) >= 4 {
_ = binary.BigEndian.Uint32(dec.enc[:4])
}
return false
}
// Instructions known to libopcodes (or xed) but not to us.
// TODO(minux): those single precision instructions are missing from ppc64.csv
// those data cache instructions are deprecated, but must be treated as no-ops, see 4.3.2.1 pg. 774.
var unsupported = strings.Fields(`
fmsubs
fmsubs.
fnmadds
fnmadds.
fnmsubs
fnmsubs.
fmuls
fmuls.
fdivs
fdivs.
fadds
fadds.
fsubs
fsubs.
dst
dstst
dssall
`)
// Instructions explicitly dropped in Power ISA that were in POWER architecture.
// See A.30 Deleted Instructions and A.31 Discontiued Opcodes
var deleted = strings.Fields(`
abs
clcs
clf
cli
dclst
div
divs
doz
dozi
lscbx
maskg
maskir
mfsri
mul
nabs
rac
rfi
rfsvc
rlmi
rrib
sle
sleq
sliq
slliq
sllq
slq
sraiq
sraq
sre
srea
sreq
sriq
srliq
srlq
srq
maskg`)

View File

@ -0,0 +1,255 @@
// Copyright 2014 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.
// Copied and simplified from rsc.io/arm/armasm/objdumpext_test.go.
package ppc64asm
import (
"bytes"
"debug/elf"
"encoding/binary"
"fmt"
"io"
"log"
"os"
"runtime"
"strconv"
"strings"
"testing"
)
const objdumpPath = "/usr/bin/objdump"
func testObjdump(t *testing.T, generate func(func([]byte))) {
if testing.Short() {
t.Skip("skipping objdump test in short mode")
}
if runtime.GOARCH != "ppc64le" && runtime.GOARCH != "ppc64" {
t.Skip("skipping; test requires host tool objdump for ppc64 or ppc64le")
}
if _, err := os.Stat(objdumpPath); err != nil {
t.Skip(err)
}
testExtDis(t, "gnu", objdump, generate, allowedMismatchObjdump)
}
func objdump(ext *ExtDis) error {
// File already written with instructions; add ELF header.
if err := writeELF64(ext.File, ext.Size); err != nil {
return err
}
b, err := ext.Run(objdumpPath, "-d", "-z", ext.File.Name())
if err != nil {
return err
}
var (
nmatch int
reading bool
next uint32 = start
addr uint32
encbuf [4]byte
enc []byte
text string
)
flush := func() {
if addr == next {
if m := pcrel.FindStringSubmatch(text); m != nil {
targ, _ := strconv.ParseUint(m[2], 16, 64)
text = fmt.Sprintf("%s.%+#x", m[1], int32(uint32(targ)-addr))
}
if strings.HasPrefix(text, "stmia") {
text = "stm" + text[5:]
}
if strings.HasPrefix(text, "stmfd") {
text = "stmdb" + text[5:]
}
if strings.HasPrefix(text, "ldmfd") {
text = "ldm" + text[5:]
}
text = strings.Replace(text, "#0.0", "#0", -1)
if text == "undefined" && len(enc) == 4 {
text = "error: unknown instruction"
enc = nil
}
if len(enc) == 4 {
// prints as word but we want to record bytes
enc[0], enc[3] = enc[3], enc[0]
enc[1], enc[2] = enc[2], enc[1]
}
ext.Dec <- ExtInst{addr, encbuf, len(enc), text}
encbuf = [4]byte{}
enc = nil
next += 4
}
}
var textangle = []byte("<.text>:")
for {
line, err := b.ReadSlice('\n')
if err != nil {
if err == io.EOF {
break
}
return fmt.Errorf("reading objdump output: %v", err)
}
if bytes.Contains(line, textangle) {
reading = true
continue
}
if !reading {
continue
}
if debug {
os.Stdout.Write(line)
}
if enc1 := parseContinuation(line, encbuf[:len(enc)]); enc1 != nil {
enc = enc1
continue
}
flush()
nmatch++
addr, enc, text = parseLine(line, encbuf[:0])
if addr > next {
return fmt.Errorf("address out of sync expected <= %#x at %q in:\n%s", next, line, line)
}
}
flush()
if next != start+uint32(ext.Size) {
return fmt.Errorf("not enough results found [%d %d]", next, start+ext.Size)
}
if err := ext.Wait(); err != nil {
return fmt.Errorf("exec: %v", err)
}
return nil
}
var (
undefined = []byte("<UNDEFINED>")
unpredictable = []byte("<UNPREDICTABLE>")
illegalShifter = []byte("<illegal shifter operand>")
)
func parseLine(line []byte, encstart []byte) (addr uint32, enc []byte, text string) {
oline := line
i := index(line, ":\t")
if i < 0 {
log.Fatalf("cannot parse disassembly: %q", oline)
}
x, err := strconv.ParseUint(string(trimSpace(line[:i])), 16, 32)
if err != nil {
log.Fatalf("cannot parse disassembly: %q", oline)
}
addr = uint32(x)
line = line[i+2:]
i = bytes.IndexByte(line, '\t')
if i < 0 {
log.Fatalf("cannot parse disassembly: %q", oline)
}
enc, ok := parseHex(line[:i], encstart)
if !ok {
log.Fatalf("cannot parse disassembly: %q", oline)
}
line = trimSpace(line[i:])
if bytes.Contains(line, undefined) {
text = "undefined"
return
}
if bytes.Contains(line, illegalShifter) {
text = "undefined"
return
}
if false && bytes.Contains(line, unpredictable) {
text = "unpredictable"
return
}
if i := bytes.IndexByte(line, ';'); i >= 0 {
line = trimSpace(line[:i])
}
text = string(fixSpace(line))
return
}
func parseContinuation(line []byte, enc []byte) []byte {
i := index(line, ":\t")
if i < 0 {
return nil
}
line = line[i+1:]
enc, _ = parseHex(line, enc)
return enc
}
// writeELF64 writes an ELF64 header to the file,
// describing a text segment that starts at start
// and extends for size bytes.
func writeELF64(f *os.File, size int) error {
f.Seek(0, 0)
var hdr elf.Header64
var prog elf.Prog64
var sect elf.Section64
var buf bytes.Buffer
binary.Write(&buf, binary.BigEndian, &hdr)
off1 := buf.Len()
binary.Write(&buf, binary.BigEndian, &prog)
off2 := buf.Len()
binary.Write(&buf, binary.BigEndian, &sect)
off3 := buf.Len()
buf.Reset()
data := byte(elf.ELFDATA2MSB)
hdr = elf.Header64{
Ident: [16]byte{0x7F, 'E', 'L', 'F', 2, data, 1},
Type: 2,
Machine: uint16(elf.EM_PPC64),
Version: 1,
Entry: start,
Phoff: uint64(off1),
Shoff: uint64(off2),
Flags: 0x05000002,
Ehsize: uint16(off1),
Phentsize: uint16(off2 - off1),
Phnum: 1,
Shentsize: uint16(off3 - off2),
Shnum: 3,
Shstrndx: 2,
}
binary.Write(&buf, binary.BigEndian, &hdr)
prog = elf.Prog64{
Type: 1,
Off: start,
Vaddr: start,
Paddr: start,
Filesz: uint64(size),
Memsz: uint64(size),
Flags: 5,
Align: start,
}
binary.Write(&buf, binary.BigEndian, &prog)
binary.Write(&buf, binary.BigEndian, &sect) // NULL section
sect = elf.Section64{
Name: 1,
Type: uint32(elf.SHT_PROGBITS),
Addr: start,
Off: start,
Size: uint64(size),
Flags: uint64(elf.SHF_ALLOC | elf.SHF_EXECINSTR),
Addralign: 4,
}
binary.Write(&buf, binary.BigEndian, &sect) // .text
sect = elf.Section64{
Name: uint32(len("\x00.text\x00")),
Type: uint32(elf.SHT_STRTAB),
Addr: 0,
Off: uint64(off2 + (off3-off2)*3),
Size: uint64(len("\x00.text\x00.shstrtab\x00")),
Addralign: 1,
}
binary.Write(&buf, binary.BigEndian, &sect)
buf.WriteString("\x00.text\x00.shstrtab\x00")
f.Write(buf.Bytes())
return nil
}

172
vendor/golang.org/x/arch/ppc64/ppc64asm/plan9.go generated vendored Normal file
View File

@ -0,0 +1,172 @@
// Copyright 2015 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 ppc64asm
import (
"fmt"
"strings"
)
// GoSyntax returns the Go assembler syntax for the instruction.
// The pc is the program counter of the first instruction, used for expanding
// PC-relative addresses into absolute ones.
// The symname function queries the symbol table for the program
// being disassembled. It returns the name and base address of the symbol
// containing the target, if any; otherwise it returns "", 0.
func GoSyntax(inst Inst, pc uint64, symname func(uint64) (string, uint64)) string {
if symname == nil {
symname = func(uint64) (string, uint64) { return "", 0 }
}
if inst.Op == 0 {
return "?"
}
var args []string
for i, a := range inst.Args[:] {
if a == nil {
break
}
if s := plan9Arg(&inst, i, pc, a, symname); s != "" {
args = append(args, s)
}
}
var op string
op = plan9OpMap[inst.Op]
if op == "" {
op = strings.ToUpper(inst.Op.String())
}
// laid out the instruction
switch inst.Op {
default: // dst, sA, sB, ...
if len(args) == 0 {
return op
} else if len(args) == 1 {
return fmt.Sprintf("%s %s", op, args[0])
}
args = append(args, args[0])
return op + " " + strings.Join(args[1:], ", ")
// store instructions always have the memory operand at the end, no need to reorder
case STB, STBU, STBX, STBUX,
STH, STHU, STHX, STHUX,
STW, STWU, STWX, STWUX,
STD, STDU, STDX, STDUX,
STQ,
STHBRX, STWBRX:
return op + " " + strings.Join(args, ", ")
// branch instructions needs additional handling
case BCLR:
if int(inst.Args[0].(Imm))&20 == 20 { // unconditional
return "RET"
}
return op + " " + strings.Join(args, ", ")
case BC:
if int(inst.Args[0].(Imm))&0x1c == 12 { // jump on cond bit set
return fmt.Sprintf("B%s %s", args[1], args[2])
} else if int(inst.Args[0].(Imm))&0x1c == 4 && revCondMap[args[1]] != "" { // jump on cond bit not set
return fmt.Sprintf("B%s %s", revCondMap[args[1]], args[2])
}
return op + " " + strings.Join(args, ", ")
case BCCTR:
if int(inst.Args[0].(Imm))&20 == 20 { // unconditional
return "BR (CTR)"
}
return op + " " + strings.Join(args, ", ")
case BCCTRL:
if int(inst.Args[0].(Imm))&20 == 20 { // unconditional
return "BL (CTR)"
}
return op + " " + strings.Join(args, ", ")
case BCA, BCL, BCLA, BCLRL, BCTAR, BCTARL:
return op + " " + strings.Join(args, ", ")
}
}
// plan9Arg formats arg (which is the argIndex's arg in inst) according to Plan 9 rules.
// NOTE: because Plan9Syntax is the only caller of this func, and it receives a copy
// of inst, it's ok to modify inst.Args here.
func plan9Arg(inst *Inst, argIndex int, pc uint64, arg Arg, symname func(uint64) (string, uint64)) string {
// special cases for load/store instructions
if _, ok := arg.(Offset); ok {
if argIndex+1 == len(inst.Args) || inst.Args[argIndex+1] == nil {
panic(fmt.Errorf("wrong table: offset not followed by register"))
}
}
switch arg := arg.(type) {
case Reg:
if isLoadStoreOp(inst.Op) && argIndex == 1 && arg == R0 {
return "0"
}
if arg == R30 {
return "g"
}
return strings.ToUpper(arg.String())
case CondReg:
if arg == CR0 && strings.HasPrefix(inst.Op.String(), "cmp") {
return "" // don't show cr0 for cmp instructions
} else if arg >= CR0 {
return fmt.Sprintf("CR%d", int(arg-CR0))
}
bit := [4]string{"LT", "GT", "EQ", "SO"}[(arg-Cond0LT)%4]
if arg <= Cond0SO {
return bit
}
return fmt.Sprintf("4*CR%d+%s", int(arg-Cond0LT)/4, bit)
case Imm:
return fmt.Sprintf("$%d", arg)
case SpReg:
switch arg {
case 8:
return "LR"
case 9:
return "CTR"
}
return fmt.Sprintf("SPR(%d)", int(arg))
case PCRel:
addr := pc + uint64(int64(arg))
if s, base := symname(addr); s != "" && base == addr {
return fmt.Sprintf("%s(SB)", s)
}
return fmt.Sprintf("%#x", addr)
case Label:
return fmt.Sprintf("%#x", int(arg))
case Offset:
reg := inst.Args[argIndex+1].(Reg)
removeArg(inst, argIndex+1)
if reg == R0 {
return fmt.Sprintf("%d(0)", int(arg))
}
return fmt.Sprintf("%d(R%d)", int(arg), reg-R0)
}
return fmt.Sprintf("???(%v)", arg)
}
// revCondMap maps a conditional register bit to its inverse, if possible.
var revCondMap = map[string]string{
"LT": "GE", "GT": "LE", "EQ": "NE",
}
// plan9OpMap maps an Op to its Plan 9 mnemonics, if different than its GNU mnemonics.
var plan9OpMap = map[Op]string{
LWARX: "LWAR", STWCX_: "STWCCC",
LDARX: "LDAR", STDCX_: "STDCCC",
LHARX: "LHAR", STHCX_: "STHCCC",
LBARX: "LBAR", STBCX_: "STBCCC",
ADDI: "ADD",
ADD_: "ADDCC",
LBZ: "MOVBZ", STB: "MOVB",
LBZU: "MOVBZU", STBU: "MOVBU", // TODO(minux): indexed forms are not handled
LHZ: "MOVHZ", LHA: "MOVH", STH: "MOVH",
LHZU: "MOVHZU", STHU: "MOVHU",
LI: "MOVD",
LIS: "ADDIS",
LWZ: "MOVWZ", LWA: "MOVW", STW: "MOVW",
LWZU: "MOVWZU", STWU: "MOVWU",
LD: "MOVD", STD: "MOVD",
LDU: "MOVDU", STDU: "MOVDU",
MTSPR: "MOVD", MFSPR: "MOVD", // the width is ambiguous for SPRs
B: "BR",
BL: "CALL",
CMPLD: "CMPU", CMPLW: "CMPWU",
CMPD: "CMP", CMPW: "CMPW",
}

5421
vendor/golang.org/x/arch/ppc64/ppc64asm/tables.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,25 @@
6d746162| gnu xoris r20,r11,24930
4c040000| gnu mcrf cr0,cr1
88000017| gnu lbz r0,23(0)
4abaa88a| gnu ba 0xfebaa888
7d8fc2a6| gnu mfspr r12,783
00000000| gnu error: unknown instruction
a1841e80| gnu lhz r12,7808(r4)
42093d10| gnu bc 16,4*cr2+gt,.+0x3d10
e38d5b90| gnu lq r28,23440(r13)
84127a20| gnu lwzu r0,31264(r18)
c61bb730| gnu lfsu f16,-18640(r27)
0825f440| gnu tdi 1,r5,-3008
a9a912c1| gnu lha r13,4801(r9)
ebb24fd1| gnu ldu r29,20432(r18)
b1ce0612| gnu sth r14,1554(r14)
f3c04322| gnu xvcvdpuxws vs30,vs40
945c62a2| gnu stwu r2,25250(r28)
9c8156e3| gnu stbu r4,22243(r1)
f91b9c7a| gnu stq r8,-25480(r27)
2c1c81b4| gnu cmpwi r28,-32332
f87b904d| gnu stdu r3,-28596(r27)
eab3c832| gnu lwa r21,-14288(r19)
4320336b| gnu bcla 25,lt,0x3368
7e40092e| gnu stwx r18,0,r1
7c103c2c| gnu lwbrx r0,r16,r7

596
vendor/golang.org/x/arch/ppc64/ppc64map/map.go generated vendored Normal file
View File

@ -0,0 +1,596 @@
// Copyright 2014 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.
// ppc64map constructs the ppc64 opcode map from the instruction set CSV file.
//
// Usage:
// ppc64map [-fmt=format] ppc64.csv
//
// The known output formats are:
//
// text (default) - print decoding tree in text form
// decoder - print decoding tables for the ppc64asm package
package main
import (
"bufio"
"bytes"
"encoding/csv"
"flag"
"fmt"
gofmt "go/format"
"log"
"os"
"regexp"
"strconv"
"strings"
"text/template"
asm "golang.org/x/arch/ppc64/ppc64asm"
)
var format = flag.String("fmt", "text", "output format: text, decoder")
var debug = flag.Bool("debug", false, "enable debugging output")
var inputFile string
func usage() {
fmt.Fprintf(os.Stderr, "usage: ppc64map [-fmt=format] ppc64.csv\n")
os.Exit(2)
}
func main() {
log.SetFlags(0)
log.SetPrefix("ppc64map: ")
flag.Usage = usage
flag.Parse()
if flag.NArg() != 1 {
usage()
}
inputFile = flag.Arg(0)
var print func(*Prog)
switch *format {
default:
log.Fatalf("unknown output format %q", *format)
case "text":
print = printText
case "decoder":
print = printDecoder
}
p, err := readCSV(flag.Arg(0))
log.Printf("Parsed %d instruction forms.", len(p.Insts))
if err != nil {
log.Fatal(err)
}
print(p)
}
// readCSV reads the CSV file and returns the corresponding Prog.
// It may print details about problems to standard error using the log package.
func readCSV(file string) (*Prog, error) {
// Read input.
// Skip leading blank and # comment lines.
f, err := os.Open(file)
if err != nil {
return nil, err
}
b := bufio.NewReader(f)
for {
c, err := b.ReadByte()
if err != nil {
break
}
if c == '\n' {
continue
}
if c == '#' {
b.ReadBytes('\n')
continue
}
b.UnreadByte()
break
}
table, err := csv.NewReader(b).ReadAll()
if err != nil {
return nil, fmt.Errorf("parsing %s: %v", file, err)
}
if len(table) == 0 {
return nil, fmt.Errorf("empty csv input")
}
if len(table[0]) < 4 {
return nil, fmt.Errorf("csv too narrow: need at least four columns")
}
p := &Prog{}
for _, row := range table {
add(p, row[0], row[1], row[2], row[3])
}
return p, nil
}
type Prog struct {
Insts []Inst
OpRanges map[string]string
}
type Field struct {
Name string
BitFields asm.BitFields
Type asm.ArgType
Shift uint8
}
func (f Field) String() string {
return fmt.Sprintf("%v(%s%v)", f.Type, f.Name, f.BitFields)
}
type Inst struct {
Text string
Encoding string
Op string
Mask uint32
Value uint32
DontCare uint32
Fields []Field
}
func (i Inst) String() string {
return fmt.Sprintf("%s (%s) %08x/%08x[%08x] %v (%s)", i.Op, i.Encoding, i.Value, i.Mask, i.DontCare, i.Fields, i.Text)
}
type Arg struct {
Name string
Bits int8
Offs int8
}
func (a Arg) String() string {
return fmt.Sprintf("%s[%d:%d]", a.Name, a.Offs, a.Offs+a.Bits-1)
}
func (a Arg) Maximum() int {
return 1<<uint8(a.Bits) - 1
}
func (a Arg) BitMask() uint32 {
return uint32(a.Maximum()) << a.Shift()
}
func (a Arg) Shift() uint8 {
return uint8(32 - a.Offs - a.Bits)
}
type Args []Arg
func (as Args) String() string {
ss := make([]string, len(as))
for i := range as {
ss[i] = as[i].String()
}
return strings.Join(ss, "|")
}
func (as Args) Find(name string) int {
for i := range as {
if as[i].Name == name {
return i
}
}
return -1
}
func (as *Args) Append(a Arg) {
*as = append(*as, a)
}
func (as *Args) Delete(i int) {
*as = append((*as)[:i], (*as)[i+1:]...)
}
func (as Args) Clone() Args {
return append(Args{}, as...)
}
func (a Arg) isDontCare() bool {
return a.Name[0] == '/' && a.Name == strings.Repeat("/", len(a.Name))
}
// add adds the entry from the CSV described by text, mnemonics, encoding, and tags
// to the program p.
func add(p *Prog, text, mnemonics, encoding, tags string) {
if strings.HasPrefix(mnemonics, "e_") || strings.HasPrefix(mnemonics, "se_") {
// TODO(minux): VLE instructions are ignored.
return
}
// Parse encoding, building size and offset of each field.
// The first field in the encoding is the smallest offset.
// And note the MSB is bit 0, not bit 31.
// Example: "31@0|RS@6|RA@11|///@16|26@21|Rc@31|"
var args Args
fields := strings.Split(encoding, "|")
for i, f := range fields {
name, off := "", -1
if f == "" {
off = 32
if i == 0 || i != len(fields)-1 {
fmt.Fprintf(os.Stderr, "%s: wrong %d-th encoding field: %q\n", text, i, f)
return
}
} else {
j := strings.Index(f, "@")
if j < 0 {
fmt.Fprintf(os.Stderr, "%s: wrong %d-th encoding field: %q\n", text, i, f)
continue
}
off, _ = strconv.Atoi(f[j+1:])
name = f[:j]
}
if len(args) > 0 {
args[len(args)-1].Bits += int8(off)
}
if name != "" {
arg := Arg{Name: name, Offs: int8(off), Bits: int8(-off)}
args.Append(arg)
}
}
var mask, value, dontCare uint32
for i := 0; i < len(args); i++ {
arg := args[i]
v, err := strconv.Atoi(arg.Name)
switch {
case err == nil: // is a numbered field
if v < 0 || v > arg.Maximum() {
fmt.Fprintf(os.Stderr, "%s: field %s value (%d) is out of range (%d-bit)\n", text, arg, v, arg.Bits)
}
mask |= arg.BitMask()
value |= uint32(v) << arg.Shift()
args.Delete(i)
i--
case arg.Name[0] == '/': // is don't care
if arg.Name != strings.Repeat("/", len(arg.Name)) {
log.Fatalf("%s: arg %v named like a don't care bit, but it's not", text, arg)
}
dontCare |= arg.BitMask()
args.Delete(i)
i--
default:
continue
}
}
// rename duplicated fields (e.g. 30@0|RS@6|RA@11|sh@16|mb@21|0@27|sh@30|Rc@31|)
// but only support two duplicated fields
for i := 1; i < len(args); i++ {
if args[:i].Find(args[i].Name) >= 0 {
args[i].Name += "2"
}
if args[:i].Find(args[i].Name) >= 0 {
log.Fatalf("%s: more than one duplicated fields: %s", text, args)
}
}
// sanity checks
if mask&dontCare != 0 {
log.Fatalf("%s: mask (%08x) and don't care (%08x) collide", text, mask, dontCare)
}
if value&^mask != 0 {
log.Fatalf("%s: value (%08x) out of range of mask (%08x)", text, value, mask)
}
var argMask uint32
for _, arg := range args {
if arg.Bits <= 0 || arg.Bits > 32 || arg.Offs > 31 || arg.Offs <= 0 {
log.Fatalf("%s: arg %v has wrong bit field spec", text, arg)
}
if mask&arg.BitMask() != 0 {
log.Fatalf("%s: mask (%08x) intersect with arg %v", text, mask, arg)
}
if argMask&arg.BitMask() != 0 {
log.Fatalf("%s: arg %v overlap with other args %v", text, arg, args)
}
argMask |= arg.BitMask()
}
if 1<<32-1 != mask|dontCare|argMask {
log.Fatalf("%s: args %v fail to cover all 32 bits", text, args)
}
// split mnemonics into individual instructions
// example: "b target_addr (AA=0 LK=0)|ba target_addr (AA=1 LK=0)|bl target_addr (AA=0 LK=1)|bla target_addr (AA=1 LK=1)"
insts := strings.Split(categoryRe.ReplaceAllString(mnemonics, ""), "|")
for _, inst := range insts {
value, mask := value, mask
args := args.Clone()
if inst == "" {
continue
}
// amend mask and value
parts := instRe.FindStringSubmatch(inst)
if parts == nil {
log.Fatalf("%v couldn't match %s", instRe, inst)
}
conds := condRe.FindAllStringSubmatch(parts[2], -1)
isPCRel := true
for _, cond := range conds {
i := args.Find(cond[1])
v, _ := strconv.ParseInt(cond[2], 16, 32) // the regular expression has checked the number format
if i < 0 {
log.Fatalf("%s: %s don't contain arg %s used in %s", text, args, cond[1], inst)
}
if cond[1] == "AA" && v == 1 {
isPCRel = false
}
mask |= args[i].BitMask()
value |= uint32(v) << args[i].Shift()
args.Delete(i)
}
inst := Inst{Text: text, Encoding: parts[1], Value: value, Mask: mask, DontCare: dontCare}
// order inst.Args according to mnemonics order
for i, opr := range operandRe.FindAllString(parts[1], -1) {
if i == 0 { // operation
inst.Op = opr
continue
}
field := Field{Name: opr}
typ := asm.TypeUnknown
var shift uint8
opr2 := ""
switch opr {
case "target_addr":
shift = 2
if isPCRel {
typ = asm.TypePCRel
} else {
typ = asm.TypeLabel
}
if args.Find("LI") >= 0 {
opr = "LI"
} else {
opr = "BD"
}
case "UI", "BO", "BH", "TH", "LEV", "NB", "L", "TO", "FXM", "U", "W", "FLM", "UIM", "SHB", "SHW", "ST", "SIX", "PS", "DCM", "DGM", "RMC", "R", "SP", "S", "DM", "CT", "EH", "E", "MO", "WC", "A", "IH", "OC", "DUI", "DUIS":
typ = asm.TypeImmUnsigned
if i := args.Find(opr); i < 0 {
opr = "D"
}
case "SH":
typ = asm.TypeImmUnsigned
if args.Find("sh2") >= 0 { // sh2 || sh
opr = "sh2"
opr2 = "sh"
}
case "MB", "ME":
typ = asm.TypeImmUnsigned
if n := strings.ToLower(opr); args.Find(n) >= 0 {
opr = n // xx[5] || xx[0:4]
}
case "SI", "SIM", "TE":
typ = asm.TypeImmSigned
if i := args.Find(opr); i < 0 {
opr = "D"
}
case "DS":
typ = asm.TypeOffset
shift = 2
case "DQ":
typ = asm.TypeOffset
shift = 4
case "D":
if i := args.Find(opr); i >= 0 {
typ = asm.TypeOffset
break
}
if i := args.Find("UI"); i >= 0 {
typ = asm.TypeImmUnsigned
opr = "UI"
break
}
if i := args.Find("SI"); i >= 0 {
typ = asm.TypeImmSigned
opr = "SI"
break
}
case "RA", "RB", "RS", "RSp", "RT", "RTp":
typ = asm.TypeReg
case "BT", "BA", "BB", "BC", "BI":
typ = asm.TypeCondRegBit
case "BF", "BFA":
typ = asm.TypeCondRegField
case "FRA", "FRB", "FRBp", "FRC", "FRS", "FRSp", "FRT", "FRTp":
typ = asm.TypeFPReg
case "XA", "XB", "XC", "XS", "XT": // 5-bit, split field
typ = asm.TypeVecSReg
opr2 = opr[1:]
opr = opr[1:] + "X"
case "VRA", "VRB", "VRC", "VRS", "VRT":
typ = asm.TypeVecReg
case "SPR", "DCRN", "BHRBE", "TBR", "SR", "TMR", "PMRN": // Note: if you add to this list and the register field needs special handling, add it to switch statement below
typ = asm.TypeSpReg
switch opr {
case "BHRBE":
opr = "bhrbe" // no special handling
case "DCRN":
opr = "DCR"
}
if n := strings.ToLower(opr); n != opr && args.Find(n) >= 0 {
opr = n // spr[5:9] || spr[0:4]
}
}
if typ == asm.TypeUnknown {
log.Fatalf("%s %s unknown type for opr %s", text, inst, opr)
}
field.Type = typ
field.Shift = shift
var f1, f2 asm.BitField
switch {
case opr2 != "":
ext := args.Find(opr)
if ext < 0 {
log.Fatalf("%s: couldn't find extended field %s in %s", text, opr, args)
}
f1.Offs, f1.Bits = uint8(args[ext].Offs), uint8(args[ext].Bits)
base := args.Find(opr2)
if base < 0 {
log.Fatalf("%s: couldn't find base field %s in %s", text, opr2, args)
}
f2.Offs, f2.Bits = uint8(args[base].Offs), uint8(args[base].Bits)
case opr == "mb", opr == "me": // xx[5] || xx[0:4]
i := args.Find(opr)
if i < 0 {
log.Fatalf("%s: couldn't find special 'm[be]' field for %s in %s", text, opr, args)
}
f1.Offs, f1.Bits = uint8(args[i].Offs+args[i].Bits)-1, 1
f2.Offs, f2.Bits = uint8(args[i].Offs), uint8(args[i].Bits)-1
case opr == "spr", opr == "tbr", opr == "tmr", opr == "dcr": // spr[5:9] || spr[0:4]
i := args.Find(opr)
if i < 0 {
log.Fatalf("%s: couldn't find special 'spr' field for %s in %s", text, opr, args)
}
if args[i].Bits != 10 {
log.Fatalf("%s: special 'spr' field is not 10-bit: %s", text, args)
}
f1.Offs, f1.Bits = uint8(args[i].Offs)+5, 5
f2.Offs, f2.Bits = uint8(args[i].Offs), 5
default:
i := args.Find(opr)
if i < 0 {
log.Fatalf("%s: couldn't find %s in %s", text, opr, args)
}
f1.Offs, f1.Bits = uint8(args[i].Offs), uint8(args[i].Bits)
}
field.BitFields.Append(f1)
if f2.Bits > 0 {
field.BitFields.Append(f2)
}
inst.Fields = append(inst.Fields, field)
}
if *debug {
fmt.Printf("%v\n", inst)
}
p.Insts = append(p.Insts, inst)
}
}
// condRegexp is a regular expression that matches condition in mnemonics (e.g. "AA=1")
const condRegexp = `\s*([[:alpha:]]+)=([0-9a-f]+)\s*`
// condRe matches condition in mnemonics (e.g. "AA=1")
var condRe = regexp.MustCompile(condRegexp)
// instRe matches instruction with potentially multiple conditions in mnemonics
var instRe = regexp.MustCompile(`^(.*?)\s?(\((` + condRegexp + `)+\))?$`)
// categoryRe matches intruction category notices in mnemonics
var categoryRe = regexp.MustCompile(`(\s*\[Category:[^]]*\]\s*)|(\s*\[Co-requisite[^]]*\]\s*)|(\s*\(\s*0[Xx][[0-9A-Fa-f_]{9}\s*\)\s*)`)
// operandRe matches each operand (including opcode) in instruction mnemonics
var operandRe = regexp.MustCompile(`([[:alpha:]][[:alnum:]_]*\.?)`)
// printText implements the -fmt=text mode, which is not implemented (yet?).
func printText(p *Prog) {
log.Fatal("-fmt=text not implemented")
}
// opName translate an opcode to a valid Go identifier all-cap op name.
func opName(op string) string {
return strings.ToUpper(strings.Replace(op, ".", "_", 1))
}
// argFieldName constructs a name for the argField
func argFieldName(f Field) string {
ns := []string{"ap", f.Type.String()}
for _, b := range f.BitFields {
ns = append(ns, fmt.Sprintf("%d_%d", b.Offs, b.Offs+b.Bits-1))
}
if f.Shift > 0 {
ns = append(ns, fmt.Sprintf("shift%d", f.Shift))
}
return strings.Join(ns, "_")
}
var funcBodyTmpl = template.Must(template.New("funcBody").Parse(``))
// printDecoder implements the -fmt=decoder mode.
// It emits the tables.go for package armasm's decoder.
func printDecoder(p *Prog) {
var buf bytes.Buffer
fmt.Fprintf(&buf, "// DO NOT EDIT\n")
fmt.Fprintf(&buf, "// generated by: ppc64map -fmt=decoder %s\n", inputFile)
fmt.Fprintf(&buf, "\n")
fmt.Fprintf(&buf, "package ppc64asm\n\n")
// Build list of opcodes, using the csv order (which corresponds to ISA docs order)
m := map[string]bool{}
fmt.Fprintf(&buf, "const (\n\t_ Op = iota\n")
for _, inst := range p.Insts {
name := opName(inst.Op)
if ok := m[name]; ok {
continue
}
m[name] = true
fmt.Fprintf(&buf, "\t%s\n", name)
}
fmt.Fprintln(&buf, ")\n\n")
// Emit slice mapping opcode number to name string.
m = map[string]bool{}
fmt.Fprintf(&buf, "var opstr = [...]string{\n")
for _, inst := range p.Insts {
name := opName(inst.Op)
if ok := m[name]; ok {
continue
}
m[name] = true
fmt.Fprintf(&buf, "\t%s: %q,\n", opName(inst.Op), inst.Op)
}
fmt.Fprintln(&buf, "}\n\n")
// print out argFields
fmt.Fprintf(&buf, "var (\n")
m = map[string]bool{}
for _, inst := range p.Insts {
for _, f := range inst.Fields {
name := argFieldName(f)
if ok := m[name]; ok {
continue
}
m[name] = true
fmt.Fprintf(&buf, "\t%s = &argField{Type: %#v, Shift: %d, BitFields: BitFields{", name, f.Type, f.Shift)
for _, b := range f.BitFields {
fmt.Fprintf(&buf, "{%d, %d},", b.Offs, b.Bits)
}
fmt.Fprintf(&buf, "}}\n")
}
}
fmt.Fprintln(&buf, ")\n\n")
// Emit decoding table.
fmt.Fprintf(&buf, "var instFormats = [...]instFormat{\n")
for _, inst := range p.Insts {
fmt.Fprintf(&buf, "\t{ %s, %#x, %#x, %#x,", opName(inst.Op), inst.Mask, inst.Value, inst.DontCare)
fmt.Fprintf(&buf, " // %s (%s)\n\t\t[5]*argField{", inst.Text, inst.Encoding)
for _, f := range inst.Fields {
fmt.Fprintf(&buf, "%s, ", argFieldName(f))
}
fmt.Fprintf(&buf, "}},\n")
}
fmt.Fprintln(&buf, "}\n")
out, err := gofmt.Source(buf.Bytes())
if err != nil {
log.Fatalf("gofmt error: %v", err)
fmt.Printf("%s", buf.Bytes())
} else {
fmt.Printf("%s", out)
}
}

505
vendor/golang.org/x/arch/ppc64/ppc64spec/spec.go generated vendored Normal file
View File

@ -0,0 +1,505 @@
// Copyright 2014 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.
// +build go1.6,amd64 go1.8
// Power64spec reads the ``Power ISA V2.07'' Manual
// to collect instruction encoding details and writes those details to standard output
// in CSV format.
//
// Usage:
// ppc64spec PowerISA_V2.07_PUBLIC.pdf >ppc64.csv
//
// Each CSV line contains four fields:
//
// instruction
// The instruction heading, such as "AAD imm8".
// mnemonic
// The instruction mnemonics, separated by | symbols.
// encoding
// The instruction encoding, a sequence of name@startbit| describing each bit field in turn.
// tags
// For now, empty.
//
// For more on the exact meaning of these fields, see the Power manual.
//
package main
import (
"bufio"
"fmt"
"log"
"math"
"os"
"regexp"
"sort"
"strconv"
"strings"
"rsc.io/pdf"
)
type Inst struct {
Name string
Text string
Enc string
}
const debugPage = 0
var stdout *bufio.Writer
func main() {
log.SetFlags(0)
log.SetPrefix("armspec: ")
if len(os.Args) != 2 {
fmt.Fprintf(os.Stderr, "usage: armspec file.pdf\n")
os.Exit(2)
}
f, err := pdf.Open(os.Args[1])
if err != nil {
log.Fatal(err)
}
// Find instruction set reference in outline, to build instruction list.
instList := instHeadings(f.Outline())
if len(instList) < 200 {
log.Fatalf("only found %d instructions in table of contents", len(instList))
}
var all = []Inst{
// Split across multiple columns and pages!
{"Count Leading Zeros Word X-form", "cntlzw RA, RS (Rc=0)\ncntlzw. RA, RS (Rc=1)", "31@0|RS@6|RA@11|///@16|26@21|Rc@31|"},
}
for j, headline := range instList {
for _, inst := range all {
if headline == inst.Name {
instList[j] = ""
break
}
}
}
// Scan document looking for instructions.
// Must find exactly the ones in the outline.
n := f.NumPage()
for pageNum := 1; pageNum <= n; pageNum++ {
if debugPage > 0 && pageNum != debugPage {
continue
}
p := f.Page(pageNum)
table := parsePage(pageNum, p)
if len(table) == 0 {
continue
}
InstLoop:
for _, inst := range table {
for j, headline := range instList {
if inst.Name == headline {
instList[j] = ""
continue InstLoop
}
}
fmt.Fprintf(os.Stderr, "page %d: unexpected instruction %q\n", pageNum, inst.Name)
}
all = append(all, table...)
}
if debugPage == 0 {
for _, headline := range instList {
if headline != "" {
switch headline {
default:
fmt.Fprintf(os.Stderr, "missing instruction %q\n", headline)
case "CHKA": // ThumbEE
case "CPS": // system instruction
case "CPY": // synonym for MOV
case "ENTERX": // ThumbEE
case "F* (former VFP instruction mnemonics)": // synonyms
case "HB, HBL, HBLP, HBP": // ThumbEE
case "LEAVEX": // ThumbEE
case "MOV (shifted register)": // pseudo instruction for ASR, LSL, LSR, ROR, and RRX
case "NEG": // synonym for RSB
case "RFE": // system instruction
case "SMC (previously SMI)": // system instruction
case "SRS": // system instruction
case "SUBS PC, LR and related instructions": // system instruction
case "VAND (immediate)": // pseudo instruction
case "VCLE (register)": // pseudo instruction
case "VCLT (register)": // pseudo instruction
case "VORN (immediate)": // pseudo instruction
}
}
}
}
stdout = bufio.NewWriter(os.Stdout)
for _, inst := range all {
fmt.Fprintf(stdout, "%q,%q,%q,%q\n", inst.Name, strings.Replace(inst.Text, "\n", "|", -1), inst.Enc, "")
}
stdout.Flush()
}
func instHeadings(outline pdf.Outline) []string {
return appendInstHeadings(outline, nil)
}
var instRE = regexp.MustCompile(` ([A-Z0-9]+-form|Byte|Word|Doubleword|Halfword)($| \[)`)
var sectionRE = regexp.MustCompile(`^[0-9A-Z]+\.[0-9]`)
func appendInstHeadings(outline pdf.Outline, list []string) []string {
if strings.Contains(outline.Title, "Variable Length Encoding (VLE) Encoding") {
for _, child := range outline.Child {
vle = appendInstHeadings(child, vle)
}
return list
}
if instRE.MatchString(outline.Title) && !sectionRE.MatchString(outline.Title) {
list = append(list, outline.Title)
}
if outline.Title == "Transaction Abort Word Conditional" {
list = append(list, outline.Title+" X-form")
}
for _, child := range outline.Child {
list = appendInstHeadings(child, list)
}
return list
}
const inch = 72.0
func parsePage(num int, p pdf.Page) []Inst {
content := p.Content()
var text []pdf.Text
for _, t := range content.Text {
text = append(text, t)
}
text = findWords(text)
if debugPage > 0 {
for _, t := range text {
fmt.Println(t)
}
for _, r := range content.Rect {
fmt.Println(r)
}
}
// Look for instruction encodings.
// Some begin with a Helvetica-BoldOblique size 11 headline like "AND X-Form",
// is followed by Helvetica 9 mnemonic, and then a bit box with
// Helvetica 9 fields and Helvetica 7 bit offsets.
// Others use Arial,BoldItalic 11 for the headline,
// Arial 8 for the mnemonic, and Arial 4.2 for the bit offsets.
var insts []Inst
for {
// Heading
for len(text) > 0 && !match(text[0], "Helvetica-BoldOblique", 11, "") && !match(text[0], "Arial,BoldItalic", 11, "") && !match(text[0], "Arial,BoldItalic", 10, "") {
text = text[1:]
}
if len(text) == 0 {
break
}
heading := text[0].S
text = text[1:]
for len(text) > 0 && (match(text[0], "Helvetica-BoldOblique", 11, "") || match(text[0], "Arial,BoldItalic", 11, "") || match(text[0], "Arial,BoldItalic", 10, "")) {
heading += " " + text[0].S
text = text[1:]
}
heading = strings.Replace(heading, "]", "] ", -1)
heading = strings.Replace(heading, " ", " ", -1)
heading = strings.Replace(heading, "rEVX-form", "r EVX-form", -1)
heading = strings.Replace(heading, "eX-form", "e X-form", -1)
heading = strings.Replace(heading, "mSD4-form", "m SD4-form", -1)
heading = strings.Replace(heading, "eSCI8-form", "e SCI8-form", -1)
heading = strings.TrimSpace(heading)
if isVLE(heading) {
continue
}
// Mnemonic
if len(text) == 0 || (!match(text[0], "Helvetica", 9, "") && !match(text[0], "Helvetica-BoldOblique", 9, "") && !match(text[0], "Arial", 9, "") && !match(text[0], "Arial", 10, "")) {
continue
}
mnemonic := ""
y := text[0].Y
x0 := text[0].X
for len(text) > 0 && (match(text[0], "Helvetica", 9, "") || match(text[0], "Helvetica-BoldOblique", 9, "") || match(text[0], "Arial", 9, "") || match(text[0], "Courier", 8, "") || match(text[0], "LucidaConsole", 7.17, "") || text[0].Y == y) {
if text[0].Y != y {
if math.Abs(text[0].X-x0) > 4 {
break
}
mnemonic += "\n"
y = text[0].Y
} else if mnemonic != "" {
mnemonic += " "
}
mnemonic += text[0].S
text = text[1:]
}
// Encoding
bits, i := readBitBox(heading, content, text, num)
if i == 0 {
continue
}
insts = append(insts, Inst{heading, mnemonic, bits})
}
return insts
}
var vle = []string{
"System Call C-form,ESC-form",
}
func isVLE(s string) bool {
for _, v := range vle {
if s == v {
return true
}
}
return false
}
func readBitBox(headline string, content pdf.Content, text []pdf.Text, pageNum int) (string, int) {
// fields
i := 0
if len(text) == 0 || (!match(text[i], "Helvetica", 9, "") && !match(text[i], "Helvetica", 7.26, "") && !match(text[i], "Arial", 9, "") && !match(text[i], "Arial", 7.98, "") && !match(text[i], "Arial", 7.2, "")) {
fmt.Fprintf(os.Stderr, "page %d: no bit fields for %q\n", pageNum, headline)
if len(text) > 0 {
fmt.Fprintf(os.Stderr, "\tlast text: %v\n", text[0])
}
return "", 0
}
sz := text[i].FontSize
y2 := text[i].Y
x2 := 0.0
for i < len(text) && text[i].Y == y2 {
if x2 < text[i].X+text[i].W {
x2 = text[i].X + text[i].W
}
i++
}
y2 += sz / 2
// bit numbers
if i >= len(text) || text[i].S != "0" {
if headline == "Transaction Abort Doubleword Conditional X-form" {
// Split across the next page.
return "31@0|TO@6|RA@11|RB@16|814@21|1@31|", i
}
if headline == "Add Scaled Immediate SCI8-form" {
// Very strange fonts.
return "06@0|RT@6|RA@11|8@16|Rc@20|F@21|SCL@22|UI8@24|", i
}
fmt.Fprintf(os.Stderr, "page %d: no bit numbers for %s\n", pageNum, headline)
if i < len(text) {
fmt.Fprintf(os.Stderr, "\tlast text: %v\n", text[i])
}
return "", 0
}
sz = text[i].FontSize
y1 := text[i].Y
x1 := text[i].X
for i < len(text) && text[i].Y == y1 {
if x2 < text[i].X+text[i].W {
x2 = text[i].X + text[i].W
}
i++
}
if debugPage > 0 {
fmt.Println("encoding box", x1, y1, x2, y2, i, text[0], text[i])
}
// Find lines (thin rectangles) separating bit fields.
var bottom, top pdf.Rect
const (
yMargin = 0.25 * 72
xMargin = 1 * 72
)
for _, r := range content.Rect {
// Only consider lines in the same column.
if (x1 < 306) != (r.Max.X < 306) {
continue
}
if r.Max.Y-r.Min.Y < 2 && x1-xMargin < r.Min.X && r.Min.X < x1 && x2 < r.Max.X && r.Max.X < x2+xMargin {
if y1-yMargin < r.Min.Y && r.Min.Y < y1 {
bottom = r
}
if y2 < r.Min.Y && r.Min.Y < y2+8 {
top = r
}
}
}
if bottom.Min.X == 0 {
// maybe bit numbers are outside box; see doze, nap, sleep, rvwinkle.
for _, r := range content.Rect {
// Only consider lines in the same column.
if (x1 < 306) != (r.Max.X < 306) {
continue
}
if r.Max.Y-r.Min.Y < 2 && x1-xMargin < r.Min.X && r.Min.X < x1 && x2 < r.Max.X && r.Max.X < x2+xMargin {
if y1+sz/2 < r.Min.Y && r.Min.Y < y2 {
bottom = r
}
}
}
}
if debugPage > 0 {
fmt.Println("top", top, "bottom", bottom)
}
const ε = 0.1 * 72
var bars []pdf.Rect
for _, r := range content.Rect {
if r.Max.X-r.Min.X < 2 && math.Abs(r.Min.Y-bottom.Min.Y) < ε && math.Abs(r.Max.Y-top.Min.Y) < ε && (bottom.Min.X < 306) == (r.Max.X < 306) {
bars = append(bars, r)
}
}
sort.Sort(RectHorizontal(bars))
out := ""
for i := 0; i < len(bars)-1; i++ {
var sub []pdf.Text
x1, x2 := bars[i].Min.X, bars[i+1].Min.X
for _, t := range content.Text {
tx := t.X + t.W/2
ty := t.Y + t.FontSize/4
if x1 < tx && tx < x2 && y1 < ty && ty < y2 {
sub = append(sub, t)
}
}
var str []string
for _, t := range findWords(sub) {
str = append(str, t.S)
}
s := strings.Join(str, "@")
out += s + "|"
}
if out == "" {
fmt.Fprintf(os.Stderr, "page %d: no bit encodings for %s\n", pageNum, headline)
}
return out, i
}
type RectHorizontal []pdf.Rect
func (x RectHorizontal) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
func (x RectHorizontal) Less(i, j int) bool { return x[i].Min.X < x[j].Min.X }
func (x RectHorizontal) Len() int { return len(x) }
func checkNoEncodings(num int, text []pdf.Text) {
for _, t := range text {
if match(t, "Helvetica-Bold", 9, "Encoding") {
fmt.Fprintf(os.Stderr, "page %d: unexpected encoding: %s\n", num, t.S)
}
}
}
func match(t pdf.Text, font string, size float64, substr string) bool {
return t.Font == font && (size == 0 || math.Abs(t.FontSize-size) < 0.1) && strings.Contains(t.S, substr)
}
func findWords(chars []pdf.Text) (words []pdf.Text) {
// Sort by Y coordinate and normalize.
const nudge = 1.5
sort.Sort(pdf.TextVertical(chars))
old := -100000.0
for i, c := range chars {
if c.Y != old && math.Abs(old-c.Y) < nudge {
chars[i].Y = old
} else {
old = c.Y
}
}
// Sort by Y coordinate, breaking ties with X.
// This will bring letters in a single word together.
sort.Sort(pdf.TextVertical(chars))
// Loop over chars.
for i := 0; i < len(chars); {
// Find all chars on line.
j := i + 1
for j < len(chars) && chars[j].Y == chars[i].Y {
j++
}
var end float64
// Split line into words (really, phrases).
for k := i; k < j; {
ck := &chars[k]
s := ck.S
end = ck.X + ck.W
charSpace := ck.FontSize / 6
wordSpace := ck.FontSize * 2 / 3
l := k + 1
for l < j {
// Grow word.
cl := &chars[l]
if sameFont(cl.Font, ck.Font) && math.Abs(cl.FontSize-ck.FontSize) < 0.1 && cl.X <= end+charSpace {
s += cl.S
end = cl.X + cl.W
l++
continue
}
// Add space to phrase before next word.
if sameFont(cl.Font, ck.Font) && math.Abs(cl.FontSize-ck.FontSize) < 0.1 && cl.X <= end+wordSpace {
s += " " + cl.S
end = cl.X + cl.W
l++
continue
}
break
}
f := ck.Font
f = strings.TrimSuffix(f, ",Italic")
f = strings.TrimSuffix(f, "-Italic")
words = append(words, pdf.Text{f, ck.FontSize, ck.X, ck.Y, end - ck.X, s})
k = l
}
i = j
}
// Split into two columns.
var col1, col2 []pdf.Text
for _, w := range words {
if w.X > 306 {
col2 = append(col2, w)
} else {
col1 = append(col1, w)
}
}
return append(col1, col2...)
}
func sameFont(f1, f2 string) bool {
f1 = strings.TrimSuffix(f1, ",Italic")
f1 = strings.TrimSuffix(f1, "-Italic")
f2 = strings.TrimSuffix(f1, ",Italic")
f2 = strings.TrimSuffix(f1, "-Italic")
return strings.TrimSuffix(f1, ",Italic") == strings.TrimSuffix(f2, ",Italic") || f1 == "Symbol" || f2 == "Symbol" || f1 == "TimesNewRoman" || f2 == "TimesNewRoman"
}
var jsFix = strings.NewReplacer(
// `\u003c`, `<`,
// `\u003e`, `>`,
// `\u0026`, `&`,
// `\u0009`, `\t`,
)
func printTable(name string, table []Inst) {
_ = strconv.Atoi
}

2355
vendor/golang.org/x/arch/x86/x86.csv generated vendored Normal file

File diff suppressed because it is too large Load Diff

3
vendor/golang.org/x/arch/x86/x86asm/Makefile generated vendored Normal file
View File

@ -0,0 +1,3 @@
tables.go: ../x86map/map.go ../x86.csv
go run ../x86map/map.go -fmt=decoder ../x86.csv >_tables.go && gofmt _tables.go >tables.go && rm _tables.go

1724
vendor/golang.org/x/arch/x86/x86asm/decode.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

71
vendor/golang.org/x/arch/x86/x86asm/decode_test.go generated vendored Normal file
View File

@ -0,0 +1,71 @@
// Copyright 2014 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 x86asm
import (
"encoding/hex"
"io/ioutil"
"strconv"
"strings"
"testing"
)
func TestDecode(t *testing.T) {
data, err := ioutil.ReadFile("testdata/decode.txt")
if err != nil {
t.Fatal(err)
}
all := string(data)
for strings.Contains(all, "\t\t") {
all = strings.Replace(all, "\t\t", "\t", -1)
}
for _, line := range strings.Split(all, "\n") {
line = strings.TrimSpace(line)
if line == "" || strings.HasPrefix(line, "#") {
continue
}
f := strings.SplitN(line, "\t", 4)
i := strings.Index(f[0], "|")
if i < 0 {
t.Errorf("parsing %q: missing | separator", f[0])
continue
}
if i%2 != 0 {
t.Errorf("parsing %q: misaligned | separator", f[0])
}
size := i / 2
code, err := hex.DecodeString(f[0][:i] + f[0][i+1:])
if err != nil {
t.Errorf("parsing %q: %v", f[0], err)
continue
}
mode, err := strconv.Atoi(f[1])
if err != nil {
t.Errorf("invalid mode %q in: %s", f[1], line)
continue
}
syntax, asm := f[2], f[3]
inst, err := Decode(code, mode)
var out string
if err != nil {
out = "error: " + err.Error()
} else {
switch syntax {
case "gnu":
out = GNUSyntax(inst)
case "intel":
out = IntelSyntax(inst)
case "plan9": // [sic]
out = GoSyntax(inst, 0, nil)
default:
t.Errorf("unknown syntax %q", syntax)
continue
}
}
if out != asm || inst.Len != size {
t.Errorf("Decode(%s) [%s] = %s, %d, want %s, %d", f[0], syntax, out, inst.Len, asm, size)
}
}
}

810
vendor/golang.org/x/arch/x86/x86asm/ext_test.go generated vendored Normal file
View File

@ -0,0 +1,810 @@
// Copyright 2014 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.
// Support for testing against external disassembler program.
package x86asm
import (
"bufio"
"bytes"
"encoding/hex"
"flag"
"fmt"
"io/ioutil"
"log"
"math/rand"
"os"
"os/exec"
"regexp"
"runtime"
"strings"
"testing"
"time"
)
var (
printTests = flag.Bool("printtests", false, "print test cases that exercise new code paths")
dumpTest = flag.Bool("dump", false, "dump all encodings")
mismatch = flag.Bool("mismatch", false, "log allowed mismatches")
longTest = flag.Bool("long", false, "long test")
keep = flag.Bool("keep", false, "keep object files around")
debug = false
)
// A ExtInst represents a single decoded instruction parsed
// from an external disassembler's output.
type ExtInst struct {
addr uint32
enc [32]byte
nenc int
text string
}
func (r ExtInst) String() string {
return fmt.Sprintf("%#x: % x: %s", r.addr, r.enc, r.text)
}
// An ExtDis is a connection between an external disassembler and a test.
type ExtDis struct {
Arch int
Dec chan ExtInst
File *os.File
Size int
KeepFile bool
Cmd *exec.Cmd
}
// Run runs the given command - the external disassembler - and returns
// a buffered reader of its standard output.
func (ext *ExtDis) Run(cmd ...string) (*bufio.Reader, error) {
if *keep {
log.Printf("%s\n", strings.Join(cmd, " "))
}
ext.Cmd = exec.Command(cmd[0], cmd[1:]...)
out, err := ext.Cmd.StdoutPipe()
if err != nil {
return nil, fmt.Errorf("stdoutpipe: %v", err)
}
if err := ext.Cmd.Start(); err != nil {
return nil, fmt.Errorf("exec: %v", err)
}
b := bufio.NewReaderSize(out, 1<<20)
return b, nil
}
// Wait waits for the command started with Run to exit.
func (ext *ExtDis) Wait() error {
return ext.Cmd.Wait()
}
// testExtDis tests a set of byte sequences against an external disassembler.
// The disassembler is expected to produce the given syntax and be run
// in the given architecture mode (16, 32, or 64-bit).
// The extdis function must start the external disassembler
// and then parse its output, sending the parsed instructions on ext.Dec.
// The generate function calls its argument f once for each byte sequence
// to be tested. The generate function itself will be called twice, and it must
// make the same sequence of calls to f each time.
// When a disassembly does not match the internal decoding,
// allowedMismatch determines whether this mismatch should be
// allowed, or else considered an error.
func testExtDis(
t *testing.T,
syntax string,
arch int,
extdis func(ext *ExtDis) error,
generate func(f func([]byte)),
allowedMismatch func(text string, size int, inst *Inst, dec ExtInst) bool,
) {
start := time.Now()
ext := &ExtDis{
Dec: make(chan ExtInst),
Arch: arch,
}
errc := make(chan error)
// First pass: write instructions to input file for external disassembler.
file, f, size, err := writeInst(generate)
if err != nil {
t.Fatal(err)
}
ext.Size = size
ext.File = f
defer func() {
f.Close()
if !*keep {
os.Remove(file)
}
}()
// Second pass: compare disassembly against our decodings.
var (
totalTests = 0
totalSkips = 0
totalErrors = 0
errors = make([]string, 0, 100) // sampled errors, at most cap
)
go func() {
errc <- extdis(ext)
}()
generate(func(enc []byte) {
dec, ok := <-ext.Dec
if !ok {
t.Errorf("decoding stream ended early")
return
}
inst, text := disasm(syntax, arch, pad(enc))
totalTests++
if *dumpTest {
fmt.Printf("%x -> %s [%d]\n", enc[:len(enc)], dec.text, dec.nenc)
}
if text != dec.text || inst.Len != dec.nenc {
suffix := ""
if allowedMismatch(text, size, &inst, dec) {
totalSkips++
if !*mismatch {
return
}
suffix += " (allowed mismatch)"
}
totalErrors++
if len(errors) >= cap(errors) {
j := rand.Intn(totalErrors)
if j >= cap(errors) {
return
}
errors = append(errors[:j], errors[j+1:]...)
}
errors = append(errors, fmt.Sprintf("decode(%x) = %q, %d, want %q, %d%s", enc, text, inst.Len, dec.text, dec.nenc, suffix))
}
})
if *mismatch {
totalErrors -= totalSkips
}
for _, b := range errors {
t.Log(b)
}
if totalErrors > 0 {
t.Fail()
}
t.Logf("%d test cases, %d expected mismatches, %d failures; %.0f cases/second", totalTests, totalSkips, totalErrors, float64(totalTests)/time.Since(start).Seconds())
if err := <-errc; err != nil {
t.Fatalf("external disassembler: %v", err)
}
}
const start = 0x8000 // start address of text
// writeInst writes the generated byte sequences to a new file
// starting at offset start. That file is intended to be the input to
// the external disassembler.
func writeInst(generate func(func([]byte))) (file string, f *os.File, size int, err error) {
f, err = ioutil.TempFile("", "x86map")
if err != nil {
return
}
file = f.Name()
f.Seek(start, 0)
w := bufio.NewWriter(f)
defer w.Flush()
size = 0
generate(func(x []byte) {
if len(x) > 16 {
x = x[:16]
}
if debug {
fmt.Printf("%#x: %x%x\n", start+size, x, pops[len(x):])
}
w.Write(x)
w.Write(pops[len(x):])
size += len(pops)
})
return file, f, size, nil
}
// 0x5F is a single-byte pop instruction.
// We pad the bytes we want decoded with enough 0x5Fs
// that no matter what state the instruction stream is in
// after reading our bytes, the pops will get us back to
// a forced instruction boundary.
var pops = []byte{
0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
}
// pad pads the code sequence with pops.
func pad(enc []byte) []byte {
return append(enc[:len(enc):len(enc)], pops...)
}
// disasm returns the decoded instruction and text
// for the given source bytes, using the given syntax and mode.
func disasm(syntax string, mode int, src []byte) (inst Inst, text string) {
// If printTests is set, we record the coverage value
// before and after, and we write out the inputs for which
// coverage went up, in the format expected in testdata/decode.text.
// This produces a fairly small set of test cases that exercise nearly
// all the code.
var cover float64
if *printTests {
cover -= coverage()
}
inst, err := decode1(src, mode, syntax == "gnu")
if err != nil {
text = "error: " + err.Error()
} else {
switch syntax {
case "gnu":
text = GNUSyntax(inst)
case "intel":
text = IntelSyntax(inst)
case "plan9": // [sic]
text = GoSyntax(inst, 0, nil)
default:
text = "error: unknown syntax " + syntax
}
}
if *printTests {
cover += coverage()
if cover > 0 {
max := len(src)
if max > 16 && inst.Len <= 16 {
max = 16
}
fmt.Printf("%x|%x\t%d\t%s\t%s\n", src[:inst.Len], src[inst.Len:max], mode, syntax, text)
}
}
return
}
// coverage returns a floating point number denoting the
// test coverage until now. The number increases when new code paths are exercised,
// both in the Go program and in the decoder byte code.
func coverage() float64 {
/*
testing.Coverage is not in the main distribution.
The implementation, which must go in package testing, is:
// Coverage reports the current code coverage as a fraction in the range [0, 1].
func Coverage() float64 {
var n, d int64
for _, counters := range cover.Counters {
for _, c := range counters {
if c > 0 {
n++
}
d++
}
}
if d == 0 {
return 0
}
return float64(n) / float64(d)
}
*/
var f float64
// f += testing.Coverage()
f += decodeCoverage()
return f
}
func decodeCoverage() float64 {
n := 0
for _, t := range decoderCover {
if t {
n++
}
}
return float64(1+n) / float64(1+len(decoderCover))
}
// Helpers for writing disassembler output parsers.
// isPrefix reports whether text is the name of an instruction prefix.
func isPrefix(text string) bool {
return prefixByte[text] > 0
}
// prefixByte maps instruction prefix text to actual prefix byte values.
var prefixByte = map[string]byte{
"es": 0x26,
"cs": 0x2e,
"ss": 0x36,
"ds": 0x3e,
"fs": 0x64,
"gs": 0x65,
"data16": 0x66,
"addr16": 0x67,
"lock": 0xf0,
"repn": 0xf2,
"repne": 0xf2,
"rep": 0xf3,
"repe": 0xf3,
"xacquire": 0xf2,
"xrelease": 0xf3,
"bnd": 0xf2,
"addr32": 0x66,
"data32": 0x67,
}
// hasPrefix reports whether any of the space-separated words in the text s
// begins with any of the given prefixes.
func hasPrefix(s string, prefixes ...string) bool {
for _, prefix := range prefixes {
for s := s; s != ""; {
if strings.HasPrefix(s, prefix) {
return true
}
i := strings.Index(s, " ")
if i < 0 {
break
}
s = s[i+1:]
}
}
return false
}
// contains reports whether the text s contains any of the given substrings.
func contains(s string, substrings ...string) bool {
for _, sub := range substrings {
if strings.Contains(s, sub) {
return true
}
}
return false
}
// isHex reports whether b is a hexadecimal character (0-9A-Fa-f).
func isHex(b byte) bool { return b == '0' || unhex[b] > 0 }
// parseHex parses the hexadecimal byte dump in hex,
// appending the parsed bytes to raw and returning the updated slice.
// The returned bool signals whether any invalid hex was found.
// Spaces and tabs between bytes are okay but any other non-hex is not.
func parseHex(hex []byte, raw []byte) ([]byte, bool) {
hex = trimSpace(hex)
for j := 0; j < len(hex); {
for hex[j] == ' ' || hex[j] == '\t' {
j++
}
if j >= len(hex) {
break
}
if j+2 > len(hex) || !isHex(hex[j]) || !isHex(hex[j+1]) {
return nil, false
}
raw = append(raw, unhex[hex[j]]<<4|unhex[hex[j+1]])
j += 2
}
return raw, true
}
var unhex = [256]byte{
'0': 0,
'1': 1,
'2': 2,
'3': 3,
'4': 4,
'5': 5,
'6': 6,
'7': 7,
'8': 8,
'9': 9,
'A': 10,
'B': 11,
'C': 12,
'D': 13,
'E': 14,
'F': 15,
'a': 10,
'b': 11,
'c': 12,
'd': 13,
'e': 14,
'f': 15,
}
// index is like bytes.Index(s, []byte(t)) but avoids the allocation.
func index(s []byte, t string) int {
i := 0
for {
j := bytes.IndexByte(s[i:], t[0])
if j < 0 {
return -1
}
i = i + j
if i+len(t) > len(s) {
return -1
}
for k := 1; k < len(t); k++ {
if s[i+k] != t[k] {
goto nomatch
}
}
return i
nomatch:
i++
}
}
// fixSpace rewrites runs of spaces, tabs, and newline characters into single spaces in s.
// If s must be rewritten, it is rewritten in place.
func fixSpace(s []byte) []byte {
s = trimSpace(s)
for i := 0; i < len(s); i++ {
if s[i] == '\t' || s[i] == '\n' || i > 0 && s[i] == ' ' && s[i-1] == ' ' {
goto Fix
}
}
return s
Fix:
b := s
w := 0
for i := 0; i < len(s); i++ {
c := s[i]
if c == '\t' || c == '\n' {
c = ' '
}
if c == ' ' && w > 0 && b[w-1] == ' ' {
continue
}
b[w] = c
w++
}
if w > 0 && b[w-1] == ' ' {
w--
}
return b[:w]
}
// trimSpace trims leading and trailing space from s, returning a subslice of s.
func trimSpace(s []byte) []byte {
j := len(s)
for j > 0 && (s[j-1] == ' ' || s[j-1] == '\t' || s[j-1] == '\n') {
j--
}
i := 0
for i < j && (s[i] == ' ' || s[i] == '\t') {
i++
}
return s[i:j]
}
// pcrel and pcrelw match instructions using relative addressing mode.
var (
pcrel = regexp.MustCompile(`^((?:.* )?(?:j[a-z]+|call|ljmp|loopn?e?w?|xbegin)q?(?:,p[nt])?) 0x([0-9a-f]+)$`)
pcrelw = regexp.MustCompile(`^((?:.* )?(?:callw|jmpw|xbeginw|ljmpw)(?:,p[nt])?) 0x([0-9a-f]+)$`)
)
// Generators.
//
// The test cases are described as functions that invoke a callback repeatedly,
// with a new input sequence each time. These helpers make writing those
// a little easier.
// hexCases generates the cases written in hexadecimal in the encoded string.
// Spaces in 'encoded' separate entire test cases, not individual bytes.
func hexCases(t *testing.T, encoded string) func(func([]byte)) {
return func(try func([]byte)) {
for _, x := range strings.Fields(encoded) {
src, err := hex.DecodeString(x)
if err != nil {
t.Errorf("parsing %q: %v", x, err)
}
try(src)
}
}
}
// testdataCases generates the test cases recorded in testdata/decode.txt.
// It only uses the inputs; it ignores the answers recorded in that file.
func testdataCases(t *testing.T) func(func([]byte)) {
var codes [][]byte
data, err := ioutil.ReadFile("testdata/decode.txt")
if err != nil {
t.Fatal(err)
}
for _, line := range strings.Split(string(data), "\n") {
line = strings.TrimSpace(line)
if line == "" || strings.HasPrefix(line, "#") {
continue
}
f := strings.Fields(line)[0]
i := strings.Index(f, "|")
if i < 0 {
t.Errorf("parsing %q: missing | separator", f)
continue
}
if i%2 != 0 {
t.Errorf("parsing %q: misaligned | separator", f)
}
code, err := hex.DecodeString(f[:i] + f[i+1:])
if err != nil {
t.Errorf("parsing %q: %v", f, err)
continue
}
codes = append(codes, code)
}
return func(try func([]byte)) {
for _, code := range codes {
try(code)
}
}
}
// manyPrefixes generates all possible 2⁹ combinations of nine chosen prefixes.
// The relative ordering of the prefixes within the combinations varies deterministically.
func manyPrefixes(try func([]byte)) {
var prefixBytes = []byte{0x66, 0x67, 0xF0, 0xF2, 0xF3, 0x3E, 0x36, 0x66, 0x67}
var enc []byte
for i := 0; i < 1<<uint(len(prefixBytes)); i++ {
enc = enc[:0]
for j, p := range prefixBytes {
if i&(1<<uint(j)) != 0 {
enc = append(enc, p)
}
}
if len(enc) > 0 {
k := i % len(enc)
enc[0], enc[k] = enc[k], enc[0]
}
try(enc)
}
}
// basicPrefixes geneartes 8 different possible prefix cases: no prefix
// and then one each of seven different prefix bytes.
func basicPrefixes(try func([]byte)) {
try(nil)
for _, b := range []byte{0x66, 0x67, 0xF0, 0xF2, 0xF3, 0x3E, 0x36} {
try([]byte{b})
}
}
func rexPrefixes(try func([]byte)) {
try(nil)
for _, b := range []byte{0x40, 0x48, 0x43, 0x4C} {
try([]byte{b})
}
}
// concat takes two generators and returns a generator for the
// cross product of the two, concatenating the results from each.
func concat(gen1, gen2 func(func([]byte))) func(func([]byte)) {
return func(try func([]byte)) {
gen1(func(enc1 []byte) {
gen2(func(enc2 []byte) {
try(append(enc1[:len(enc1):len(enc1)], enc2...))
})
})
}
}
// concat3 takes three generators and returns a generator for the
// cross product of the three, concatenating the results from each.
func concat3(gen1, gen2, gen3 func(func([]byte))) func(func([]byte)) {
return func(try func([]byte)) {
gen1(func(enc1 []byte) {
gen2(func(enc2 []byte) {
gen3(func(enc3 []byte) {
try(append(append(enc1[:len(enc1):len(enc1)], enc2...), enc3...))
})
})
})
}
}
// concat4 takes four generators and returns a generator for the
// cross product of the four, concatenating the results from each.
func concat4(gen1, gen2, gen3, gen4 func(func([]byte))) func(func([]byte)) {
return func(try func([]byte)) {
gen1(func(enc1 []byte) {
gen2(func(enc2 []byte) {
gen3(func(enc3 []byte) {
gen4(func(enc4 []byte) {
try(append(append(append(enc1[:len(enc1):len(enc1)], enc2...), enc3...), enc4...))
})
})
})
})
}
}
// filter generates the sequences from gen that satisfy ok.
func filter(gen func(func([]byte)), ok func([]byte) bool) func(func([]byte)) {
return func(try func([]byte)) {
gen(func(enc []byte) {
if ok(enc) {
try(enc)
}
})
}
}
// enum8bit generates all possible 1-byte sequences, followed by distinctive padding.
func enum8bit(try func([]byte)) {
for i := 0; i < 1<<8; i++ {
try([]byte{byte(i), 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88})
}
}
// enum8bit generates all possible 2-byte sequences, followed by distinctive padding.
func enum16bit(try func([]byte)) {
for i := 0; i < 1<<16; i++ {
try([]byte{byte(i), byte(i >> 8), 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88})
}
}
// enum24bit generates all possible 3-byte sequences, followed by distinctive padding.
func enum24bit(try func([]byte)) {
for i := 0; i < 1<<24; i++ {
try([]byte{byte(i), byte(i >> 8), byte(i >> 16), 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88})
}
}
// enumModRM generates all possible modrm bytes and, for modrm values that indicate
// a following sib byte, all possible modrm, sib combinations.
func enumModRM(try func([]byte)) {
for i := 0; i < 256; i++ {
if (i>>3)&07 == 04 && i>>6 != 3 { // has sib
for j := 0; j < 256; j++ {
try([]byte{0, byte(i), byte(j), 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}) // byte encodings
try([]byte{1, byte(i), byte(j), 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}) // word encodings
}
} else {
try([]byte{0, byte(i), 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}) // byte encodings
try([]byte{1, byte(i), 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}) // word encodings
}
}
}
// fixed generates the single case b.
// It's mainly useful to prepare an argument for concat or concat3.
func fixed(b ...byte) func(func([]byte)) {
return func(try func([]byte)) {
try(b)
}
}
// testBasic runs the given test function with cases all using opcode as the initial opcode bytes.
// It runs three phases:
//
// First, zero-or-one prefixes followed by opcode followed by all possible 1-byte values.
// If in -short mode, that's all.
//
// Second, zero-or-one prefixes followed by opcode followed by all possible 2-byte values.
// If not in -long mode, that's all. This phase and the next run in parallel with other tests
// (using t.Parallel).
//
// Finally, opcode followed by all possible 3-byte values. The test can take a very long time
// and prints progress messages to package log.
func testBasic(t *testing.T, testfn func(*testing.T, func(func([]byte))), opcode ...byte) {
testfn(t, concat3(basicPrefixes, fixed(opcode...), enum8bit))
if testing.Short() {
return
}
t.Parallel()
testfn(t, concat3(basicPrefixes, fixed(opcode...), enum16bit))
if !*longTest {
return
}
name := caller(2)
op1 := make([]byte, len(opcode)+1)
copy(op1, opcode)
for i := 0; i < 256; i++ {
log.Printf("%s 24-bit: %d/256\n", name, i)
op1[len(opcode)] = byte(i)
testfn(t, concat(fixed(op1...), enum16bit))
}
}
func testBasicREX(t *testing.T, testfn func(*testing.T, func(func([]byte))), opcode ...byte) {
testfn(t, filter(concat4(basicPrefixes, rexPrefixes, fixed(opcode...), enum8bit), isValidREX))
if testing.Short() {
return
}
t.Parallel()
testfn(t, filter(concat4(basicPrefixes, rexPrefixes, fixed(opcode...), enum16bit), isValidREX))
if !*longTest {
return
}
name := caller(2)
op1 := make([]byte, len(opcode)+1)
copy(op1, opcode)
for i := 0; i < 256; i++ {
log.Printf("%s 24-bit: %d/256\n", name, i)
op1[len(opcode)] = byte(i)
testfn(t, filter(concat3(rexPrefixes, fixed(op1...), enum16bit), isValidREX))
}
}
// testPrefix runs the given test function for all many prefix possibilities
// followed by all possible 1-byte sequences.
//
// If in -long mode, it then runs a test of all the prefix possibilities followed
// by all possible 2-byte sequences.
func testPrefix(t *testing.T, testfn func(*testing.T, func(func([]byte)))) {
t.Parallel()
testfn(t, concat(manyPrefixes, enum8bit))
if testing.Short() || !*longTest {
return
}
name := caller(2)
for i := 0; i < 256; i++ {
log.Printf("%s 16-bit: %d/256\n", name, i)
testfn(t, concat3(manyPrefixes, fixed(byte(i)), enum8bit))
}
}
func testPrefixREX(t *testing.T, testfn func(*testing.T, func(func([]byte)))) {
t.Parallel()
testfn(t, filter(concat3(manyPrefixes, rexPrefixes, enum8bit), isValidREX))
if testing.Short() || !*longTest {
return
}
name := caller(2)
for i := 0; i < 256; i++ {
log.Printf("%s 16-bit: %d/256\n", name, i)
testfn(t, filter(concat4(manyPrefixes, rexPrefixes, fixed(byte(i)), enum8bit), isValidREX))
}
}
func caller(skip int) string {
pc, _, _, _ := runtime.Caller(skip)
f := runtime.FuncForPC(pc)
name := "?"
if f != nil {
name = f.Name()
if i := strings.LastIndex(name, "."); i >= 0 {
name = name[i+1:]
}
}
return name
}
func isValidREX(x []byte) bool {
i := 0
for i < len(x) && isPrefixByte(x[i]) {
i++
}
if i < len(x) && Prefix(x[i]).IsREX() {
i++
if i < len(x) {
return !isPrefixByte(x[i]) && !Prefix(x[i]).IsREX()
}
}
return true
}
func isPrefixByte(b byte) bool {
switch b {
case 0x26, 0x2E, 0x36, 0x3E, 0x64, 0x65, 0x66, 0x67, 0xF0, 0xF2, 0xF3:
return true
}
return false
}

928
vendor/golang.org/x/arch/x86/x86asm/gnu.go generated vendored Normal file
View File

@ -0,0 +1,928 @@
// Copyright 2014 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 x86asm
import (
"fmt"
"strings"
)
// GNUSyntax returns the GNU assembler syntax for the instruction, as defined by GNU binutils.
// This general form is often called ``AT&T syntax'' as a reference to AT&T System V Unix.
func GNUSyntax(inst Inst) string {
// Rewrite instruction to mimic GNU peculiarities.
// Note that inst has been passed by value and contains
// no pointers, so any changes we make here are local
// and will not propagate back out to the caller.
// Adjust opcode [sic].
switch inst.Op {
case FDIV, FDIVR, FSUB, FSUBR, FDIVP, FDIVRP, FSUBP, FSUBRP:
// DC E0, DC F0: libopcodes swaps FSUBR/FSUB and FDIVR/FDIV, at least
// if you believe the Intel manual is correct (the encoding is irregular as given;
// libopcodes uses the more regular expected encoding).
// TODO(rsc): Test to ensure Intel manuals are correct and report to libopcodes maintainers?
// NOTE: iant thinks this is deliberate, but we can't find the history.
_, reg1 := inst.Args[0].(Reg)
_, reg2 := inst.Args[1].(Reg)
if reg1 && reg2 && (inst.Opcode>>24 == 0xDC || inst.Opcode>>24 == 0xDE) {
switch inst.Op {
case FDIV:
inst.Op = FDIVR
case FDIVR:
inst.Op = FDIV
case FSUB:
inst.Op = FSUBR
case FSUBR:
inst.Op = FSUB
case FDIVP:
inst.Op = FDIVRP
case FDIVRP:
inst.Op = FDIVP
case FSUBP:
inst.Op = FSUBRP
case FSUBRP:
inst.Op = FSUBP
}
}
case MOVNTSD:
// MOVNTSD is F2 0F 2B /r.
// MOVNTSS is F3 0F 2B /r (supposedly; not in manuals).
// Usually inner prefixes win for display,
// so that F3 F2 0F 2B 11 is REP MOVNTSD
// and F2 F3 0F 2B 11 is REPN MOVNTSS.
// Libopcodes always prefers MOVNTSS regardless of prefix order.
if countPrefix(&inst, 0xF3) > 0 {
found := false
for i := len(inst.Prefix) - 1; i >= 0; i-- {
switch inst.Prefix[i] & 0xFF {
case 0xF3:
if !found {
found = true
inst.Prefix[i] |= PrefixImplicit
}
case 0xF2:
inst.Prefix[i] &^= PrefixImplicit
}
}
inst.Op = MOVNTSS
}
}
// Add implicit arguments.
switch inst.Op {
case MONITOR:
inst.Args[0] = EDX
inst.Args[1] = ECX
inst.Args[2] = EAX
if inst.AddrSize == 16 {
inst.Args[2] = AX
}
case MWAIT:
if inst.Mode == 64 {
inst.Args[0] = RCX
inst.Args[1] = RAX
} else {
inst.Args[0] = ECX
inst.Args[1] = EAX
}
}
// Adjust which prefixes will be displayed.
// The rule is to display all the prefixes not implied by
// the usual instruction display, that is, all the prefixes
// except the ones with PrefixImplicit set.
// However, of course, there are exceptions to the rule.
switch inst.Op {
case CRC32:
// CRC32 has a mandatory F2 prefix.
// If there are multiple F2s and no F3s, the extra F2s do not print.
// (And Decode has already marked them implicit.)
// However, if there is an F3 anywhere, then the extra F2s do print.
// If there are multiple F2 prefixes *and* an (ignored) F3,
// then libopcodes prints the extra F2s as REPNs.
if countPrefix(&inst, 0xF2) > 1 {
unmarkImplicit(&inst, 0xF2)
markLastImplicit(&inst, 0xF2)
}
// An unused data size override should probably be shown,
// to distinguish DATA16 CRC32B from plain CRC32B,
// but libopcodes always treats the final override as implicit
// and the others as explicit.
unmarkImplicit(&inst, PrefixDataSize)
markLastImplicit(&inst, PrefixDataSize)
case CVTSI2SD, CVTSI2SS:
if !isMem(inst.Args[1]) {
markLastImplicit(&inst, PrefixDataSize)
}
case CVTSD2SI, CVTSS2SI, CVTTSD2SI, CVTTSS2SI,
ENTER, FLDENV, FNSAVE, FNSTENV, FRSTOR, LGDT, LIDT, LRET,
POP, PUSH, RET, SGDT, SIDT, SYSRET, XBEGIN:
markLastImplicit(&inst, PrefixDataSize)
case LOOP, LOOPE, LOOPNE, MONITOR:
markLastImplicit(&inst, PrefixAddrSize)
case MOV:
// The 16-bit and 32-bit forms of MOV Sreg, dst and MOV src, Sreg
// cannot be distinguished when src or dst refers to memory, because
// Sreg is always a 16-bit value, even when we're doing a 32-bit
// instruction. Because the instruction tables distinguished these two,
// any operand size prefix has been marked as used (to decide which
// branch to take). Unmark it, so that it will show up in disassembly,
// so that the reader can tell the size of memory operand.
// up with the same arguments
dst, _ := inst.Args[0].(Reg)
src, _ := inst.Args[1].(Reg)
if ES <= src && src <= GS && isMem(inst.Args[0]) || ES <= dst && dst <= GS && isMem(inst.Args[1]) {
unmarkImplicit(&inst, PrefixDataSize)
}
case MOVDQU:
if countPrefix(&inst, 0xF3) > 1 {
unmarkImplicit(&inst, 0xF3)
markLastImplicit(&inst, 0xF3)
}
case MOVQ2DQ:
markLastImplicit(&inst, PrefixDataSize)
case SLDT, SMSW, STR, FXRSTOR, XRSTOR, XSAVE, XSAVEOPT, CMPXCHG8B:
if isMem(inst.Args[0]) {
unmarkImplicit(&inst, PrefixDataSize)
}
case SYSEXIT:
unmarkImplicit(&inst, PrefixDataSize)
}
if isCondJmp[inst.Op] || isLoop[inst.Op] || inst.Op == JCXZ || inst.Op == JECXZ || inst.Op == JRCXZ {
if countPrefix(&inst, PrefixCS) > 0 && countPrefix(&inst, PrefixDS) > 0 {
for i, p := range inst.Prefix {
switch p & 0xFFF {
case PrefixPN, PrefixPT:
inst.Prefix[i] &= 0xF0FF // cut interpretation bits, producing original segment prefix
}
}
}
}
// XACQUIRE/XRELEASE adjustment.
if inst.Op == MOV {
// MOV into memory is a candidate for turning REP into XRELEASE.
// However, if the REP is followed by a REPN, that REPN blocks the
// conversion.
haveREPN := false
for i := len(inst.Prefix) - 1; i >= 0; i-- {
switch inst.Prefix[i] &^ PrefixIgnored {
case PrefixREPN:
haveREPN = true
case PrefixXRELEASE:
if haveREPN {
inst.Prefix[i] = PrefixREP
}
}
}
}
// We only format the final F2/F3 as XRELEASE/XACQUIRE.
haveXA := false
haveXR := false
for i := len(inst.Prefix) - 1; i >= 0; i-- {
switch inst.Prefix[i] &^ PrefixIgnored {
case PrefixXRELEASE:
if !haveXR {
haveXR = true
} else {
inst.Prefix[i] = PrefixREP
}
case PrefixXACQUIRE:
if !haveXA {
haveXA = true
} else {
inst.Prefix[i] = PrefixREPN
}
}
}
// Determine opcode.
op := strings.ToLower(inst.Op.String())
if alt := gnuOp[inst.Op]; alt != "" {
op = alt
}
// Determine opcode suffix.
// Libopcodes omits the suffix if the width of the operation
// can be inferred from a register arguments. For example,
// add $1, %ebx has no suffix because you can tell from the
// 32-bit register destination that it is a 32-bit add,
// but in addl $1, (%ebx), the destination is memory, so the
// size is not evident without the l suffix.
needSuffix := true
SuffixLoop:
for i, a := range inst.Args {
if a == nil {
break
}
switch a := a.(type) {
case Reg:
switch inst.Op {
case MOVSX, MOVZX:
continue
case SHL, SHR, RCL, RCR, ROL, ROR, SAR:
if i == 1 {
// shift count does not tell us operand size
continue
}
case CRC32:
// The source argument does tell us operand size,
// but libopcodes still always puts a suffix on crc32.
continue
case PUSH, POP:
// Even though segment registers are 16-bit, push and pop
// can save/restore them from 32-bit slots, so they
// do not imply operand size.
if ES <= a && a <= GS {
continue
}
case CVTSI2SD, CVTSI2SS:
// The integer register argument takes priority.
if X0 <= a && a <= X15 {
continue
}
}
if AL <= a && a <= R15 || ES <= a && a <= GS || X0 <= a && a <= X15 || M0 <= a && a <= M7 {
needSuffix = false
break SuffixLoop
}
}
}
if needSuffix {
switch inst.Op {
case CMPXCHG8B, FLDCW, FNSTCW, FNSTSW, LDMXCSR, LLDT, LMSW, LTR, PCLMULQDQ,
SETA, SETAE, SETB, SETBE, SETE, SETG, SETGE, SETL, SETLE, SETNE, SETNO, SETNP, SETNS, SETO, SETP, SETS,
SLDT, SMSW, STMXCSR, STR, VERR, VERW:
// For various reasons, libopcodes emits no suffix for these instructions.
case CRC32:
op += byteSizeSuffix(argBytes(&inst, inst.Args[1]))
case LGDT, LIDT, SGDT, SIDT:
op += byteSizeSuffix(inst.DataSize / 8)
case MOVZX, MOVSX:
// Integer size conversions get two suffixes.
op = op[:4] + byteSizeSuffix(argBytes(&inst, inst.Args[1])) + byteSizeSuffix(argBytes(&inst, inst.Args[0]))
case LOOP, LOOPE, LOOPNE:
// Add w suffix to indicate use of CX register instead of ECX.
if inst.AddrSize == 16 {
op += "w"
}
case CALL, ENTER, JMP, LCALL, LEAVE, LJMP, LRET, RET, SYSRET, XBEGIN:
// Add w suffix to indicate use of 16-bit target.
// Exclude JMP rel8.
if inst.Opcode>>24 == 0xEB {
break
}
if inst.DataSize == 16 && inst.Mode != 16 {
markLastImplicit(&inst, PrefixDataSize)
op += "w"
} else if inst.Mode == 64 {
op += "q"
}
case FRSTOR, FNSAVE, FNSTENV, FLDENV:
// Add s suffix to indicate shortened FPU state (I guess).
if inst.DataSize == 16 {
op += "s"
}
case PUSH, POP:
if markLastImplicit(&inst, PrefixDataSize) {
op += byteSizeSuffix(inst.DataSize / 8)
} else if inst.Mode == 64 {
op += "q"
} else {
op += byteSizeSuffix(inst.MemBytes)
}
default:
if isFloat(inst.Op) {
// I can't explain any of this, but it's what libopcodes does.
switch inst.MemBytes {
default:
if (inst.Op == FLD || inst.Op == FSTP) && isMem(inst.Args[0]) {
op += "t"
}
case 4:
if isFloatInt(inst.Op) {
op += "l"
} else {
op += "s"
}
case 8:
if isFloatInt(inst.Op) {
op += "ll"
} else {
op += "l"
}
}
break
}
op += byteSizeSuffix(inst.MemBytes)
}
}
// Adjust special case opcodes.
switch inst.Op {
case 0:
if inst.Prefix[0] != 0 {
return strings.ToLower(inst.Prefix[0].String())
}
case INT:
if inst.Opcode>>24 == 0xCC {
inst.Args[0] = nil
op = "int3"
}
case CMPPS, CMPPD, CMPSD_XMM, CMPSS:
imm, ok := inst.Args[2].(Imm)
if ok && 0 <= imm && imm < 8 {
inst.Args[2] = nil
op = cmppsOps[imm] + op[3:]
}
case PCLMULQDQ:
imm, ok := inst.Args[2].(Imm)
if ok && imm&^0x11 == 0 {
inst.Args[2] = nil
op = pclmulqOps[(imm&0x10)>>3|(imm&1)]
}
case XLATB:
if markLastImplicit(&inst, PrefixAddrSize) {
op = "xlat" // not xlatb
}
}
// Build list of argument strings.
var (
usedPrefixes bool // segment prefixes consumed by Mem formatting
args []string // formatted arguments
)
for i, a := range inst.Args {
if a == nil {
break
}
switch inst.Op {
case MOVSB, MOVSW, MOVSD, MOVSQ, OUTSB, OUTSW, OUTSD:
if i == 0 {
usedPrefixes = true // disable use of prefixes for first argument
} else {
usedPrefixes = false
}
}
if a == Imm(1) && (inst.Opcode>>24)&^1 == 0xD0 {
continue
}
args = append(args, gnuArg(&inst, a, &usedPrefixes))
}
// The default is to print the arguments in reverse Intel order.
// A few instructions inhibit this behavior.
switch inst.Op {
case BOUND, LCALL, ENTER, LJMP:
// no reverse
default:
// reverse args
for i, j := 0, len(args)-1; i < j; i, j = i+1, j-1 {
args[i], args[j] = args[j], args[i]
}
}
// Build prefix string.
// Must be after argument formatting, which can turn off segment prefixes.
var (
prefix = "" // output string
numAddr = 0
numData = 0
implicitData = false
)
for _, p := range inst.Prefix {
if p&0xFF == PrefixDataSize && p&PrefixImplicit != 0 {
implicitData = true
}
}
for _, p := range inst.Prefix {
if p == 0 || p.IsVEX() {
break
}
if p&PrefixImplicit != 0 {
continue
}
switch p &^ (PrefixIgnored | PrefixInvalid) {
default:
if p.IsREX() {
if p&0xFF == PrefixREX {
prefix += "rex "
} else {
prefix += "rex." + p.String()[4:] + " "
}
break
}
prefix += strings.ToLower(p.String()) + " "
case PrefixPN:
op += ",pn"
continue
case PrefixPT:
op += ",pt"
continue
case PrefixAddrSize, PrefixAddr16, PrefixAddr32:
// For unknown reasons, if the addr16 prefix is repeated,
// libopcodes displays all but the last as addr32, even though
// the addressing form used in a memory reference is clearly
// still 16-bit.
n := 32
if inst.Mode == 32 {
n = 16
}
numAddr++
if countPrefix(&inst, PrefixAddrSize) > numAddr {
n = inst.Mode
}
prefix += fmt.Sprintf("addr%d ", n)
continue
case PrefixData16, PrefixData32:
if implicitData && countPrefix(&inst, PrefixDataSize) > 1 {
// Similar to the addr32 logic above, but it only kicks in
// when something used the data size prefix (one is implicit).
n := 16
if inst.Mode == 16 {
n = 32
}
numData++
if countPrefix(&inst, PrefixDataSize) > numData {
if inst.Mode == 16 {
n = 16
} else {
n = 32
}
}
prefix += fmt.Sprintf("data%d ", n)
continue
}
prefix += strings.ToLower(p.String()) + " "
}
}
// Finally! Put it all together.
text := prefix + op
if args != nil {
text += " "
// Indirect call/jmp gets a star to distinguish from direct jump address.
if (inst.Op == CALL || inst.Op == JMP || inst.Op == LJMP || inst.Op == LCALL) && (isMem(inst.Args[0]) || isReg(inst.Args[0])) {
text += "*"
}
text += strings.Join(args, ",")
}
return text
}
// gnuArg returns the GNU syntax for the argument x from the instruction inst.
// If *usedPrefixes is false and x is a Mem, then the formatting
// includes any segment prefixes and sets *usedPrefixes to true.
func gnuArg(inst *Inst, x Arg, usedPrefixes *bool) string {
if x == nil {
return "<nil>"
}
switch x := x.(type) {
case Reg:
switch inst.Op {
case CVTSI2SS, CVTSI2SD, CVTSS2SI, CVTSD2SI, CVTTSD2SI, CVTTSS2SI:
if inst.DataSize == 16 && EAX <= x && x <= R15L {
x -= EAX - AX
}
case IN, INSB, INSW, INSD, OUT, OUTSB, OUTSW, OUTSD:
// DX is the port, but libopcodes prints it as if it were a memory reference.
if x == DX {
return "(%dx)"
}
case VMOVDQA, VMOVDQU, VMOVNTDQA, VMOVNTDQ:
return strings.Replace(gccRegName[x], "xmm", "ymm", -1)
}
return gccRegName[x]
case Mem:
seg := ""
var haveCS, haveDS, haveES, haveFS, haveGS, haveSS bool
switch x.Segment {
case CS:
haveCS = true
case DS:
haveDS = true
case ES:
haveES = true
case FS:
haveFS = true
case GS:
haveGS = true
case SS:
haveSS = true
}
switch inst.Op {
case INSB, INSW, INSD, STOSB, STOSW, STOSD, STOSQ, SCASB, SCASW, SCASD, SCASQ:
// These do not accept segment prefixes, at least in the GNU rendering.
default:
if *usedPrefixes {
break
}
for i := len(inst.Prefix) - 1; i >= 0; i-- {
p := inst.Prefix[i] &^ PrefixIgnored
if p == 0 {
continue
}
switch p {
case PrefixCS:
if !haveCS {
haveCS = true
inst.Prefix[i] |= PrefixImplicit
}
case PrefixDS:
if !haveDS {
haveDS = true
inst.Prefix[i] |= PrefixImplicit
}
case PrefixES:
if !haveES {
haveES = true
inst.Prefix[i] |= PrefixImplicit
}
case PrefixFS:
if !haveFS {
haveFS = true
inst.Prefix[i] |= PrefixImplicit
}
case PrefixGS:
if !haveGS {
haveGS = true
inst.Prefix[i] |= PrefixImplicit
}
case PrefixSS:
if !haveSS {
haveSS = true
inst.Prefix[i] |= PrefixImplicit
}
}
}
*usedPrefixes = true
}
if haveCS {
seg += "%cs:"
}
if haveDS {
seg += "%ds:"
}
if haveSS {
seg += "%ss:"
}
if haveES {
seg += "%es:"
}
if haveFS {
seg += "%fs:"
}
if haveGS {
seg += "%gs:"
}
disp := ""
if x.Disp != 0 {
disp = fmt.Sprintf("%#x", x.Disp)
}
if x.Scale == 0 || x.Index == 0 && x.Scale == 1 && (x.Base == ESP || x.Base == RSP || x.Base == 0 && inst.Mode == 64) {
if x.Base == 0 {
return seg + disp
}
return fmt.Sprintf("%s%s(%s)", seg, disp, gccRegName[x.Base])
}
base := gccRegName[x.Base]
if x.Base == 0 {
base = ""
}
index := gccRegName[x.Index]
if x.Index == 0 {
if inst.AddrSize == 64 {
index = "%riz"
} else {
index = "%eiz"
}
}
if AX <= x.Base && x.Base <= DI {
// 16-bit addressing - no scale
return fmt.Sprintf("%s%s(%s,%s)", seg, disp, base, index)
}
return fmt.Sprintf("%s%s(%s,%s,%d)", seg, disp, base, index, x.Scale)
case Rel:
return fmt.Sprintf(".%+#x", int32(x))
case Imm:
if inst.Mode == 32 {
return fmt.Sprintf("$%#x", uint32(x))
}
return fmt.Sprintf("$%#x", int64(x))
}
return x.String()
}
var gccRegName = [...]string{
0: "REG0",
AL: "%al",
CL: "%cl",
BL: "%bl",
DL: "%dl",
AH: "%ah",
CH: "%ch",
BH: "%bh",
DH: "%dh",
SPB: "%spl",
BPB: "%bpl",
SIB: "%sil",
DIB: "%dil",
R8B: "%r8b",
R9B: "%r9b",
R10B: "%r10b",
R11B: "%r11b",
R12B: "%r12b",
R13B: "%r13b",
R14B: "%r14b",
R15B: "%r15b",
AX: "%ax",
CX: "%cx",
BX: "%bx",
DX: "%dx",
SP: "%sp",
BP: "%bp",
SI: "%si",
DI: "%di",
R8W: "%r8w",
R9W: "%r9w",
R10W: "%r10w",
R11W: "%r11w",
R12W: "%r12w",
R13W: "%r13w",
R14W: "%r14w",
R15W: "%r15w",
EAX: "%eax",
ECX: "%ecx",
EDX: "%edx",
EBX: "%ebx",
ESP: "%esp",
EBP: "%ebp",
ESI: "%esi",
EDI: "%edi",
R8L: "%r8d",
R9L: "%r9d",
R10L: "%r10d",
R11L: "%r11d",
R12L: "%r12d",
R13L: "%r13d",
R14L: "%r14d",
R15L: "%r15d",
RAX: "%rax",
RCX: "%rcx",
RDX: "%rdx",
RBX: "%rbx",
RSP: "%rsp",
RBP: "%rbp",
RSI: "%rsi",
RDI: "%rdi",
R8: "%r8",
R9: "%r9",
R10: "%r10",
R11: "%r11",
R12: "%r12",
R13: "%r13",
R14: "%r14",
R15: "%r15",
IP: "%ip",
EIP: "%eip",
RIP: "%rip",
F0: "%st",
F1: "%st(1)",
F2: "%st(2)",
F3: "%st(3)",
F4: "%st(4)",
F5: "%st(5)",
F6: "%st(6)",
F7: "%st(7)",
M0: "%mm0",
M1: "%mm1",
M2: "%mm2",
M3: "%mm3",
M4: "%mm4",
M5: "%mm5",
M6: "%mm6",
M7: "%mm7",
X0: "%xmm0",
X1: "%xmm1",
X2: "%xmm2",
X3: "%xmm3",
X4: "%xmm4",
X5: "%xmm5",
X6: "%xmm6",
X7: "%xmm7",
X8: "%xmm8",
X9: "%xmm9",
X10: "%xmm10",
X11: "%xmm11",
X12: "%xmm12",
X13: "%xmm13",
X14: "%xmm14",
X15: "%xmm15",
CS: "%cs",
SS: "%ss",
DS: "%ds",
ES: "%es",
FS: "%fs",
GS: "%gs",
GDTR: "%gdtr",
IDTR: "%idtr",
LDTR: "%ldtr",
MSW: "%msw",
TASK: "%task",
CR0: "%cr0",
CR1: "%cr1",
CR2: "%cr2",
CR3: "%cr3",
CR4: "%cr4",
CR5: "%cr5",
CR6: "%cr6",
CR7: "%cr7",
CR8: "%cr8",
CR9: "%cr9",
CR10: "%cr10",
CR11: "%cr11",
CR12: "%cr12",
CR13: "%cr13",
CR14: "%cr14",
CR15: "%cr15",
DR0: "%db0",
DR1: "%db1",
DR2: "%db2",
DR3: "%db3",
DR4: "%db4",
DR5: "%db5",
DR6: "%db6",
DR7: "%db7",
TR0: "%tr0",
TR1: "%tr1",
TR2: "%tr2",
TR3: "%tr3",
TR4: "%tr4",
TR5: "%tr5",
TR6: "%tr6",
TR7: "%tr7",
}
var gnuOp = map[Op]string{
CBW: "cbtw",
CDQ: "cltd",
CMPSD: "cmpsl",
CMPSD_XMM: "cmpsd",
CWD: "cwtd",
CWDE: "cwtl",
CQO: "cqto",
INSD: "insl",
IRET: "iretw",
IRETD: "iret",
IRETQ: "iretq",
LODSB: "lods",
LODSD: "lods",
LODSQ: "lods",
LODSW: "lods",
MOVSD: "movsl",
MOVSD_XMM: "movsd",
OUTSD: "outsl",
POPA: "popaw",
POPAD: "popa",
POPF: "popfw",
POPFD: "popf",
PUSHA: "pushaw",
PUSHAD: "pusha",
PUSHF: "pushfw",
PUSHFD: "pushf",
SCASB: "scas",
SCASD: "scas",
SCASQ: "scas",
SCASW: "scas",
STOSB: "stos",
STOSD: "stos",
STOSQ: "stos",
STOSW: "stos",
XLATB: "xlat",
}
var cmppsOps = []string{
"cmpeq",
"cmplt",
"cmple",
"cmpunord",
"cmpneq",
"cmpnlt",
"cmpnle",
"cmpord",
}
var pclmulqOps = []string{
"pclmullqlqdq",
"pclmulhqlqdq",
"pclmullqhqdq",
"pclmulhqhqdq",
}
func countPrefix(inst *Inst, target Prefix) int {
n := 0
for _, p := range inst.Prefix {
if p&0xFF == target&0xFF {
n++
}
}
return n
}
func markLastImplicit(inst *Inst, prefix Prefix) bool {
for i := len(inst.Prefix) - 1; i >= 0; i-- {
p := inst.Prefix[i]
if p&0xFF == prefix {
inst.Prefix[i] |= PrefixImplicit
return true
}
}
return false
}
func unmarkImplicit(inst *Inst, prefix Prefix) {
for i := len(inst.Prefix) - 1; i >= 0; i-- {
p := inst.Prefix[i]
if p&0xFF == prefix {
inst.Prefix[i] &^= PrefixImplicit
}
}
}
func byteSizeSuffix(b int) string {
switch b {
case 1:
return "b"
case 2:
return "w"
case 4:
return "l"
case 8:
return "q"
}
return ""
}
func argBytes(inst *Inst, arg Arg) int {
if isMem(arg) {
return inst.MemBytes
}
return regBytes(arg)
}
func isFloat(op Op) bool {
switch op {
case FADD, FCOM, FCOMP, FDIV, FDIVR, FIADD, FICOM, FICOMP, FIDIV, FIDIVR, FILD, FIMUL, FIST, FISTP, FISTTP, FISUB, FISUBR, FLD, FMUL, FST, FSTP, FSUB, FSUBR:
return true
}
return false
}
func isFloatInt(op Op) bool {
switch op {
case FIADD, FICOM, FICOMP, FIDIV, FIDIVR, FILD, FIMUL, FIST, FISTP, FISTTP, FISUB, FISUBR:
return true
}
return false
}

649
vendor/golang.org/x/arch/x86/x86asm/inst.go generated vendored Normal file
View File

@ -0,0 +1,649 @@
// Copyright 2014 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 x86asm implements decoding of x86 machine code.
package x86asm
import (
"bytes"
"fmt"
)
// An Inst is a single instruction.
type Inst struct {
Prefix Prefixes // Prefixes applied to the instruction.
Op Op // Opcode mnemonic
Opcode uint32 // Encoded opcode bits, left aligned (first byte is Opcode>>24, etc)
Args Args // Instruction arguments, in Intel order
Mode int // processor mode in bits: 16, 32, or 64
AddrSize int // address size in bits: 16, 32, or 64
DataSize int // operand size in bits: 16, 32, or 64
MemBytes int // size of memory argument in bytes: 1, 2, 4, 8, 16, and so on.
Len int // length of encoded instruction in bytes
PCRel int // length of PC-relative address in instruction encoding
PCRelOff int // index of start of PC-relative address in instruction encoding
}
// Prefixes is an array of prefixes associated with a single instruction.
// The prefixes are listed in the same order as found in the instruction:
// each prefix byte corresponds to one slot in the array. The first zero
// in the array marks the end of the prefixes.
type Prefixes [14]Prefix
// A Prefix represents an Intel instruction prefix.
// The low 8 bits are the actual prefix byte encoding,
// and the top 8 bits contain distinguishing bits and metadata.
type Prefix uint16
const (
// Metadata about the role of a prefix in an instruction.
PrefixImplicit Prefix = 0x8000 // prefix is implied by instruction text
PrefixIgnored Prefix = 0x4000 // prefix is ignored: either irrelevant or overridden by a later prefix
PrefixInvalid Prefix = 0x2000 // prefix makes entire instruction invalid (bad LOCK)
// Memory segment overrides.
PrefixES Prefix = 0x26 // ES segment override
PrefixCS Prefix = 0x2E // CS segment override
PrefixSS Prefix = 0x36 // SS segment override
PrefixDS Prefix = 0x3E // DS segment override
PrefixFS Prefix = 0x64 // FS segment override
PrefixGS Prefix = 0x65 // GS segment override
// Branch prediction.
PrefixPN Prefix = 0x12E // predict not taken (conditional branch only)
PrefixPT Prefix = 0x13E // predict taken (conditional branch only)
// Size attributes.
PrefixDataSize Prefix = 0x66 // operand size override
PrefixData16 Prefix = 0x166
PrefixData32 Prefix = 0x266
PrefixAddrSize Prefix = 0x67 // address size override
PrefixAddr16 Prefix = 0x167
PrefixAddr32 Prefix = 0x267
// One of a kind.
PrefixLOCK Prefix = 0xF0 // lock
PrefixREPN Prefix = 0xF2 // repeat not zero
PrefixXACQUIRE Prefix = 0x1F2
PrefixBND Prefix = 0x2F2
PrefixREP Prefix = 0xF3 // repeat
PrefixXRELEASE Prefix = 0x1F3
// The REX prefixes must be in the range [PrefixREX, PrefixREX+0x10).
// the other bits are set or not according to the intended use.
PrefixREX Prefix = 0x40 // REX 64-bit extension prefix
PrefixREXW Prefix = 0x08 // extension bit W (64-bit instruction width)
PrefixREXR Prefix = 0x04 // extension bit R (r field in modrm)
PrefixREXX Prefix = 0x02 // extension bit X (index field in sib)
PrefixREXB Prefix = 0x01 // extension bit B (r/m field in modrm or base field in sib)
PrefixVEX2Bytes Prefix = 0xC5 // Short form of vex prefix
PrefixVEX3Bytes Prefix = 0xC4 // Long form of vex prefix
)
// IsREX reports whether p is a REX prefix byte.
func (p Prefix) IsREX() bool {
return p&0xF0 == PrefixREX
}
func (p Prefix) IsVEX() bool {
return p&0xFF == PrefixVEX2Bytes || p&0xFF == PrefixVEX3Bytes
}
func (p Prefix) String() string {
p &^= PrefixImplicit | PrefixIgnored | PrefixInvalid
if s := prefixNames[p]; s != "" {
return s
}
if p.IsREX() {
s := "REX."
if p&PrefixREXW != 0 {
s += "W"
}
if p&PrefixREXR != 0 {
s += "R"
}
if p&PrefixREXX != 0 {
s += "X"
}
if p&PrefixREXB != 0 {
s += "B"
}
return s
}
return fmt.Sprintf("Prefix(%#x)", int(p))
}
// An Op is an x86 opcode.
type Op uint32
func (op Op) String() string {
i := int(op)
if i < 0 || i >= len(opNames) || opNames[i] == "" {
return fmt.Sprintf("Op(%d)", i)
}
return opNames[i]
}
// An Args holds the instruction arguments.
// If an instruction has fewer than 4 arguments,
// the final elements in the array are nil.
type Args [4]Arg
// An Arg is a single instruction argument,
// one of these types: Reg, Mem, Imm, Rel.
type Arg interface {
String() string
isArg()
}
// Note that the implements of Arg that follow are all sized
// so that on a 64-bit machine the data can be inlined in
// the interface value instead of requiring an allocation.
// A Reg is a single register.
// The zero Reg value has no name but indicates ``no register.''
type Reg uint8
const (
_ Reg = iota
// 8-bit
AL
CL
DL
BL
AH
CH
DH
BH
SPB
BPB
SIB
DIB
R8B
R9B
R10B
R11B
R12B
R13B
R14B
R15B
// 16-bit
AX
CX
DX
BX
SP
BP
SI
DI
R8W
R9W
R10W
R11W
R12W
R13W
R14W
R15W
// 32-bit
EAX
ECX
EDX
EBX
ESP
EBP
ESI
EDI
R8L
R9L
R10L
R11L
R12L
R13L
R14L
R15L
// 64-bit
RAX
RCX
RDX
RBX
RSP
RBP
RSI
RDI
R8
R9
R10
R11
R12
R13
R14
R15
// Instruction pointer.
IP // 16-bit
EIP // 32-bit
RIP // 64-bit
// 387 floating point registers.
F0
F1
F2
F3
F4
F5
F6
F7
// MMX registers.
M0
M1
M2
M3
M4
M5
M6
M7
// XMM registers.
X0
X1
X2
X3
X4
X5
X6
X7
X8
X9
X10
X11
X12
X13
X14
X15
// Segment registers.
ES
CS
SS
DS
FS
GS
// System registers.
GDTR
IDTR
LDTR
MSW
TASK
// Control registers.
CR0
CR1
CR2
CR3
CR4
CR5
CR6
CR7
CR8
CR9
CR10
CR11
CR12
CR13
CR14
CR15
// Debug registers.
DR0
DR1
DR2
DR3
DR4
DR5
DR6
DR7
DR8
DR9
DR10
DR11
DR12
DR13
DR14
DR15
// Task registers.
TR0
TR1
TR2
TR3
TR4
TR5
TR6
TR7
)
const regMax = TR7
func (Reg) isArg() {}
func (r Reg) String() string {
i := int(r)
if i < 0 || i >= len(regNames) || regNames[i] == "" {
return fmt.Sprintf("Reg(%d)", i)
}
return regNames[i]
}
// A Mem is a memory reference.
// The general form is Segment:[Base+Scale*Index+Disp].
type Mem struct {
Segment Reg
Base Reg
Scale uint8
Index Reg
Disp int64
}
func (Mem) isArg() {}
func (m Mem) String() string {
var base, plus, scale, index, disp string
if m.Base != 0 {
base = m.Base.String()
}
if m.Scale != 0 {
if m.Base != 0 {
plus = "+"
}
if m.Scale > 1 {
scale = fmt.Sprintf("%d*", m.Scale)
}
index = m.Index.String()
}
if m.Disp != 0 || m.Base == 0 && m.Scale == 0 {
disp = fmt.Sprintf("%+#x", m.Disp)
}
return "[" + base + plus + scale + index + disp + "]"
}
// A Rel is an offset relative to the current instruction pointer.
type Rel int32
func (Rel) isArg() {}
func (r Rel) String() string {
return fmt.Sprintf(".%+d", r)
}
// An Imm is an integer constant.
type Imm int64
func (Imm) isArg() {}
func (i Imm) String() string {
return fmt.Sprintf("%#x", int64(i))
}
func (i Inst) String() string {
var buf bytes.Buffer
for _, p := range i.Prefix {
if p == 0 {
break
}
if p&PrefixImplicit != 0 {
continue
}
fmt.Fprintf(&buf, "%v ", p)
}
fmt.Fprintf(&buf, "%v", i.Op)
sep := " "
for _, v := range i.Args {
if v == nil {
break
}
fmt.Fprintf(&buf, "%s%v", sep, v)
sep = ", "
}
return buf.String()
}
func isReg(a Arg) bool {
_, ok := a.(Reg)
return ok
}
func isSegReg(a Arg) bool {
r, ok := a.(Reg)
return ok && ES <= r && r <= GS
}
func isMem(a Arg) bool {
_, ok := a.(Mem)
return ok
}
func isImm(a Arg) bool {
_, ok := a.(Imm)
return ok
}
func regBytes(a Arg) int {
r, ok := a.(Reg)
if !ok {
return 0
}
if AL <= r && r <= R15B {
return 1
}
if AX <= r && r <= R15W {
return 2
}
if EAX <= r && r <= R15L {
return 4
}
if RAX <= r && r <= R15 {
return 8
}
return 0
}
func isSegment(p Prefix) bool {
switch p {
case PrefixCS, PrefixDS, PrefixES, PrefixFS, PrefixGS, PrefixSS:
return true
}
return false
}
// The Op definitions and string list are in tables.go.
var prefixNames = map[Prefix]string{
PrefixCS: "CS",
PrefixDS: "DS",
PrefixES: "ES",
PrefixFS: "FS",
PrefixGS: "GS",
PrefixSS: "SS",
PrefixLOCK: "LOCK",
PrefixREP: "REP",
PrefixREPN: "REPN",
PrefixAddrSize: "ADDRSIZE",
PrefixDataSize: "DATASIZE",
PrefixAddr16: "ADDR16",
PrefixData16: "DATA16",
PrefixAddr32: "ADDR32",
PrefixData32: "DATA32",
PrefixBND: "BND",
PrefixXACQUIRE: "XACQUIRE",
PrefixXRELEASE: "XRELEASE",
PrefixREX: "REX",
PrefixPT: "PT",
PrefixPN: "PN",
}
var regNames = [...]string{
AL: "AL",
CL: "CL",
BL: "BL",
DL: "DL",
AH: "AH",
CH: "CH",
BH: "BH",
DH: "DH",
SPB: "SPB",
BPB: "BPB",
SIB: "SIB",
DIB: "DIB",
R8B: "R8B",
R9B: "R9B",
R10B: "R10B",
R11B: "R11B",
R12B: "R12B",
R13B: "R13B",
R14B: "R14B",
R15B: "R15B",
AX: "AX",
CX: "CX",
BX: "BX",
DX: "DX",
SP: "SP",
BP: "BP",
SI: "SI",
DI: "DI",
R8W: "R8W",
R9W: "R9W",
R10W: "R10W",
R11W: "R11W",
R12W: "R12W",
R13W: "R13W",
R14W: "R14W",
R15W: "R15W",
EAX: "EAX",
ECX: "ECX",
EDX: "EDX",
EBX: "EBX",
ESP: "ESP",
EBP: "EBP",
ESI: "ESI",
EDI: "EDI",
R8L: "R8L",
R9L: "R9L",
R10L: "R10L",
R11L: "R11L",
R12L: "R12L",
R13L: "R13L",
R14L: "R14L",
R15L: "R15L",
RAX: "RAX",
RCX: "RCX",
RDX: "RDX",
RBX: "RBX",
RSP: "RSP",
RBP: "RBP",
RSI: "RSI",
RDI: "RDI",
R8: "R8",
R9: "R9",
R10: "R10",
R11: "R11",
R12: "R12",
R13: "R13",
R14: "R14",
R15: "R15",
IP: "IP",
EIP: "EIP",
RIP: "RIP",
F0: "F0",
F1: "F1",
F2: "F2",
F3: "F3",
F4: "F4",
F5: "F5",
F6: "F6",
F7: "F7",
M0: "M0",
M1: "M1",
M2: "M2",
M3: "M3",
M4: "M4",
M5: "M5",
M6: "M6",
M7: "M7",
X0: "X0",
X1: "X1",
X2: "X2",
X3: "X3",
X4: "X4",
X5: "X5",
X6: "X6",
X7: "X7",
X8: "X8",
X9: "X9",
X10: "X10",
X11: "X11",
X12: "X12",
X13: "X13",
X14: "X14",
X15: "X15",
CS: "CS",
SS: "SS",
DS: "DS",
ES: "ES",
FS: "FS",
GS: "GS",
GDTR: "GDTR",
IDTR: "IDTR",
LDTR: "LDTR",
MSW: "MSW",
TASK: "TASK",
CR0: "CR0",
CR1: "CR1",
CR2: "CR2",
CR3: "CR3",
CR4: "CR4",
CR5: "CR5",
CR6: "CR6",
CR7: "CR7",
CR8: "CR8",
CR9: "CR9",
CR10: "CR10",
CR11: "CR11",
CR12: "CR12",
CR13: "CR13",
CR14: "CR14",
CR15: "CR15",
DR0: "DR0",
DR1: "DR1",
DR2: "DR2",
DR3: "DR3",
DR4: "DR4",
DR5: "DR5",
DR6: "DR6",
DR7: "DR7",
DR8: "DR8",
DR9: "DR9",
DR10: "DR10",
DR11: "DR11",
DR12: "DR12",
DR13: "DR13",
DR14: "DR14",
DR15: "DR15",
TR0: "TR0",
TR1: "TR1",
TR2: "TR2",
TR3: "TR3",
TR4: "TR4",
TR5: "TR5",
TR6: "TR6",
TR7: "TR7",
}

20
vendor/golang.org/x/arch/x86/x86asm/inst_test.go generated vendored Normal file
View File

@ -0,0 +1,20 @@
// Copyright 2014 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 x86asm
import (
"strings"
"testing"
)
func TestRegString(t *testing.T) {
for r := Reg(1); r <= regMax; r++ {
if regNames[r] == "" {
t.Errorf("regNames[%d] is missing", int(r))
} else if s := r.String(); strings.Contains(s, "Reg(") {
t.Errorf("Reg(%d).String() = %s, want proper name", int(r), s)
}
}
}

532
vendor/golang.org/x/arch/x86/x86asm/intel.go generated vendored Normal file
View File

@ -0,0 +1,532 @@
// Copyright 2014 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 x86asm
import (
"fmt"
"strings"
)
// IntelSyntax returns the Intel assembler syntax for the instruction, as defined by Intel's XED tool.
func IntelSyntax(inst Inst) string {
var iargs []Arg
for _, a := range inst.Args {
if a == nil {
break
}
iargs = append(iargs, a)
}
switch inst.Op {
case INSB, INSD, INSW, OUTSB, OUTSD, OUTSW, LOOPNE, JCXZ, JECXZ, JRCXZ, LOOP, LOOPE, MOV, XLATB:
if inst.Op == MOV && (inst.Opcode>>16)&0xFFFC != 0x0F20 {
break
}
for i, p := range inst.Prefix {
if p&0xFF == PrefixAddrSize {
inst.Prefix[i] &^= PrefixImplicit
}
}
}
switch inst.Op {
case MOV:
dst, _ := inst.Args[0].(Reg)
src, _ := inst.Args[1].(Reg)
if ES <= dst && dst <= GS && EAX <= src && src <= R15L {
src -= EAX - AX
iargs[1] = src
}
if ES <= dst && dst <= GS && RAX <= src && src <= R15 {
src -= RAX - AX
iargs[1] = src
}
if inst.Opcode>>24&^3 == 0xA0 {
for i, p := range inst.Prefix {
if p&0xFF == PrefixAddrSize {
inst.Prefix[i] |= PrefixImplicit
}
}
}
}
switch inst.Op {
case AAM, AAD:
if imm, ok := iargs[0].(Imm); ok {
if inst.DataSize == 32 {
iargs[0] = Imm(uint32(int8(imm)))
} else if inst.DataSize == 16 {
iargs[0] = Imm(uint16(int8(imm)))
}
}
case PUSH:
if imm, ok := iargs[0].(Imm); ok {
iargs[0] = Imm(uint32(imm))
}
}
for _, p := range inst.Prefix {
if p&PrefixImplicit != 0 {
for j, pj := range inst.Prefix {
if pj&0xFF == p&0xFF {
inst.Prefix[j] |= PrefixImplicit
}
}
}
}
if inst.Op != 0 {
for i, p := range inst.Prefix {
switch p &^ PrefixIgnored {
case PrefixData16, PrefixData32, PrefixCS, PrefixDS, PrefixES, PrefixSS:
inst.Prefix[i] |= PrefixImplicit
}
if p.IsREX() {
inst.Prefix[i] |= PrefixImplicit
}
if p.IsVEX() {
if p == PrefixVEX3Bytes {
inst.Prefix[i+2] |= PrefixImplicit
}
inst.Prefix[i] |= PrefixImplicit
inst.Prefix[i+1] |= PrefixImplicit
}
}
}
if isLoop[inst.Op] || inst.Op == JCXZ || inst.Op == JECXZ || inst.Op == JRCXZ {
for i, p := range inst.Prefix {
if p == PrefixPT || p == PrefixPN {
inst.Prefix[i] |= PrefixImplicit
}
}
}
switch inst.Op {
case AAA, AAS, CBW, CDQE, CLC, CLD, CLI, CLTS, CMC, CPUID, CQO, CWD, DAA, DAS,
FDECSTP, FINCSTP, FNCLEX, FNINIT, FNOP, FWAIT, HLT,
ICEBP, INSB, INSD, INSW, INT, INTO, INVD, IRET, IRETQ,
LAHF, LEAVE, LRET, MONITOR, MWAIT, NOP, OUTSB, OUTSD, OUTSW,
PAUSE, POPA, POPF, POPFQ, PUSHA, PUSHF, PUSHFQ,
RDMSR, RDPMC, RDTSC, RDTSCP, RET, RSM,
SAHF, STC, STD, STI, SYSENTER, SYSEXIT, SYSRET,
UD2, WBINVD, WRMSR, XEND, XLATB, XTEST:
if inst.Op == NOP && inst.Opcode>>24 != 0x90 {
break
}
if inst.Op == RET && inst.Opcode>>24 != 0xC3 {
break
}
if inst.Op == INT && inst.Opcode>>24 != 0xCC {
break
}
if inst.Op == LRET && inst.Opcode>>24 != 0xcb {
break
}
for i, p := range inst.Prefix {
if p&0xFF == PrefixDataSize {
inst.Prefix[i] &^= PrefixImplicit | PrefixIgnored
}
}
case 0:
// ok
}
switch inst.Op {
case INSB, INSD, INSW, OUTSB, OUTSD, OUTSW, MONITOR, MWAIT, XLATB:
iargs = nil
case STOSB, STOSW, STOSD, STOSQ:
iargs = iargs[:1]
case LODSB, LODSW, LODSD, LODSQ, SCASB, SCASW, SCASD, SCASQ:
iargs = iargs[1:]
}
const (
haveData16 = 1 << iota
haveData32
haveAddr16
haveAddr32
haveXacquire
haveXrelease
haveLock
haveHintTaken
haveHintNotTaken
haveBnd
)
var prefixBits uint32
prefix := ""
for _, p := range inst.Prefix {
if p == 0 {
break
}
if p&0xFF == 0xF3 {
prefixBits &^= haveBnd
}
if p&(PrefixImplicit|PrefixIgnored) != 0 {
continue
}
switch p {
default:
prefix += strings.ToLower(p.String()) + " "
case PrefixCS, PrefixDS, PrefixES, PrefixFS, PrefixGS, PrefixSS:
if inst.Op == 0 {
prefix += strings.ToLower(p.String()) + " "
}
case PrefixREPN:
prefix += "repne "
case PrefixLOCK:
prefixBits |= haveLock
case PrefixData16, PrefixDataSize:
prefixBits |= haveData16
case PrefixData32:
prefixBits |= haveData32
case PrefixAddrSize, PrefixAddr16:
prefixBits |= haveAddr16
case PrefixAddr32:
prefixBits |= haveAddr32
case PrefixXACQUIRE:
prefixBits |= haveXacquire
case PrefixXRELEASE:
prefixBits |= haveXrelease
case PrefixPT:
prefixBits |= haveHintTaken
case PrefixPN:
prefixBits |= haveHintNotTaken
case PrefixBND:
prefixBits |= haveBnd
}
}
switch inst.Op {
case JMP:
if inst.Opcode>>24 == 0xEB {
prefixBits &^= haveBnd
}
case RET, LRET:
prefixBits &^= haveData16 | haveData32
}
if prefixBits&haveXacquire != 0 {
prefix += "xacquire "
}
if prefixBits&haveXrelease != 0 {
prefix += "xrelease "
}
if prefixBits&haveLock != 0 {
prefix += "lock "
}
if prefixBits&haveBnd != 0 {
prefix += "bnd "
}
if prefixBits&haveHintTaken != 0 {
prefix += "hint-taken "
}
if prefixBits&haveHintNotTaken != 0 {
prefix += "hint-not-taken "
}
if prefixBits&haveAddr16 != 0 {
prefix += "addr16 "
}
if prefixBits&haveAddr32 != 0 {
prefix += "addr32 "
}
if prefixBits&haveData16 != 0 {
prefix += "data16 "
}
if prefixBits&haveData32 != 0 {
prefix += "data32 "
}
if inst.Op == 0 {
if prefix == "" {
return "<no instruction>"
}
return prefix[:len(prefix)-1]
}
var args []string
for _, a := range iargs {
if a == nil {
break
}
args = append(args, intelArg(&inst, a))
}
var op string
switch inst.Op {
case NOP:
if inst.Opcode>>24 == 0x0F {
if inst.DataSize == 16 {
args = append(args, "ax")
} else {
args = append(args, "eax")
}
}
case BLENDVPD, BLENDVPS, PBLENDVB:
args = args[:2]
case INT:
if inst.Opcode>>24 == 0xCC {
args = nil
op = "int3"
}
case LCALL, LJMP:
if len(args) == 2 {
args[0], args[1] = args[1], args[0]
}
case FCHS, FABS, FTST, FLDPI, FLDL2E, FLDLG2, F2XM1, FXAM, FLD1, FLDL2T, FSQRT, FRNDINT, FCOS, FSIN:
if len(args) == 0 {
args = append(args, "st0")
}
case FPTAN, FSINCOS, FUCOMPP, FCOMPP, FYL2X, FPATAN, FXTRACT, FPREM1, FPREM, FYL2XP1, FSCALE:
if len(args) == 0 {
args = []string{"st0", "st1"}
}
case FST, FSTP, FISTTP, FIST, FISTP, FBSTP:
if len(args) == 1 {
args = append(args, "st0")
}
case FLD, FXCH, FCOM, FCOMP, FIADD, FIMUL, FICOM, FICOMP, FISUBR, FIDIV, FUCOM, FUCOMP, FILD, FBLD, FADD, FMUL, FSUB, FSUBR, FISUB, FDIV, FDIVR, FIDIVR:
if len(args) == 1 {
args = []string{"st0", args[0]}
}
case MASKMOVDQU, MASKMOVQ, XLATB, OUTSB, OUTSW, OUTSD:
FixSegment:
for i := len(inst.Prefix) - 1; i >= 0; i-- {
p := inst.Prefix[i] & 0xFF
switch p {
case PrefixCS, PrefixES, PrefixFS, PrefixGS, PrefixSS:
if inst.Mode != 64 || p == PrefixFS || p == PrefixGS {
args = append(args, strings.ToLower((inst.Prefix[i] & 0xFF).String()))
break FixSegment
}
case PrefixDS:
if inst.Mode != 64 {
break FixSegment
}
}
}
}
if op == "" {
op = intelOp[inst.Op]
}
if op == "" {
op = strings.ToLower(inst.Op.String())
}
if args != nil {
op += " " + strings.Join(args, ", ")
}
return prefix + op
}
func intelArg(inst *Inst, arg Arg) string {
switch a := arg.(type) {
case Imm:
if inst.Mode == 32 {
return fmt.Sprintf("%#x", uint32(a))
}
if Imm(int32(a)) == a {
return fmt.Sprintf("%#x", int64(a))
}
return fmt.Sprintf("%#x", uint64(a))
case Mem:
if a.Base == EIP {
a.Base = RIP
}
prefix := ""
switch inst.MemBytes {
case 1:
prefix = "byte "
case 2:
prefix = "word "
case 4:
prefix = "dword "
case 8:
prefix = "qword "
case 16:
prefix = "xmmword "
case 32:
prefix = "ymmword "
}
switch inst.Op {
case INVLPG:
prefix = "byte "
case STOSB, MOVSB, CMPSB, LODSB, SCASB:
prefix = "byte "
case STOSW, MOVSW, CMPSW, LODSW, SCASW:
prefix = "word "
case STOSD, MOVSD, CMPSD, LODSD, SCASD:
prefix = "dword "
case STOSQ, MOVSQ, CMPSQ, LODSQ, SCASQ:
prefix = "qword "
case LAR:
prefix = "word "
case BOUND:
if inst.Mode == 32 {
prefix = "qword "
} else {
prefix = "dword "
}
case PREFETCHW, PREFETCHNTA, PREFETCHT0, PREFETCHT1, PREFETCHT2, CLFLUSH:
prefix = "zmmword "
}
switch inst.Op {
case MOVSB, MOVSW, MOVSD, MOVSQ, CMPSB, CMPSW, CMPSD, CMPSQ, STOSB, STOSW, STOSD, STOSQ, SCASB, SCASW, SCASD, SCASQ, LODSB, LODSW, LODSD, LODSQ:
switch a.Base {
case DI, EDI, RDI:
if a.Segment == ES {
a.Segment = 0
}
case SI, ESI, RSI:
if a.Segment == DS {
a.Segment = 0
}
}
case LEA:
a.Segment = 0
default:
switch a.Base {
case SP, ESP, RSP, BP, EBP, RBP:
if a.Segment == SS {
a.Segment = 0
}
default:
if a.Segment == DS {
a.Segment = 0
}
}
}
if inst.Mode == 64 && a.Segment != FS && a.Segment != GS {
a.Segment = 0
}
prefix += "ptr "
if a.Segment != 0 {
prefix += strings.ToLower(a.Segment.String()) + ":"
}
prefix += "["
if a.Base != 0 {
prefix += intelArg(inst, a.Base)
}
if a.Scale != 0 && a.Index != 0 {
if a.Base != 0 {
prefix += "+"
}
prefix += fmt.Sprintf("%s*%d", intelArg(inst, a.Index), a.Scale)
}
if a.Disp != 0 {
if prefix[len(prefix)-1] == '[' && (a.Disp >= 0 || int64(int32(a.Disp)) != a.Disp) {
prefix += fmt.Sprintf("%#x", uint64(a.Disp))
} else {
prefix += fmt.Sprintf("%+#x", a.Disp)
}
}
prefix += "]"
return prefix
case Rel:
return fmt.Sprintf(".%+#x", int64(a))
case Reg:
if int(a) < len(intelReg) && intelReg[a] != "" {
switch inst.Op {
case VMOVDQA, VMOVDQU, VMOVNTDQA, VMOVNTDQ:
return strings.Replace(intelReg[a], "xmm", "ymm", -1)
default:
return intelReg[a]
}
}
}
return strings.ToLower(arg.String())
}
var intelOp = map[Op]string{
JAE: "jnb",
JA: "jnbe",
JGE: "jnl",
JNE: "jnz",
JG: "jnle",
JE: "jz",
SETAE: "setnb",
SETA: "setnbe",
SETGE: "setnl",
SETNE: "setnz",
SETG: "setnle",
SETE: "setz",
CMOVAE: "cmovnb",
CMOVA: "cmovnbe",
CMOVGE: "cmovnl",
CMOVNE: "cmovnz",
CMOVG: "cmovnle",
CMOVE: "cmovz",
LCALL: "call far",
LJMP: "jmp far",
LRET: "ret far",
ICEBP: "int1",
MOVSD_XMM: "movsd",
XLATB: "xlat",
}
var intelReg = [...]string{
F0: "st0",
F1: "st1",
F2: "st2",
F3: "st3",
F4: "st4",
F5: "st5",
F6: "st6",
F7: "st7",
M0: "mmx0",
M1: "mmx1",
M2: "mmx2",
M3: "mmx3",
M4: "mmx4",
M5: "mmx5",
M6: "mmx6",
M7: "mmx7",
X0: "xmm0",
X1: "xmm1",
X2: "xmm2",
X3: "xmm3",
X4: "xmm4",
X5: "xmm5",
X6: "xmm6",
X7: "xmm7",
X8: "xmm8",
X9: "xmm9",
X10: "xmm10",
X11: "xmm11",
X12: "xmm12",
X13: "xmm13",
X14: "xmm14",
X15: "xmm15",
// TODO: Maybe the constants are named wrong.
SPB: "spl",
BPB: "bpl",
SIB: "sil",
DIB: "dil",
R8L: "r8d",
R9L: "r9d",
R10L: "r10d",
R11L: "r11d",
R12L: "r12d",
R13L: "r13d",
R14L: "r14d",
R15L: "r15d",
}

385
vendor/golang.org/x/arch/x86/x86asm/objdump_test.go generated vendored Normal file
View File

@ -0,0 +1,385 @@
// Copyright 2014 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 x86asm
import (
"bytes"
"strings"
"testing"
)
func TestObjdump32Manual(t *testing.T) { testObjdump32(t, hexCases(t, objdumpManualTests)) }
func TestObjdump32Testdata(t *testing.T) { testObjdump32(t, concat(basicPrefixes, testdataCases(t))) }
func TestObjdump32ModRM(t *testing.T) { testObjdump32(t, concat(basicPrefixes, enumModRM)) }
func TestObjdump32OneByte(t *testing.T) { testBasic(t, testObjdump32) }
func TestObjdump320F(t *testing.T) { testBasic(t, testObjdump32, 0x0F) }
func TestObjdump320F38(t *testing.T) { testBasic(t, testObjdump32, 0x0F, 0x38) }
func TestObjdump320F3A(t *testing.T) { testBasic(t, testObjdump32, 0x0F, 0x3A) }
func TestObjdump32Prefix(t *testing.T) { testPrefix(t, testObjdump32) }
func TestObjdump64Manual(t *testing.T) { testObjdump64(t, hexCases(t, objdumpManualTests)) }
func TestObjdump64Testdata(t *testing.T) { testObjdump64(t, concat(basicPrefixes, testdataCases(t))) }
func TestObjdump64ModRM(t *testing.T) { testObjdump64(t, concat(basicPrefixes, enumModRM)) }
func TestObjdump64OneByte(t *testing.T) { testBasic(t, testObjdump64) }
func TestObjdump640F(t *testing.T) { testBasic(t, testObjdump64, 0x0F) }
func TestObjdump640F38(t *testing.T) { testBasic(t, testObjdump64, 0x0F, 0x38) }
func TestObjdump640F3A(t *testing.T) { testBasic(t, testObjdump64, 0x0F, 0x3A) }
func TestObjdump64Prefix(t *testing.T) { testPrefix(t, testObjdump64) }
func TestObjdump64REXTestdata(t *testing.T) {
testObjdump64(t, filter(concat3(basicPrefixes, rexPrefixes, testdataCases(t)), isValidREX))
}
func TestObjdump64REXModRM(t *testing.T) {
testObjdump64(t, concat3(basicPrefixes, rexPrefixes, enumModRM))
}
func TestObjdump64REXOneByte(t *testing.T) { testBasicREX(t, testObjdump64) }
func TestObjdump64REX0F(t *testing.T) { testBasicREX(t, testObjdump64, 0x0F) }
func TestObjdump64REX0F38(t *testing.T) { testBasicREX(t, testObjdump64, 0x0F, 0x38) }
func TestObjdump64REX0F3A(t *testing.T) { testBasicREX(t, testObjdump64, 0x0F, 0x3A) }
func TestObjdump64REXPrefix(t *testing.T) { testPrefixREX(t, testObjdump64) }
// objdumpManualTests holds test cases that will be run by TestObjdumpManual.
// If you are debugging a few cases that turned up in a longer run, it can be useful
// to list them here and then use -run=ObjdumpManual, particularly with tracing enabled.
var objdumpManualTests = `
4883FE017413
488DFC2500000000
488D3D00000000
`
// allowedMismatchObjdump reports whether the mismatch between text and dec
// should be allowed by the test.
func allowedMismatchObjdump(text string, size int, inst *Inst, dec ExtInst) bool {
if size == 15 && dec.nenc == 15 && contains(text, "truncated") && contains(dec.text, "(bad)") {
return true
}
if i := strings.LastIndex(dec.text, " "); isPrefix(dec.text[i+1:]) && size == 1 && isPrefix(text) {
return true
}
if size == dec.nenc && contains(dec.text, "movupd") && contains(dec.text, "data32") {
s := strings.Replace(dec.text, "data32 ", "", -1)
if text == s {
return true
}
}
// Simplify our invalid instruction text.
if text == "error: unrecognized instruction" {
text = "BAD"
}
// Invalid instructions for which libopcodes prints %? register.
// FF E8 11 22 33 44:
// Invalid instructions for which libopcodes prints "internal disassembler error".
// Invalid instructions for which libopcodes prints 8087 only (e.g., DB E0)
// or prints 287 only (e.g., DB E4).
if contains(dec.text, "%?", "<internal disassembler error>", "(8087 only)", "(287 only)") {
dec.text = "(bad)"
}
// 0F 19 11, 0F 1C 11, 0F 1D 11, 0F 1E 11, 0F 1F 11: libopcodes says nop,
// but the Intel manuals say that the only NOP there is 0F 1F /0.
// Perhaps libopcodes is reporting an older encoding.
i := bytes.IndexByte(dec.enc[:], 0x0F)
if contains(dec.text, "nop") && i >= 0 && i+2 < len(dec.enc) && dec.enc[i+1]&^7 == 0x18 && (dec.enc[i+1] != 0x1F || (dec.enc[i+2]>>3)&7 != 0) {
dec.text = "(bad)"
}
// Any invalid instruction.
if text == "BAD" && contains(dec.text, "(bad)") {
return true
}
// Instructions libopcodes knows but we do not (e.g., 0F 19 11).
if (text == "BAD" || size == 1 && isPrefix(text)) && hasPrefix(dec.text, unsupported...) {
return true
}
// Instructions we know but libopcodes does not (e.g., 0F D0 11).
if (contains(dec.text, "(bad)") || dec.nenc == 1 && isPrefix(dec.text)) && hasPrefix(text, libopcodesUnsupported...) {
return true
}
// Libopcodes rejects F2 90 as NOP. Not sure why.
if (contains(dec.text, "(bad)") || dec.nenc == 1 && isPrefix(dec.text)) && inst.Opcode>>24 == 0x90 && countPrefix(inst, 0xF2) > 0 {
return true
}
// 0F 20 11, 0F 21 11, 0F 22 11, 0F 23 11, 0F 24 11:
// Moves into and out of some control registers seem to be unsupported by libopcodes.
// TODO(rsc): Are they invalid somehow?
if (contains(dec.text, "(bad)") || dec.nenc == 1 && isPrefix(dec.text)) && contains(text, "%cr", "%db", "%tr") {
return true
}
if contains(dec.text, "fwait") && dec.nenc == 1 && dec.enc[0] != 0x9B {
return true
}
// 9B D9 11: libopcodes reports FSTSW instead of FWAIT + FNSTSW.
// This is correct in that FSTSW is a pseudo-op for the pair, but it really
// is a pair of instructions: execution can stop between them.
// Our decoder chooses to separate them.
if (text == "fwait" || strings.HasSuffix(text, " fwait")) && dec.nenc >= len(strings.Fields(text)) && dec.enc[len(strings.Fields(text))-1] == 0x9B {
return true
}
// 0F 18 77 11:
// Invalid instructions for which libopcodes prints "nop/reserved".
// Perhaps libopcodes is reporting an older encoding.
if text == "BAD" && contains(dec.text, "nop/reserved") {
return true
}
// 0F C7 B0 11 22 33 44: libopcodes says vmptrld 0x44332211(%eax); we say rdrand %eax.
// TODO(rsc): Fix, since we are probably wrong, but we don't have vmptrld in the manual.
if contains(text, "rdrand") && contains(dec.text, "vmptrld", "vmxon", "vmclear") {
return true
}
// DD C8: libopcodes says FNOP but the Intel manual is clear FNOP is only D9 D0.
// Perhaps libopcodes is reporting an older encoding.
if text == "BAD" && contains(dec.text, "fnop") && (dec.enc[0] != 0xD9 || dec.enc[1] != 0xD0) {
return true
}
// 66 90: libopcodes says xchg %ax,%ax; we say 'data16 nop'.
// The 16-bit swap will preserve the high bits of the register,
// so they are the same.
if contains(text, "nop") && contains(dec.text, "xchg %ax,%ax") {
return true
}
// If there are multiple prefixes, allow libopcodes to use an alternate name.
if size == 1 && dec.nenc == 1 && prefixByte[text] > 0 && prefixByte[text] == prefixByte[dec.text] {
return true
}
// 26 9B: libopcodes reports "fwait"/1, ignoring segment prefix.
// https://sourceware.org/bugzilla/show_bug.cgi?id=16891
// F0 82: Decode="lock"/1 but libopcodes="lock (bad)"/2.
if size == 1 && dec.nenc >= 1 && prefixByte[text] == dec.enc[0] && contains(dec.text, "(bad)", "fwait", "fnop") {
return true
}
// libopcodes interprets 660f801122 as taking a rel16 but
// truncating the address at 16 bits. Not sure what is correct.
if contains(text, ".+0x2211", ".+0x11") && contains(dec.text, " .-") {
return true
}
// 66 F3 0F D6 C5, 66 F2 0F D6 C0: libopcodes reports use of XMM register instead of MMX register,
// but only when the instruction has a 66 prefix. Maybe they know something we don't.
if countPrefix(inst, 0x66) > 0 && contains(dec.text, "movdq2q", "movq2dq") && !contains(dec.text, "%mm") {
return true
}
// 0F 01 F8, 0F 05, 0F 07: these are 64-bit instructions but libopcodes accepts them.
if (text == "BAD" || size == 1 && isPrefix(text)) && contains(dec.text, "swapgs", "syscall", "sysret", "rdfsbase", "rdgsbase", "wrfsbase", "wrgsbase") {
return true
}
return false
}
// Instructions known to libopcodes (or xed) but not to us.
// Most of these come from supplementary manuals of one form or another.
var unsupported = strings.Fields(`
bndc
bndl
bndm
bnds
clac
clgi
femms
fldln
fldz
getsec
invlpga
kmov
montmul
pavg
pf2i
pfacc
pfadd
pfcmp
pfmax
pfmin
pfmul
pfna
pfpnac
pfrc
pfrs
pfsub
phadd
phsub
pi2f
pmulhr
prefetch
pswap
ptest
rdseed
sha1
sha256
skinit
stac
stgi
vadd
vand
vcmp
vcomis
vcvt
vcvt
vdiv
vhadd
vhsub
vld
vmax
vmcall
vmfunc
vmin
vmlaunch
vmload
vmmcall
vmov
vmov
vmov
vmptrld
vmptrst
vmread
vmresume
vmrun
vmsave
vmul
vmwrite
vmxoff
vor
vpack
vpadd
vpand
vpavg
vpcmp
vpcmp
vpins
vpmadd
vpmax
vpmin
vpmul
vpmul
vpor
vpsad
vpshuf
vpsll
vpsra
vpsrad
vpsrl
vpsub
vpunp
vpxor
vrcp
vrsqrt
vshuf
vsqrt
vsub
vucomis
vunp
vxor
vzero
xcrypt
xsha1
xsha256
xstore-rng
insertq
extrq
vmclear
invvpid
adox
vmxon
invept
adcx
vmclear
prefetchwt1
enclu
encls
salc
fstpnce
fdisi8087_nop
fsetpm287_nop
feni8087_nop
syscall
sysret
`)
// Instructions known to us but not to libopcodes (at least in binutils 2.24).
var libopcodesUnsupported = strings.Fields(`
addsubps
aes
blend
cvttpd2dq
dpp
extract
haddps
hsubps
insert
invpcid
lddqu
movmsk
movnt
movq2dq
mps
pack
pblend
pclmul
pcmp
pext
phmin
pins
pmax
pmin
pmov
pmovmsk
pmul
popcnt
pslld
psllq
psllw
psrad
psraw
psrl
ptest
punpck
round
xrstor
xsavec
xsaves
comis
ucomis
movhps
movntps
rsqrt
rcpp
puncpck
bsf
movq2dq
cvttpd2dq
movq
hsubpd
movdqa
movhpd
addsubpd
movd
haddpd
cvtps2dq
bsr
cvtdq2ps
rdrand
maskmov
movq2dq
movlhps
movbe
movlpd
`)

313
vendor/golang.org/x/arch/x86/x86asm/objdumpext_test.go generated vendored Normal file
View File

@ -0,0 +1,313 @@
// Copyright 2014 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 x86asm
import (
"bytes"
"debug/elf"
"encoding/binary"
"fmt"
"io"
"log"
"os"
"strconv"
"strings"
"testing"
)
// Apologies for the proprietary path, but we need objdump 2.24 + some committed patches that will land in 2.25.
const objdumpPath = "/Users/rsc/bin/objdump2"
func testObjdump32(t *testing.T, generate func(func([]byte))) {
testObjdumpArch(t, generate, 32)
}
func testObjdump64(t *testing.T, generate func(func([]byte))) {
testObjdumpArch(t, generate, 64)
}
func testObjdumpArch(t *testing.T, generate func(func([]byte)), arch int) {
if testing.Short() {
t.Skip("skipping objdump test in short mode")
}
if _, err := os.Stat(objdumpPath); err != nil {
t.Skip(err)
}
testExtDis(t, "gnu", arch, objdump, generate, allowedMismatchObjdump)
}
func objdump(ext *ExtDis) error {
// File already written with instructions; add ELF header.
if ext.Arch == 32 {
if err := writeELF32(ext.File, ext.Size); err != nil {
return err
}
} else {
if err := writeELF64(ext.File, ext.Size); err != nil {
return err
}
}
b, err := ext.Run(objdumpPath, "-d", "-z", ext.File.Name())
if err != nil {
return err
}
var (
nmatch int
reading bool
next uint32 = start
addr uint32
encbuf [32]byte
enc []byte
text string
)
flush := func() {
if addr == next {
switch text {
case "repz":
text = "rep"
case "repnz":
text = "repn"
default:
text = strings.Replace(text, "repz ", "rep ", -1)
text = strings.Replace(text, "repnz ", "repn ", -1)
}
if m := pcrelw.FindStringSubmatch(text); m != nil {
targ, _ := strconv.ParseUint(m[2], 16, 64)
text = fmt.Sprintf("%s .%+#x", m[1], int16(uint32(targ)-uint32(uint16(addr))-uint32(len(enc))))
}
if m := pcrel.FindStringSubmatch(text); m != nil {
targ, _ := strconv.ParseUint(m[2], 16, 64)
text = fmt.Sprintf("%s .%+#x", m[1], int32(uint32(targ)-addr-uint32(len(enc))))
}
text = strings.Replace(text, "0x0(", "(", -1)
text = strings.Replace(text, "%st(0)", "%st", -1)
ext.Dec <- ExtInst{addr, encbuf, len(enc), text}
encbuf = [32]byte{}
enc = nil
next += 32
}
}
var textangle = []byte("<.text>:")
for {
line, err := b.ReadSlice('\n')
if err != nil {
if err == io.EOF {
break
}
return fmt.Errorf("reading objdump output: %v", err)
}
if bytes.Contains(line, textangle) {
reading = true
continue
}
if !reading {
continue
}
if debug {
os.Stdout.Write(line)
}
if enc1 := parseContinuation(line, encbuf[:len(enc)]); enc1 != nil {
enc = enc1
continue
}
flush()
nmatch++
addr, enc, text = parseLine(line, encbuf[:0])
if addr > next {
return fmt.Errorf("address out of sync expected <= %#x at %q in:\n%s", next, line, line)
}
}
flush()
if next != start+uint32(ext.Size) {
return fmt.Errorf("not enough results found [%d %d]", next, start+ext.Size)
}
if err := ext.Wait(); err != nil {
return fmt.Errorf("exec: %v", err)
}
return nil
}
func parseLine(line []byte, encstart []byte) (addr uint32, enc []byte, text string) {
oline := line
i := index(line, ":\t")
if i < 0 {
log.Fatalf("cannot parse disassembly: %q", oline)
}
x, err := strconv.ParseUint(string(trimSpace(line[:i])), 16, 32)
if err != nil {
log.Fatalf("cannot parse disassembly: %q", oline)
}
addr = uint32(x)
line = line[i+2:]
i = bytes.IndexByte(line, '\t')
if i < 0 {
log.Fatalf("cannot parse disassembly: %q", oline)
}
enc, ok := parseHex(line[:i], encstart)
if !ok {
log.Fatalf("cannot parse disassembly: %q", oline)
}
line = trimSpace(line[i:])
if i := bytes.IndexByte(line, '#'); i >= 0 {
line = trimSpace(line[:i])
}
text = string(fixSpace(line))
return
}
func parseContinuation(line []byte, enc []byte) []byte {
i := index(line, ":\t")
if i < 0 {
return nil
}
line = line[i+1:]
enc, _ = parseHex(line, enc)
return enc
}
// writeELF32 writes an ELF32 header to the file,
// describing a text segment that starts at start
// and extends for size bytes.
func writeELF32(f *os.File, size int) error {
f.Seek(0, 0)
var hdr elf.Header32
var prog elf.Prog32
var sect elf.Section32
var buf bytes.Buffer
binary.Write(&buf, binary.LittleEndian, &hdr)
off1 := buf.Len()
binary.Write(&buf, binary.LittleEndian, &prog)
off2 := buf.Len()
binary.Write(&buf, binary.LittleEndian, &sect)
off3 := buf.Len()
buf.Reset()
data := byte(elf.ELFDATA2LSB)
hdr = elf.Header32{
Ident: [16]byte{0x7F, 'E', 'L', 'F', 1, data, 1},
Type: 2,
Machine: uint16(elf.EM_386),
Version: 1,
Entry: start,
Phoff: uint32(off1),
Shoff: uint32(off2),
Flags: 0x05000002,
Ehsize: uint16(off1),
Phentsize: uint16(off2 - off1),
Phnum: 1,
Shentsize: uint16(off3 - off2),
Shnum: 3,
Shstrndx: 2,
}
binary.Write(&buf, binary.LittleEndian, &hdr)
prog = elf.Prog32{
Type: 1,
Off: start,
Vaddr: start,
Paddr: start,
Filesz: uint32(size),
Memsz: uint32(size),
Flags: 5,
Align: start,
}
binary.Write(&buf, binary.LittleEndian, &prog)
binary.Write(&buf, binary.LittleEndian, &sect) // NULL section
sect = elf.Section32{
Name: 1,
Type: uint32(elf.SHT_PROGBITS),
Addr: start,
Off: start,
Size: uint32(size),
Flags: uint32(elf.SHF_ALLOC | elf.SHF_EXECINSTR),
Addralign: 4,
}
binary.Write(&buf, binary.LittleEndian, &sect) // .text
sect = elf.Section32{
Name: uint32(len("\x00.text\x00")),
Type: uint32(elf.SHT_STRTAB),
Addr: 0,
Off: uint32(off2 + (off3-off2)*3),
Size: uint32(len("\x00.text\x00.shstrtab\x00")),
Addralign: 1,
}
binary.Write(&buf, binary.LittleEndian, &sect)
buf.WriteString("\x00.text\x00.shstrtab\x00")
f.Write(buf.Bytes())
return nil
}
// writeELF64 writes an ELF64 header to the file,
// describing a text segment that starts at start
// and extends for size bytes.
func writeELF64(f *os.File, size int) error {
f.Seek(0, 0)
var hdr elf.Header64
var prog elf.Prog64
var sect elf.Section64
var buf bytes.Buffer
binary.Write(&buf, binary.LittleEndian, &hdr)
off1 := buf.Len()
binary.Write(&buf, binary.LittleEndian, &prog)
off2 := buf.Len()
binary.Write(&buf, binary.LittleEndian, &sect)
off3 := buf.Len()
buf.Reset()
data := byte(elf.ELFDATA2LSB)
hdr = elf.Header64{
Ident: [16]byte{0x7F, 'E', 'L', 'F', 2, data, 1},
Type: 2,
Machine: uint16(elf.EM_X86_64),
Version: 1,
Entry: start,
Phoff: uint64(off1),
Shoff: uint64(off2),
Flags: 0x05000002,
Ehsize: uint16(off1),
Phentsize: uint16(off2 - off1),
Phnum: 1,
Shentsize: uint16(off3 - off2),
Shnum: 3,
Shstrndx: 2,
}
binary.Write(&buf, binary.LittleEndian, &hdr)
prog = elf.Prog64{
Type: 1,
Off: start,
Vaddr: start,
Paddr: start,
Filesz: uint64(size),
Memsz: uint64(size),
Flags: 5,
Align: start,
}
binary.Write(&buf, binary.LittleEndian, &prog)
binary.Write(&buf, binary.LittleEndian, &sect) // NULL section
sect = elf.Section64{
Name: 1,
Type: uint32(elf.SHT_PROGBITS),
Addr: start,
Off: start,
Size: uint64(size),
Flags: uint64(elf.SHF_ALLOC | elf.SHF_EXECINSTR),
Addralign: 4,
}
binary.Write(&buf, binary.LittleEndian, &sect) // .text
sect = elf.Section64{
Name: uint32(len("\x00.text\x00")),
Type: uint32(elf.SHT_STRTAB),
Addr: 0,
Off: uint64(off2 + (off3-off2)*3),
Size: uint64(len("\x00.text\x00.shstrtab\x00")),
Addralign: 1,
}
binary.Write(&buf, binary.LittleEndian, &sect)
buf.WriteString("\x00.text\x00.shstrtab\x00")
f.Write(buf.Bytes())
return nil
}

119
vendor/golang.org/x/arch/x86/x86asm/plan9ext_test.go generated vendored Normal file
View File

@ -0,0 +1,119 @@
// Copyright 2014 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 x86asm
import (
"bytes"
"fmt"
"io"
"log"
"os"
"strconv"
"testing"
)
const plan9Path = "testdata/libmach8db"
func testPlan9Arch(t *testing.T, arch int, generate func(func([]byte))) {
if testing.Short() {
t.Skip("skipping libmach test in short mode")
}
if _, err := os.Stat(plan9Path); err != nil {
t.Skip(err)
}
testExtDis(t, "plan9", arch, plan9, generate, allowedMismatchPlan9)
}
func testPlan932(t *testing.T, generate func(func([]byte))) {
testPlan9Arch(t, 32, generate)
}
func testPlan964(t *testing.T, generate func(func([]byte))) {
testPlan9Arch(t, 64, generate)
}
func plan9(ext *ExtDis) error {
flag := "-8"
if ext.Arch == 64 {
flag = "-6"
}
b, err := ext.Run(plan9Path, flag, ext.File.Name())
if err != nil {
return err
}
nmatch := 0
next := uint32(start)
var (
addr uint32
encbuf [32]byte
enc []byte
text string
)
for {
line, err := b.ReadSlice('\n')
if err != nil {
if err == io.EOF {
break
}
return fmt.Errorf("reading libmach8db output: %v", err)
}
if debug {
os.Stdout.Write(line)
}
nmatch++
addr, enc, text = parseLinePlan9(line, encbuf[:0])
if addr > next {
return fmt.Errorf("address out of sync expected <= %#x at %q in:\n%s", next, line, line)
}
if addr < next {
continue
}
if m := pcrelw.FindStringSubmatch(text); m != nil {
targ, _ := strconv.ParseUint(m[2], 16, 64)
text = fmt.Sprintf("%s .%+#x", m[1], int16(uint32(targ)-uint32(uint16(addr))-uint32(len(enc))))
}
if m := pcrel.FindStringSubmatch(text); m != nil {
targ, _ := strconv.ParseUint(m[2], 16, 64)
text = fmt.Sprintf("%s .%+#x", m[1], int32(uint32(targ)-addr-uint32(len(enc))))
}
ext.Dec <- ExtInst{addr, encbuf, len(enc), text}
encbuf = [32]byte{}
enc = nil
next += 32
}
if next != start+uint32(ext.Size) {
return fmt.Errorf("not enough results found [%d %d]", next, start+ext.Size)
}
if err := ext.Wait(); err != nil {
return fmt.Errorf("exec: %v", err)
}
return nil
}
func parseLinePlan9(line []byte, encstart []byte) (addr uint32, enc []byte, text string) {
i := bytes.IndexByte(line, ' ')
if i < 0 || line[0] != '0' || line[1] != 'x' {
log.Fatalf("cannot parse disassembly: %q", line)
}
j := bytes.IndexByte(line[i+1:], ' ')
if j < 0 {
log.Fatalf("cannot parse disassembly: %q", line)
}
j += i + 1
x, err := strconv.ParseUint(string(trimSpace(line[2:i])), 16, 32)
if err != nil {
log.Fatalf("cannot parse disassembly: %q", line)
}
addr = uint32(x)
enc, ok := parseHex(line[i+1:j], encstart)
if !ok {
log.Fatalf("cannot parse disassembly: %q", line)
}
return addr, enc, string(fixSpace(line[j+1:]))
}

362
vendor/golang.org/x/arch/x86/x86asm/plan9x.go generated vendored Normal file
View File

@ -0,0 +1,362 @@
// Copyright 2014 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 x86asm
import (
"fmt"
"strings"
)
// GoSyntax returns the Go assembler syntax for the instruction.
// The syntax was originally defined by Plan 9.
// The pc is the program counter of the instruction, used for expanding
// PC-relative addresses into absolute ones.
// The symname function queries the symbol table for the program
// being disassembled. Given a target address it returns the name and base
// address of the symbol containing the target, if any; otherwise it returns "", 0.
func GoSyntax(inst Inst, pc uint64, symname func(uint64) (string, uint64)) string {
if symname == nil {
symname = func(uint64) (string, uint64) { return "", 0 }
}
var args []string
for i := len(inst.Args) - 1; i >= 0; i-- {
a := inst.Args[i]
if a == nil {
continue
}
args = append(args, plan9Arg(&inst, pc, symname, a))
}
var rep string
var last Prefix
for _, p := range inst.Prefix {
if p == 0 || p.IsREX() || p.IsVEX() {
break
}
switch {
// Don't show prefixes implied by the instruction text.
case p&0xFF00 == PrefixImplicit:
continue
// Only REP and REPN are recognized repeaters. Plan 9 syntax
// treats them as separate opcodes.
case p&0xFF == PrefixREP:
rep = "REP; "
case p&0xFF == PrefixREPN:
rep = "REPNE; "
default:
last = p
}
}
prefix := ""
switch last & 0xFF {
case 0, 0x66, 0x67:
// ignore
default:
prefix += last.String() + " "
}
op := inst.Op.String()
if plan9Suffix[inst.Op] {
s := inst.DataSize
if inst.MemBytes != 0 {
s = inst.MemBytes * 8
}
switch s {
case 8:
op += "B"
case 16:
op += "W"
case 32:
op += "L"
case 64:
op += "Q"
}
}
if args != nil {
op += " " + strings.Join(args, ", ")
}
return rep + prefix + op
}
func plan9Arg(inst *Inst, pc uint64, symname func(uint64) (string, uint64), arg Arg) string {
switch a := arg.(type) {
case Reg:
return plan9Reg[a]
case Rel:
if pc == 0 {
break
}
// If the absolute address is the start of a symbol, use the name.
// Otherwise use the raw address, so that things like relative
// jumps show up as JMP 0x123 instead of JMP f+10(SB).
// It is usually easier to search for 0x123 than to do the mental
// arithmetic to find f+10.
addr := pc + uint64(inst.Len) + uint64(a)
if s, base := symname(addr); s != "" && addr == base {
return fmt.Sprintf("%s(SB)", s)
}
return fmt.Sprintf("%#x", addr)
case Imm:
if s, base := symname(uint64(a)); s != "" {
suffix := ""
if uint64(a) != base {
suffix = fmt.Sprintf("%+d", uint64(a)-base)
}
return fmt.Sprintf("$%s%s(SB)", s, suffix)
}
if inst.Mode == 32 {
return fmt.Sprintf("$%#x", uint32(a))
}
if Imm(int32(a)) == a {
return fmt.Sprintf("$%#x", int64(a))
}
return fmt.Sprintf("$%#x", uint64(a))
case Mem:
if a.Segment == 0 && a.Disp != 0 && a.Base == 0 && (a.Index == 0 || a.Scale == 0) {
if s, base := symname(uint64(a.Disp)); s != "" {
suffix := ""
if uint64(a.Disp) != base {
suffix = fmt.Sprintf("%+d", uint64(a.Disp)-base)
}
return fmt.Sprintf("%s%s(SB)", s, suffix)
}
}
s := ""
if a.Segment != 0 {
s += fmt.Sprintf("%s:", plan9Reg[a.Segment])
}
if a.Disp != 0 {
s += fmt.Sprintf("%#x", a.Disp)
} else {
s += "0"
}
if a.Base != 0 {
s += fmt.Sprintf("(%s)", plan9Reg[a.Base])
}
if a.Index != 0 && a.Scale != 0 {
s += fmt.Sprintf("(%s*%d)", plan9Reg[a.Index], a.Scale)
}
return s
}
return arg.String()
}
var plan9Suffix = [maxOp + 1]bool{
ADC: true,
ADD: true,
AND: true,
BSF: true,
BSR: true,
BT: true,
BTC: true,
BTR: true,
BTS: true,
CMP: true,
CMPXCHG: true,
CVTSI2SD: true,
CVTSI2SS: true,
CVTSD2SI: true,
CVTSS2SI: true,
CVTTSD2SI: true,
CVTTSS2SI: true,
DEC: true,
DIV: true,
FLDENV: true,
FRSTOR: true,
IDIV: true,
IMUL: true,
IN: true,
INC: true,
LEA: true,
MOV: true,
MOVNTI: true,
MUL: true,
NEG: true,
NOP: true,
NOT: true,
OR: true,
OUT: true,
POP: true,
POPA: true,
PUSH: true,
PUSHA: true,
RCL: true,
RCR: true,
ROL: true,
ROR: true,
SAR: true,
SBB: true,
SHL: true,
SHLD: true,
SHR: true,
SHRD: true,
SUB: true,
TEST: true,
XADD: true,
XCHG: true,
XOR: true,
}
var plan9Reg = [...]string{
AL: "AL",
CL: "CL",
BL: "BL",
DL: "DL",
AH: "AH",
CH: "CH",
BH: "BH",
DH: "DH",
SPB: "SP",
BPB: "BP",
SIB: "SI",
DIB: "DI",
R8B: "R8",
R9B: "R9",
R10B: "R10",
R11B: "R11",
R12B: "R12",
R13B: "R13",
R14B: "R14",
R15B: "R15",
AX: "AX",
CX: "CX",
BX: "BX",
DX: "DX",
SP: "SP",
BP: "BP",
SI: "SI",
DI: "DI",
R8W: "R8",
R9W: "R9",
R10W: "R10",
R11W: "R11",
R12W: "R12",
R13W: "R13",
R14W: "R14",
R15W: "R15",
EAX: "AX",
ECX: "CX",
EDX: "DX",
EBX: "BX",
ESP: "SP",
EBP: "BP",
ESI: "SI",
EDI: "DI",
R8L: "R8",
R9L: "R9",
R10L: "R10",
R11L: "R11",
R12L: "R12",
R13L: "R13",
R14L: "R14",
R15L: "R15",
RAX: "AX",
RCX: "CX",
RDX: "DX",
RBX: "BX",
RSP: "SP",
RBP: "BP",
RSI: "SI",
RDI: "DI",
R8: "R8",
R9: "R9",
R10: "R10",
R11: "R11",
R12: "R12",
R13: "R13",
R14: "R14",
R15: "R15",
IP: "IP",
EIP: "IP",
RIP: "IP",
F0: "F0",
F1: "F1",
F2: "F2",
F3: "F3",
F4: "F4",
F5: "F5",
F6: "F6",
F7: "F7",
M0: "M0",
M1: "M1",
M2: "M2",
M3: "M3",
M4: "M4",
M5: "M5",
M6: "M6",
M7: "M7",
X0: "X0",
X1: "X1",
X2: "X2",
X3: "X3",
X4: "X4",
X5: "X5",
X6: "X6",
X7: "X7",
X8: "X8",
X9: "X9",
X10: "X10",
X11: "X11",
X12: "X12",
X13: "X13",
X14: "X14",
X15: "X15",
CS: "CS",
SS: "SS",
DS: "DS",
ES: "ES",
FS: "FS",
GS: "GS",
GDTR: "GDTR",
IDTR: "IDTR",
LDTR: "LDTR",
MSW: "MSW",
TASK: "TASK",
CR0: "CR0",
CR1: "CR1",
CR2: "CR2",
CR3: "CR3",
CR4: "CR4",
CR5: "CR5",
CR6: "CR6",
CR7: "CR7",
CR8: "CR8",
CR9: "CR9",
CR10: "CR10",
CR11: "CR11",
CR12: "CR12",
CR13: "CR13",
CR14: "CR14",
CR15: "CR15",
DR0: "DR0",
DR1: "DR1",
DR2: "DR2",
DR3: "DR3",
DR4: "DR4",
DR5: "DR5",
DR6: "DR6",
DR7: "DR7",
DR8: "DR8",
DR9: "DR9",
DR10: "DR10",
DR11: "DR11",
DR12: "DR12",
DR13: "DR13",
DR14: "DR14",
DR15: "DR15",
TR0: "TR0",
TR1: "TR1",
TR2: "TR2",
TR3: "TR3",
TR4: "TR4",
TR5: "TR5",
TR6: "TR6",
TR7: "TR7",
}

54
vendor/golang.org/x/arch/x86/x86asm/plan9x_test.go generated vendored Normal file
View File

@ -0,0 +1,54 @@
// Copyright 2014 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 x86asm
import (
"strings"
"testing"
)
func TestPlan932Manual(t *testing.T) { testPlan932(t, hexCases(t, plan9ManualTests)) }
func TestPlan932Testdata(t *testing.T) { testPlan932(t, concat(basicPrefixes, testdataCases(t))) }
func TestPlan932ModRM(t *testing.T) { testPlan932(t, concat(basicPrefixes, enumModRM)) }
func TestPlan932OneByte(t *testing.T) { testBasic(t, testPlan932) }
func TestPlan9320F(t *testing.T) { testBasic(t, testPlan932, 0x0F) }
func TestPlan9320F38(t *testing.T) { testBasic(t, testPlan932, 0x0F, 0x38) }
func TestPlan9320F3A(t *testing.T) { testBasic(t, testPlan932, 0x0F, 0x3A) }
func TestPlan932Prefix(t *testing.T) { testPrefix(t, testPlan932) }
func TestPlan964Manual(t *testing.T) { testPlan964(t, hexCases(t, plan9ManualTests)) }
func TestPlan964Testdata(t *testing.T) { testPlan964(t, concat(basicPrefixes, testdataCases(t))) }
func TestPlan964ModRM(t *testing.T) { testPlan964(t, concat(basicPrefixes, enumModRM)) }
func TestPlan964OneByte(t *testing.T) { testBasic(t, testPlan964) }
func TestPlan9640F(t *testing.T) { testBasic(t, testPlan964, 0x0F) }
func TestPlan9640F38(t *testing.T) { testBasic(t, testPlan964, 0x0F, 0x38) }
func TestPlan9640F3A(t *testing.T) { testBasic(t, testPlan964, 0x0F, 0x3A) }
func TestPlan964Prefix(t *testing.T) { testPrefix(t, testPlan964) }
func TestPlan964REXTestdata(t *testing.T) {
testPlan964(t, filter(concat3(basicPrefixes, rexPrefixes, testdataCases(t)), isValidREX))
}
func TestPlan964REXModRM(t *testing.T) { testPlan964(t, concat3(basicPrefixes, rexPrefixes, enumModRM)) }
func TestPlan964REXOneByte(t *testing.T) { testBasicREX(t, testPlan964) }
func TestPlan964REX0F(t *testing.T) { testBasicREX(t, testPlan964, 0x0F) }
func TestPlan964REX0F38(t *testing.T) { testBasicREX(t, testPlan964, 0x0F, 0x38) }
func TestPlan964REX0F3A(t *testing.T) { testBasicREX(t, testPlan964, 0x0F, 0x3A) }
func TestPlan964REXPrefix(t *testing.T) { testPrefixREX(t, testPlan964) }
// plan9ManualTests holds test cases that will be run by TestPlan9Manual32 and TestPlan9Manual64.
// If you are debugging a few cases that turned up in a longer run, it can be useful
// to list them here and then use -run=Plan9Manual, particularly with tracing enabled.
var plan9ManualTests = `
`
// allowedMismatchPlan9 reports whether the mismatch between text and dec
// should be allowed by the test.
func allowedMismatchPlan9(text string, size int, inst *Inst, dec ExtInst) bool {
return false
}
// Instructions known to us but not to plan9.
var plan9Unsupported = strings.Fields(`
`)

9902
vendor/golang.org/x/arch/x86/x86asm/tables.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

12
vendor/golang.org/x/arch/x86/x86asm/testdata/Makefile generated vendored Normal file
View File

@ -0,0 +1,12 @@
libmach8db: libmach8db.c
9c libmach8db.c && 9l -o libmach8db libmach8db.o; rm libmach8db.o
newdecode.txt:
cd ..; go test -cover -run 'Objdump.*32' -v -timeout 10h -printtests 2>&1 | tee log
cd ..; go test -cover -run 'Objdump.*64' -v -timeout 10h -printtests 2>&1 | tee -a log
cd ..; go test -cover -run 'Xed.*32' -v -timeout 10h -printtests 2>&1 | tee -a log
cd ..; go test -cover -run 'Xed.*64' -v -timeout 10h -printtests 2>&1 | tee -a log
cd ..; go test -cover -run 'Plan9.*32' -v -timeout 10h -printtests 2>&1 | tee -a log
cd ..; go test -cover -run 'Plan9.*64' -v -timeout 10h -printtests 2>&1 | tee -a log
egrep ' (gnu|intel|plan9) ' ../log |sort >newdecode.txt

6771
vendor/golang.org/x/arch/x86/x86asm/testdata/decode.txt generated vendored Normal file

File diff suppressed because it is too large Load Diff

2075
vendor/golang.org/x/arch/x86/x86asm/testdata/libmach8db.c generated vendored Normal file

File diff suppressed because it is too large Load Diff

211
vendor/golang.org/x/arch/x86/x86asm/xed_test.go generated vendored Normal file
View File

@ -0,0 +1,211 @@
// Copyright 2014 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 x86asm
import (
"bytes"
"strings"
"testing"
)
func TestXed32Manual(t *testing.T) { testXed32(t, hexCases(t, xedManualTests)) }
func TestXed32Testdata(t *testing.T) { testXed32(t, concat(basicPrefixes, testdataCases(t))) }
func TestXed32ModRM(t *testing.T) { testXed32(t, concat(basicPrefixes, enumModRM)) }
func TestXed32OneByte(t *testing.T) { testBasic(t, testXed32) }
func TestXed320F(t *testing.T) { testBasic(t, testXed32, 0x0F) }
func TestXed320F38(t *testing.T) { testBasic(t, testXed32, 0x0F, 0x38) }
func TestXed320F3A(t *testing.T) { testBasic(t, testXed32, 0x0F, 0x3A) }
func TestXed32Prefix(t *testing.T) { testPrefix(t, testXed32) }
func TestXed64Manual(t *testing.T) { testXed64(t, hexCases(t, xedManualTests)) }
func TestXed64Testdata(t *testing.T) { testXed64(t, concat(basicPrefixes, testdataCases(t))) }
func TestXed64ModRM(t *testing.T) { testXed64(t, concat(basicPrefixes, enumModRM)) }
func TestXed64OneByte(t *testing.T) { testBasic(t, testXed64) }
func TestXed640F(t *testing.T) { testBasic(t, testXed64, 0x0F) }
func TestXed640F38(t *testing.T) { testBasic(t, testXed64, 0x0F, 0x38) }
func TestXed640F3A(t *testing.T) { testBasic(t, testXed64, 0x0F, 0x3A) }
func TestXed64Prefix(t *testing.T) { testPrefix(t, testXed64) }
func TestXed64REXTestdata(t *testing.T) {
testXed64(t, filter(concat3(basicPrefixes, rexPrefixes, testdataCases(t)), isValidREX))
}
func TestXed64REXModRM(t *testing.T) { testXed64(t, concat3(basicPrefixes, rexPrefixes, enumModRM)) }
func TestXed64REXOneByte(t *testing.T) { testBasicREX(t, testXed64) }
func TestXed64REX0F(t *testing.T) { testBasicREX(t, testXed64, 0x0F) }
func TestXed64REX0F38(t *testing.T) { testBasicREX(t, testXed64, 0x0F, 0x38) }
func TestXed64REX0F3A(t *testing.T) { testBasicREX(t, testXed64, 0x0F, 0x3A) }
func TestXed64REXPrefix(t *testing.T) { testPrefixREX(t, testXed64) }
// xedManualTests holds test cases that will be run by TestXedManual32 and TestXedManual64.
// If you are debugging a few cases that turned up in a longer run, it can be useful
// to list them here and then use -run=XedManual, particularly with tracing enabled.
var xedManualTests = `
6690
`
// allowedMismatchXed reports whether the mismatch between text and dec
// should be allowed by the test.
func allowedMismatchXed(text string, size int, inst *Inst, dec ExtInst) bool {
if (contains(text, "error:") || isPrefix(text) && size == 1) && contains(dec.text, "GENERAL_ERROR", "INSTR_TOO_LONG", "BAD_LOCK_PREFIX") {
return true
}
if contains(dec.text, "BAD_LOCK_PREFIX") && countExactPrefix(inst, PrefixLOCK|PrefixInvalid) > 0 {
return true
}
if contains(dec.text, "BAD_LOCK_PREFIX", "GENERAL_ERROR") && countExactPrefix(inst, PrefixLOCK|PrefixImplicit) > 0 {
return true
}
if text == "lock" && size == 1 && contains(dec.text, "BAD_LOCK_PREFIX") {
return true
}
// Instructions not known to us.
if (contains(text, "error:") || isPrefix(text) && size == 1) && contains(dec.text, unsupported...) {
return true
}
// Instructions not known to xed.
if contains(text, xedUnsupported...) && contains(dec.text, "ERROR") {
return true
}
if (contains(text, "error:") || isPrefix(text) && size == 1) && contains(dec.text, "shl ") && (inst.Opcode>>16)&0xEC38 == 0xC030 {
return true
}
// 82 11 22: xed says 'adc byte ptr [ecx], 0x22' but there is no justification in the manuals for that.
// C0 30 11: xed says 'shl byte ptr [eax], 0x11' but there is no justification in the manuals for that.
// F6 08 11: xed says 'test byte ptr [eax], 0x11' but there is no justification in the manuals for that.
if (contains(text, "error:") || isPrefix(text) && size == 1) && hasByte(dec.enc[:dec.nenc], 0x82, 0xC0, 0xC1, 0xD0, 0xD1, 0xD2, 0xD3, 0xF6, 0xF7) {
return true
}
// F3 11 22 and many others: xed allows and drops misused rep/repn prefix.
if (text == "rep" && dec.enc[0] == 0xF3 || (text == "repn" || text == "repne") && dec.enc[0] == 0xF2) && (!contains(dec.text, "ins", "outs", "movs", "lods", "cmps", "scas") || contains(dec.text, "xmm")) {
return true
}
// 0F C7 30: xed says vmptrld qword ptr [eax]; we say rdrand eax.
// TODO(rsc): Fix, since we are probably wrong, but we don't have vmptrld in the manual.
if contains(text, "rdrand") && contains(dec.text, "vmptrld", "vmxon", "vmclear") {
return true
}
// F3 0F AE 00: we say 'rdfsbase dword ptr [eax]' but RDFSBASE needs a register.
// Also, this is a 64-bit only instruction.
// TODO(rsc): Fix to reject this encoding.
if contains(text, "rdfsbase", "rdgsbase", "wrfsbase", "wrgsbase") && contains(dec.text, "ERROR") {
return true
}
// 0F 01 F8: we say swapgs but that's only valid in 64-bit mode.
// TODO(rsc): Fix.
if contains(text, "swapgs") {
return true
}
// 0F 24 11: 'mov ecx, tr2' except there is no TR2.
// Or maybe the MOV to TR registers doesn't use RMF.
if contains(text, "cr1", "cr5", "cr6", "cr7", "tr0", "tr1", "tr2", "tr3", "tr4", "tr5", "tr6", "tr7") && contains(dec.text, "ERROR") {
return true
}
// 0F 19 11, 0F 1C 11, 0F 1D 11, 0F 1E 11, 0F 1F 11: xed says nop,
// but the Intel manuals say that the only NOP there is 0F 1F /0.
// Perhaps xed is reporting an older encoding.
if (contains(text, "error:") || isPrefix(text) && size == 1) && contains(dec.text, "nop ") && (inst.Opcode>>8)&0xFFFF38 != 0x0F1F00 {
return true
}
// 66 0F AE 38: clflushopt but we only know clflush
if contains(text, "clflush") && contains(dec.text, "clflushopt") {
return true
}
// 0F 20 04 11: MOV SP, CR0 but has mod!=3 despite register argument.
// (This encoding ignores the mod bits.) The decoder sees the non-register
// mod and reads farther ahead to decode the memory reference that
// isn't really there, causing the size to be too large.
// TODO(rsc): Fix.
if text == dec.text && size > dec.nenc && contains(text, " cr", " dr", " tr") {
return true
}
// 0F AE E9: xed says lfence, which is wrong (only 0F AE E8 is lfence). And so on.
if contains(dec.text, "fence") && hasByte(dec.enc[:dec.nenc], 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF) {
return true
}
// DD C9, DF C9: xed says 'fxch st0, st1' but that instruction is D9 C9.
if (contains(text, "error:") || isPrefix(text) && size == 1) && contains(dec.text, "fxch ") && hasByte(dec.enc[:dec.nenc], 0xDD, 0xDF) {
return true
}
// DC D4: xed says 'fcom st0, st4' but that instruction is D8 D4.
if (contains(text, "error:") || isPrefix(text) && size == 1) && contains(dec.text, "fcom ") && hasByte(dec.enc[:dec.nenc], 0xD8, 0xDC) {
return true
}
// DE D4: xed says 'fcomp st0, st4' but that instruction is D8 D4.
if (contains(text, "error:") || isPrefix(text) && size == 1) && contains(dec.text, "fcomp ") && hasByte(dec.enc[:dec.nenc], 0xDC, 0xDE) {
return true
}
// DF D4: xed says 'fstp st4, st0' but that instruction is DD D4.
if (contains(text, "error:") || isPrefix(text) && size == 1) && contains(dec.text, "fstp ") && hasByte(dec.enc[:dec.nenc], 0xDF) {
return true
}
return false
}
func countExactPrefix(inst *Inst, target Prefix) int {
n := 0
for _, p := range inst.Prefix {
if p == target {
n++
}
}
return n
}
func hasByte(src []byte, target ...byte) bool {
for _, b := range target {
if bytes.IndexByte(src, b) >= 0 {
return true
}
}
return false
}
// Instructions known to us but not to xed.
var xedUnsupported = strings.Fields(`
xrstor
xsave
xsave
ud1
xgetbv
xsetbv
fxsave
fxrstor
clflush
lfence
mfence
sfence
rsqrtps
rcpps
emms
ldmxcsr
stmxcsr
movhpd
movnti
rdrand
movbe
movlpd
sysret
`)

205
vendor/golang.org/x/arch/x86/x86asm/xedext_test.go generated vendored Normal file
View File

@ -0,0 +1,205 @@
package x86asm
import (
"bytes"
"fmt"
"io"
"log"
"os"
"strconv"
"strings"
"testing"
)
// xed binary from Intel sde-external-6.22.0-2014-03-06.
const xedPath = "/Users/rsc/bin/xed"
func testXedArch(t *testing.T, arch int, generate func(func([]byte))) {
if testing.Short() {
t.Skip("skipping xed test in short mode")
}
if _, err := os.Stat(xedPath); err != nil {
t.Skip(err)
}
testExtDis(t, "intel", arch, xed, generate, allowedMismatchXed)
}
func testXed32(t *testing.T, generate func(func([]byte))) {
testXedArch(t, 32, generate)
}
func testXed64(t *testing.T, generate func(func([]byte))) {
testXedArch(t, 64, generate)
}
func xed(ext *ExtDis) error {
b, err := ext.Run(xedPath, fmt.Sprintf("-%d", ext.Arch), "-n", "1G", "-ir", ext.File.Name())
if err != nil {
return err
}
nmatch := 0
next := uint32(start)
var (
addr uint32
encbuf [32]byte
enc []byte
text string
)
var xedEnd = []byte("# end of text section")
var xedEnd1 = []byte("# Errors")
eof := false
for {
line, err := b.ReadSlice('\n')
if err != nil {
if err == io.EOF {
break
}
return fmt.Errorf("reading objdump output: %v", err)
}
if debug {
os.Stdout.Write(line)
}
if bytes.HasPrefix(line, xedEnd) || bytes.HasPrefix(line, xedEnd1) {
eof = true
}
if eof {
continue
}
nmatch++
addr, enc, text = parseLineXed(line, encbuf[:0])
if addr > next {
return fmt.Errorf("address out of sync expected <= %#x at %q in:\n%s", next, line, line)
}
if addr < next {
continue
}
switch text {
case "repz":
text = "rep"
case "repnz":
text = "repn"
default:
text = strings.Replace(text, "repz ", "rep ", -1)
text = strings.Replace(text, "repnz ", "repn ", -1)
}
if m := pcrelw.FindStringSubmatch(text); m != nil {
targ, _ := strconv.ParseUint(m[2], 16, 64)
text = fmt.Sprintf("%s .%+#x", m[1], int16(uint32(targ)-uint32(uint16(addr))-uint32(len(enc))))
}
if m := pcrel.FindStringSubmatch(text); m != nil {
targ, _ := strconv.ParseUint(m[2], 16, 64)
text = fmt.Sprintf("%s .%+#x", m[1], int32(uint32(targ)-addr-uint32(len(enc))))
}
ext.Dec <- ExtInst{addr, encbuf, len(enc), text}
encbuf = [32]byte{}
enc = nil
next += 32
}
if next != start+uint32(ext.Size) {
return fmt.Errorf("not enough results found [%d %d]", next, start+ext.Size)
}
if err := ext.Wait(); err != nil {
return fmt.Errorf("exec: %v", err)
}
return nil
}
var (
xedInRaw = []byte("In raw...")
xedDots = []byte("...")
xdis = []byte("XDIS ")
xedError = []byte("ERROR: ")
xedNoDecode = []byte("Could not decode at offset: 0x")
)
func parseLineXed(line []byte, encstart []byte) (addr uint32, enc []byte, text string) {
oline := line
if bytes.HasPrefix(line, xedInRaw) || bytes.HasPrefix(line, xedDots) {
return 0, nil, ""
}
if bytes.HasPrefix(line, xedError) {
i := bytes.IndexByte(line[len(xedError):], ' ')
if i < 0 {
log.Fatalf("cannot parse error: %q", oline)
}
errstr := string(line[len(xedError):])
i = bytes.Index(line, xedNoDecode)
if i < 0 {
log.Fatalf("cannot parse error: %q", oline)
}
i += len(xedNoDecode)
j := bytes.IndexByte(line[i:], ' ')
if j < 0 {
log.Fatalf("cannot parse error: %q", oline)
}
x, err := strconv.ParseUint(string(trimSpace(line[i:i+j])), 16, 32)
if err != nil {
log.Fatalf("cannot parse disassembly: %q", oline)
}
addr = uint32(x)
return addr, nil, errstr
}
if !bytes.HasPrefix(line, xdis) {
log.Fatalf("cannot parse disassembly: %q", oline)
}
i := bytes.IndexByte(line, ':')
if i < 0 {
log.Fatalf("cannot parse disassembly: %q", oline)
}
x, err := strconv.ParseUint(string(trimSpace(line[len(xdis):i])), 16, 32)
if err != nil {
log.Fatalf("cannot parse disassembly: %q", oline)
}
addr = uint32(x)
// spaces
i++
for i < len(line) && line[i] == ' ' {
i++
}
// instruction class, spaces
for i < len(line) && line[i] != ' ' {
i++
}
for i < len(line) && line[i] == ' ' {
i++
}
// instruction set, spaces
for i < len(line) && line[i] != ' ' {
i++
}
for i < len(line) && line[i] == ' ' {
i++
}
// hex
hexStart := i
for i < len(line) && line[i] != ' ' {
i++
}
hexEnd := i
for i < len(line) && line[i] == ' ' {
i++
}
// text
textStart := i
for i < len(line) && line[i] != '\n' {
i++
}
textEnd := i
enc, ok := parseHex(line[hexStart:hexEnd], encstart)
if !ok {
log.Fatalf("cannot parse disassembly: %q", oline)
}
return addr, enc, string(fixSpace(line[textStart:textEnd]))
}

1392
vendor/golang.org/x/arch/x86/x86map/map.go generated vendored Normal file

File diff suppressed because it is too large Load Diff