// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
// Package dashapi defines data structures used in dashboard communication
// and provides client interface.
package dashapi
import (
"bytes"
"compress/gzip"
"encoding/json"
"fmt"
"io"
"mime/multipart"
"net/http"
"net/mail"
"reflect"
"time"
"github.com/google/syzkaller/pkg/auth"
)
type Dashboard struct {
Client string
Addr string
Key string
ctor RequestCtor
doer RequestDoer
logger RequestLogger
errorHandler func(error)
}
type DashboardOpts any
type UserAgent string
func New(client, addr, key string, opts ...DashboardOpts) (*Dashboard, error) {
ctor := http.NewRequest
for _, o := range opts {
switch opt := o.(type) {
case UserAgent:
ctor = func(method, url string, body io.Reader) (*http.Request, error) {
req, err := http.NewRequest(method, url, body)
if err != nil {
return nil, err
}
req.Header.Add("User-Agent", string(opt))
return req, nil
}
}
}
return NewCustom(client, addr, key, ctor, http.DefaultClient.Do, nil, nil)
}
type (
RequestCtor func(method, url string, body io.Reader) (*http.Request, error)
RequestDoer func(req *http.Request) (*http.Response, error)
RequestLogger func(msg string, args ...interface{})
)
// key == "" indicates that the ambient GCE service account authority
// should be used as a bearer token.
func NewCustom(client, addr, key string, ctor RequestCtor, doer RequestDoer,
logger RequestLogger, errorHandler func(error)) (*Dashboard, error) {
wrappedDoer := doer
if key == "" {
tokenCache, err := auth.MakeCache(ctor, doer)
if err != nil {
return nil, err
}
wrappedDoer = func(req *http.Request) (*http.Response, error) {
token, err := tokenCache.Get(time.Now())
if err != nil {
return nil, err
}
req.Header.Add("Authorization", token)
return doer(req)
}
}
return &Dashboard{
Client: client,
Addr: addr,
Key: key,
ctor: ctor,
doer: wrappedDoer,
logger: logger,
errorHandler: errorHandler,
}, nil
}
// Build describes all aspects of a kernel build.
type Build struct {
Manager string
ID string
OS string
Arch string
VMArch string
SyzkallerCommit string
SyzkallerCommitDate time.Time
CompilerID string
KernelRepo string
KernelBranch string
KernelCommit string
KernelCommitTitle string
KernelCommitDate time.Time
KernelConfig []byte
Commits []string // see BuilderPoll
FixCommits []Commit
Assets []NewAsset
}
type Commit struct {
Hash string
Title string
Author string
AuthorName string
CC []string // deprecated in favor of Recipients
Recipients Recipients
BugIDs []string // ID's extracted from Reported-by tags
Date time.Time
Link string // set if the commit is a part of a reply
}
func (dash *Dashboard) UploadBuild(build *Build) error {
return dash.Query("upload_build", build, nil)
}
// BuilderPoll request is done by kernel builder before uploading a new build
// with UploadBuild request. Response contains list of commit titles that
// dashboard is interested in (i.e. commits that fix open bugs) and email that
// appears in Reported-by tags for bug ID extraction. When uploading a new build
// builder will pass subset of the commit titles that are present in the build
// in Build.Commits field and list of {bug ID, commit title} pairs extracted
// from git log.
type BuilderPollReq struct {
Manager string
}
type BuilderPollResp struct {
PendingCommits []string
ReportEmail string
}
func (dash *Dashboard) BuilderPoll(manager string) (*BuilderPollResp, error) {
req := &BuilderPollReq{
Manager: manager,
}
resp := new(BuilderPollResp)
err := dash.Query("builder_poll", req, resp)
return resp, err
}
// Jobs workflow:
// - syz-ci sends JobResetReq to indicate that no previously started jobs
// are any longer in progress.
// - syz-ci sends JobPollReq periodically to check for new jobs,
// request contains list of managers that this syz-ci runs.
// - dashboard replies with JobPollResp that contains job details,
// if no new jobs available ID is set to empty string.
// - when syz-ci finishes the job, it sends JobDoneReq which contains
// job execution result (Build, Crash or Error details),
// ID must match JobPollResp.ID.
type JobResetReq struct {
Managers []string
}
type JobPollReq struct {
Managers map[string]ManagerJobs
}
type ManagerJobs struct {
TestPatches bool
BisectCause bool
BisectFix bool
}
func (m ManagerJobs) Any() bool {
return m.TestPatches || m.BisectCause || m.BisectFix
}
type JobPollResp struct {
ID string
Type JobType
Manager string
KernelRepo string
// KernelBranch is used for patch testing and serves as the current HEAD
// for bisections.
KernelBranch string
MergeBaseRepo string
MergeBaseBranch string
// Bisection starts from KernelCommit.
KernelCommit string
KernelCommitTitle string
KernelConfig []byte
SyzkallerCommit string
Patch []byte
ReproOpts []byte
ReproSyz []byte
ReproC []byte
}
type JobDoneReq struct {
ID string
Build Build
Error []byte
Log []byte // bisection log
CrashTitle string
CrashAltTitles []string
CrashLog []byte
CrashReport []byte
// Bisection results:
// If there is 0 commits:
// - still happens on HEAD for fix bisection
// - already happened on the oldest release
// If there is 1 commits: bisection result (cause or fix).
// If there are more than 1: suspected commits due to skips (broken build/boot).
Commits []Commit
Flags JobDoneFlags
}
type JobType int
const (
JobTestPatch JobType = iota
JobBisectCause
JobBisectFix
)
type JobDoneFlags int64
const (
BisectResultMerge JobDoneFlags = 1 << iota // bisected to a merge commit
BisectResultNoop // commit does not affect resulting kernel binary
BisectResultRelease // commit is a kernel release
BisectResultIgnore // this particular commit should be ignored, see syz-ci/jobs.go
BisectResultInfraError // the bisect failed due to an infrastructure problem
)
func (flags JobDoneFlags) String() string {
if flags&BisectResultInfraError != 0 {
return "[infra failure]"
}
res := ""
if flags&BisectResultMerge != 0 {
res += "merge "
}
if flags&BisectResultNoop != 0 {
res += "no-op "
}
if flags&BisectResultRelease != 0 {
res += "release "
}
if flags&BisectResultIgnore != 0 {
res += "ignored "
}
if res == "" {
return res
}
return "[" + res + "commit]"
}
func (dash *Dashboard) JobPoll(req *JobPollReq) (*JobPollResp, error) {
resp := new(JobPollResp)
err := dash.Query("job_poll", req, resp)
return resp, err
}
func (dash *Dashboard) JobDone(req *JobDoneReq) error {
return dash.Query("job_done", req, nil)
}
func (dash *Dashboard) JobReset(req *JobResetReq) error {
return dash.Query("job_reset", req, nil)
}
type BuildErrorReq struct {
Build Build
Crash Crash
}
func (dash *Dashboard) ReportBuildError(req *BuildErrorReq) error {
return dash.Query("report_build_error", req, nil)
}
type CommitPollResp struct {
ReportEmail string
Repos []Repo
Commits []string
}
type CommitPollResultReq struct {
Commits []Commit
}
type Repo struct {
URL string
Branch string
}
func (dash *Dashboard) CommitPoll() (*CommitPollResp, error) {
resp := new(CommitPollResp)
err := dash.Query("commit_poll", nil, resp)
return resp, err
}
func (dash *Dashboard) UploadCommits(commits []Commit) error {
if len(commits) == 0 {
return nil
}
return dash.Query("upload_commits", &CommitPollResultReq{commits}, nil)
}
type CrashFlags int64
const (
CrashUnderStrace CrashFlags = 1 << iota
)
// Crash describes a single kernel crash (potentially with repro).
type Crash struct {
BuildID string // refers to Build.ID
Title string
AltTitles []string // alternative titles, used for better deduplication
Corrupted bool // report is corrupted (corrupted title, no stacks, etc)
Suppressed bool
Maintainers []string // deprecated in favor of Recipients
Recipients Recipients
Log []byte
Flags CrashFlags
Report []byte
MachineInfo []byte
Assets []NewAsset
GuiltyFiles []string
// The following is optional and is filled only after repro.
ReproOpts []byte
ReproSyz []byte
ReproC []byte
ReproLog []byte
OriginalTitle string // Title before we began bug reproduction.
}
type ReportCrashResp struct {
NeedRepro bool
}
func (dash *Dashboard) ReportCrash(crash *Crash) (*ReportCrashResp, error) {
resp := new(ReportCrashResp)
err := dash.Query("report_crash", crash, resp)
return resp, err
}
// CrashID is a short summary of a crash for repro queries.
type CrashID struct {
BuildID string
Title string
Corrupted bool
Suppressed bool
MayBeMissing bool
ReproLog []byte
}
type NeedReproResp struct {
NeedRepro bool
}
// NeedRepro checks if dashboard needs a repro for this crash or not.
func (dash *Dashboard) NeedRepro(crash *CrashID) (bool, error) {
resp := new(NeedReproResp)
err := dash.Query("need_repro", crash, resp)
return resp.NeedRepro, err
}
// ReportFailedRepro notifies dashboard about a failed repro attempt for the crash.
func (dash *Dashboard) ReportFailedRepro(crash *CrashID) error {
return dash.Query("report_failed_repro", crash, nil)
}
type LogToReproReq struct {
BuildID string
}
type LogToReproType string
const (
ManualLog LogToReproType = "manual"
RetryReproLog LogToReproType = "retry"
)
type LogToReproResp struct {
Title string
CrashLog []byte
Type LogToReproType
}
// LogToRepro are crash logs for older bugs that need to be reproduced on the
// querying instance.
func (dash *Dashboard) LogToRepro(req *LogToReproReq) (*LogToReproResp, error) {
resp := new(LogToReproResp)
err := dash.Query("log_to_repro", req, resp)
return resp, err
}
type LogEntry struct {
Name string
Text string
}
// Centralized logging on dashboard.
func (dash *Dashboard) LogError(name, msg string, args ...interface{}) {
req := &LogEntry{
Name: name,
Text: fmt.Sprintf(msg, args...),
}
dash.Query("log_error", req, nil)
}
// BugReport describes a single bug.
// Used by dashboard external reporting.
type BugReport struct {
Type ReportType
BugStatus BugStatus
Namespace string
Config []byte
ID string
JobID string
ExtID string // arbitrary reporting ID forwarded from BugUpdate.ExtID
First bool // Set for first report for this bug (Type == ReportNew).
Moderation bool
NoRepro bool // We don't expect repro (e.g. for build/boot errors).
Title string
Link string // link to the bug on dashboard
CreditEmail string // email for the Reported-by tag
Maintainers []string // deprecated in favor of Recipients
CC []string // deprecated in favor of Recipients
Recipients Recipients
OS string
Arch string
VMArch string
UserSpaceArch string // user-space arch as kernel developers know it (rather than Go names)
BuildID string
BuildTime time.Time
CompilerID string
KernelRepo string
KernelRepoAlias string
KernelBranch string
KernelCommit string
KernelCommitTitle string
KernelCommitDate time.Time
KernelConfig []byte
KernelConfigLink string
SyzkallerCommit string
Log []byte
LogLink string
LogHasStrace bool
Report []byte
ReportLink string
ReproC []byte
ReproCLink string
ReproSyz []byte
ReproSyzLink string
ReproIsRevoked bool
ReproOpts []byte
MachineInfo []byte
MachineInfoLink string
Manager string
CrashID int64 // returned back in BugUpdate
CrashTime time.Time
NumCrashes int64
HappenedOn []string // list of kernel repo aliases
CrashTitle string // job execution crash title
Error []byte // job execution error
ErrorLink string
ErrorTruncated bool // full Error text is too large and was truncated
PatchLink string
BisectCause *BisectResult
BisectFix *BisectResult
Assets []Asset
Subsystems []BugSubsystem
ReportElements *ReportElements
LabelMessages map[string]string // notification messages for bug labels
}
type ReportElements struct {
GuiltyFiles []string
}
type BugSubsystem struct {
Name string
Link string
SetBy string
}
type Asset struct {
Title string
DownloadURL string
Type AssetType
FsckLogURL string
FsIsClean bool
}
type AssetType string
// Asset types used throughout the system.
// DO NOT change them, this will break compatibility with DB content.
const (
BootableDisk AssetType = "bootable_disk"
NonBootableDisk AssetType = "non_bootable_disk"
KernelObject AssetType = "kernel_object"
KernelImage AssetType = "kernel_image"
HTMLCoverageReport AssetType = "html_coverage_report"
MountInRepro AssetType = "mount_in_repro"
)
type BisectResult struct {
Commit *Commit // for conclusive bisection
Commits []*Commit // for inconclusive bisection
LogLink string
CrashLogLink string
CrashReportLink string
Fix bool
CrossTree bool
// In case a missing backport was backported.
Backported *Commit
}
type BugListReport struct {
ID string
Created time.Time
Config []byte
Bugs []BugListItem
TotalStats BugListReportStats
PeriodStats BugListReportStats
PeriodDays int
Link string
Subsystem string
Maintainers []string
Moderation bool
}
type BugListReportStats struct {
Reported int
LowPrio int
Fixed int
}
// BugListItem represents a single bug from the BugListReport entity.
type BugListItem struct {
ID string
Title string
Link string
ReproLevel ReproLevel
Hits int64
}
type BugListUpdate struct {
ID string // copied from BugListReport
ExtID string
Link string
Command BugListUpdateCommand
}
type BugListUpdateCommand string
const (
BugListSentCmd BugListUpdateCommand = "sent"
BugListUpdateCmd BugListUpdateCommand = "update"
BugListUpstreamCmd BugListUpdateCommand = "upstream"
BugListRegenerateCmd BugListUpdateCommand = "regenerate"
)
type BugUpdate struct {
ID string // copied from BugReport
JobID string // copied from BugReport
ExtID string
Link string
Status BugStatus
StatusReason BugStatusReason
Labels []string // the reported labels
ReproLevel ReproLevel
DupOf string
OnHold bool // If set for open bugs, don't upstream this bug.
Notification bool // Reply to a notification.
ResetFixCommits bool // Remove all commits (empty FixCommits means leave intact).
FixCommits []string // Titles of commits that fix this bug.
CC []string // Additional emails to add to CC list in future emails.
CrashID int64 // This is a deprecated field, left here for backward compatibility.
// The new interface that allows to report and unreport several crashes at the same time.
// This is not relevant for emails, but may be important for external reportings.
ReportCrashIDs []int64
UnreportCrashIDs []int64
}
type BugUpdateReply struct {
// Bug update can fail for 2 reason:
// - update does not pass logical validataion, in this case OK=false
// - internal/datastore error, in this case Error=true
OK bool
Error bool
Text string
}
type PollBugsRequest struct {
Type string
}
type PollBugsResponse struct {
Reports []*BugReport
}
type BugNotification struct {
Type BugNotif
Namespace string
Config []byte
ID string
ExtID string // arbitrary reporting ID forwarded from BugUpdate.ExtID
Title string
Text string // meaning depends on Type
Label string // for BugNotifLabel Type specifies the exact label
CC []string // deprecated in favor of Recipients
Maintainers []string // deprecated in favor of Recipients
Link string
Recipients Recipients
TreeJobs []*JobInfo // set for some BugNotifLabel
// Public is what we want all involved people to see (e.g. if we notify about a wrong commit title,
// people need to see it and provide the right title). Not public is what we want to send only
// to a minimal set of recipients (our mailing list) (e.g. notification about an obsoleted bug
// is mostly "for the record").
Public bool
}
type PollNotificationsRequest struct {
Type string
}
type PollNotificationsResponse struct {
Notifications []*BugNotification
}
type PollClosedRequest struct {
IDs []string
}
type PollClosedResponse struct {
IDs []string
}
type DiscussionSource string
const (
NoDiscussion DiscussionSource = ""
DiscussionLore DiscussionSource = "lore"
)
type DiscussionType string
const (
DiscussionReport DiscussionType = "report"
DiscussionPatch DiscussionType = "patch"
DiscussionReminder DiscussionType = "reminder"
DiscussionMention DiscussionType = "mention"
)
type Discussion struct {
ID string
Source DiscussionSource
Type DiscussionType
Subject string
BugIDs []string
Messages []DiscussionMessage
}
type DiscussionMessage struct {
ID string
External bool // true if the message is not from the bot itself
Time time.Time
Email string // not saved to the DB
}
type SaveDiscussionReq struct {
// If the discussion already exists, Messages and BugIDs will be appended to it.
Discussion *Discussion
}
func (dash *Dashboard) SaveDiscussion(req *SaveDiscussionReq) error {
return dash.Query("save_discussion", req, nil)
}
func (dash *Dashboard) CreateUploadURL() (string, error) {
uploadURL := new(string)
if err := dash.Query("create_upload_url", nil, uploadURL); err != nil {
return "", fmt.Errorf("create_upload_url: %w", err)
}
return *uploadURL, nil
}
// SaveCoverage returns amount of records created in db.
func (dash *Dashboard) SaveCoverage(gcpURL string) (int, error) {
rowsWritten := new(int)
if err := dash.Query("save_coverage", gcpURL, rowsWritten); err != nil {
return 0, fmt.Errorf("save_coverage: %w", err)
}
return *rowsWritten, nil
}
type TestPatchRequest struct {
BugID string
Link string
User string
Repo string
Branch string
Patch []byte
}
type TestPatchReply struct {
ErrorText string
}
func (dash *Dashboard) ReportingPollBugs(typ string) (*PollBugsResponse, error) {
req := &PollBugsRequest{
Type: typ,
}
resp := new(PollBugsResponse)
if err := dash.Query("reporting_poll_bugs", req, resp); err != nil {
return nil, err
}
return resp, nil
}
func (dash *Dashboard) ReportingPollNotifications(typ string) (*PollNotificationsResponse, error) {
req := &PollNotificationsRequest{
Type: typ,
}
resp := new(PollNotificationsResponse)
if err := dash.Query("reporting_poll_notifs", req, resp); err != nil {
return nil, err
}
return resp, nil
}
func (dash *Dashboard) ReportingPollClosed(ids []string) ([]string, error) {
req := &PollClosedRequest{
IDs: ids,
}
resp := new(PollClosedResponse)
if err := dash.Query("reporting_poll_closed", req, resp); err != nil {
return nil, err
}
return resp.IDs, nil
}
func (dash *Dashboard) ReportingUpdate(upd *BugUpdate) (*BugUpdateReply, error) {
resp := new(BugUpdateReply)
if err := dash.Query("reporting_update", upd, resp); err != nil {
return nil, err
}
return resp, nil
}
func (dash *Dashboard) NewTestJob(upd *TestPatchRequest) (*TestPatchReply, error) {
resp := new(TestPatchReply)
if err := dash.Query("new_test_job", upd, resp); err != nil {
return nil, err
}
return resp, nil
}
type ManagerStatsReq struct {
Name string
Addr string
// Current level:
UpTime time.Duration
Corpus uint64
PCs uint64 // coverage
Cover uint64 // what we call feedback signal everywhere else
CrashTypes uint64
// Delta since last sync:
FuzzingTime time.Duration
Crashes uint64
SuppressedCrashes uint64
Execs uint64
// Non-zero only when set.
TriagedCoverage uint64
TriagedPCs uint64
}
func (dash *Dashboard) UploadManagerStats(req *ManagerStatsReq) error {
return dash.Query("manager_stats", req, nil)
}
// Asset lifetime:
// 1. syz-ci uploads it to GCS and reports to the dashboard via add_build_asset.
// 2. dashboard periodically checks if the asset is still needed.
// 3. syz-ci queries needed_assets to figure out which assets are still needed.
// 4. Once an asset is not needed, syz-ci removes the corresponding file.
type NewAsset struct {
DownloadURL string
Type AssetType
FsckLog []byte
FsIsClean bool
}
type AddBuildAssetsReq struct {
BuildID string
Assets []NewAsset
}
func (dash *Dashboard) AddBuildAssets(req *AddBuildAssetsReq) error {
return dash.Query("add_build_assets", req, nil)
}
type NeededAssetsResp struct {
DownloadURLs []string
}
func (dash *Dashboard) NeededAssetsList() (*NeededAssetsResp, error) {
resp := new(NeededAssetsResp)
err := dash.Query("needed_assets", nil, resp)
return resp, err
}
type BugListResp struct {
List []string
}
func (dash *Dashboard) BugList() (*BugListResp, error) {
resp := new(BugListResp)
err := dash.Query("bug_list", nil, resp)
return resp, err
}
type LoadBugReq struct {
ID string
}
func (dash *Dashboard) LoadBug(id string) (*BugReport, error) {
req := LoadBugReq{id}
resp := new(BugReport)
err := dash.Query("load_bug", req, resp)
return resp, err
}
type LoadFullBugReq struct {
BugID string
}
type FullBugInfo struct {
SimilarBugs []*SimilarBugInfo
BisectCause *BugReport
BisectFix *BugReport
Crashes []*BugReport
TreeJobs []*JobInfo
FixCandidate *BugReport
}
type SimilarBugInfo struct {
Title string
Status BugStatus
Namespace string
Link string
ReportLink string
Closed time.Time
ReproLevel ReproLevel
}
func (dash *Dashboard) LoadFullBug(req *LoadFullBugReq) (*FullBugInfo, error) {
resp := new(FullBugInfo)
err := dash.Query("load_full_bug", req, resp)
return resp, err
}
type UpdateReportReq struct {
BugID string
CrashID int64
GuiltyFiles *[]string
}
func (dash *Dashboard) UpdateReport(req *UpdateReportReq) error {
return dash.Query("update_report", req, nil)
}
type SendEmailReq struct {
Sender string
To []string
Cc []string
Subject string
InReplyTo string
Body string
}
func (dash *Dashboard) SendEmail(req *SendEmailReq) error {
return dash.Query("send_email", req, nil)
}
type (
BugStatus int
BugStatusReason string
BugNotif int
ReproLevel int
ReportType int
)
const (
BugStatusOpen BugStatus = iota
BugStatusUpstream
BugStatusInvalid
BugStatusDup
BugStatusUpdate // aux info update (i.e. ExtID/Link/CC)
BugStatusUnCC // don't CC sender on any future communication
BugStatusFixed
)
const (
InvalidatedByRevokedRepro = BugStatusReason("invalid_no_repro")
InvalidatedByNoActivity = BugStatusReason("invalid_no_activity")
)
const (
// Upstream bug into next reporting.
// If the action succeeds, reporting sends BugStatusUpstream update.
BugNotifUpstream BugNotif = iota
// Bug needs to be closed as obsoleted.
// If the action succeeds, reporting sends BugStatusInvalid update.
BugNotifObsoleted
// Bug fixing commit can't be discovered (wrong commit title).
BugNotifBadCommit
// New bug label has been assigned (only if enabled).
// Text contains the custome message that needs to be delivered to the user.
BugNotifLabel
)
const (
ReproLevelNone ReproLevel = iota
ReproLevelSyz
ReproLevelC
)
const (
ReportNew ReportType = iota // First report for this bug in the reporting stage.
ReportRepro // Found repro for an already reported bug.
ReportTestPatch // Patch testing result.
ReportBisectCause // Cause bisection result for an already reported bug.
ReportBisectFix // Fix bisection result for an already reported bug.
)
type JobInfo struct {
JobKey string
Type JobType
Flags JobDoneFlags
Created time.Time
BugLink string
ExternalLink string
User string
Reporting string
Namespace string
Manager string
BugTitle string
BugID string
KernelRepo string
KernelBranch string
KernelAlias string
KernelCommit string
KernelCommitLink string
KernelLink string
PatchLink string
Attempts int
Started time.Time
Finished time.Time
Duration time.Duration
CrashTitle string
CrashLogLink string
CrashReportLink string
LogLink string
ErrorLink string
ReproCLink string
ReproSyzLink string
Commit *Commit // for conclusive bisection
Commits []*Commit // for inconclusive bisection
Reported bool
InvalidatedBy string
TreeOrigin bool
OnMergeBase bool
}
func (dash *Dashboard) Query(method string, req, reply interface{}) error {
if dash.logger != nil {
dash.logger("API(%v): %#v", method, req)
}
err := dash.queryImpl(method, req, reply)
if err != nil {
if dash.logger != nil {
dash.logger("API(%v): ERROR: %v", method, err)
}
if dash.errorHandler != nil {
dash.errorHandler(err)
}
return err
}
if dash.logger != nil {
dash.logger("API(%v): REPLY: %#v", method, reply)
}
return nil
}
func (dash *Dashboard) queryImpl(method string, req, reply interface{}) error {
if reply != nil {
// json decoding behavior is somewhat surprising
// (see // https://github.com/golang/go/issues/21092).
// To avoid any surprises, we zero the reply.
typ := reflect.TypeOf(reply)
if typ.Kind() != reflect.Ptr {
return fmt.Errorf("resp must be a pointer")
}
reflect.ValueOf(reply).Elem().Set(reflect.New(typ.Elem()).Elem())
}
body := &bytes.Buffer{}
mWriter := multipart.NewWriter(body)
err := mWriter.WriteField("client", dash.Client)
if err != nil {
return err
}
err = mWriter.WriteField("key", dash.Key)
if err != nil {
return err
}
err = mWriter.WriteField("method", method)
if err != nil {
return err
}
if req != nil {
w, err := mWriter.CreateFormField("payload")
if err != nil {
return err
}
gz := gzip.NewWriter(w)
encoder := json.NewEncoder(gz)
if err := encoder.Encode(req); err != nil {
return fmt.Errorf("failed to marshal request: %w", err)
}
if err := gz.Close(); err != nil {
return err
}
}
mWriter.Close()
r, err := dash.ctor("POST", fmt.Sprintf("%v/api", dash.Addr), body)
if err != nil {
return err
}
r.Header.Set("Content-Type", mWriter.FormDataContentType())
resp, err := dash.doer(r)
if err != nil {
return fmt.Errorf("http request failed: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
data, _ := io.ReadAll(resp.Body)
return fmt.Errorf("request failed with %v: %s", resp.Status, data)
}
if reply != nil {
if err := json.NewDecoder(resp.Body).Decode(reply); err != nil {
return fmt.Errorf("failed to unmarshal response: %w", err)
}
}
return nil
}
type RecipientType int
const (
To RecipientType = iota
Cc
)
func (t RecipientType) String() string {
return [...]string{"To", "Cc"}[t]
}
type RecipientInfo struct {
Address mail.Address
Type RecipientType
}
type Recipients []RecipientInfo
func (r Recipients) Len() int { return len(r) }
func (r Recipients) Less(i, j int) bool { return r[i].Address.Address < r[j].Address.Address }
func (r Recipients) Swap(i, j int) { r[i], r[j] = r[j], r[i] }
// Copyright 2022 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package asset
import (
"fmt"
"strings"
"time"
"github.com/google/syzkaller/pkg/gcs"
)
type objectUploadCallback func(req *uploadRequest) (*uploadResponse, error)
type objectRemoveCallback func(url string) error
type dummyObject struct {
createdAt time.Time
contentType string
contentEncoding string
}
type dummyStorageBackend struct {
currentTime time.Time
objects map[string]*dummyObject
objectUpload objectUploadCallback
objectRemove objectRemoveCallback
}
func makeDummyStorageBackend() *dummyStorageBackend {
return &dummyStorageBackend{
currentTime: time.Now(),
objects: make(map[string]*dummyObject),
}
}
type dummyWriteCloser struct {
}
func (dwc *dummyWriteCloser) Write(p []byte) (int, error) {
return len(p), nil
}
func (dwc *dummyWriteCloser) Close() error {
return nil
}
func (be *dummyStorageBackend) upload(req *uploadRequest) (*uploadResponse, error) {
be.objects[req.savePath] = &dummyObject{
createdAt: be.currentTime,
contentType: req.contentType,
contentEncoding: req.contentEncoding,
}
if be.objectUpload != nil {
return be.objectUpload(req)
}
return &uploadResponse{writer: &dummyWriteCloser{}, path: req.savePath}, nil
}
func (be *dummyStorageBackend) downloadURL(path string, publicURL bool) (string, error) {
return "http://download/" + path, nil
}
func (be *dummyStorageBackend) getPath(url string) (string, error) {
if strings.HasPrefix(url, "http://unknown-bucket/") {
return "", ErrUnknownBucket
}
if strings.HasPrefix(url, "http://download/") {
return strings.TrimPrefix(url, "http://download/"), nil
}
return "", fmt.Errorf("unknown URL format")
}
func (be *dummyStorageBackend) list() ([]*gcs.Object, error) {
ret := []*gcs.Object{}
for path, obj := range be.objects {
ret = append(ret, &gcs.Object{
Path: path,
CreatedAt: obj.createdAt,
})
}
return ret, nil
}
func (be *dummyStorageBackend) remove(path string) error {
if be.objectRemove != nil {
if err := be.objectRemove(path); err != nil {
return err
}
}
if _, ok := be.objects[path]; !ok {
return ErrAssetDoesNotExist
}
delete(be.objects, path)
return nil
}
func (be *dummyStorageBackend) hasOnly(paths []string) error {
makeError := func() error {
return fmt.Errorf("object sets are not equal; needed: %#v; uploaded: %#v", paths, be.objects)
}
if len(paths) != len(be.objects) {
return makeError()
}
for _, path := range paths {
if be.objects[path] == nil {
return makeError()
}
}
return nil
}
// Copyright 2022 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package asset
import (
"context"
"fmt"
"io"
"net/url"
"regexp"
"strings"
"github.com/google/syzkaller/pkg/debugtracer"
"github.com/google/syzkaller/pkg/gcs"
)
type cloudStorageBackend struct {
client gcs.Client
bucket string
tracer debugtracer.DebugTracer
}
func makeCloudStorageBackend(bucket string, tracer debugtracer.DebugTracer) (*cloudStorageBackend, error) {
tracer.Log("created gcs backend for bucket '%s'", bucket)
client, err := gcs.NewClient(context.Background())
if err != nil {
return nil, fmt.Errorf("the call to NewClient failed: %w", err)
}
return &cloudStorageBackend{
client: client,
bucket: bucket,
tracer: tracer,
}, nil
}
// Actual write errors might be hidden, so we wrap the writer here
// to ensure that they get logged.
type writeErrorLogger struct {
writeCloser io.WriteCloser
tracer debugtracer.DebugTracer
}
func (wel *writeErrorLogger) Write(p []byte) (n int, err error) {
n, err = wel.writeCloser.Write(p)
if err != nil {
wel.tracer.Log("cloud storage write error: %s", err)
}
return
}
func (wel *writeErrorLogger) Close() error {
err := wel.writeCloser.Close()
if err != nil {
wel.tracer.Log("cloud storage writer close error: %s", err)
}
return err
}
func (csb *cloudStorageBackend) upload(req *uploadRequest) (*uploadResponse, error) {
path := fmt.Sprintf("%s/%s", csb.bucket, req.savePath)
// Best-effort check only. In the worst case we'll just overwite the file.
// The alternative would be to add an If-precondition, but it'd require
// complicated error-during-write handling.
exists, err := csb.client.FileExists(path)
if err != nil {
return nil, err
}
if exists {
return nil, &FileExistsError{req.savePath}
}
w, err := csb.client.FileWriter(path, req.contentType, req.contentEncoding)
csb.tracer.Log("gcs upload: obtained a writer for %s, error %s", path, err)
if err != nil {
return nil, err
}
return &uploadResponse{
writer: &writeErrorLogger{
writeCloser: w,
tracer: csb.tracer,
},
path: req.savePath,
}, nil
}
func (csb *cloudStorageBackend) downloadURL(path string, publicURL bool) (string, error) {
return gcs.GetDownloadURL(fmt.Sprintf("%s/%s", csb.bucket, path), publicURL), nil
}
var allowedDomainsRe = regexp.MustCompile(`^storage\.googleapis\.com|storage\.cloud\.google\.com$`)
func (csb *cloudStorageBackend) getPath(downloadURL string) (string, error) {
u, err := url.Parse(downloadURL)
if err != nil {
return "", fmt.Errorf("failed to parse the URL: %w", err)
}
if !allowedDomainsRe.MatchString(u.Host) {
return "", fmt.Errorf("not allowed host: %s", u.Host)
}
prefix := "/" + csb.bucket + "/"
if !strings.HasPrefix(u.Path, prefix) {
return "", ErrUnknownBucket
}
return u.Path[len(prefix):], nil
}
func (csb *cloudStorageBackend) list() ([]*gcs.Object, error) {
return csb.client.ListObjects(csb.bucket)
}
func (csb *cloudStorageBackend) remove(path string) error {
path = fmt.Sprintf("%s/%s", csb.bucket, path)
err := csb.client.DeleteFile(path)
if err == gcs.ErrFileNotFound {
return ErrAssetDoesNotExist
}
return err
}
// Copyright 2022 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package asset
import (
"fmt"
"strings"
"github.com/google/syzkaller/dashboard/dashapi"
)
type Config struct {
// Debug mode forces syz-ci upload artifacts on each syz-manager restart and also forces
// it to produce more logs.
Debug bool `json:"debug"`
// Where to upload artifacts.
// If "gs://bucket/" is specified, assets will be stored in the corresponding GCS bucket.
// If "dummy://" is specified, assets will not be actually stored anywhere. May be helpful
// for debugging.
UploadTo string `json:"upload_to"`
// Perform asset deprecation from this instance. If several syz-ci's share a common stoage,
// it make sense to enable derprecation only on one of them.
DoDeprecation bool `json:"do_deprecation"`
// Make assets publicly available (note that it also might require special configuration
// on the storage backend's side).
PublicAccess bool `json:"public_access"`
// Some asset type-specific configurations. By default all asset types are enabled.
Assets map[dashapi.AssetType]TypeConfig `json:"assets"`
}
type TypeConfig struct {
Never bool `json:"never"`
// TODO: in future there'll also be `OnlyOn` and `NeverOn`, but so far we don't really need that.
// TODO: here will also go compression settings, should we ever want to make it configurable.
}
func (tc *TypeConfig) Validate() error {
return nil
}
func (c *Config) IsEnabled(assetType dashapi.AssetType) bool {
return !c.Assets[assetType].Never
}
func (c *Config) IsEmpty() bool {
return c == nil
}
func (c *Config) Validate() error {
for assetType, cfg := range c.Assets {
if GetTypeDescription(assetType) == nil {
return fmt.Errorf("invalid asset type: %s", assetType)
}
if err := cfg.Validate(); err != nil {
return fmt.Errorf("invalid config for %s: %w", assetType, err)
}
}
if c.UploadTo == "" && len(c.Assets) != 0 {
return fmt.Errorf("assets are specified, but upload_to is empty")
}
allowedFormats := []string{"gs://", "dummy://"}
if c.UploadTo != "" {
any := false
for _, prefix := range allowedFormats {
if strings.HasPrefix(c.UploadTo, prefix) {
any = true
}
}
if !any {
return fmt.Errorf("the currently supported upload destinations are: %v", allowedFormats)
}
}
return nil
}
// Copyright 2022 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package asset
import (
"compress/gzip"
"crypto/sha256"
"errors"
"fmt"
"io"
"os"
"os/exec"
"path/filepath"
"strings"
"time"
"github.com/google/syzkaller/pkg/gcs"
"github.com/ulikunitz/xz"
"github.com/google/syzkaller/dashboard/dashapi"
"github.com/google/syzkaller/pkg/debugtracer"
)
type Storage struct {
cfg *Config
backend StorageBackend
dash Dashboard
tracer debugtracer.DebugTracer
}
type Dashboard interface {
AddBuildAssets(req *dashapi.AddBuildAssetsReq) error
NeededAssetsList() (*dashapi.NeededAssetsResp, error)
}
func StorageFromConfig(cfg *Config, dash Dashboard) (*Storage, error) {
if dash == nil {
return nil, fmt.Errorf("dashboard api instance is necessary")
}
tracer := debugtracer.DebugTracer(&debugtracer.NullTracer{})
if cfg.Debug {
tracer = &debugtracer.GenericTracer{
WithTime: true,
TraceWriter: os.Stdout,
}
}
var backend StorageBackend
if strings.HasPrefix(cfg.UploadTo, "gs://") {
var err error
backend, err = makeCloudStorageBackend(strings.TrimPrefix(cfg.UploadTo, "gs://"), tracer)
if err != nil {
return nil, fmt.Errorf("the call to MakeCloudStorageBackend failed: %w", err)
}
} else if strings.HasPrefix(cfg.UploadTo, "dummy://") {
backend = makeDummyStorageBackend()
} else {
return nil, fmt.Errorf("unknown UploadTo during StorageFromConfig(): %#v", cfg.UploadTo)
}
return &Storage{
cfg: cfg,
backend: backend,
dash: dash,
tracer: tracer,
}, nil
}
func (storage *Storage) AssetTypeEnabled(assetType dashapi.AssetType) bool {
return storage.cfg.IsEnabled(assetType)
}
func (storage *Storage) getDefaultCompressor() Compressor {
return xzCompressor
}
type ExtraUploadArg struct {
// It is assumed that paths constructed with same UniqueTag values
// always correspond to an asset having the same content.
UniqueTag string
// If the asset being uploaded already exists (see above), don't return
// an error, abort uploading and return the download URL.
SkipIfExists bool
}
var ErrAssetTypeDisabled = errors.New("uploading assets of this type is disabled")
func (storage *Storage) assetPath(name string, extra *ExtraUploadArg) string {
folderName := ""
if extra != nil && extra.UniqueTag != "" {
folderName = extra.UniqueTag
} else {
// The idea is to make a file name useful and yet unique.
// So we put a file to a pseudo-unique "folder".
folderNameBytes := sha256.Sum256([]byte(fmt.Sprintf("%v", time.Now().UnixNano())))
folderName = fmt.Sprintf("%x", folderNameBytes)
}
const folderPrefix = 12
if len(folderName) > folderPrefix {
folderName = folderName[0:folderPrefix]
}
return fmt.Sprintf("%s/%s", folderName, name)
}
func (storage *Storage) uploadFileStream(reader io.Reader, assetType dashapi.AssetType,
name string, extra *ExtraUploadArg) (string, error) {
if name == "" {
return "", fmt.Errorf("file name is not specified")
}
typeDescr := GetTypeDescription(assetType)
if typeDescr == nil {
return "", fmt.Errorf("asset type %s is unknown", assetType)
}
if !storage.AssetTypeEnabled(assetType) {
return "", fmt.Errorf("not allowed to upload an asset of type %s: %w",
assetType, ErrAssetTypeDisabled)
}
path := storage.assetPath(name, extra)
req := &uploadRequest{
savePath: path,
contentType: typeDescr.ContentType,
contentEncoding: typeDescr.ContentEncoding,
preserveExtension: typeDescr.preserveExtension,
}
if req.contentType == "" {
req.contentType = "application/octet-stream"
}
compressor := storage.getDefaultCompressor()
if typeDescr.customCompressor != nil {
compressor = typeDescr.customCompressor
}
res, err := compressor(req, storage.backend.upload)
var existsErr *FileExistsError
if errors.As(err, &existsErr) {
storage.tracer.Log("asset %s already exists", path)
if extra == nil || !extra.SkipIfExists {
return "", err
}
// Let's just return the download URL.
return storage.backend.downloadURL(existsErr.Path, storage.cfg.PublicAccess)
} else if err != nil {
return "", fmt.Errorf("failed to query writer: %w", err)
} else {
written, err := io.Copy(res.writer, reader)
if err != nil {
more := ""
closeErr := res.writer.Close()
var exiterr *exec.ExitError
if errors.As(closeErr, &exiterr) {
more = fmt.Sprintf(", process state '%s'", exiterr.ProcessState)
}
return "", fmt.Errorf("failed to redirect byte stream: copied %d bytes, error %w%s",
written, err, more)
}
err = res.writer.Close()
if err != nil {
return "", fmt.Errorf("failed to close writer: %w", err)
}
}
return storage.backend.downloadURL(res.path, storage.cfg.PublicAccess)
}
func (storage *Storage) UploadBuildAsset(reader io.Reader, fileName string, assetType dashapi.AssetType,
build *dashapi.Build, extra *ExtraUploadArg) (dashapi.NewAsset, error) {
const commitPrefix = 8
commit := build.KernelCommit
if len(commit) > commitPrefix {
commit = commit[:commitPrefix]
}
baseName := filepath.Base(fileName)
fileExt := filepath.Ext(baseName)
name := fmt.Sprintf("%s-%s%s",
strings.TrimSuffix(baseName, fileExt),
commit,
fileExt)
url, err := storage.uploadFileStream(reader, assetType, name, extra)
if err != nil {
return dashapi.NewAsset{}, err
}
return dashapi.NewAsset{
Type: assetType,
DownloadURL: url,
}, nil
}
func (storage *Storage) ReportBuildAssets(build *dashapi.Build, assets ...dashapi.NewAsset) error {
// If the server denies the reques, we'll delete the orphaned file during deprecated files
// deletion later.
return storage.dash.AddBuildAssets(&dashapi.AddBuildAssetsReq{
BuildID: build.ID,
Assets: assets,
})
}
func (storage *Storage) UploadCrashAsset(reader io.Reader, fileName string, assetType dashapi.AssetType,
extra *ExtraUploadArg) (dashapi.NewAsset, error) {
url, err := storage.uploadFileStream(reader, assetType, fileName, extra)
if err != nil {
return dashapi.NewAsset{}, err
}
return dashapi.NewAsset{
Type: assetType,
DownloadURL: url,
}, nil
}
var ErrAssetDoesNotExist = errors.New("the asset did not exist")
type FileExistsError struct {
// The path gets changed by wrappers, so we need to return it back.
Path string
}
func (e *FileExistsError) Error() string {
return fmt.Sprintf("asset exists: %s", e.Path)
}
var ErrUnknownBucket = errors.New("the asset is not in the currently managed bucket")
const deletionEmbargo = time.Hour * 24 * 7
type DeprecateStats struct {
Needed int // The count of assets currently needed in the dashboard.
Existing int // The number of assets currently stored.
Deleted int // How many were deleted during DeprecateAssets().
}
// Best way: convert download URLs to paths.
// We don't want to risk killing all assets after a slight domain change.
func (storage *Storage) DeprecateAssets() (DeprecateStats, error) {
var stats DeprecateStats
resp, err := storage.dash.NeededAssetsList()
if err != nil {
return stats, fmt.Errorf("failed to query needed assets: %w", err)
}
needed := map[string]bool{}
for _, url := range resp.DownloadURLs {
path, err := storage.backend.getPath(url)
if err == ErrUnknownBucket {
// The asset is not managed by the particular instance.
continue
} else if err != nil {
// If we failed to parse just one URL, let's stop the entire process.
// Otherwise we'll start deleting still needed files we couldn't recognize.
return stats, fmt.Errorf("failed to parse '%s': %w", url, err)
}
needed[path] = true
}
stats.Needed = len(needed)
storage.tracer.Log("queried needed assets: %#v", needed)
existing, err := storage.backend.list()
if err != nil {
return stats, fmt.Errorf("failed to query object list: %w", err)
}
stats.Existing = len(existing)
toDelete := []string{}
intersection := 0
for _, obj := range existing {
keep := false
if time.Since(obj.CreatedAt) < deletionEmbargo {
// To avoid races between object upload and object deletion, we don't delete
// newly uploaded files for a while after they're uploaded.
keep = true
}
if val, ok := needed[obj.Path]; ok && val {
keep = true
intersection++
}
storage.tracer.Log("-- object %v, %v: keep %t", obj.Path, obj.CreatedAt, keep)
if !keep {
toDelete = append(toDelete, obj.Path)
}
}
const intersectionCheckCutOff = 4
if len(existing) > intersectionCheckCutOff && intersection == 0 {
// This is a last-resort protection against possible dashboard bugs.
// If the needed assets have no intersection with the existing assets,
// don't delete anything. Otherwise, if it was a bug, we will lose all files.
return stats, fmt.Errorf("needed assets have almost no intersection with the existing ones")
}
for _, path := range toDelete {
err := storage.backend.remove(path)
storage.tracer.Log("-- deleted %v: %v", path, err)
// Several syz-ci's might be sharing the same storage. So let's tolerate
// races during file deletion.
if err != nil && err != ErrAssetDoesNotExist {
return stats, fmt.Errorf("asset deletion failure: %w", err)
}
}
stats.Deleted = len(toDelete)
return stats, nil
}
type uploadRequest struct {
savePath string
contentEncoding string
contentType string
preserveExtension bool
}
type uploadResponse struct {
path string
writer io.WriteCloser
}
type StorageBackend interface {
upload(req *uploadRequest) (*uploadResponse, error)
list() ([]*gcs.Object, error)
remove(path string) error
downloadURL(path string, publicURL bool) (string, error)
getPath(url string) (string, error)
}
type Compressor func(req *uploadRequest,
next func(req *uploadRequest) (*uploadResponse, error)) (*uploadResponse, error)
func xzCompressor(req *uploadRequest,
next func(req *uploadRequest) (*uploadResponse, error)) (*uploadResponse, error) {
newReq := *req
if !req.preserveExtension {
newReq.savePath = fmt.Sprintf("%s.xz", newReq.savePath)
}
resp, err := next(&newReq)
if err != nil {
return nil, err
}
xzWriter, err := xz.NewWriter(resp.writer)
if err != nil {
return nil, fmt.Errorf("failed to create xz writer: %w", err)
}
return &uploadResponse{
path: resp.path,
writer: &wrappedWriteCloser{
writer: xzWriter,
closeCallback: resp.writer.Close,
},
}, nil
}
const gzipCompressionRatio = 4
// This struct allows to attach a callback on the Close() method invocation of
// an existing io.WriteCloser. Also, it can convert an io.Writer to an io.WriteCloser.
type wrappedWriteCloser struct {
writer io.Writer
closeCallback func() error
}
func (wwc *wrappedWriteCloser) Write(p []byte) (int, error) {
return wwc.writer.Write(p)
}
func (wwc *wrappedWriteCloser) Close() error {
var err error
closer, ok := wwc.writer.(io.Closer)
if ok {
err = closer.Close()
}
err2 := wwc.closeCallback()
if err != nil {
return err
} else if err2 != nil {
return err2
}
return nil
}
func gzipCompressor(req *uploadRequest,
next func(req *uploadRequest) (*uploadResponse, error)) (*uploadResponse, error) {
newReq := *req
if !req.preserveExtension {
newReq.savePath = fmt.Sprintf("%s.gz", newReq.savePath)
}
resp, err := next(&newReq)
if err != nil {
return nil, err
}
gzip, err := gzip.NewWriterLevel(resp.writer, gzipCompressionRatio)
if err != nil {
resp.writer.Close()
return nil, err
}
return &uploadResponse{
path: resp.path,
writer: &wrappedWriteCloser{
writer: gzip,
closeCallback: func() error {
return resp.writer.Close()
},
},
}, nil
}
// Copyright 2022 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package asset
import (
"github.com/google/syzkaller/dashboard/dashapi"
"github.com/google/syzkaller/sys/targets"
)
type TypeDescription struct {
AllowMultiple bool
GetTitle QueryTypeTitle
ContentType string
ContentEncoding string
ReportingPrio int // the smaller, the higher the asset is on the list during reporting
NoReporting bool
customCompressor Compressor
preserveExtension bool
}
var assetTypes = map[dashapi.AssetType]*TypeDescription{
dashapi.BootableDisk: {
GetTitle: constTitle("disk image"),
ReportingPrio: 1,
},
dashapi.NonBootableDisk: {
GetTitle: constTitle("disk image (non-bootable)"),
ReportingPrio: 2,
},
dashapi.KernelObject: {
GetTitle: func(target *targets.Target) string {
if target != nil && target.KernelObject != "" {
return target.KernelObject
}
return "kernel object"
},
ReportingPrio: 3,
},
dashapi.KernelImage: {
GetTitle: constTitle("kernel image"),
ReportingPrio: 4,
},
dashapi.HTMLCoverageReport: {
GetTitle: constTitle("coverage report(html)"),
AllowMultiple: true,
ContentType: "text/html",
ContentEncoding: "gzip", // We do want to decompress than right in the browser.
NoReporting: true,
customCompressor: gzipCompressor,
preserveExtension: true,
},
dashapi.MountInRepro: {
GetTitle: constTitle("mounted in repro"),
ReportingPrio: 5,
// It feels that such images are very well compressible, so we can just use
// the omnipresent gzip compression.
customCompressor: gzipCompressor,
},
}
type QueryTypeTitle func(*targets.Target) string
func constTitle(title string) QueryTypeTitle {
return func(*targets.Target) string {
return title
}
}
func GetTypeDescription(assetType dashapi.AssetType) *TypeDescription {
return assetTypes[assetType]
}
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
// Package ast parses and formats sys files.
package ast
// Pos represents source info for AST nodes.
type Pos struct {
File string
Off int // byte offset, starting at 0
Line int // line number, starting at 1
Col int // column number, starting at 1 (byte count)
}
// Description contains top-level nodes of a parsed sys description.
type Description struct {
Nodes []Node
}
// Node is AST node interface.
type Node interface {
Info() (pos Pos, typ, name string)
// Clone makes a deep copy of the node.
Clone() Node
// walk calls callback cb for all child nodes of this node.
// Note: it's not recursive. Use Recursive helper for recursive walk.
walk(cb func(Node))
}
type Flags[T FlagValue] interface {
SetValues(values []T)
GetValues() []T
GetPos() Pos
}
type FlagValue interface {
GetName() string
}
// Top-level AST nodes.
type NewLine struct {
Pos Pos
}
func (n *NewLine) Info() (Pos, string, string) {
return n.Pos, tok2str[tokNewLine], ""
}
type Comment struct {
Pos Pos
Text string
}
func (n *Comment) Info() (Pos, string, string) {
return n.Pos, tok2str[tokComment], ""
}
type Meta struct {
Pos Pos
Value *Type
}
func (n *Meta) Info() (Pos, string, string) {
return n.Pos, "meta", n.Value.Ident
}
type Include struct {
Pos Pos
File *String
}
func (n *Include) Info() (Pos, string, string) {
return n.Pos, tok2str[tokInclude], n.File.Value
}
type Incdir struct {
Pos Pos
Dir *String
}
func (n *Incdir) Info() (Pos, string, string) {
return n.Pos, tok2str[tokInclude], ""
}
type Define struct {
Pos Pos
Name *Ident
Value *Int
}
func (n *Define) Info() (Pos, string, string) {
return n.Pos, tok2str[tokDefine], n.Name.Name
}
type Resource struct {
Pos Pos
Name *Ident
Base *Type
Values []*Int
}
func (n *Resource) Info() (Pos, string, string) {
return n.Pos, tok2str[tokResource], n.Name.Name
}
type Call struct {
Pos Pos
Name *Ident
CallName string
NR uint64
Args []*Field
Ret *Type
Attrs []*Type
}
func (n *Call) Info() (Pos, string, string) {
return n.Pos, "syscall", n.Name.Name
}
type Struct struct {
Pos Pos
Name *Ident
Fields []*Field
Attrs []*Type
Comments []*Comment
IsUnion bool
}
func (n *Struct) Info() (Pos, string, string) {
typ := "struct"
if n.IsUnion {
typ = "union"
}
return n.Pos, typ, n.Name.Name
}
type IntFlags struct {
Pos Pos
Name *Ident
Values []*Int
}
func (n *IntFlags) Info() (Pos, string, string) {
return n.Pos, "flags", n.Name.Name
}
func (n *IntFlags) SetValues(values []*Int) {
n.Values = values
}
func (n *IntFlags) GetValues() []*Int {
return n.Values
}
func (n *IntFlags) GetPos() Pos {
return n.Pos
}
type StrFlags struct {
Pos Pos
Name *Ident
Values []*String
}
func (n *StrFlags) Info() (Pos, string, string) {
return n.Pos, "string flags", n.Name.Name
}
func (n *StrFlags) SetValues(values []*String) {
n.Values = values
}
func (n *StrFlags) GetValues() []*String {
return n.Values
}
func (n *StrFlags) GetPos() Pos {
return n.Pos
}
type TypeDef struct {
Pos Pos
Name *Ident
// Non-template type aliases have only Type filled.
// Templates have Args and either Type or Struct filled.
Args []*Ident
Type *Type
Struct *Struct
}
func (n *TypeDef) Info() (Pos, string, string) {
return n.Pos, "type", n.Name.Name
}
// Not top-level AST nodes.
type Ident struct {
Pos Pos
Name string
}
func (n *Ident) Info() (Pos, string, string) {
return n.Pos, tok2str[tokIdent], n.Name
}
type String struct {
Pos Pos
Value string
Fmt StrFmt
}
func (n *String) Info() (Pos, string, string) {
return n.Pos, tok2str[tokString], ""
}
func (n *String) GetName() string {
return n.Value
}
type IntFmt int
const (
IntFmtDec IntFmt = iota
IntFmtNeg
IntFmtHex
IntFmtChar
)
type StrFmt int
const (
StrFmtRaw StrFmt = iota
StrFmtHex
StrFmtIdent
)
type Int struct {
Pos Pos
// Only one of Value, Ident, CExpr is filled.
Value uint64
ValueFmt IntFmt
Ident string
CExpr string
}
func (n *Int) Info() (Pos, string, string) {
return n.Pos, tok2str[tokInt], ""
}
func (n *Int) GetName() string {
return n.Ident
}
type Operator int
const (
OperatorCompareEq = iota + 1
OperatorCompareNeq
OperatorBinaryAnd
OperatorOr
)
type BinaryExpression struct {
Pos Pos
Operator Operator
Left *Type
Right *Type
}
func (n *BinaryExpression) Info() (Pos, string, string) {
return n.Pos, "binary-expression", ""
}
type Type struct {
Pos Pos
// Only one of Value, Ident, String, Expression is filled.
Value uint64
ValueFmt IntFmt
Ident string
String string
StringFmt StrFmt
HasString bool
Expression *BinaryExpression
// Parts after COLON (for ranges and bitfields).
Colon []*Type
// Sub-types in [].
Args []*Type
}
func (n *Type) Info() (Pos, string, string) {
return n.Pos, "type-opt", n.Ident
}
type Field struct {
Pos Pos
Name *Ident
Type *Type
Attrs []*Type
NewBlock bool // separated from previous fields by a new line
Comments []*Comment
}
func (n *Field) Info() (Pos, string, string) {
return n.Pos, "arg/field", n.Name.Name
}
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package ast
func (desc *Description) Clone() *Description {
desc1 := &Description{}
for _, n := range desc.Nodes {
desc1.Nodes = append(desc1.Nodes, n.Clone())
}
return desc1
}
func (n *NewLine) Clone() Node {
return &NewLine{
Pos: n.Pos,
}
}
func (n *Comment) Clone() Node {
return &Comment{
Pos: n.Pos,
Text: n.Text,
}
}
func (n *Meta) Clone() Node {
return &Meta{
Pos: n.Pos,
Value: n.Value.Clone().(*Type),
}
}
func (n *Include) Clone() Node {
return &Include{
Pos: n.Pos,
File: n.File.Clone().(*String),
}
}
func (n *Incdir) Clone() Node {
return &Incdir{
Pos: n.Pos,
Dir: n.Dir.Clone().(*String),
}
}
func (n *Define) Clone() Node {
return &Define{
Pos: n.Pos,
Name: n.Name.Clone().(*Ident),
Value: n.Value.Clone().(*Int),
}
}
func (n *Resource) Clone() Node {
return &Resource{
Pos: n.Pos,
Name: n.Name.Clone().(*Ident),
Base: n.Base.Clone().(*Type),
Values: cloneInts(n.Values),
}
}
func (n *TypeDef) Clone() Node {
var args []*Ident
for _, v := range n.Args {
args = append(args, v.Clone().(*Ident))
}
var typ *Type
if n.Type != nil {
typ = n.Type.Clone().(*Type)
}
var str *Struct
if n.Struct != nil {
str = n.Struct.Clone().(*Struct)
}
return &TypeDef{
Pos: n.Pos,
Name: n.Name.Clone().(*Ident),
Args: args,
Type: typ,
Struct: str,
}
}
func (n *Call) Clone() Node {
var ret *Type
if n.Ret != nil {
ret = n.Ret.Clone().(*Type)
}
return &Call{
Pos: n.Pos,
Name: n.Name.Clone().(*Ident),
CallName: n.CallName,
NR: n.NR,
Args: cloneFields(n.Args),
Ret: ret,
Attrs: cloneTypes(n.Attrs),
}
}
func (n *Struct) Clone() Node {
return &Struct{
Pos: n.Pos,
Name: n.Name.Clone().(*Ident),
Fields: cloneFields(n.Fields),
Attrs: cloneTypes(n.Attrs),
Comments: cloneComments(n.Comments),
IsUnion: n.IsUnion,
}
}
func (n *IntFlags) Clone() Node {
return &IntFlags{
Pos: n.Pos,
Name: n.Name.Clone().(*Ident),
Values: cloneInts(n.Values),
}
}
func (n *StrFlags) Clone() Node {
var values []*String
for _, v := range n.Values {
values = append(values, v.Clone().(*String))
}
return &StrFlags{
Pos: n.Pos,
Name: n.Name.Clone().(*Ident),
Values: values,
}
}
func (n *Ident) Clone() Node {
return &Ident{
Pos: n.Pos,
Name: n.Name,
}
}
func (n *String) Clone() Node {
return &String{
Pos: n.Pos,
Value: n.Value,
Fmt: n.Fmt,
}
}
func (n *Int) Clone() Node {
return &Int{
Pos: n.Pos,
Value: n.Value,
ValueFmt: n.ValueFmt,
Ident: n.Ident,
CExpr: n.CExpr,
}
}
func (n *Type) Clone() Node {
ret := &Type{
Pos: n.Pos,
Value: n.Value,
ValueFmt: n.ValueFmt,
Ident: n.Ident,
String: n.String,
StringFmt: n.StringFmt,
HasString: n.HasString,
Colon: cloneTypes(n.Colon),
Args: cloneTypes(n.Args),
}
if n.Expression != nil {
ret.Expression = n.Expression.Clone().(*BinaryExpression)
}
return ret
}
func (n *Field) Clone() Node {
return &Field{
Pos: n.Pos,
Name: n.Name.Clone().(*Ident),
Type: n.Type.Clone().(*Type),
Attrs: cloneTypes(n.Attrs),
NewBlock: n.NewBlock,
Comments: cloneComments(n.Comments),
}
}
func (n *BinaryExpression) Clone() Node {
return &BinaryExpression{
Pos: n.Pos,
Operator: n.Operator,
Left: n.Left.Clone().(*Type),
Right: n.Right.Clone().(*Type),
}
}
func cloneFields(list []*Field) (res []*Field) {
for _, n := range list {
res = append(res, n.Clone().(*Field))
}
return
}
func cloneInts(list []*Int) (res []*Int) {
for _, n := range list {
res = append(res, n.Clone().(*Int))
}
return
}
func cloneTypes(list []*Type) (res []*Type) {
for _, n := range list {
res = append(res, n.Clone().(*Type))
}
return
}
func cloneComments(list []*Comment) (res []*Comment) {
for _, n := range list {
res = append(res, n.Clone().(*Comment))
}
return
}
// Copyright 2018 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package ast
func (desc *Description) Filter(predicate func(Node) bool) *Description {
desc1 := &Description{}
for _, n := range desc.Nodes {
if predicate(n) {
desc1.Nodes = append(desc1.Nodes, n.Clone())
}
}
return desc1
}
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package ast
import (
"bytes"
"fmt"
"io"
"strings"
)
func Format(desc *Description) []byte {
buf := new(bytes.Buffer)
FormatWriter(buf, desc)
return buf.Bytes()
}
func FormatWriter(w io.Writer, desc *Description) {
for _, n := range desc.Nodes {
s, ok := n.(serializer)
if !ok {
panic(fmt.Sprintf("unknown top level decl: %#v", n))
}
s.serialize(w)
}
}
func SerializeNode(n Node) string {
s, ok := n.(serializer)
if !ok {
panic(fmt.Sprintf("unknown node: %#v", n))
}
buf := new(bytes.Buffer)
s.serialize(buf)
return buf.String()
}
func FormatInt(v uint64, format IntFmt) string {
switch format {
case IntFmtDec:
return fmt.Sprint(v)
case IntFmtNeg:
return fmt.Sprint(int64(v))
case IntFmtHex:
return fmt.Sprintf("0x%x", v)
case IntFmtChar:
return fmt.Sprintf("'%c'", v)
default:
panic(fmt.Sprintf("unknown int format %v", format))
}
}
func FormatStr(v string, format StrFmt) string {
switch format {
case StrFmtRaw:
return fmt.Sprintf(`"%v"`, v)
case StrFmtHex:
return fmt.Sprintf("`%x`", v)
case StrFmtIdent:
return fmt.Sprintf("%v", v)
default:
panic(fmt.Sprintf("unknown str format %v", format))
}
}
type serializer interface {
serialize(w io.Writer)
}
func (n *NewLine) serialize(w io.Writer) {
fmt.Fprintf(w, "\n")
}
func (n *Comment) serialize(w io.Writer) {
fmt.Fprintf(w, "#%v\n", strings.TrimRight(n.Text, " \t"))
}
func (n *Meta) serialize(w io.Writer) {
fmt.Fprintf(w, "meta ")
n.Value.serialize(w)
fmt.Fprintf(w, "\n")
}
func (n *Include) serialize(w io.Writer) {
fmt.Fprintf(w, "include <%v>\n", n.File.Value)
}
func (n *Incdir) serialize(w io.Writer) {
fmt.Fprintf(w, "incdir <%v>\n", n.Dir.Value)
}
func (n *Define) serialize(w io.Writer) {
fmt.Fprintf(w, "define %v\t%v\n", n.Name.Name, fmtInt(n.Value))
}
func (n *Resource) serialize(w io.Writer) {
fmt.Fprintf(w, "resource %v[%v]", n.Name.Name, fmtType(n.Base))
for i, v := range n.Values {
fmt.Fprintf(w, "%v%v", comma(i, ": "), fmtInt(v))
}
fmt.Fprintf(w, "\n")
}
func (n *TypeDef) serialize(w io.Writer) {
fmt.Fprintf(w, "type %v%v", n.Name.Name, fmtIdentList(n.Args))
if n.Type != nil {
fmt.Fprintf(w, " %v\n", fmtType(n.Type))
}
if n.Struct != nil {
n.Struct.serialize(w)
}
}
func (n *Call) serialize(w io.Writer) {
fmt.Fprintf(w, "%v(", n.Name.Name)
for i, a := range n.Args {
fmt.Fprintf(w, "%v%v", comma(i, ""), fmtField(a))
}
fmt.Fprintf(w, ")")
if n.Ret != nil {
fmt.Fprintf(w, " %v", fmtType(n.Ret))
}
if len(n.Attrs) != 0 {
fmt.Fprintf(w, " %v", fmtTypeList(n.Attrs, "(", ")"))
}
fmt.Fprintf(w, "\n")
}
func (n *Struct) serialize(w io.Writer) {
opening, closing := '{', '}'
if n.IsUnion {
opening, closing = '[', ']'
}
fmt.Fprintf(w, "%v %c\n", n.Name.Name, opening)
// Align all field types to the same column.
const tabWidth = 8
maxTabs := 0
for _, f := range n.Fields {
tabs := (len(f.Name.Name) + tabWidth) / tabWidth
maxTabs = max(maxTabs, tabs)
}
for _, f := range n.Fields {
if f.NewBlock {
fmt.Fprintf(w, "\n")
}
for _, com := range f.Comments {
com.serialize(w)
}
fmt.Fprintf(w, "\t%v\t", f.Name.Name)
for tabs := len(f.Name.Name)/tabWidth + 1; tabs < maxTabs; tabs++ {
fmt.Fprintf(w, "\t")
}
fmt.Fprintf(w, "%v", fmtType(f.Type))
if len(f.Attrs) != 0 {
fmt.Fprintf(w, "\t%v", fmtTypeList(f.Attrs, "(", ")"))
}
fmt.Fprintf(w, "\n")
}
for _, com := range n.Comments {
com.serialize(w)
}
fmt.Fprintf(w, "%c", closing)
if attrs := fmtTypeList(n.Attrs, "[", "]"); attrs != "" {
fmt.Fprintf(w, " %v", attrs)
}
fmt.Fprintf(w, "\n")
}
func (n *IntFlags) serialize(w io.Writer) {
fmt.Fprintf(w, "%v = ", n.Name.Name)
for i, v := range n.Values {
fmt.Fprintf(w, "%v%v", comma(i, ""), fmtInt(v))
}
fmt.Fprintf(w, "\n")
}
func (n *StrFlags) serialize(w io.Writer) {
fmt.Fprintf(w, "%v = ", n.Name.Name)
for i, v := range n.Values {
fmt.Fprintf(w, "%v%v", comma(i, ""), FormatStr(v.Value, v.Fmt))
}
fmt.Fprintf(w, "\n")
}
func fmtField(f *Field) string {
return fmt.Sprintf("%v %v", f.Name.Name, fmtType(f.Type))
}
func (n *Type) serialize(w io.Writer) {
w.Write([]byte(fmtType(n)))
}
func fmtType(t *Type) string {
var sb strings.Builder
fmtExpressionRec(&sb, t, -1)
return sb.String()
}
func fmtEndType(t *Type) string {
v := ""
switch {
case t.Ident != "":
v = t.Ident
case t.HasString:
v = FormatStr(t.String, t.StringFmt)
default:
v = FormatInt(t.Value, t.ValueFmt)
}
for _, c := range t.Colon {
v += ":" + fmtType(c)
}
v += fmtTypeList(t.Args, "[", "]")
return v
}
func fmtTypeList(args []*Type, opening, closing string) string {
if len(args) == 0 {
return ""
}
w := new(bytes.Buffer)
fmt.Fprint(w, opening)
for i, t := range args {
fmt.Fprintf(w, "%v%v", comma(i, ""), fmtType(t))
}
fmt.Fprint(w, closing)
return w.String()
}
func fmtIdentList(args []*Ident) string {
if len(args) == 0 {
return ""
}
w := new(bytes.Buffer)
fmt.Fprintf(w, "[")
for i, arg := range args {
fmt.Fprintf(w, "%v%v", comma(i, ""), arg.Name)
}
fmt.Fprintf(w, "]")
return w.String()
}
func fmtInt(i *Int) string {
switch {
case i.Ident != "":
return i.Ident
case i.CExpr != "":
return fmt.Sprintf("%v", i.CExpr)
default:
return FormatInt(i.Value, i.ValueFmt)
}
}
func fmtExpressionRec(sb *strings.Builder, t *Type, parentPrio int) {
if t.Expression == nil {
sb.WriteString(fmtEndType(t))
return
}
be := t.Expression
myPrio := operatorPrio(be.Operator)
parentheses := myPrio < parentPrio
if parentheses {
sb.WriteByte('(')
}
fmtExpressionRec(sb, be.Left, myPrio)
sb.WriteByte(' ')
switch be.Operator {
case OperatorCompareEq:
sb.WriteString("==")
case OperatorCompareNeq:
sb.WriteString("!=")
case OperatorBinaryAnd:
sb.WriteString("&")
case OperatorOr:
sb.WriteString("||")
default:
panic(fmt.Sprintf("unknown operator %q", be.Operator))
}
sb.WriteByte(' ')
fmtExpressionRec(sb, be.Right, myPrio)
if parentheses {
sb.WriteByte(')')
}
}
func operatorPrio(op Operator) int {
for _, info := range binaryOperators {
if info.op == op {
return info.prio
}
}
panic(fmt.Sprintf("unknown operator %q", op))
}
func comma(i int, or string) string {
if i == 0 {
return or
}
return ", "
}
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package ast
import (
"errors"
"fmt"
"os"
"path/filepath"
"strconv"
"strings"
)
// Parse parses sys description into AST and returns top-level nodes.
// If any errors are encountered, returns nil.
func Parse(data []byte, filename string, errorHandler ErrorHandler) *Description {
p := &parser{s: newScanner(data, filename, errorHandler)}
prevNewLine, prevComment := false, false
var top []Node
for p.next(); p.tok != tokEOF; {
decl := p.parseTopRecover()
if decl == nil {
continue
}
// Add new lines around structs, remove duplicate new lines.
if _, ok := decl.(*NewLine); ok && prevNewLine {
continue
}
if str, ok := decl.(*Struct); ok && !prevNewLine && !prevComment {
top = append(top, &NewLine{Pos: str.Pos})
}
top = append(top, decl)
if str, ok := decl.(*Struct); ok {
decl = &NewLine{Pos: str.Pos}
top = append(top, decl)
}
_, prevNewLine = decl.(*NewLine)
_, prevComment = decl.(*Comment)
}
if prevNewLine {
top = top[:len(top)-1]
}
if !p.s.Ok() {
return nil
}
return &Description{top}
}
func ParseGlob(glob string, errorHandler ErrorHandler) *Description {
if errorHandler == nil {
errorHandler = LoggingHandler
}
files, err := filepath.Glob(glob)
if err != nil {
errorHandler(Pos{}, fmt.Sprintf("failed to find input files: %v", err))
return nil
}
if len(files) == 0 {
errorHandler(Pos{}, fmt.Sprintf("no files matched by glob %q", glob))
return nil
}
desc := &Description{}
for _, f := range files {
data, err := os.ReadFile(f)
if err != nil {
errorHandler(Pos{}, fmt.Sprintf("failed to read input file: %v", err))
return nil
}
desc1 := Parse(data, f, errorHandler)
if desc1 == nil {
desc = nil
}
if desc != nil {
desc.Nodes = append(desc.Nodes, desc1.Nodes...)
}
}
return desc
}
type parser struct {
s *scanner
// Current token:
tok token
lit string
pos Pos
}
// Skip parsing till the next NEWLINE, for error recovery.
var errSkipLine = errors.New("")
func (p *parser) parseTopRecover() Node {
defer func() {
switch err := recover(); err {
case nil:
case errSkipLine:
// Try to recover by consuming everything until next NEWLINE.
for p.tok != tokNewLine && p.tok != tokEOF {
p.next()
}
p.tryConsume(tokNewLine)
default:
panic(err)
}
}()
decl := p.parseTop()
if decl == nil {
panic("not reachable")
}
p.consume(tokNewLine)
return decl
}
func (p *parser) parseTop() Node {
switch p.tok {
case tokNewLine:
return &NewLine{Pos: p.pos}
case tokComment:
return p.parseComment()
case tokDefine:
return p.parseDefine()
case tokInclude:
return p.parseInclude()
case tokIncdir:
return p.parseIncdir()
case tokResource:
return p.parseResource()
case tokIdent:
name := p.parseIdent()
switch name.Name {
case "meta":
return p.parseMeta()
case "type":
return p.parseTypeDef()
}
switch p.tok {
case tokLParen:
return p.parseCall(name)
case tokLBrace, tokLBrack:
return p.parseStruct(name)
case tokEq:
return p.parseFlags(name)
default:
p.expect(tokLParen, tokLBrace, tokLBrack, tokEq)
}
case tokIllegal:
// Scanner has already producer an error for this one.
panic(errSkipLine)
default:
p.expect(tokComment, tokDefine, tokInclude, tokResource, tokIdent)
}
panic("not reachable")
}
func (p *parser) next() {
p.tok, p.lit, p.pos = p.s.Scan()
}
func (p *parser) consume(tok token) {
p.expect(tok)
p.next()
}
func (p *parser) tryConsume(tok token) bool {
if p.tok != tok {
return false
}
p.next()
return true
}
func (p *parser) expect(tokens ...token) {
for _, tok := range tokens {
if p.tok == tok {
return
}
}
var str []string
for _, tok := range tokens {
str = append(str, tok.String())
}
p.s.Errorf(p.pos, "unexpected %v, expecting %v", p.tok, strings.Join(str, ", "))
panic(errSkipLine)
}
func (p *parser) parseComment() *Comment {
c := &Comment{
Pos: p.pos,
Text: p.lit,
}
p.consume(tokComment)
return c
}
func (p *parser) parseMeta() *Meta {
return &Meta{
Pos: p.pos,
Value: p.parseType(),
}
}
func (p *parser) parseDefine() *Define {
pos0 := p.pos
p.consume(tokDefine)
name := p.parseIdent()
p.expect(tokInt, tokIdent, tokCExpr)
var val *Int
if p.tok == tokCExpr {
val = p.parseCExpr()
} else {
val = p.parseInt()
}
return &Define{
Pos: pos0,
Name: name,
Value: val,
}
}
func (p *parser) parseInclude() *Include {
pos0 := p.pos
p.consume(tokInclude)
return &Include{
Pos: pos0,
File: p.parseString(),
}
}
func (p *parser) parseIncdir() *Incdir {
pos0 := p.pos
p.consume(tokIncdir)
return &Incdir{
Pos: pos0,
Dir: p.parseString(),
}
}
func (p *parser) parseResource() *Resource {
pos0 := p.pos
p.consume(tokResource)
name := p.parseIdent()
p.consume(tokLBrack)
base := p.parseType()
p.consume(tokRBrack)
var values []*Int
if p.tryConsume(tokColon) {
values = append(values, p.parseInt())
for p.tryConsume(tokComma) {
values = append(values, p.parseInt())
}
}
return &Resource{
Pos: pos0,
Name: name,
Base: base,
Values: values,
}
}
func (p *parser) parseTypeDef() *TypeDef {
pos0 := p.pos
name := p.parseIdent()
var typ *Type
var str *Struct
var args []*Ident
p.expect(tokLBrack, tokIdent)
if p.tryConsume(tokLBrack) {
args = append(args, p.parseIdent())
for p.tryConsume(tokComma) {
args = append(args, p.parseIdent())
}
p.consume(tokRBrack)
if p.tok == tokLBrace || p.tok == tokLBrack {
emptyName := &Ident{
Pos: pos0,
Name: "",
}
str = p.parseStruct(emptyName)
} else {
typ = p.parseType()
}
} else {
typ = p.parseType()
}
return &TypeDef{
Pos: pos0,
Name: name,
Args: args,
Type: typ,
Struct: str,
}
}
func (p *parser) parseCall(name *Ident) *Call {
c := &Call{
Pos: name.Pos,
Name: name,
CallName: callName(name.Name),
}
p.consume(tokLParen)
for p.tok != tokRParen {
c.Args = append(c.Args, p.parseField(false))
p.expect(tokComma, tokRParen)
p.tryConsume(tokComma)
}
p.consume(tokRParen)
if p.tok != tokNewLine && p.tok != tokLParen {
c.Ret = p.parseType()
}
if p.tryConsume(tokLParen) {
c.Attrs = append(c.Attrs, p.parseType())
for p.tryConsume(tokComma) {
c.Attrs = append(c.Attrs, p.parseType())
}
p.consume(tokRParen)
}
return c
}
func callName(s string) string {
pos := strings.IndexByte(s, '$')
if pos == -1 {
return s
}
return s[:pos]
}
func (p *parser) parseFlags(name *Ident) Node {
p.consume(tokEq)
switch p.tok {
case tokInt, tokIdent:
return p.parseIntFlags(name)
case tokString, tokStringHex:
return p.parseStrFlags(name)
default:
p.expect(tokInt, tokIdent, tokString)
return nil
}
}
func (p *parser) parseIntFlags(name *Ident) *IntFlags {
values := []*Int{p.parseInt()}
for p.tryConsume(tokComma) {
values = append(values, p.parseInt())
}
return &IntFlags{
Pos: name.Pos,
Name: name,
Values: values,
}
}
func (p *parser) parseStrFlags(name *Ident) *StrFlags {
values := []*String{p.parseString()}
for p.tryConsume(tokComma) {
values = append(values, p.parseString())
}
return &StrFlags{
Pos: name.Pos,
Name: name,
Values: values,
}
}
func (p *parser) parseStruct(name *Ident) *Struct {
str := &Struct{
Pos: name.Pos,
Name: name,
}
closing := tokRBrace
if p.tok == tokLBrack {
str.IsUnion = true
closing = tokRBrack
}
p.next()
p.consume(tokNewLine)
for {
newBlock := false
for p.tok == tokNewLine {
newBlock = true
p.next()
}
comments := p.parseCommentBlock()
if p.tryConsume(closing) {
str.Comments = comments
break
}
fld := p.parseField(true)
fld.NewBlock = newBlock
fld.Comments = comments
str.Fields = append(str.Fields, fld)
p.consume(tokNewLine)
}
if p.tryConsume(tokLBrack) {
str.Attrs = append(str.Attrs, p.parseType())
for p.tryConsume(tokComma) {
str.Attrs = append(str.Attrs, p.parseType())
}
p.consume(tokRBrack)
}
return str
}
func (p *parser) parseCommentBlock() []*Comment {
var comments []*Comment
for p.tok == tokComment {
comments = append(comments, p.parseComment())
p.consume(tokNewLine)
for p.tryConsume(tokNewLine) {
}
}
return comments
}
func (p *parser) parseField(parseAttrs bool) *Field {
name := p.parseIdent()
field := &Field{
Pos: name.Pos,
Name: name,
Type: p.parseType(),
}
if parseAttrs && p.tryConsume(tokLParen) {
field.Attrs = append(field.Attrs, p.parseType())
for p.tryConsume(tokComma) {
field.Attrs = append(field.Attrs, p.parseType())
}
p.consume(tokRParen)
}
return field
}
type operatorInfo struct {
op Operator
prio int
}
const maxOperatorPrio = 2
// The highest priority is 0.
var binaryOperators = map[token]operatorInfo{
tokOr: {op: OperatorOr, prio: 0},
tokCmpEq: {op: OperatorCompareEq, prio: 1},
tokCmpNeq: {op: OperatorCompareNeq, prio: 1},
tokBinAnd: {op: OperatorBinaryAnd, prio: 2},
}
// Parse out a single Type object, which can either be a plain object or an expression.
// For now, only expressions constructed via '(', ')', "==", "!=", '&', '||' are supported.
func (p *parser) parseType() *Type {
return p.parseBinaryExpr(0)
}
func (p *parser) parseBinaryExpr(expectPrio int) *Type {
if expectPrio > maxOperatorPrio {
return p.parseExprFactor()
}
lastPos := p.pos
curr := p.parseBinaryExpr(expectPrio + 1)
for {
info, ok := binaryOperators[p.tok]
if !ok || info.prio != expectPrio {
return curr
}
p.consume(p.tok)
curr = &Type{
Pos: lastPos,
Expression: &BinaryExpression{
Pos: p.pos,
Operator: info.op,
Left: curr,
Right: p.parseBinaryExpr(expectPrio + 1),
},
}
lastPos = p.pos
}
}
func (p *parser) parseExprFactor() *Type {
if p.tok == tokLParen {
p.consume(tokLParen)
ret := p.parseBinaryExpr(0)
p.consume(tokRParen)
return ret
}
arg := &Type{
Pos: p.pos,
}
allowColon := false
switch p.tok {
case tokInt:
allowColon = true
arg.Value, arg.ValueFmt = p.parseIntValue()
case tokIdent:
allowColon = true
arg.Ident = p.lit
case tokString, tokStringHex:
arg.String = p.lit
arg.HasString = true
arg.StringFmt = strTokToFmt(p.tok)
default:
p.expect(tokInt, tokIdent, tokString)
}
p.next()
if allowColon {
for p.tryConsume(tokColon) {
col := &Type{
Pos: p.pos,
}
switch p.tok {
case tokInt:
col.Value, col.ValueFmt = p.parseIntValue()
case tokIdent:
col.Ident = p.lit
default:
p.expect(tokInt, tokIdent)
}
arg.Colon = append(arg.Colon, col)
p.next()
}
}
arg.Args = p.parseTypeList()
return arg
}
func (p *parser) parseTypeList() []*Type {
var args []*Type
if p.tryConsume(tokLBrack) {
args = append(args, p.parseType())
for p.tryConsume(tokComma) {
args = append(args, p.parseType())
}
p.consume(tokRBrack)
}
return args
}
func (p *parser) parseIdent() *Ident {
p.expect(tokIdent)
ident := &Ident{
Pos: p.pos,
Name: p.lit,
}
p.next()
return ident
}
func (p *parser) parseString() *String {
p.expect(tokString, tokStringHex, tokIdent)
str := &String{
Pos: p.pos,
Value: p.lit,
Fmt: strTokToFmt(p.tok),
}
p.next()
return str
}
func strTokToFmt(tok token) StrFmt {
switch tok {
case tokString:
return StrFmtRaw
case tokStringHex:
return StrFmtHex
case tokIdent:
return StrFmtIdent
default:
panic("bad string token")
}
}
func (p *parser) parseInt() *Int {
i := &Int{
Pos: p.pos,
}
switch p.tok {
case tokInt:
i.Value, i.ValueFmt = p.parseIntValue()
case tokIdent:
i.Ident = p.lit
default:
p.expect(tokInt, tokIdent)
}
p.next()
return i
}
func (p *parser) parseIntValue() (uint64, IntFmt) {
if p.lit[0] == '\'' {
return uint64(p.lit[1]), IntFmtChar
}
if v, err := strconv.ParseUint(p.lit, 10, 64); err == nil {
return v, IntFmtDec
}
if v, err := strconv.ParseInt(p.lit, 10, 64); err == nil {
return uint64(v), IntFmtNeg
}
if len(p.lit) > 2 && p.lit[0] == '0' && p.lit[1] == 'x' {
if v, err := strconv.ParseUint(p.lit[2:], 16, 64); err == nil {
return v, IntFmtHex
}
}
panic(fmt.Sprintf("scanner returned bad integer %q", p.lit))
}
func (p *parser) parseCExpr() *Int {
i := &Int{
Pos: p.pos,
CExpr: p.lit,
}
p.consume(tokCExpr)
return i
}
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package ast
import (
"bytes"
"encoding/hex"
"fmt"
"os"
"strconv"
)
type token int
const (
tokIllegal token = iota
tokComment
tokIdent
tokInclude
tokIncdir
tokDefine
tokResource
tokString
tokStringHex
tokCExpr
tokInt
tokNewLine
tokLParen
tokRParen
tokLBrack
tokRBrack
tokLBrace
tokRBrace
tokEq
tokComma
tokColon
tokBinAnd
tokCmpEq
tokCmpNeq
tokOr
tokEOF
)
var punctuation = [256]token{
'\n': tokNewLine,
'(': tokLParen,
')': tokRParen,
'[': tokLBrack,
']': tokRBrack,
'{': tokLBrace,
'}': tokRBrace,
'=': tokEq,
',': tokComma,
':': tokColon,
'&': tokBinAnd,
}
var tok2str = [...]string{
tokIllegal: "ILLEGAL",
tokComment: "comment",
tokIdent: "identifier",
tokInclude: "include",
tokIncdir: "incdir",
tokDefine: "define",
tokResource: "resource",
tokString: "string",
tokStringHex: "hex string",
tokCExpr: "CEXPR",
tokInt: "int",
tokNewLine: "NEWLINE",
tokEOF: "EOF",
tokCmpEq: "==",
tokCmpNeq: "!=",
tokOr: "||",
}
func init() {
for ch, tok := range punctuation {
if tok == tokIllegal {
continue
}
tok2str[tok] = fmt.Sprintf("%q", ch)
}
}
var keywords = map[string]token{
"include": tokInclude,
"incdir": tokIncdir,
"define": tokDefine,
"resource": tokResource,
}
func (tok token) String() string {
return tok2str[tok]
}
type scanner struct {
data []byte
filename string
errorHandler ErrorHandler
ch byte
off int
line int
col int
prev1 token
prev2 token
errors int
}
func newScanner(data []byte, filename string, errorHandler ErrorHandler) *scanner {
if errorHandler == nil {
errorHandler = LoggingHandler
}
s := &scanner{
data: data,
filename: filename,
errorHandler: errorHandler,
off: -1,
}
s.next()
return s
}
type ErrorHandler func(pos Pos, msg string)
func LoggingHandler(pos Pos, msg string) {
fmt.Fprintf(os.Stderr, "%v: %v\n", pos, msg)
}
const BuiltinFile = "BUILTINS"
func (pos Pos) Builtin() bool {
return pos.File == BuiltinFile
}
func (pos Pos) String() string {
if pos.Builtin() {
return "builtins"
}
if pos.Col == 0 {
return fmt.Sprintf("%v:%v", pos.File, pos.Line)
}
return fmt.Sprintf("%v:%v:%v", pos.File, pos.Line, pos.Col)
}
func (pos Pos) less(other Pos) bool {
if pos.File != other.File {
return pos.File < other.File
}
if pos.Line != other.Line {
return pos.Line < other.Line
}
return pos.Col < other.Col
}
func (s *scanner) Scan() (tok token, lit string, pos Pos) {
s.skipWhitespace()
pos = s.pos()
switch {
case s.ch == 0:
tok = tokEOF
s.next()
case s.prev2 == tokDefine && s.prev1 == tokIdent:
tok = tokCExpr
for ; s.ch != '\n'; s.next() {
}
lit = string(s.data[pos.Off:s.off])
case s.ch == '#':
tok = tokComment
for s.next(); s.ch != '\n'; s.next() {
}
lit = string(s.data[pos.Off+1 : s.off])
case s.ch == '"' || s.ch == '<':
tok = tokString
lit = s.scanStr(pos)
case s.ch == '`':
tok = tokStringHex
lit = s.scanStr(pos)
case s.ch >= '0' && s.ch <= '9' || s.ch == '-':
tok = tokInt
lit = s.scanInt(pos)
case s.ch == '\'':
tok = tokInt
lit = s.scanChar(pos)
case s.ch == '_' || s.ch >= 'a' && s.ch <= 'z' || s.ch >= 'A' && s.ch <= 'Z':
tok, lit = s.scanIdent(pos)
case s.tryConsume("=="):
tok = tokCmpEq
case s.tryConsume("!="):
tok = tokCmpNeq
case s.tryConsume("||"):
tok = tokOr
default:
tok = punctuation[s.ch]
if tok == tokIllegal {
s.Errorf(pos, "illegal character %#U", s.ch)
}
s.next()
}
s.prev2 = s.prev1
s.prev1 = tok
return
}
func (s *scanner) scanStr(pos Pos) string {
// TODO(dvyukov): get rid of <...> strings, that's only includes
closing := s.ch
if s.ch == '<' {
closing = '>'
}
for s.next(); s.ch != closing; s.next() {
if s.ch == 0 || s.ch == '\n' {
s.Errorf(pos, "string literal is not terminated")
return ""
}
}
lit := string(s.data[pos.Off+1 : s.off])
if i := IsValidStringLit(lit); i >= 0 {
pos1 := pos
pos1.Col += i + 1
pos1.Off += i + 1
s.Errorf(pos1, "illegal character %#U in string literal %q", lit[i], lit)
}
s.next()
if closing != '`' {
return lit
}
decoded, err := hex.DecodeString(lit)
if err != nil {
s.Errorf(pos, "bad hex string literal: %v", err)
}
return string(decoded)
}
func (s *scanner) scanInt(pos Pos) string {
for s.ch >= '0' && s.ch <= '9' ||
s.ch >= 'a' && s.ch <= 'f' ||
s.ch >= 'A' && s.ch <= 'F' ||
s.ch == 'x' || s.ch == '-' {
s.next()
}
lit := string(s.data[pos.Off:s.off])
if _, err := strconv.ParseUint(lit, 10, 64); err == nil {
return lit
}
if len(lit) > 1 && lit[0] == '-' {
if _, err := strconv.ParseInt(lit, 10, 64); err == nil {
return lit
}
}
if len(lit) > 2 && lit[0] == '0' && lit[1] == 'x' {
if _, err := strconv.ParseUint(lit[2:], 16, 64); err == nil {
return lit
}
}
s.Errorf(pos, "bad integer %q", lit)
return "0"
}
func (s *scanner) scanChar(pos Pos) string {
s.next()
s.next()
if s.ch != '\'' {
s.Errorf(pos, "char literal is not terminated")
return "0"
}
s.next()
return string(s.data[pos.Off : pos.Off+3])
}
func (s *scanner) scanIdent(pos Pos) (tok token, lit string) {
tok = tokIdent
for s.ch == '_' || s.ch == '$' ||
s.ch >= 'a' && s.ch <= 'z' ||
s.ch >= 'A' && s.ch <= 'Z' ||
s.ch >= '0' && s.ch <= '9' {
s.next()
}
lit = string(s.data[pos.Off:s.off])
if key, ok := keywords[lit]; ok {
tok = key
}
return
}
func (s *scanner) Errorf(pos Pos, msg string, args ...interface{}) {
s.errors++
s.errorHandler(pos, fmt.Sprintf(msg, args...))
}
func (s *scanner) Ok() bool {
return s.errors == 0
}
func (s *scanner) next() {
s.off++
for s.off < len(s.data) && s.data[s.off] == '\r' {
s.off++
}
if s.off == len(s.data) {
// Always emit NEWLINE before EOF.
// Makes lots of things simpler as we always
// want to treat EOF as NEWLINE as well.
s.ch = '\n'
return
}
if s.off > len(s.data) {
s.ch = 0
return
}
if s.off == 0 || s.data[s.off-1] == '\n' {
s.line++
s.col = 0
}
s.ch = s.data[s.off]
s.col++
if s.ch == 0 {
s.Errorf(s.pos(), "illegal character \\x00")
}
}
func (s *scanner) tryConsume(str string) bool {
if !bytes.HasPrefix(s.data[s.off:], []byte(str)) {
return false
}
for i := 0; i < len(str); i++ {
s.next()
}
return true
}
func (s *scanner) skipWhitespace() {
for s.ch == ' ' || s.ch == '\t' {
s.next()
}
}
func (s *scanner) pos() Pos {
return Pos{
File: s.filename,
Off: s.off,
Line: s.line,
Col: s.col,
}
}
func IsValidStringLit(lit string) int {
for i := 0; i < len(lit); i++ {
if lit[i] < 0x20 || lit[i] >= 0x80 {
return i
}
}
return -1
}
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package ast
import (
"bufio"
"bytes"
"fmt"
"os"
"path/filepath"
"regexp"
"sort"
"strings"
"testing"
)
type ErrorMatcher struct {
t *testing.T
Data []byte
expect []*errorDesc
got []*errorDesc
}
type errorDesc struct {
pos Pos
text string
matched bool
}
func NewErrorMatcher(t *testing.T, file string) *ErrorMatcher {
data, err := os.ReadFile(file)
if err != nil {
t.Fatalf("failed to open input file: %v", err)
}
var stripped []byte
var errors []*errorDesc
s := bufio.NewScanner(bytes.NewReader(data))
for i := 1; s.Scan(); i++ {
ln := s.Bytes()
for {
pos := bytes.LastIndex(ln, []byte("###"))
if pos == -1 {
break
}
errors = append(errors, &errorDesc{
pos: Pos{File: filepath.Base(file), Line: i},
text: strings.TrimSpace(string(ln[pos+3:])),
})
ln = ln[:pos]
}
stripped = append(stripped, ln...)
stripped = append(stripped, '\n')
}
if err := s.Err(); err != nil {
t.Fatalf("failed to scan input file: %v", err)
}
return &ErrorMatcher{
t: t,
Data: stripped,
expect: errors,
}
}
var errorLocationRe = regexp.MustCompile(`at [a-z][a-z0-9]+\.txt:[0-9]+:[0-9]+`)
func (em *ErrorMatcher) ErrorHandler(pos Pos, msg string) {
if match := errorLocationRe.FindStringSubmatchIndex(msg); match != nil {
msg = msg[0:match[0]] + "at LOCATION" + msg[match[1]:]
}
em.got = append(em.got, &errorDesc{
pos: pos,
text: msg,
})
}
func (em *ErrorMatcher) Count() int {
return len(em.got)
}
func (em *ErrorMatcher) Check() {
em.t.Helper()
errors := make(map[Pos][]string)
nextErr:
for _, e := range em.got {
for _, want := range em.expect {
if want.matched || want.pos.Line != e.pos.Line || want.text != e.text {
continue
}
want.matched = true
continue nextErr
}
pos := e.pos
pos.Col = 0
pos.Off = 0
errors[pos] = append(errors[pos], fmt.Sprintf("unexpected: %v", e.text))
}
for _, want := range em.expect {
if want.matched {
continue
}
errors[want.pos] = append(errors[want.pos], fmt.Sprintf("unmatched : %v", want.text))
}
if len(errors) == 0 {
return
}
type Sorted struct {
pos Pos
msgs []string
}
sorted := []Sorted{}
for pos, msgs := range errors {
sorted = append(sorted, Sorted{pos, msgs})
}
sort.Slice(sorted, func(i, j int) bool {
return sorted[i].pos.less(sorted[j].pos)
})
buf := new(bytes.Buffer)
for _, err := range sorted {
if len(err.msgs) == 1 {
fmt.Fprintf(buf, "%v: %v\n", err.pos, err.msgs[0])
continue
}
sort.Strings(err.msgs)
fmt.Fprintf(buf, "%v:\n\t%v\n", err.pos, strings.Join(err.msgs, "\n\t"))
}
em.t.Errorf("\n%s", buf.Bytes())
}
func (em *ErrorMatcher) DumpErrors() {
em.t.Helper()
for _, e := range em.got {
em.t.Logf("%v: %v", e.pos, e.text)
}
}
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package ast
// Walk calls callback cb for every top-level node in description.
// Note: it's not recursive. Use Recursive/PostRecursive helpers for recursive walk.
func (desc *Description) Walk(cb func(Node)) {
for _, n := range desc.Nodes {
cb(n)
}
}
func Recursive(cb func(Node) bool) func(Node) {
var rec func(Node)
rec = func(n Node) {
if cb(n) {
n.walk(rec)
}
}
return rec
}
func PostRecursive(cb func(Node)) func(Node) {
var rec func(Node)
rec = func(n Node) {
n.walk(rec)
cb(n)
}
return rec
}
func (n *NewLine) walk(cb func(Node)) {}
func (n *Comment) walk(cb func(Node)) {}
func (n *Ident) walk(cb func(Node)) {}
func (n *String) walk(cb func(Node)) {}
func (n *Int) walk(cb func(Node)) {}
func (n *Meta) walk(cb func(Node)) {
cb(n.Value)
}
func (n *Include) walk(cb func(Node)) {
cb(n.File)
}
func (n *Incdir) walk(cb func(Node)) {
cb(n.Dir)
}
func (n *Define) walk(cb func(Node)) {
cb(n.Name)
cb(n.Value)
}
func (n *Resource) walk(cb func(Node)) {
cb(n.Name)
cb(n.Base)
for _, v := range n.Values {
cb(v)
}
}
func (n *TypeDef) walk(cb func(Node)) {
cb(n.Name)
for _, a := range n.Args {
cb(a)
}
if n.Type != nil {
cb(n.Type)
}
if n.Struct != nil {
cb(n.Struct)
}
}
func (n *Call) walk(cb func(Node)) {
cb(n.Name)
for _, f := range n.Args {
cb(f)
}
if n.Ret != nil {
cb(n.Ret)
}
for _, a := range n.Attrs {
cb(a)
}
}
func (n *Struct) walk(cb func(Node)) {
cb(n.Name)
for _, f := range n.Fields {
cb(f)
}
for _, a := range n.Attrs {
cb(a)
}
for _, c := range n.Comments {
cb(c)
}
}
func (n *IntFlags) walk(cb func(Node)) {
cb(n.Name)
for _, v := range n.Values {
cb(v)
}
}
func (n *StrFlags) walk(cb func(Node)) {
cb(n.Name)
for _, v := range n.Values {
cb(v)
}
}
func (n *Type) walk(cb func(Node)) {
for _, t := range n.Args {
cb(t)
}
if n.Expression != nil {
cb(n.Expression)
}
}
func (n *Field) walk(cb func(Node)) {
cb(n.Name)
cb(n.Type)
for _, a := range n.Attrs {
cb(a)
}
for _, c := range n.Comments {
cb(c)
}
}
func (n *BinaryExpression) walk(cb func(Node)) {
cb(n.Left)
cb(n.Right)
}
// Copyright 2021 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
// Relies on tokeninfo because it is properly documented:
// https://developers.google.com/identity/protocols/oauth2/openid-connect#validatinganidtoken
// The client
// The VM that wants to invoke the API:
// 1) Gets a token from the metainfo server with this http request:
// META=http://metadata.google.internal/computeMetadata/v1
// AUD=https://syzkaller.appspot.com/api
// curl -sH 'Metadata-Flavor: Google' \
// "$META/instance/service-accounts/default/identity?audience=$AUD"
// 2) Invokes /api with header 'Authorization: Bearer <token>'
//
// The AppEngine api server:
// 1) Receive the token, invokes this http request:
// curl -s "https://oauth2.googleapis.com/tokeninfo?id_token=<token>"
// 2) Checks the resulting JSON having the expected audience and expiration.
// 3) Looks up the permissions in the config using the value of sub.
//
// https://cloud.google.com/iap/docs/signed-headers-howto#retrieving_the_user_identity
// from the IAP docs agrees to trust sub.
// Package auth contains authentication related code supporting secret
// passwords and oauth2 tokens on GCE.
package auth
import (
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"strconv"
"strings"
"time"
)
const (
// The official google oauth2 endpoint.
GoogleTokenInfoEndpoint = "https://oauth2.googleapis.com/tokeninfo"
// Used in the config map as a prefix to distinguish auth identifiers from secret passwords
// (which contain arbitrary strings, that can't have this prefix).
OauthMagic = "OauthSubject:"
)
// Represent a verification backend.
type Endpoint struct {
// URL supporting tokeninfo auth2 protocol.
url string
// TODO(blackgnezdo): cache tokens with a bit of care for concurrency.
}
func MakeEndpoint(u string) Endpoint {
return Endpoint{url: u}
}
// The JSON representation of JWT claims.
type jwtClaimsParse struct {
Subject string `json:"sub"`
Audience string `json:"aud"`
// The field in the JSON is a string but contains a UNIX time.
Expiration string `json:"exp"`
}
// The typed representation of JWT claims.
type jwtClaims struct {
Subject string
Audience string
// The app uses the typed value.
Expiration time.Time
}
func (auth *Endpoint) queryTokenInfo(tokenValue string) (*jwtClaims, error) {
var resp *http.Response
var err error
for i := 0; i < 3; i++ {
resp, err = http.PostForm(auth.url, url.Values{"id_token": {tokenValue}})
if err == nil {
break
}
}
if err != nil {
return nil, fmt.Errorf("http.PostForm failed 3 times: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("verification failed %v", resp.StatusCode)
}
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("io.ReadAll: %w", err)
}
claims := new(jwtClaimsParse)
if err = json.Unmarshal(body, claims); err != nil {
return nil, fmt.Errorf("json.Unmarshal: %w", err)
}
expInt, err := strconv.ParseInt(claims.Expiration, 10, 64)
if err != nil {
return nil, fmt.Errorf("strconv.ParseInt: %w", err)
}
r := jwtClaims{
Subject: claims.Subject,
Audience: claims.Audience,
Expiration: time.Unix(expInt, 0),
}
return &r, nil
}
// Returns the verified subject value based on the provided header
// value or "" if it can't be determined. A valid result starts with
// auth.OauthMagic. The now parameter is the current time to compare the
// claims against. The authHeader is styled as is typical for HTTP headers
// which carry the tokens prefixed by "Bearer " string.
func (auth *Endpoint) DetermineAuthSubj(now time.Time, authHeader []string) (string, error) {
if len(authHeader) != 1 || !strings.HasPrefix(authHeader[0], "Bearer") {
// This is a normal case when the client uses a password.
return "", nil
}
// Values past this point are real authentication attempts. Whether
// or not they are valid is the question.
tokenValue := strings.TrimSpace(strings.TrimPrefix(authHeader[0], "Bearer"))
claims, err := auth.queryTokenInfo(tokenValue)
if err != nil {
return "", fmt.Errorf("auth.queryTokenInfo: %w", err)
}
if claims.Audience != DashboardAudience {
return "", fmt.Errorf("unexpected audience %v", claims.Audience)
}
if claims.Expiration.Before(now) {
return "", fmt.Errorf("token past expiration %v", claims.Expiration)
}
return OauthMagic + claims.Subject, nil
}
// Copyright 2021 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package auth
import (
"encoding/base64"
"encoding/json"
"fmt"
"io"
"net/http"
"strings"
"sync"
"time"
)
const (
DashboardAudience = "https://syzkaller.appspot.com/api"
)
type expiringToken struct {
value string
expiration time.Time
}
// Returns the unverified expiration value from the given JWT token.
func extractJwtExpiration(token string) (time.Time, error) {
// https://datatracker.ietf.org/doc/html/rfc7519#section-3
pieces := strings.Split(token, ".")
if len(pieces) != 3 {
return time.Time{}, fmt.Errorf("unexpected number of JWT components %v", len(pieces))
}
decoded, err := base64.RawURLEncoding.DecodeString(pieces[1])
if err != nil {
return time.Time{}, err
}
claims := struct {
Expiration int64 `json:"exp"`
}{-123456} // Hopefully a notably broken value.
if err = json.Unmarshal(decoded, &claims); err != nil {
return time.Time{}, err
}
return time.Unix(claims.Expiration, 0), nil
}
type (
// The types of ctor and doer are the same as in http.NewRequest and
// http.DefaultClient.Do.
requestCtor func(method, url string, body io.Reader) (*http.Request, error)
requestDoer func(req *http.Request) (*http.Response, error)
)
// Queries the metadata server and returns the bearer token of the
// service account. The token is scoped for the official dashboard.
func retrieveJwtToken(ctor requestCtor, doer requestDoer) (*expiringToken, error) {
const v1meta = "http://metadata.google.internal/computeMetadata/v1"
req, err := ctor("GET", v1meta+"/instance/service-accounts/default/identity?audience="+DashboardAudience, nil)
if err != nil {
return nil, err
}
req.Header.Add("Metadata-Flavor", "Google")
resp, err := doer(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
token := string(data)
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("failed metadata get %v: %s", resp.Status, token)
}
expiration, err := extractJwtExpiration(token)
if err != nil {
return nil, err
}
return &expiringToken{token, expiration}, nil
}
// TokenCache keeps the tokens for reuse by Get.
type TokenCache struct {
lock sync.Mutex
token *expiringToken
ctor requestCtor
doer requestDoer
}
// MakeCache creates a new cache or returns an error if tokens aren't
// available.
func MakeCache(ctor func(method, url string, body io.Reader) (*http.Request, error),
doer func(req *http.Request) (*http.Response, error)) (*TokenCache, error) {
token, err := retrieveJwtToken(ctor, doer)
if err != nil {
return nil, err
}
return &TokenCache{sync.Mutex{}, token, ctor, doer}, nil
}
// Get returns a potentially cached value of the token or renews as
// necessary. The now parameter provides the current time for cache
// expiration. The returned value is suitable for Authorization header
// and syz-hub Key requests.
func (cache *TokenCache) Get(now time.Time) (string, error) {
cache.lock.Lock()
defer cache.lock.Unlock()
// A typical token returned by metadata server is valid for an hour.
// Refreshing a minute early should give the recipient plenty of time
// to verify the token.
if cache.token.expiration.Sub(now) < time.Minute {
// Keeping the lock while making http request is dubious, but
// making multiple concurrent requests is not any better.
t, err := retrieveJwtToken(cache.ctor, cache.doer)
if err != nil {
// Can't get a new token, so returning the error preemptively.
return "", err
}
cache.token = t
}
return "Bearer " + cache.token.value, nil
}
// Copyright 2023 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package minimize
import (
"errors"
"fmt"
"math"
"slices"
"strings"
)
type Config[T any] struct {
// The original slice is minimized with respect to this predicate.
// If Pred(X) returns true, X is assumed to contain all elements that must stay.
Pred func([]T) (bool, error)
// MaxSteps is a limit on the number of predicate calls during bisection.
// If it's hit, the bisection continues as if Pred() begins to return false.
// If it's set to 0 (by default), no limit is applied.
MaxSteps int
// MaxChunks sets a limit on the number of chunks pursued by the bisection algorithm.
// If we hit the limit, bisection is stopped and Array() returns ErrTooManyChunks
// anongside the intermediate bisection result (a valid, but not fully minimized slice).
MaxChunks int
// Logf is used for sharing debugging output.
Logf func(string, ...interface{})
}
// Slice() finds a minimal subsequence of slice elements that still gives Pred() == true.
// The algorithm works by sequentially splitting the slice into smaller-size chunks and running
// Pred() witout those chunks. Slice() receives the original slice chunks.
// The expected number of Pred() runs is O(|result|*log2(|elements|)).
func Slice[T any](config Config[T], slice []T) ([]T, error) {
if config.Logf == nil {
config.Logf = func(string, ...interface{}) {}
}
ctx := &sliceCtx[T]{
Config: config,
chunks: []*arrayChunk[T]{
{
elements: slice,
},
},
}
return ctx.bisect()
}
// SliceWithFixed behaves like Slice, but also allows to designate the elements that
// must always remain (the "fixed" ones).
func SliceWithFixed[T any](config Config[T], slice []T, fixed func(T) bool) ([]T, error) {
var freeIdx, fixedIdx []int
for i := 0; i < len(slice); i++ {
if fixed(slice[i]) {
fixedIdx = append(fixedIdx, i)
} else {
freeIdx = append(freeIdx, i)
}
}
if len(freeIdx) == 0 {
return slice, nil
}
convert := func(idx []int) []T {
ret := make([]T, 0, len(idx)+len(fixedIdx))
idx, fixedIdx := slices.Clone(idx), slices.Clone(fixedIdx)
for len(idx)+len(fixedIdx) > 0 {
if len(idx) > 0 && (len(fixedIdx) == 0 ||
len(fixedIdx) > 0 && idx[0] < fixedIdx[0]) {
ret = append(ret, slice[idx[0]])
idx = idx[1:]
} else {
ret = append(ret, slice[fixedIdx[0]])
fixedIdx = fixedIdx[1:]
}
}
return ret
}
newConfig := Config[int]{
MaxSteps: config.MaxSteps,
MaxChunks: config.MaxChunks,
Pred: func(idx []int) (bool, error) {
return config.Pred(convert(idx))
},
Logf: config.Logf,
}
result, err := Slice[int](newConfig, freeIdx)
if err != nil {
return nil, err
}
return convert(result), nil
}
type sliceCtx[T any] struct {
Config[T]
chunks []*arrayChunk[T]
predRuns int
}
type arrayChunk[T any] struct {
elements []T
final bool // There's no way to further split this chunk.
}
// ErrTooManyChunks is returned if the number of necessary chunks surpassed MaxChunks.
var ErrTooManyChunks = errors.New("the bisection process is following too many necessary chunks")
func (ctx *sliceCtx[T]) bisect() ([]T, error) {
// At first, we don't know if the original chunks are really necessary.
err := ctx.splitChunks(false)
// Then, keep on splitting the chunks layer by layer until we have identified
// all necessary elements.
// This way we ensure that we always go from larger to smaller chunks.
for err == nil && !ctx.done() {
if ctx.MaxChunks > 0 && len(ctx.chunks) > ctx.MaxChunks {
err = ErrTooManyChunks
break
}
err = ctx.splitChunks(true)
}
if err != nil && err != ErrTooManyChunks {
return nil, err
}
return ctx.elements(), err
}
// splitChunks() splits each chunk in two and only leaves the necessary sub-parts.
func (ctx *sliceCtx[T]) splitChunks(someNeeded bool) error {
ctx.Logf("split chunks (needed=%v): %s", someNeeded, ctx.chunkInfo())
splitInto := 2
if !someNeeded && len(ctx.chunks) == 1 {
// It's our first iteration.
splitInto = ctx.initialSplit(len(ctx.chunks[0].elements))
}
var newChunks []*arrayChunk[T]
for i, chunk := range ctx.chunks {
if chunk.final {
newChunks = append(newChunks, chunk)
continue
}
ctx.Logf("split chunk #%d of len %d into %d parts", i, len(chunk.elements), splitInto)
chunks := splitChunk[T](chunk.elements, splitInto)
if len(chunks) == 1 && someNeeded {
ctx.Logf("no way to further split the chunk")
chunk.final = true
newChunks = append(newChunks, chunk)
continue
}
foundNeeded := false
for j := range chunks {
ctx.Logf("testing without sub-chunk %d/%d", j+1, len(chunks))
if j < len(chunks)-1 || foundNeeded || !someNeeded {
ret, err := ctx.predRun(
newChunks,
mergeRawChunks(chunks[j+1:]),
ctx.chunks[i+1:],
)
if err != nil {
return err
}
if ret {
ctx.Logf("the chunk can be dropped")
continue
}
} else {
ctx.Logf("no need to test this chunk, it's definitely needed")
}
foundNeeded = true
newChunks = append(newChunks, &arrayChunk[T]{
elements: chunks[j],
})
}
}
ctx.chunks = newChunks
return nil
}
// Since Pred() runs can be costly, the objective is to get the most out of the
// limited number of Pred() calls.
// We try to achieve it by splitting the initial array in more than 2 elements.
func (ctx *sliceCtx[T]) initialSplit(size int) int {
// If the number of steps is small and the number of elements is big,
// let's just split the initial array into MaxSteps chunks.
// There's no solid reasoning behind the condition below, so feel free to
// change it if you have better ideas.
if ctx.MaxSteps > 0 && math.Log2(float64(size)) > float64(ctx.MaxSteps) {
return ctx.MaxSteps
}
// Otherwise let's split in 3.
return 3
}
// predRun() determines whether (before + mid + after) covers the necessary elements.
func (ctx *sliceCtx[T]) predRun(before []*arrayChunk[T], mid []T, after []*arrayChunk[T]) (bool, error) {
if ctx.MaxSteps > 0 && ctx.predRuns >= ctx.MaxSteps {
ctx.Logf("we have reached the limit on predicate runs (%d); pretend it returns false",
ctx.MaxSteps)
return false, nil
}
ctx.predRuns++
return ctx.Pred(mergeChunks(before, mid, after))
}
// The bisection process is done once every chunk is marked as final.
func (ctx *sliceCtx[T]) done() bool {
if ctx.MaxSteps > 0 && ctx.predRuns >= ctx.MaxSteps {
// No reason to continue.
return true
}
for _, chunk := range ctx.chunks {
if !chunk.final {
return false
}
}
return true
}
func (ctx *sliceCtx[T]) elements() []T {
return mergeChunks(ctx.chunks, nil, nil)
}
func (ctx *sliceCtx[T]) chunkInfo() string {
var parts []string
for _, chunk := range ctx.chunks {
str := ""
if chunk.final {
str = ", final"
}
parts = append(parts, fmt.Sprintf("<%d%s>", len(chunk.elements), str))
}
return strings.Join(parts, ", ")
}
func mergeChunks[T any](before []*arrayChunk[T], mid []T, after []*arrayChunk[T]) []T {
var ret []T
for _, chunk := range before {
ret = append(ret, chunk.elements...)
}
ret = append(ret, mid...)
for _, chunk := range after {
ret = append(ret, chunk.elements...)
}
return ret
}
func mergeRawChunks[T any](chunks [][]T) []T {
var ret []T
for _, chunk := range chunks {
ret = append(ret, chunk...)
}
return ret
}
func splitChunk[T any](chunk []T, parts int) [][]T {
chunkSize := (len(chunk) + parts - 1) / parts
if chunkSize == 0 {
chunkSize = 1
}
var ret [][]T
for i := 0; i < len(chunk); i += chunkSize {
end := min(i+chunkSize, len(chunk))
ret = append(ret, chunk[i:end])
}
return ret
}
// Copyright 2020 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package compiler
import (
"reflect"
"github.com/google/syzkaller/pkg/ast"
"github.com/google/syzkaller/prog"
)
type attrDescAttrType int
const (
flagAttr attrDescAttrType = iota
// TODO: Ultimately we want to replace intAttr with exprAttr.
// This will facilitate const expressions in e.g. size[] or align[].
intAttr
exprAttr
stringAttr
)
type attrDesc struct {
Name string
// For now we assume attributes can have only 1 argument and it's either an
// integer or an expression.
Type attrDescAttrType
// This function is not invoked for per-field attributes, only for whole
// structs/unions.
CheckConsts func(comp *compiler, parent ast.Node, attr *ast.Type)
}
var (
attrPacked = &attrDesc{Name: "packed"}
attrVarlen = &attrDesc{Name: "varlen"}
attrSize = &attrDesc{Name: "size", Type: intAttr}
attrAlign = &attrDesc{Name: "align", Type: intAttr}
attrIn = &attrDesc{Name: "in"}
attrOut = &attrDesc{Name: "out"}
attrInOut = &attrDesc{Name: "inout"}
attrOutOverlay = &attrDesc{Name: "out_overlay"}
attrIf = &attrDesc{Name: "if", Type: exprAttr}
structAttrs = makeAttrs(attrPacked, attrSize, attrAlign)
unionAttrs = makeAttrs(attrVarlen, attrSize)
structFieldAttrs = makeAttrs(attrIn, attrOut, attrInOut, attrOutOverlay, attrIf)
unionFieldAttrs = makeAttrs(attrIn, attrIf) // attrIn is safe.
callAttrs = make(map[string]*attrDesc)
)
func init() {
initCallAttrs()
attrSize.CheckConsts = func(comp *compiler, parent ast.Node, attr *ast.Type) {
_, typ, name := parent.Info()
if comp.structIsVarlen(name) {
comp.error(attr.Pos, "varlen %v %v has size attribute", typ, name)
}
sz := attr.Args[0].Value
if sz == 0 || sz > 1<<20 {
comp.error(attr.Args[0].Pos, "size attribute has bad value %v"+
", expect [1, 1<<20]", sz)
}
}
attrAlign.CheckConsts = func(comp *compiler, parent ast.Node, attr *ast.Type) {
_, _, name := parent.Info()
a := attr.Args[0].Value
if a&(a-1) != 0 || a == 0 || a > 1<<30 {
comp.error(attr.Pos, "bad struct %v alignment %v (must be a sane power of 2)", name, a)
}
}
}
func initCallAttrs() {
attrs := reflect.TypeOf(prog.SyscallAttrs{})
for i := 0; i < attrs.NumField(); i++ {
attr := attrs.Field(i)
desc := &attrDesc{Name: attr.Name}
switch attr.Type.Kind() {
case reflect.Bool:
case reflect.Uint64:
desc.Type = intAttr
case reflect.String:
desc.Type = stringAttr
default:
panic("unsupported syscall attribute type")
}
callAttrs[prog.CppName(desc.Name)] = desc
}
}
func structOrUnionAttrs(n *ast.Struct) map[string]*attrDesc {
if n.IsUnion {
return unionAttrs
}
return structAttrs
}
func structOrUnionFieldAttrs(n *ast.Struct) map[string]*attrDesc {
if n.IsUnion {
return unionFieldAttrs
}
return structFieldAttrs
}
func makeAttrs(attrs ...*attrDesc) map[string]*attrDesc {
m := make(map[string]*attrDesc)
for _, attr := range attrs {
m[attr.Name] = attr
}
return m
}
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
// Package compiler generates sys descriptions of syscalls, types and resources
// from textual descriptions.
package compiler
import (
"errors"
"fmt"
"regexp"
"strings"
"github.com/google/syzkaller/pkg/ast"
"github.com/google/syzkaller/prog"
"github.com/google/syzkaller/sys/targets"
)
func (comp *compiler) typecheck() {
comp.checkComments()
comp.checkDirectives()
comp.checkNames()
comp.checkFlags()
comp.checkFields()
comp.checkTypedefs()
comp.checkTypes()
}
func (comp *compiler) check(consts map[string]uint64) {
comp.checkTypeValues()
comp.checkAttributeValues()
comp.checkUnused()
comp.checkRecursion()
comp.checkFieldPaths()
comp.checkConstructors()
comp.checkVarlens()
comp.checkDupConsts()
comp.checkConstsFlags(consts)
}
func (comp *compiler) checkComments() {
confusingComment := regexp.MustCompile(`^\s*(include|incdir|define)`)
for _, decl := range comp.desc.Nodes {
switch n := decl.(type) {
case *ast.Comment:
if confusingComment.MatchString(n.Text) {
comp.error(n.Pos, "confusing comment faking a directive (rephrase if it's intentional)")
}
}
}
}
func (comp *compiler) checkDirectives() {
includes := make(map[string]bool)
incdirs := make(map[string]bool)
defines := make(map[string]bool)
for _, decl := range comp.desc.Nodes {
switch n := decl.(type) {
case *ast.Include:
name := n.File.Value
path := n.Pos.File + "/" + name
if includes[path] {
comp.error(n.Pos, "duplicate include %q", name)
}
includes[path] = true
case *ast.Incdir:
name := n.Dir.Value
path := n.Pos.File + "/" + name
if incdirs[path] {
comp.error(n.Pos, "duplicate incdir %q", name)
}
incdirs[path] = true
case *ast.Define:
name := n.Name.Name
path := n.Pos.File + "/" + name
if defines[path] {
comp.error(n.Pos, "duplicate define %v", name)
}
defines[path] = true
}
}
}
func (comp *compiler) checkNames() {
calls := make(map[string]*ast.Call)
for _, decl := range comp.desc.Nodes {
switch n := decl.(type) {
case *ast.Resource, *ast.Struct, *ast.TypeDef:
pos, typ, name := decl.Info()
if reservedName[name] {
comp.error(pos, "%v uses reserved name %v", typ, name)
continue
}
if builtinTypes[name] != nil {
comp.error(pos, "%v name %v conflicts with builtin type", typ, name)
continue
}
if prev := comp.resources[name]; prev != nil {
comp.error(pos, "type %v redeclared, previously declared as resource at %v",
name, prev.Pos)
continue
}
if prev := comp.typedefs[name]; prev != nil {
comp.error(pos, "type %v redeclared, previously declared as type alias at %v",
name, prev.Pos)
continue
}
if prev := comp.structs[name]; prev != nil {
_, typ, _ := prev.Info()
comp.error(pos, "type %v redeclared, previously declared as %v at %v",
name, typ, prev.Pos)
continue
}
switch n := decl.(type) {
case *ast.Resource:
comp.resources[name] = n
case *ast.TypeDef:
comp.typedefs[name] = n
case *ast.Struct:
comp.structs[name] = n
}
case *ast.IntFlags:
name := n.Name.Name
if name == "_" {
continue
}
if reservedName[name] {
comp.error(n.Pos, "flags uses reserved name %v", name)
continue
}
if prev := comp.intFlags[name]; prev != nil {
comp.error(n.Pos, "flags %v redeclared, previously declared at %v",
name, prev.Pos)
continue
}
comp.intFlags[name] = n
case *ast.StrFlags:
name := n.Name.Name
if reservedName[name] {
comp.error(n.Pos, "string flags uses reserved name %v", name)
continue
}
if prev := comp.strFlags[name]; prev != nil {
comp.error(n.Pos, "string flags %v redeclared, previously declared at %v",
name, prev.Pos)
continue
}
comp.strFlags[name] = n
case *ast.Call:
name := n.Name.Name
if prev := calls[name]; prev != nil {
comp.error(n.Pos, "syscall %v redeclared, previously declared at %v",
name, prev.Pos)
}
calls[name] = n
}
}
}
func (comp *compiler) checkFlags() {
checkFlagsGeneric[*ast.IntFlags, *ast.Int](comp, comp.intFlags)
checkFlagsGeneric[*ast.StrFlags, *ast.String](comp, comp.strFlags)
}
func checkFlagsGeneric[F ast.Flags[V], V ast.FlagValue](comp *compiler, allFlags map[string]F) {
for name, flags := range allFlags {
inConstIdent := true
for _, val := range flags.GetValues() {
if _, ok := allFlags[val.GetName()]; ok {
inConstIdent = false
} else {
if !inConstIdent {
comp.error(flags.GetPos(), "flags identifier not at the end in %v definition", name)
break
}
}
}
}
}
func (comp *compiler) checkFields() {
for _, decl := range comp.desc.Nodes {
switch n := decl.(type) {
case *ast.Struct:
_, typ, name := n.Info()
comp.checkStructFields(n, typ, name)
case *ast.TypeDef:
if n.Struct != nil {
_, typ, _ := n.Struct.Info()
comp.checkStructFields(n.Struct, "template "+typ, n.Name.Name)
}
case *ast.Call:
name := n.Name.Name
comp.checkFieldGroup(n.Args, "argument", "syscall "+name)
if len(n.Args) > prog.MaxArgs {
comp.error(n.Pos, "syscall %v has %v arguments, allowed maximum is %v",
name, len(n.Args), prog.MaxArgs)
}
}
}
}
func (comp *compiler) checkStructFields(n *ast.Struct, typ, name string) {
comp.checkFieldGroup(n.Fields, "field", typ+" "+name)
if len(n.Fields) < 1 {
comp.error(n.Pos, "%v %v has no fields, need at least 1 field", typ, name)
}
hasDirections, hasOutOverlay := false, false
prevFieldHadIf := false
for fieldIdx, f := range n.Fields {
if n.IsUnion {
_, exprs, _ := comp.parseAttrs(unionFieldAttrs, f, f.Attrs)
if fieldIdx > 0 && fieldIdx+1 < len(n.Fields) &&
prevFieldHadIf && exprs[attrIf] == nil {
comp.error(f.Pos, "either no fields have conditions or all except the last")
}
prevFieldHadIf = exprs[attrIf] != nil
if fieldIdx+1 == len(n.Fields) && exprs[attrIf] != nil {
comp.error(f.Pos, "unions must not have if conditions on the last field")
}
continue
}
attrs, _, _ := comp.parseAttrs(structFieldAttrs, f, f.Attrs)
dirCount := attrs[attrIn] + attrs[attrOut] + attrs[attrInOut]
if dirCount != 0 {
hasDirections = true
}
if dirCount > 1 {
_, typ, _ := f.Info()
comp.error(f.Pos, "%v has multiple direction attributes", typ)
}
if attrs[attrOutOverlay] > 0 {
if fieldIdx == 0 {
comp.error(f.Pos, "%v attribute must not be specified on the first field", attrOutOverlay.Name)
}
if hasOutOverlay || attrs[attrOutOverlay] > 1 {
comp.error(f.Pos, "multiple %v attributes", attrOutOverlay.Name)
}
hasOutOverlay = true
}
if hasDirections && hasOutOverlay {
comp.error(f.Pos, "mix of direction and %v attributes is not supported", attrOutOverlay.Name)
}
}
}
func (comp *compiler) checkFieldGroup(fields []*ast.Field, what, ctx string) {
existing := make(map[string]bool)
for _, f := range fields {
fn := f.Name.Name
if fn == prog.ParentRef || fn == prog.SyscallRef {
comp.error(f.Pos, "reserved %v name %v in %v", what, fn, ctx)
}
if existing[fn] {
comp.error(f.Pos, "duplicate %v %v in %v", what, fn, ctx)
}
existing[fn] = true
}
}
const argBase = "BASE"
func (comp *compiler) checkTypedefs() {
for _, decl := range comp.desc.Nodes {
switch n := decl.(type) {
case *ast.TypeDef:
if len(n.Args) == 0 {
// Non-template types are fully typed, so we check them ahead of time.
err0 := comp.errors
comp.checkType(checkCtx{}, n.Type, checkIsTypedef)
if err0 != comp.errors {
// To not produce confusing errors on broken type usage.
delete(comp.typedefs, n.Name.Name)
}
} else {
// For templates we only do basic checks of arguments.
names := make(map[string]bool)
for i, arg := range n.Args {
if arg.Name == argBase && i != len(n.Args)-1 {
comp.error(arg.Pos, "type argument BASE must be the last argument")
}
if names[arg.Name] {
comp.error(arg.Pos, "duplicate type argument %v", arg.Name)
}
names[arg.Name] = true
for _, c := range arg.Name {
if c >= 'A' && c <= 'Z' ||
c >= '0' && c <= '9' ||
c == '_' {
continue
}
comp.error(arg.Pos, "type argument %v must be ALL_CAPS",
arg.Name)
break
}
}
}
}
}
}
func (comp *compiler) checkTypes() {
for _, decl := range comp.desc.Nodes {
switch n := decl.(type) {
case *ast.Resource:
comp.checkType(checkCtx{}, n.Base, checkIsResourceBase)
case *ast.Struct:
comp.checkStruct(checkCtx{}, n)
case *ast.Call:
comp.checkCall(n)
}
}
}
func (comp *compiler) checkTypeValues() {
for _, decl := range comp.desc.Nodes {
switch n := decl.(type) {
case *ast.Call, *ast.Struct, *ast.Resource, *ast.TypeDef:
comp.foreachType(decl, func(t *ast.Type, desc *typeDesc,
args []*ast.Type, base prog.IntTypeCommon) {
if desc.CheckConsts != nil {
desc.CheckConsts(comp, t, args, base)
}
for i, arg := range args {
if check := desc.Args[i].Type.CheckConsts; check != nil {
check(comp, arg)
}
}
})
case *ast.IntFlags:
allEqual := len(n.Values) >= 2
for _, val := range n.Values {
if val.Value != n.Values[0].Value {
allEqual = false
}
}
if allEqual {
comp.error(n.Pos, "all %v values are equal %v", n.Name.Name, n.Values[0].Value)
}
}
}
}
func (comp *compiler) checkAttributeValues() {
for _, decl := range comp.desc.Nodes {
switch n := decl.(type) {
case *ast.Struct:
for _, attr := range n.Attrs {
desc := structOrUnionAttrs(n)[attr.Ident]
if desc.CheckConsts != nil {
desc.CheckConsts(comp, n, attr)
}
}
// Check each field's attributes.
st := decl.(*ast.Struct)
hasOutOverlay := false
for _, f := range st.Fields {
isOut := hasOutOverlay
for _, attr := range f.Attrs {
switch attr.Ident {
case attrOutOverlay.Name:
hasOutOverlay = true
fallthrough
case attrOut.Name, attrInOut.Name:
isOut = true
}
}
if isOut && comp.getTypeDesc(f.Type).CantBeOut {
comp.error(f.Pos, "%v type must not be used as output", f.Type.Ident)
}
}
case *ast.Call:
attrNames := make(map[string]bool)
descAttrs := comp.parseIntAttrs(callAttrs, n, n.Attrs)
for desc := range descAttrs {
attrNames[prog.CppName(desc.Name)] = true
}
checked := make(map[string]bool)
for _, a := range n.Args {
comp.checkRequiredCallAttrs(n, attrNames, a.Type, checked)
}
}
}
}
func (comp *compiler) checkRequiredCallAttrs(call *ast.Call, callAttrNames map[string]bool,
t *ast.Type, checked map[string]bool) {
desc := comp.getTypeDesc(t)
for attr := range desc.RequiresCallAttrs {
if !callAttrNames[attr] {
comp.error(call.Pos, "call %v refers to type %v and so must be marked %s", call.Name.Name, t.Ident, attr)
}
}
switch desc {
case typeStruct:
s := comp.structs[t.Ident]
// Prune recursion, can happen even on correct tree via opt pointers.
if checked[s.Name.Name] {
return
}
checked[s.Name.Name] = true
fields := s.Fields
for _, fld := range fields {
comp.checkRequiredCallAttrs(call, callAttrNames, fld.Type, checked)
}
case typeArray:
typ := t.Args[0]
comp.checkRequiredCallAttrs(call, callAttrNames, typ, checked)
case typePtr:
typ := t.Args[1]
comp.checkRequiredCallAttrs(call, callAttrNames, typ, checked)
}
}
func (comp *compiler) checkFieldPaths() {
warned := make(map[string]bool)
for _, decl := range comp.desc.Nodes {
switch n := decl.(type) {
case *ast.Call:
for _, arg := range n.Args {
checked := make(map[string]bool)
parents := []parentDesc{{fields: n.Args, call: n.Name.Name}}
comp.checkFieldPathsRec(arg.Type, arg.Type, parents, checked, warned, true)
}
}
}
}
type parentDesc struct {
call string
name string
fields []*ast.Field
}
func (pd *parentDesc) String() string {
if pd.call != "" {
return fmt.Sprintf("<%s>", pd.call)
}
return pd.name
}
// templateBase return the part before '[' for full template names.
func templateBase(name string) string {
if pos := strings.IndexByte(name, '['); pos != -1 {
return name[:pos]
}
return name
}
func parentTargetName(s *ast.Struct) string {
// For template parents name is "struct_name[ARG1, ARG2]", strip the part after '['.
return templateBase(s.Name.Name)
}
func (comp *compiler) checkFieldPathsRec(t0, t *ast.Type, parents []parentDesc,
checked, warned map[string]bool, isArg bool) {
desc := comp.getTypeDesc(t)
if desc == typeStruct {
s := comp.structs[t.Ident]
// Prune recursion, can happen even on correct tree via opt pointers.
// There may be several paths to the same type, let's at least look
// at the nearest parent.
checkName := s.Name.Name
if len(parents) > 1 {
checkName = parents[len(parents)-2].name + " " + checkName
}
if checked[checkName] {
return
}
checked[checkName] = true
fields := s.Fields
if s.IsUnion {
fields = nil
}
parentName := parentTargetName(s)
parents = append([]parentDesc{}, parents...)
parents = append(parents, parentDesc{name: parentName, fields: fields})
for _, fld := range s.Fields {
comp.checkFieldPathsRec(fld.Type, fld.Type, parents, checked, warned, false)
for _, attr := range fld.Attrs {
attrDesc := structFieldAttrs[attr.Ident]
if attrDesc == nil || attrDesc.Type != exprAttr {
continue
}
if attrDesc == attrIf {
comp.checkExprFieldType(fld.Type)
}
ast.Recursive(func(n ast.Node) bool {
exprType, ok := n.(*ast.Type)
if !ok || exprType.Ident != valueIdent {
return true
}
comp.validateFieldPath(exprType.Args[0], t0, exprType, parents, warned)
return false
})(attr.Args[0])
}
}
return
}
_, args, _ := comp.getArgsBase(t, isArg)
for i, arg := range args {
argDesc := desc.Args[i]
switch argDesc.Type {
case typeArgLenTarget:
comp.validateFieldPath(arg, t0, t, parents, warned)
case typeArgType:
comp.checkFieldPathsRec(t0, arg, parents, checked, warned, argDesc.IsArg)
}
}
}
func (comp *compiler) validateFieldPath(arg, fieldType, t *ast.Type, parents []parentDesc,
warned map[string]bool) {
targets := append([]*ast.Type{arg}, arg.Colon...)
const maxParents = 2
for i, target := range targets {
if target.Ident == prog.ParentRef &&
(i >= maxParents || targets[0].Ident != prog.ParentRef) {
// It's not a fundamental limitation, but it helps prune recursion in checkLenType().
// If we need more, we need to adjust the key of the "checked" map.
if !warned[parents[len(parents)-1].name] {
comp.error(target.Pos, "%v may only stay at the beginning (max %d times)",
prog.ParentRef, maxParents)
}
warned[parents[len(parents)-1].name] = true
return
}
if target.Ident == prog.SyscallRef {
if i != 0 {
comp.error(target.Pos, "syscall can't be in the middle of path expressions")
return
}
if len(targets) == 1 {
comp.error(targets[0].Pos, "no argument name after syscall reference")
return
}
}
}
// Drop parents from the prefix (it will simplify further code).
droppedParents := 0
for len(targets) > 0 && targets[0].Ident == prog.ParentRef {
target := targets[0]
if parents[len(parents)-1].call != "" {
comp.error(target.Pos, "%v reached the call (%v)",
prog.ParentRef, parents[0].call)
return
}
droppedParents++
targets = targets[1:]
// Ignore the first "parent" item.
if droppedParents > 1 {
if len(parents) < 2 {
comp.error(target.Pos, "too many %v elements", prog.ParentRef)
return
}
parents = parents[:len(parents)-1]
}
}
comp.validateFieldPathRec(fieldType, t, targets, parents, warned)
}
func (comp *compiler) validateFieldPathRec(t0, t *ast.Type, targets []*ast.Type,
parents []parentDesc, warned map[string]bool) {
if len(targets) == 0 {
if t.Ident == "offsetof" {
comp.error(t.Pos, "%v must refer to fields", t.Ident)
return
}
return
}
isValuePath := t.Ident == valueIdent
target := targets[0]
targets = targets[1:]
fields := parents[len(parents)-1].fields
for _, fld := range fields {
if target.Ident != fld.Name.Name {
continue
}
if fld.Type == t0 {
comp.error(target.Pos, "%v target %v refers to itself", t.Ident, target.Ident)
return
}
if !comp.checkPathField(target, t, fld) {
return
}
if len(targets) == 0 {
if t.Ident == "len" {
typ, desc := comp.derefPointers(fld.Type)
if desc == typeArray && comp.isVarlen(typ.Args[0]) {
// We can reach the same struct multiple times starting from different
// syscall arguments. Warn only once.
if !warned[parents[len(parents)-1].name] {
warned[parents[len(parents)-1].name] = true
comp.warning(target.Pos, "len target %v refer to an array with"+
" variable-size elements (do you mean bytesize?)",
target.Ident)
}
}
}
if isValuePath {
comp.checkExprLastField(target, fld)
}
return
}
typ, desc := comp.derefPointers(fld.Type)
if desc != typeStruct {
comp.error(target.Pos, "%v path %v does not refer to a struct", t.Ident, target.Ident)
return
}
s := comp.structs[typ.Ident]
if s.IsUnion {
comp.error(target.Pos, "%v path %v does not refer to a struct", t.Ident, target.Ident)
return
}
parents = append(parents, parentDesc{name: parentTargetName(s), fields: s.Fields})
comp.validateFieldPathRec(t0, t, targets, parents, warned)
return
}
for pi := len(parents) - 1; pi >= 0; pi-- {
parent := parents[pi]
if parent.name != "" && parent.name == target.Ident ||
parent.name == "" && target.Ident == prog.SyscallRef {
parents1 := make([]parentDesc, pi+1)
copy(parents1, parents[:pi+1])
comp.validateFieldPathRec(t0, t, targets, parents1, warned)
return
}
}
warnKey := parents[len(parents)-1].name + " " + target.Pos.String()
if !warned[warnKey] {
comp.error(target.Pos, "%v target %v does not exist in %s",
t.Ident, target.Ident, parents[len(parents)-1].String())
}
warned[warnKey] = true
}
func (comp *compiler) checkPathField(target, t *ast.Type, field *ast.Field) bool {
for _, attr := range field.Attrs {
desc := structFieldAttrs[attr.Ident]
if desc == attrIf {
comp.error(target.Pos, "%s has conditions, so %s path cannot reference it",
field.Name.Name, t.Ident)
return false
}
}
return true
}
func (comp *compiler) checkExprLastField(target *ast.Type, field *ast.Field) {
_, desc := comp.derefPointers(field.Type)
if desc != typeInt && desc != typeFlags && desc != typeConst {
comp.error(target.Pos, "%v does not refer to a constant, an integer, or a flag", field.Name.Name)
}
}
func (comp *compiler) checkExprFieldType(t *ast.Type) {
desc := comp.getTypeDesc(t)
if desc == typeInt && len(t.Colon) != 0 {
comp.error(t.Pos, "bitfields may not have conditions")
}
}
func CollectUnused(desc *ast.Description, target *targets.Target, eh ast.ErrorHandler) ([]ast.Node, error) {
comp := createCompiler(desc, target, eh)
comp.typecheck()
if comp.errors > 0 {
return nil, errors.New("typecheck failed")
}
nodes := comp.collectUnused()
if comp.errors > 0 {
return nil, errors.New("collectUnused failed")
}
return nodes, nil
}
// CollectUnusedConsts returns unused defines/includes. This is used only for auto-generated descriptions.
func CollectUnusedConsts(desc *ast.Description, target *targets.Target, includeUse map[string]string,
eh ast.ErrorHandler) ([]ast.Node, error) {
comp := createCompiler(desc, target, eh)
comp.typecheck()
if comp.errors > 0 {
return nil, errors.New("typecheck failed")
}
var unused []ast.Node
for file, info := range comp.extractConsts() {
if !comp.fileMeta(ast.Pos{File: file}).Automatic {
continue
}
usedDefines := make(map[string]bool)
usedIncludes := make(map[string]bool)
for _, c := range info.Consts {
if c.Used {
usedDefines[c.Name] = true
usedIncludes[includeUse[c.Name]] = true
}
}
for _, decl := range comp.desc.Nodes {
switch n := decl.(type) {
case *ast.Define:
if n.Pos.File == file && !usedDefines[n.Name.Name] {
unused = append(unused, n)
}
case *ast.Include:
if n.Pos.File == file && !usedIncludes[n.File.Value] {
unused = append(unused, n)
}
}
}
}
return unused, nil
}
func (comp *compiler) collectUnused() []ast.Node {
var unused []ast.Node
comp.used, _, _ = comp.collectUsed(false)
structs, flags, strflags := comp.collectUsed(true)
note := func(n ast.Node) {
if pos, _, _ := n.Info(); pos.Builtin() {
return
}
unused = append(unused, n)
}
for name, n := range comp.intFlags {
if !flags[name] {
note(n)
}
}
for name, n := range comp.strFlags {
if !strflags[name] {
note(n)
}
}
for name, n := range comp.resources {
if !structs[name] {
note(n)
}
}
for name, n := range comp.structs {
if !structs[name] {
note(n)
}
}
for name, n := range comp.typedefs {
if !comp.usedTypedefs[name] {
note(n)
}
}
return unused
}
func (comp *compiler) collectUsed(all bool) (structs, flags, strflags map[string]bool) {
structs = make(map[string]bool)
flags = make(map[string]bool)
strflags = make(map[string]bool)
for _, decl := range comp.desc.Nodes {
switch n := decl.(type) {
case *ast.Call:
if !all && n.NR == ^uint64(0) {
break
}
for _, arg := range n.Args {
comp.collectUsedType(structs, flags, strflags, arg.Type, true)
}
if n.Ret != nil {
comp.collectUsedType(structs, flags, strflags, n.Ret, true)
}
}
}
return
}
func (comp *compiler) collectUsedType(structs, flags, strflags map[string]bool, t *ast.Type, isArg bool) {
desc := comp.getTypeDesc(t)
if desc == typeResource {
r := comp.resources[t.Ident]
for r != nil && !structs[r.Name.Name] {
structs[r.Name.Name] = true
r = comp.resources[r.Base.Ident]
}
return
}
if desc == typeStruct {
if structs[t.Ident] {
return
}
structs[t.Ident] = true
s := comp.structs[t.Ident]
for _, fld := range s.Fields {
comp.collectUsedType(structs, flags, strflags, fld.Type, false)
}
return
}
if desc == typeFlags ||
(desc == typeInt && len(t.Args) > 0 && t.Args[0].Ident != "") {
flags[t.Args[0].Ident] = true
return
}
if desc == typeString {
if len(t.Args) != 0 && t.Args[0].Ident != "" {
strflags[t.Args[0].Ident] = true
}
return
}
_, args, _ := comp.getArgsBase(t, isArg)
for i, arg := range args {
if desc.Args[i].Type == typeArgType {
comp.collectUsedType(structs, flags, strflags, arg, desc.Args[i].IsArg)
}
}
}
func (comp *compiler) checkUnused() {
for _, n := range comp.collectUnused() {
pos, typ, name := n.Info()
comp.error(pos, "unused %v %v", typ, name)
}
}
func (comp *compiler) checkConstsFlags(consts map[string]uint64) {
for name := range consts {
if flags, isFlag := comp.intFlags[name]; isFlag {
pos, _, _ := flags.Info()
comp.error(pos, "const %v is already a flag", name)
}
}
}
type structDir struct {
Struct string
Dir prog.Dir
}
func (comp *compiler) checkConstructors() {
ctors := make(map[string]bool) // resources for which we have ctors
inputs := make(map[string]bool) // resources which are used as inputs
checked := make(map[structDir]bool)
for _, decl := range comp.desc.Nodes {
switch n := decl.(type) {
case *ast.Call:
for _, arg := range n.Args {
comp.checkTypeCtors(arg.Type, prog.DirIn, true, true, ctors, inputs, checked, nil)
}
if n.Ret != nil {
comp.checkTypeCtors(n.Ret, prog.DirOut, true, true, ctors, inputs, checked, nil)
}
}
}
for _, decl := range comp.desc.Nodes {
switch n := decl.(type) {
case *ast.Resource:
name := n.Name.Name
if !comp.used[name] {
continue
}
if !ctors[name] {
comp.error(n.Pos, "resource %v can't be created"+
" (never mentioned as a syscall return value or output argument/field)", name)
}
if !inputs[name] {
comp.error(n.Pos, "resource %v is never used as an input"+
" (such resources are not useful)", name)
}
}
}
}
// nolint:revive
func (comp *compiler) checkTypeCtors(t *ast.Type, dir prog.Dir, isArg, canCreate bool,
ctors, inputs map[string]bool, checked map[structDir]bool, neverOutAt *ast.Pos) {
desc, args, base := comp.getArgsBase(t, isArg)
if base.IsOptional {
canCreate = false
}
if desc.CantHaveOut {
neverOutAt = &t.Pos
}
if desc == typeResource {
// TODO(dvyukov): consider changing this to "dir == prog.DirOut".
// We have few questionable cases where resources can be created
// only by inout struct fields. These structs should be split
// into two different structs: one is in and second is out.
// But that will require attaching dir to individual fields.
if dir != prog.DirIn && neverOutAt != nil {
comp.error(*neverOutAt, "resource %s cannot be created in fmt", t.Ident)
}
if canCreate && dir != prog.DirIn {
r := comp.resources[t.Ident]
for r != nil && !ctors[r.Name.Name] {
ctors[r.Name.Name] = true
r = comp.resources[r.Base.Ident]
}
}
if dir != prog.DirOut {
r := comp.resources[t.Ident]
for r != nil && !inputs[r.Name.Name] {
inputs[r.Name.Name] = true
r = comp.resources[r.Base.Ident]
}
}
return
}
if desc == typeStruct {
s := comp.structs[t.Ident]
if s.IsUnion {
canCreate = false
}
name := s.Name.Name
key := structDir{name, dir}
if checked[key] {
return
}
checked[key] = true
for _, fld := range s.Fields {
fldDir, fldHasDir := comp.genFieldDir(comp.parseIntAttrs(structFieldAttrs, fld, fld.Attrs))
if !fldHasDir {
fldDir = dir
}
comp.checkTypeCtors(fld.Type, fldDir, false, canCreate, ctors, inputs, checked, neverOutAt)
}
return
}
if desc == typePtr {
dir = genDir(t.Args[0])
}
for i, arg := range args {
if desc.Args[i].Type == typeArgType {
comp.checkTypeCtors(arg, dir, desc.Args[i].IsArg, canCreate, ctors, inputs, checked, neverOutAt)
}
}
}
func (comp *compiler) checkRecursion() {
checked := make(map[string]bool)
for _, decl := range comp.desc.Nodes {
switch n := decl.(type) {
case *ast.Resource:
comp.checkResourceRecursion(n)
case *ast.Struct:
var path []pathElem
comp.checkStructRecursion(checked, n, path)
}
}
}
func (comp *compiler) checkResourceRecursion(n *ast.Resource) {
var seen []string
for n != nil {
if arrayContains(seen, n.Name.Name) {
chain := ""
for _, r := range seen {
chain += r + "->"
}
chain += n.Name.Name
comp.error(n.Pos, "recursive resource %v", chain)
return
}
seen = append(seen, n.Name.Name)
n = comp.resources[n.Base.Ident]
}
}
type pathElem struct {
Pos ast.Pos
Struct string
Field string
}
func (comp *compiler) checkStructRecursion(checked map[string]bool, n *ast.Struct, path []pathElem) {
name := n.Name.Name
if checked[name] {
return
}
for i, elem := range path {
if elem.Struct != name {
continue
}
path = path[i:]
str := ""
for _, elem := range path {
str += fmt.Sprintf("%v.%v -> ", elem.Struct, elem.Field)
}
str += name
comp.error(path[0].Pos, "recursive declaration: %v (mark some pointers as opt, or use variable-length arrays)", str)
checked[name] = true
return
}
for _, f := range n.Fields {
path = append(path, pathElem{
Pos: f.Pos,
Struct: name,
Field: f.Name.Name,
})
comp.recurseField(checked, f.Type, path, false)
path = path[:len(path)-1]
}
checked[name] = true
}
func (comp *compiler) recurseField(checked map[string]bool, t *ast.Type, path []pathElem, isArg bool) {
desc := comp.getTypeDesc(t)
if desc == typeStruct {
comp.checkStructRecursion(checked, comp.structs[t.Ident], path)
return
}
_, args, base := comp.getArgsBase(t, isArg)
if desc == typePtr && base.IsOptional {
return // optional pointers prune recursion
}
if desc == typeArray && len(args) == 1 {
return // variable-length arrays prune recursion
}
for i, arg := range args {
if desc.Args[i].Type == typeArgType {
isArg := false
if t.Ident == "fmt" {
isArg = true
}
comp.recurseField(checked, arg, path, isArg)
}
}
}
func (comp *compiler) checkStruct(ctx checkCtx, n *ast.Struct) {
var flags checkFlags
if !n.IsUnion {
flags |= checkIsStruct
}
for _, f := range n.Fields {
comp.checkType(ctx, f.Type, flags)
}
comp.parseAttrs(structOrUnionAttrs(n), n, n.Attrs)
}
func (comp *compiler) checkCall(n *ast.Call) {
for _, a := range n.Args {
comp.checkType(checkCtx{}, a.Type, checkIsArg)
}
if n.Ret != nil {
comp.checkType(checkCtx{}, n.Ret, checkIsArg|checkIsRet)
}
comp.parseAttrs(callAttrs, n, n.Attrs)
}
type checkFlags int
const (
checkIsArg checkFlags = 1 << iota // immediate syscall arg type
checkIsRet // immediate syscall ret type
checkIsStruct // immediate struct field type
checkIsResourceBase // immediate resource base type
checkIsTypedef // immediate type alias/template type
)
type checkCtx struct {
instantiationStack []string
}
func (comp *compiler) checkType(ctx checkCtx, t *ast.Type, flags checkFlags) {
comp.checkTypeImpl(ctx, t, comp.getTypeDesc(t), flags)
}
func (comp *compiler) checkTypeImpl(ctx checkCtx, t *ast.Type, desc *typeDesc, flags checkFlags) {
if unexpected, _, ok := checkTypeKind(t, kindIdent); !ok {
comp.error(t.Pos, "unexpected %v, expect type", unexpected)
return
}
if desc == nil {
comp.error(t.Pos, "unknown type %v", t.Ident)
return
}
if desc == typeTypedef {
err0 := comp.errors
// Replace t with type alias/template target type inplace,
// and check the replaced type recursively.
comp.replaceTypedef(&ctx, t, flags)
if err0 == comp.errors {
comp.checkType(ctx, t, flags)
}
return
}
err0 := comp.errors
comp.checkTypeBasic(t, desc, flags)
if err0 != comp.errors {
return
}
args := comp.checkTypeArgs(t, desc, flags)
if err0 != comp.errors {
return
}
for i, arg := range args {
if desc.Args[i].Type == typeArgType {
var innerFlags checkFlags
if desc.Args[i].IsArg {
innerFlags |= checkIsArg
}
comp.checkType(ctx, arg, innerFlags)
} else {
comp.checkTypeArg(t, arg, desc.Args[i])
}
}
if err0 != comp.errors {
return
}
if desc.Check != nil {
_, args, base := comp.getArgsBase(t, flags&checkIsArg != 0)
desc.Check(comp, t, args, base)
}
}
func (comp *compiler) checkTypeBasic(t *ast.Type, desc *typeDesc, flags checkFlags) {
for i, col := range t.Colon {
if i >= desc.MaxColon {
comp.error(col.Pos, "unexpected ':'")
return
}
if flags&checkIsStruct == 0 {
comp.error(col.Pos, "unexpected ':', only struct fields can be bitfields")
return
}
}
if flags&checkIsTypedef != 0 && !desc.CanBeTypedef {
comp.error(t.Pos, "%v can't be type alias target", t.Ident)
return
}
if flags&checkIsResourceBase != 0 &&
(desc.CanBeResourceBase == nil || !desc.CanBeResourceBase(comp, t)) {
comp.error(t.Pos, "%v can't be resource base (int types can)", t.Ident)
return
}
canBeArg, canBeRet := false, false
if desc.CanBeArgRet != nil {
canBeArg, canBeRet = desc.CanBeArgRet(comp, t)
}
if flags&checkIsRet != 0 && !canBeRet {
comp.error(t.Pos, "%v can't be syscall return", t.Ident)
return
}
if flags&checkIsArg != 0 && !canBeArg {
comp.error(t.Pos, "%v can't be syscall argument", t.Ident)
return
}
}
func (comp *compiler) checkTypeArgs(t *ast.Type, desc *typeDesc, flags checkFlags) []*ast.Type {
args, opt := removeOpt(t)
if opt != nil {
if len(opt.Args) != 0 {
comp.error(opt.Pos, "opt can't have arguments")
}
if flags&checkIsResourceBase != 0 || desc.CantBeOpt {
what := "resource base"
if desc.CantBeOpt {
what = t.Ident
}
comp.error(opt.Pos, "%v can't be marked as opt", what)
return nil
}
}
addArgs := 0
needBase := flags&checkIsArg == 0 && desc.NeedBase
if needBase {
addArgs++ // last arg must be base type, e.g. const[0, int32]
}
if len(args) > len(desc.Args)+addArgs || len(args) < len(desc.Args)-desc.OptArgs+addArgs {
comp.error(t.Pos, "wrong number of arguments for type %v, expect %v",
t.Ident, expectedTypeArgs(desc, needBase))
return nil
}
if needBase {
base := args[len(args)-1]
args = args[:len(args)-1]
comp.checkTypeArg(t, base, typeArgBase)
}
return args
}
func (comp *compiler) replaceTypedef(ctx *checkCtx, t *ast.Type, flags checkFlags) {
typedefName := t.Ident
typedef := comp.typedefs[typedefName]
fullTypeName := ast.SerializeNode(t)
if comp.brokenTypedefs[fullTypeName] {
// We've already produced some errors for this exact type instantiation.
// Don't produce duplicates, also helps to prevent exponential
// slowdown due to some cases of recursion. But increment the number
// of errors so that callers can understand that we did not succeed.
comp.errors++
return
}
comp.usedTypedefs[typedefName] = true
err0 := comp.errors
defer func() {
comp.brokenTypedefs[fullTypeName] = err0 != comp.errors
}()
if len(t.Colon) != 0 {
comp.error(t.Pos, "type alias %v with ':'", t.Ident)
return
}
// Handling optional BASE argument.
if len(typedef.Args) > 0 && typedef.Args[len(typedef.Args)-1].Name == argBase {
if flags&checkIsArg != 0 && len(t.Args) == len(typedef.Args)-1 {
t.Args = append(t.Args, &ast.Type{
Pos: t.Pos,
Ident: "intptr",
})
} else if len(t.Args) == len(typedef.Args) {
comp.checkTypeArg(t, t.Args[len(t.Args)-1], typeArgBase)
}
}
recursion := 0
ctx.instantiationStack = append(ctx.instantiationStack, fullTypeName)
for i, prev := range ctx.instantiationStack[:len(ctx.instantiationStack)-1] {
if typedefName == templateBase(prev) {
recursion++
if recursion > 10 {
comp.error(t.Pos, "type instantiation recursion: %v", strings.Join(ctx.instantiationStack, " -> "))
return
}
}
if prev != fullTypeName {
continue
}
comp.error(t.Pos, "type instantiation loop: %v", strings.Join(ctx.instantiationStack[i:], " -> "))
return
}
nargs := len(typedef.Args)
args := t.Args
if nargs != len(t.Args) {
if nargs == 0 {
comp.error(t.Pos, "type %v is not a template", typedefName)
} else {
if flags&checkIsArg != 0 && typedef.Args[len(typedef.Args)-1].Name == argBase {
nargs--
}
comp.error(t.Pos, "template %v needs %v arguments instead of %v",
typedefName, nargs, len(t.Args))
}
return
}
pos0 := t.Pos
if typedef.Type != nil {
*t = *typedef.Type.Clone().(*ast.Type)
if !comp.instantiate(t, typedef.Args, args) {
return
}
} else {
inst := comp.structs[fullTypeName]
if inst == nil {
inst = typedef.Struct.Clone().(*ast.Struct)
inst.Name.Name = fullTypeName
if !comp.instantiate(inst, typedef.Args, args) {
return
}
comp.checkStruct(*ctx, inst)
if err0 != comp.errors {
return
}
comp.desc.Nodes = append(comp.desc.Nodes, inst)
comp.structs[fullTypeName] = inst
comp.structFiles[inst] = make(map[string]ast.Pos)
}
comp.structFiles[inst][pos0.File] = pos0
*t = ast.Type{
Ident: fullTypeName,
}
}
t.Pos = pos0
comp.maybeRemoveBase(t, flags)
}
func (comp *compiler) maybeRemoveBase(t *ast.Type, flags checkFlags) {
// Remove base type if it's not needed in this context.
// If desc is nil, will return an error later when we typecheck the result.
desc := comp.getTypeDesc(t)
if desc != nil && flags&checkIsArg != 0 && desc.NeedBase && len(t.Args) != 0 {
baseTypePos := len(t.Args) - 1
if t.Args[baseTypePos].Ident == "opt" && len(t.Args) >= 2 {
baseTypePos--
}
copy(t.Args[baseTypePos:], t.Args[baseTypePos+1:])
t.Args = t.Args[:len(t.Args)-1]
}
}
func (comp *compiler) instantiate(templ ast.Node, params []*ast.Ident, args []*ast.Type) bool {
if len(params) == 0 {
return true
}
argMap := make(map[string]*ast.Type)
for i, param := range params {
argMap[param.Name] = args[i]
}
argUsed := make(map[string]bool)
err0 := comp.errors
ast.PostRecursive(func(n ast.Node) {
templArg, ok := n.(*ast.Type)
if !ok {
return
}
if concreteArg := argMap[templArg.Ident]; concreteArg != nil {
argUsed[templArg.Ident] = true
origArgs := templArg.Args
if len(origArgs) != 0 && len(concreteArg.Args) != 0 {
comp.error(templArg.Pos, "both template parameter %v and its usage"+
" have sub-arguments", templArg.Ident)
return
}
*templArg = *concreteArg.Clone().(*ast.Type)
if len(origArgs) != 0 {
templArg.Args = origArgs
}
}
// TODO(dvyukov): somewhat hacky, but required for int8[0:CONST_ARG]
// Need more checks here. E.g. that CONST_ARG does not have subargs.
// And if CONST_ARG is a value, then use concreteArg.Value.
// Also need to error if CONST_ARG is a string.
if len(templArg.Colon) != 0 {
col := templArg.Colon[0]
if concreteArg := argMap[col.Ident]; concreteArg != nil {
argUsed[col.Ident] = true
col.Ident = concreteArg.Ident
col.Pos = concreteArg.Pos
}
}
})(templ)
for _, param := range params {
if !argUsed[param.Name] {
comp.error(argMap[param.Name].Pos,
"template argument %v is not used", param.Name)
}
}
return err0 == comp.errors
}
func (comp *compiler) checkTypeArg(t, arg *ast.Type, argDesc namedArg) {
desc := argDesc.Type
if len(desc.Names) != 0 {
if unexpected, _, ok := checkTypeKind(arg, kindIdent); !ok {
comp.error(arg.Pos, "unexpected %v for %v argument of %v type, expect %+v",
unexpected, argDesc.Name, t.Ident, desc.Names)
return
}
if !arrayContains(desc.Names, arg.Ident) {
comp.error(arg.Pos, "unexpected value %v for %v argument of %v type, expect %+v",
arg.Ident, argDesc.Name, t.Ident, desc.Names)
return
}
} else {
if unexpected, expect, ok := checkTypeKind(arg, desc.Kind); !ok {
comp.error(arg.Pos, "unexpected %v for %v argument of %v type, expect %v",
unexpected, argDesc.Name, t.Ident, expect)
return
}
}
for i, col := range arg.Colon {
if i >= desc.MaxColon {
comp.error(col.Pos, "unexpected ':'")
return
}
// We only want to perform this check if kindIdent is the only kind of
// this type. Otherwise, the token after the colon could legitimately
// be an int for example.
if desc.Kind == kindIdent {
if unexpected, expect, ok := checkTypeKind(col, kindIdent); !ok {
comp.error(arg.Pos, "unexpected %v after colon, expect %v", unexpected, expect)
return
}
}
}
if len(arg.Args) > desc.MaxArgs {
comp.error(arg.Pos, "%v argument has subargs", argDesc.Name)
return
}
if desc.Check != nil {
desc.Check(comp, arg)
}
}
func expectedTypeArgs(desc *typeDesc, needBase bool) string {
expect := ""
for i, arg := range desc.Args {
if expect != "" {
expect += ", "
}
opt := i >= len(desc.Args)-desc.OptArgs
if opt {
expect += "["
}
expect += arg.Name
if opt {
expect += "]"
}
}
if needBase {
if expect != "" {
expect += ", "
}
expect += typeArgBase.Name
}
if !desc.CantBeOpt {
if expect != "" {
expect += ", "
}
expect += "[opt]"
}
if expect == "" {
expect = "no arguments"
}
return expect
}
func checkTypeKind(t *ast.Type, kind int) (unexpected, expect string, ok bool) {
switch {
case kind == kindAny:
ok = true
case t.HasString:
ok = kind&kindString != 0
if !ok {
unexpected = fmt.Sprintf("string %q", t.String)
}
case t.Ident != "":
ok = kind&(kindIdent|kindInt) != 0
if !ok {
unexpected = fmt.Sprintf("identifier %v", t.Ident)
}
default:
ok = kind&kindInt != 0
if !ok {
unexpected = fmt.Sprintf("int %v", t.Value)
}
}
if !ok {
var expected []string
if kind&kindString != 0 {
expected = append(expected, "string")
}
if kind&kindIdent != 0 {
expected = append(expected, "identifier")
}
if kind&kindInt != 0 {
expected = append(expected, "int")
}
expect = strings.Join(expected, " or ")
}
return
}
func (comp *compiler) checkVarlens() {
for _, decl := range comp.desc.Nodes {
switch n := decl.(type) {
case *ast.Struct:
comp.checkVarlen(n)
}
}
}
func (comp *compiler) isVarlen(t *ast.Type) bool {
desc, args, _ := comp.getArgsBase(t, false)
return desc.Varlen != nil && desc.Varlen(comp, t, args)
}
func (comp *compiler) isZeroSize(t *ast.Type) bool {
// We can recurse here for a struct that recursively contains itself in an array.
// In such case it's safe to say that it is zero size, because if all other fields are zero size,
// then the struct is indeed zero size (even if it contains several versions of itself transitively).
// If there are any other "normal" fields, then we will still correctly conclude that the whole struct
// is not zero size.
if comp.recursiveQuery[t] {
return true
}
comp.recursiveQuery[t] = true
desc, args, _ := comp.getArgsBase(t, false)
res := desc.ZeroSize != nil && desc.ZeroSize(comp, t, args)
delete(comp.recursiveQuery, t)
return res
}
func (comp *compiler) checkVarlen(n *ast.Struct) {
// Non-varlen unions can't have varlen fields.
// Non-packed structs can't have varlen fields in the middle.
if n.IsUnion {
attrs := comp.parseIntAttrs(unionAttrs, n, n.Attrs)
if attrs[attrVarlen] != 0 {
return
}
} else {
attrs := comp.parseIntAttrs(structAttrs, n, n.Attrs)
if attrs[attrPacked] != 0 {
return
}
}
for i, f := range n.Fields {
_, exprs, _ := comp.parseAttrs(structOrUnionFieldAttrs(n), f, f.Attrs)
if !n.IsUnion && i == len(n.Fields)-1 {
break
}
if comp.isVarlen(f.Type) || !n.IsUnion && exprs[attrIf] != nil {
if n.IsUnion {
comp.error(f.Pos, "variable size field %v in non-varlen union %v",
f.Name.Name, n.Name.Name)
} else {
comp.error(f.Pos, "variable size field %v in the middle of non-packed struct %v",
f.Name.Name, n.Name.Name)
}
}
}
}
func (comp *compiler) checkDupConsts() {
// The idea is to detect copy-paste errors in const arguments, e.g.:
// call$FOO(fd fd, arg const[FOO])
// call$BAR(fd fd, arg const[FOO])
// The second one is meant to be const[BAR],
// Unfortunately, this does not fully work as it detects lots of false positives.
// But was useful to find real bugs as well. So for now it's disabled, but can be run manually.
if true {
return
}
dups := make(map[string]map[string]dupConstArg)
for _, decl := range comp.desc.Nodes {
switch n := decl.(type) {
case *ast.Call:
comp.checkDupConstsCall(n, dups)
}
}
}
type dupConstArg struct {
pos ast.Pos
name string
}
func (comp *compiler) checkDupConstsCall(n *ast.Call, dups map[string]map[string]dupConstArg) {
if n.NR == ^uint64(0) {
return
}
for dups[n.CallName] == nil {
dups[n.CallName] = make(map[string]dupConstArg)
}
hasConsts := false
constArgID := ""
for i, arg := range n.Args {
desc := comp.getTypeDesc(arg.Type)
switch desc {
case typeConst:
v := arg.Type.Args[0].Value
if v != 0 && v != 18446744073709551516 { // AT_FDCWD
constArgID += fmt.Sprintf("(%v-%v)", i, fmt.Sprintf("%v", v))
hasConsts = true
}
case typeResource:
constArgID += fmt.Sprintf("(%v-%v)", i, arg.Type.Ident)
}
}
if !hasConsts {
return
}
dup, ok := dups[n.CallName][constArgID]
if !ok {
dups[n.CallName][constArgID] = dupConstArg{
pos: n.Pos,
name: n.Name.Name,
}
return
}
comp.error(n.Pos, "call %v: duplicate const %v, previously used in call %v at %v",
n.Name.Name, constArgID, dup.name, dup.pos)
}
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
// Package compiler generates sys descriptions of syscalls, types and resources
// from textual descriptions.
package compiler
import (
"fmt"
"strconv"
"strings"
"github.com/google/syzkaller/pkg/ast"
"github.com/google/syzkaller/prog"
"github.com/google/syzkaller/sys/targets"
)
// Overview of compilation process:
// 1. ast.Parse on text file does tokenization and builds AST.
// This step catches basic syntax errors. AST contains full debug info.
// 2. ExtractConsts as AST returns set of constant identifiers.
// This step also does verification of include/incdir/define AST nodes.
// 3. User translates constants to values.
// 4. Compile on AST and const values does the rest of the work and returns Prog
// containing generated prog objects.
// 4.1. assignSyscallNumbers: uses consts to assign syscall numbers.
// This step also detects unsupported syscalls and discards no longer
// needed AST nodes (inlcude, define, comments, etc).
// 4.2. patchConsts: patches Int nodes referring to consts with corresponding values.
// Also detects unsupported syscalls, structs, resources due to missing consts.
// 4.3. check: does extensive semantical checks of AST.
// 4.4. gen: generates prog objects from AST.
// Prog is description compilation result.
type Prog struct {
Resources []*prog.ResourceDesc
Syscalls []*prog.Syscall
Types []prog.Type
// Set of unsupported syscalls/flags.
Unsupported map[string]bool
// Returned if consts was nil.
fileConsts map[string]*ConstInfo
}
func createCompiler(desc *ast.Description, target *targets.Target, eh ast.ErrorHandler) *compiler {
if eh == nil {
eh = ast.LoggingHandler
}
desc.Nodes = append(builtinDescs.Clone().Nodes, desc.Nodes...)
comp := &compiler{
desc: desc,
target: target,
eh: eh,
ptrSize: target.PtrSize,
unsupported: make(map[string]bool),
resources: make(map[string]*ast.Resource),
typedefs: make(map[string]*ast.TypeDef),
structs: make(map[string]*ast.Struct),
intFlags: make(map[string]*ast.IntFlags),
strFlags: make(map[string]*ast.StrFlags),
used: make(map[string]bool),
usedTypedefs: make(map[string]bool),
brokenTypedefs: make(map[string]bool),
structVarlen: make(map[string]bool),
structTypes: make(map[string]prog.Type),
structFiles: make(map[*ast.Struct]map[string]ast.Pos),
recursiveQuery: make(map[ast.Node]bool),
builtinConsts: map[string]uint64{
"PTR_SIZE": target.PtrSize,
},
}
return comp
}
// Compile compiles sys description.
func Compile(desc *ast.Description, consts map[string]uint64, target *targets.Target, eh ast.ErrorHandler) *Prog {
comp := createCompiler(desc.Clone(), target, eh)
comp.filterArch()
comp.typecheck()
comp.flattenFlags()
// The subsequent, more complex, checks expect basic validity of the tree,
// in particular corrent number of type arguments. If there were errors,
// don't proceed to avoid out-of-bounds references to type arguments.
if comp.errors != 0 {
return nil
}
if consts == nil {
fileConsts := comp.extractConsts()
if comp.errors != 0 {
return nil
}
return &Prog{fileConsts: fileConsts}
}
if comp.target.SyscallNumbers {
comp.assignSyscallNumbers(consts)
}
comp.patchConsts(consts)
comp.check(consts)
if comp.errors != 0 {
return nil
}
syscalls := comp.genSyscalls()
comp.layoutTypes(syscalls)
types := comp.generateTypes(syscalls)
prg := &Prog{
Resources: comp.genResources(),
Syscalls: syscalls,
Types: types,
Unsupported: comp.unsupported,
}
if comp.errors != 0 {
return nil
}
for _, w := range comp.warnings {
eh(w.pos, w.msg)
}
return prg
}
type compiler struct {
desc *ast.Description
target *targets.Target
eh ast.ErrorHandler
errors int
warnings []warn
ptrSize uint64
unsupported map[string]bool
resources map[string]*ast.Resource
typedefs map[string]*ast.TypeDef
structs map[string]*ast.Struct
intFlags map[string]*ast.IntFlags
strFlags map[string]*ast.StrFlags
used map[string]bool // contains used structs/resources
usedTypedefs map[string]bool
brokenTypedefs map[string]bool
structVarlen map[string]bool
structTypes map[string]prog.Type
structFiles map[*ast.Struct]map[string]ast.Pos
builtinConsts map[string]uint64
fileMetas map[string]Meta
recursiveQuery map[ast.Node]bool
}
type warn struct {
pos ast.Pos
msg string
}
func (comp *compiler) error(pos ast.Pos, msg string, args ...interface{}) {
comp.errors++
comp.eh(pos, fmt.Sprintf(msg, args...))
}
func (comp *compiler) warning(pos ast.Pos, msg string, args ...interface{}) {
comp.warnings = append(comp.warnings, warn{pos, fmt.Sprintf(msg, args...)})
}
func (comp *compiler) filterArch() {
comp.desc = comp.desc.Filter(func(n ast.Node) bool {
pos, typ, name := n.Info()
if comp.fileMeta(pos).SupportsArch(comp.target.Arch) {
return true
}
switch n.(type) {
case *ast.Resource, *ast.Struct, *ast.Call, *ast.TypeDef:
// This is required to keep the unsupported diagnostic working,
// otherwise sysgen will think that these things are still supported on some arches.
comp.unsupported[typ+" "+name] = true
}
return false
})
}
func (comp *compiler) structIsVarlen(name string) bool {
if varlen, ok := comp.structVarlen[name]; ok {
return varlen
}
s := comp.structs[name]
if s.IsUnion {
res := comp.parseIntAttrs(unionAttrs, s, s.Attrs)
if res[attrVarlen] != 0 {
comp.structVarlen[name] = true
return true
}
}
comp.structVarlen[name] = false // to not hang on recursive types
varlen := false
for _, fld := range s.Fields {
hasIfAttr := false
for _, attr := range fld.Attrs {
if structFieldAttrs[attr.Ident] == attrIf {
hasIfAttr = true
}
}
if hasIfAttr || comp.isVarlen(fld.Type) {
varlen = true
break
}
}
comp.structVarlen[name] = varlen
return varlen
}
func (comp *compiler) parseIntAttrs(descs map[string]*attrDesc, parent ast.Node,
attrs []*ast.Type) map[*attrDesc]uint64 {
intAttrs, _, _ := comp.parseAttrs(descs, parent, attrs)
return intAttrs
}
func (comp *compiler) parseAttrs(descs map[string]*attrDesc, parent ast.Node, attrs []*ast.Type) (
map[*attrDesc]uint64, map[*attrDesc]prog.Expression, map[*attrDesc]string) {
_, parentType, parentName := parent.Info()
resInt := make(map[*attrDesc]uint64)
resExpr := make(map[*attrDesc]prog.Expression)
resString := make(map[*attrDesc]string)
for _, attr := range attrs {
if unexpected, _, ok := checkTypeKind(attr, kindIdent); !ok {
comp.error(attr.Pos, "unexpected %v, expect attribute", unexpected)
return resInt, resExpr, resString
}
if len(attr.Colon) != 0 {
comp.error(attr.Colon[0].Pos, "unexpected ':'")
return resInt, resExpr, resString
}
desc := descs[attr.Ident]
if desc == nil {
comp.error(attr.Pos, "unknown %v %v attribute %v", parentType, parentName, attr.Ident)
return resInt, resExpr, resString
}
_, dupInt := resInt[desc]
_, dupExpr := resExpr[desc]
_, dupString := resString[desc]
if dupInt || dupExpr || dupString {
comp.error(attr.Pos, "duplicate %v %v attribute %v", parentType, parentName, attr.Ident)
return resInt, resExpr, resString
}
switch desc.Type {
case flagAttr:
resInt[desc] = 1
if len(attr.Args) != 0 {
comp.error(attr.Pos, "%v attribute has args", attr.Ident)
return nil, nil, nil
}
case intAttr:
resInt[desc] = comp.parseAttrIntArg(attr)
case exprAttr:
resExpr[desc] = comp.parseAttrExprArg(attr)
case stringAttr:
resString[desc] = comp.parseAttrStringArg(attr)
default:
comp.error(attr.Pos, "attribute %v has unknown type", attr.Ident)
return nil, nil, nil
}
}
return resInt, resExpr, resString
}
func (comp *compiler) parseAttrExprArg(attr *ast.Type) prog.Expression {
if len(attr.Args) != 1 {
comp.error(attr.Pos, "%v attribute is expected to have only one argument", attr.Ident)
return nil
}
arg := attr.Args[0]
if arg.HasString {
comp.error(attr.Pos, "%v argument must be an expression", attr.Ident)
return nil
}
return comp.genExpression(arg)
}
func (comp *compiler) parseAttrIntArg(attr *ast.Type) uint64 {
if len(attr.Args) != 1 {
comp.error(attr.Pos, "%v attribute is expected to have 1 argument", attr.Ident)
return 0
}
sz := attr.Args[0]
if unexpected, _, ok := checkTypeKind(sz, kindInt); !ok {
comp.error(sz.Pos, "unexpected %v, expect int", unexpected)
return 0
}
if len(sz.Colon) != 0 || len(sz.Args) != 0 {
comp.error(sz.Pos, "%v attribute has colon or args", attr.Ident)
return 0
}
return sz.Value
}
func (comp *compiler) parseAttrStringArg(attr *ast.Type) string {
if len(attr.Args) != 1 {
comp.error(attr.Pos, "%v attribute is expected to have 1 argument", attr.Ident)
return ""
}
arg := attr.Args[0]
if !arg.HasString {
comp.error(attr.Pos, "%v argument must be a string", attr.Ident)
return ""
}
return arg.String
}
func (comp *compiler) getTypeDesc(t *ast.Type) *typeDesc {
if desc := builtinTypes[t.Ident]; desc != nil {
return desc
}
if comp.resources[t.Ident] != nil {
return typeResource
}
if comp.structs[t.Ident] != nil {
return typeStruct
}
if comp.typedefs[t.Ident] != nil {
return typeTypedef
}
return nil
}
func (comp *compiler) getArgsBase(t *ast.Type, isArg bool) (*typeDesc, []*ast.Type, prog.IntTypeCommon) {
desc := comp.getTypeDesc(t)
if desc == nil {
panic(fmt.Sprintf("no type desc for %#v", *t))
}
args, opt := removeOpt(t)
com := genCommon(t.Ident, sizeUnassigned, opt != nil)
base := genIntCommon(com, 0, false)
if desc.NeedBase {
base.TypeSize = comp.ptrSize
if !isArg {
baseType := args[len(args)-1]
args = args[:len(args)-1]
base = typeInt.Gen(comp, baseType, nil, base).(*prog.IntType).IntTypeCommon
}
}
return desc, args, base
}
func (comp *compiler) derefPointers(t *ast.Type) (*ast.Type, *typeDesc) {
for {
desc := comp.getTypeDesc(t)
if desc != typePtr {
return t, desc
}
t = t.Args[1]
}
}
func (comp *compiler) foreachType(n0 ast.Node,
cb func(*ast.Type, *typeDesc, []*ast.Type, prog.IntTypeCommon)) {
switch n := n0.(type) {
case *ast.Call:
for _, arg := range n.Args {
comp.foreachSubType(arg.Type, true, cb)
}
if n.Ret != nil {
comp.foreachSubType(n.Ret, true, cb)
}
case *ast.Resource:
comp.foreachSubType(n.Base, false, cb)
case *ast.Struct:
for _, f := range n.Fields {
comp.foreachSubType(f.Type, false, cb)
}
case *ast.TypeDef:
if len(n.Args) == 0 {
comp.foreachSubType(n.Type, false, cb)
}
default:
panic(fmt.Sprintf("unexpected node %#v", n0))
}
}
func (comp *compiler) foreachSubType(t *ast.Type, isArg bool,
cb func(*ast.Type, *typeDesc, []*ast.Type, prog.IntTypeCommon)) {
desc, args, base := comp.getArgsBase(t, isArg)
cb(t, desc, args, base)
for i, arg := range args {
if desc.Args[i].Type == typeArgType {
comp.foreachSubType(arg, desc.Args[i].IsArg, cb)
}
}
}
func removeOpt(t *ast.Type) ([]*ast.Type, *ast.Type) {
args := t.Args
if last := len(args) - 1; last >= 0 && args[last].Ident == "opt" {
return args[:last], args[last]
}
return args, nil
}
func (comp *compiler) parseIntType(name string) (size uint64, bigEndian bool) {
be := strings.HasSuffix(name, "be")
if be {
name = name[:len(name)-len("be")]
}
size = comp.ptrSize
if name != "intptr" {
size, _ = strconv.ParseUint(name[3:], 10, 64)
size /= 8
}
return size, be
}
func arrayContains(a []string, v string) bool {
for _, s := range a {
if s == v {
return true
}
}
return false
}
func (comp *compiler) flattenFlags() {
comp.flattenIntFlags()
comp.flattenStrFlags()
for _, n := range comp.desc.Nodes {
switch flags := n.(type) {
case *ast.IntFlags:
// It's possible that we don't find the flag in intFlags if it was
// skipped due to errors (or special name "_") when populating
// intFlags (see checkNames).
if f, ok := comp.intFlags[flags.Name.Name]; ok {
flags.Values = f.Values
}
case *ast.StrFlags:
// Same as for intFlags above.
if f, ok := comp.strFlags[flags.Name.Name]; ok {
flags.Values = f.Values
}
}
}
}
func (comp *compiler) flattenIntFlags() {
for name, flags := range comp.intFlags {
if err := recurFlattenFlags[*ast.IntFlags, *ast.Int](comp, name, flags, comp.intFlags,
map[string]bool{}); err != nil {
comp.error(flags.Pos, "%v", err)
}
}
}
func (comp *compiler) flattenStrFlags() {
for name, flags := range comp.strFlags {
if err := recurFlattenFlags[*ast.StrFlags, *ast.String](comp, name, flags, comp.strFlags,
map[string]bool{}); err != nil {
comp.error(flags.Pos, "%v", err)
}
}
}
func recurFlattenFlags[F ast.Flags[V], V ast.FlagValue](comp *compiler, name string, flags F,
allFlags map[string]F, visitedFlags map[string]bool) error {
if _, visited := visitedFlags[name]; visited {
return fmt.Errorf("flags %v used twice or circular dependency on %v", name, name)
}
visitedFlags[name] = true
var values []V
for _, flag := range flags.GetValues() {
if f, isFlags := allFlags[flag.GetName()]; isFlags {
if err := recurFlattenFlags[F, V](comp, flag.GetName(), f, allFlags, visitedFlags); err != nil {
return err
}
values = append(values, allFlags[flag.GetName()].GetValues()...)
} else {
values = append(values, flag)
}
}
if len(values) > 100000 {
return fmt.Errorf("%v has more than 100000 values %v", name, len(values))
}
flags.SetValues(values)
return nil
}
// Copyright 2020 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package compiler
import (
"bufio"
"bytes"
"fmt"
"os"
"path/filepath"
"regexp"
"sort"
"strconv"
"strings"
"github.com/google/syzkaller/pkg/ast"
)
// ConstFile serializes/deserializes .const files.
type ConstFile struct {
arches map[string]bool
m map[string]constVal
}
type constVal struct {
name string
vals map[string]uint64 // arch -> value
// Set if the value for the arch is weak (come from auto.txt).
// Weak values are replaced on mismatch, instead of producing
// an error about mismatching values.
weak map[string]bool
}
const undefined = "???"
func NewConstFile() *ConstFile {
return &ConstFile{
arches: make(map[string]bool),
m: make(map[string]constVal),
}
}
func (cf *ConstFile) AddArch(arch string, consts map[string]uint64, undeclared map[string]bool) error {
cf.arches[arch] = true
for name, val := range consts {
if err := cf.addConst(arch, name, val, true, false); err != nil {
return err
}
}
for name := range undeclared {
if err := cf.addConst(arch, name, 0, false, false); err != nil {
return err
}
}
return nil
}
func (cf *ConstFile) addConst(arch, name string, val uint64, declared, weak bool) error {
cv := cf.m[name]
if cv.vals == nil {
cv.name = name
cv.vals = make(map[string]uint64)
cv.weak = make(map[string]bool)
}
if declared {
val0, declared0 := cv.vals[arch]
if declared0 {
if weak {
return nil
}
if !cv.weak[arch] && val != val0 {
return fmt.Errorf("const=%v arch=%v has different values: %v[%v] vs %v[%v]",
name, arch, val, declared, val0, declared0)
}
}
cv.vals[arch] = val
cv.weak[arch] = weak
}
cf.m[name] = cv
return nil
}
func (cf *ConstFile) Arch(arch string) map[string]uint64 {
if cf == nil {
return nil
}
m := make(map[string]uint64)
for name, cv := range cf.m {
if v, ok := cv.vals[arch]; ok {
m[name] = v
}
}
return m
}
func (cf *ConstFile) ExistsAny(constName string) bool {
return len(cf.m[constName].vals) > 0
}
func (cf *ConstFile) Serialize() []byte {
if len(cf.arches) == 0 {
return nil
}
var arches []string
for arch := range cf.arches {
arches = append(arches, arch)
}
sort.Strings(arches)
var consts []constVal
for _, cv := range cf.m {
consts = append(consts, cv)
}
sort.Slice(consts, func(i, j int) bool {
return consts[i].name < consts[j].name
})
buf := new(bytes.Buffer)
fmt.Fprintf(buf, "# Code generated by syz-sysgen. DO NOT EDIT.\n")
fmt.Fprintf(buf, "arches = %v\n", strings.Join(arches, ", "))
for _, cv := range consts {
fmt.Fprintf(buf, "%v = ", cv.name)
if len(cv.vals) == 0 {
// Undefined for all arches.
fmt.Fprintf(buf, "%v\n", undefined)
continue
}
count := make(map[uint64]int)
max, dflt := 0, uint64(0)
for _, val := range cv.vals {
count[val]++
if count[val] > 1 && (count[val] > max || count[val] == max && val < dflt) {
max, dflt = count[val], val
}
}
if max != 0 {
// Have a default value.
fmt.Fprintf(buf, "%v", dflt)
}
handled := make([]bool, len(arches))
for i, arch := range arches {
val, ok := cv.vals[arch]
if ok && (max != 0 && val == dflt) || handled[i] {
// Default value or serialized on a previous iteration.
continue
}
if i != 0 || max != 0 {
fmt.Fprintf(buf, ", ")
}
fmt.Fprintf(buf, "%v:", arch)
for j := i + 1; j < len(arches); j++ {
// Add more arches with the same value.
arch1 := arches[j]
val1, ok1 := cv.vals[arch1]
if ok1 == ok && val1 == val {
fmt.Fprintf(buf, "%v:", arch1)
handled[j] = true
}
}
if ok {
fmt.Fprintf(buf, "%v", val)
} else {
fmt.Fprint(buf, undefined)
}
}
fmt.Fprintf(buf, "\n")
}
return buf.Bytes()
}
func DeserializeConstFile(glob string, eh ast.ErrorHandler) *ConstFile {
if eh == nil {
eh = ast.LoggingHandler
}
files, err := filepath.Glob(glob)
if err != nil {
eh(ast.Pos{}, fmt.Sprintf("failed to find const files: %v", err))
return nil
}
if len(files) == 0 {
eh(ast.Pos{}, fmt.Sprintf("no const files matched by glob %q", glob))
return nil
}
cf := NewConstFile()
oldFormat := regexp.MustCompile(`_([a-z0-9]+)\.const$`)
for _, f := range files {
data, err := os.ReadFile(f)
if err != nil {
eh(ast.Pos{}, fmt.Sprintf("failed to read const file: %v", err))
return nil
}
// Support for old per-arch format.
// Remove it once we don't have any *_arch.const files anymore.
arch := ""
if match := oldFormat.FindStringSubmatch(f); match != nil {
arch = match[1]
}
if !cf.deserializeFile(data, filepath.Base(f), arch, eh) {
return nil
}
}
return cf
}
func (cf *ConstFile) deserializeFile(data []byte, file, arch string, eh ast.ErrorHandler) bool {
pos := ast.Pos{File: file, Line: 1}
errf := func(msg string, args ...interface{}) bool {
eh(pos, fmt.Sprintf(msg, args...))
return false
}
weak := file == "auto.txt.const"
s := bufio.NewScanner(bytes.NewReader(data))
var arches []string
for ; s.Scan(); pos.Line++ {
line := s.Text()
if line == "" || line[0] == '#' {
continue
}
eq := strings.IndexByte(line, '=')
if eq == -1 {
return errf("expect '='")
}
name, val := strings.TrimSpace(line[:eq]), strings.TrimSpace(line[eq+1:])
if arch != "" {
// Old format.
if !cf.parseOldConst(arch, name, val, errf) {
return false
}
continue
}
if arch == "" && len(arches) == 0 {
if name != "arches" {
return errf("missing arches header")
}
for _, arch := range strings.Split(val, ",") {
arches = append(arches, strings.TrimSpace(arch))
}
continue
}
if !cf.parseConst(arches, name, val, weak, errf) {
return false
}
}
if err := s.Err(); err != nil {
return errf("failed to parse: %v", err)
}
return true
}
type errft func(msg string, args ...interface{}) bool
func (cf *ConstFile) parseConst(arches []string, name, line string, weak bool, errf errft) bool {
var dflt map[string]uint64
for _, pair := range strings.Split(line, ",") {
fields := strings.Split(pair, ":")
if len(fields) == 1 {
// Default value.
if dflt != nil {
return errf("duplicate default value")
}
dflt = make(map[string]uint64)
valStr := strings.TrimSpace(fields[0])
if valStr == undefined {
continue
}
val, err := strconv.ParseUint(valStr, 0, 64)
if err != nil {
return errf("failed to parse int: %v", err)
}
for _, arch := range arches {
dflt[arch] = val
}
continue
}
if len(fields) < 2 {
return errf("bad value: %v", pair)
}
valStr := strings.TrimSpace(fields[len(fields)-1])
defined := valStr != undefined
var val uint64
if defined {
var err error
if val, err = strconv.ParseUint(valStr, 0, 64); err != nil {
return errf("failed to parse int: %v", err)
}
}
for _, arch := range fields[:len(fields)-1] {
arch = strings.TrimSpace(arch)
delete(dflt, arch)
if err := cf.addConst(arch, name, val, defined, weak); err != nil {
return errf("%v", err)
}
}
}
for arch, val := range dflt {
if err := cf.addConst(arch, name, val, true, weak); err != nil {
return errf("%v", err)
}
}
return true
}
func (cf *ConstFile) parseOldConst(arch, name, line string, errf errft) bool {
val, err := strconv.ParseUint(strings.TrimSpace(line), 0, 64)
if err != nil {
return errf("failed to parse int: %v", err)
}
if err := cf.addConst(arch, name, val, true, false); err != nil {
return errf("%v", err)
}
return true
}
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package compiler
import (
"fmt"
"sort"
"strings"
"github.com/google/syzkaller/pkg/ast"
"github.com/google/syzkaller/prog"
"github.com/google/syzkaller/sys/targets"
)
type ConstInfo struct {
Consts []*Const
Includes []string
Incdirs []string
Defines map[string]string
}
type Const struct {
Name string
Pos ast.Pos
Used bool // otherwise only defined
}
func ExtractConsts(desc *ast.Description, target *targets.Target, eh ast.ErrorHandler) map[string]*ConstInfo {
res := Compile(desc, nil, target, eh)
if res == nil {
return nil
}
return res.fileConsts
}
// FabricateSyscallConsts adds syscall number constants to consts map.
// Used for test OS to not bother specifying consts for all syscalls.
func FabricateSyscallConsts(target *targets.Target, constInfo map[string]*ConstInfo, cf *ConstFile) {
if !target.SyscallNumbers {
return
}
for _, info := range constInfo {
for _, c := range info.Consts {
if strings.HasPrefix(c.Name, target.SyscallPrefix) {
cf.addConst(target.Arch, c.Name, 0, true, false)
}
}
}
}
type constContext struct {
infos map[string]*constInfo
instantionStack []map[string]ast.Pos
}
// extractConsts returns list of literal constants and other info required for const value extraction.
func (comp *compiler) extractConsts() map[string]*ConstInfo {
ctx := &constContext{
infos: make(map[string]*constInfo),
}
extractIntConsts := ast.Recursive(func(n0 ast.Node) bool {
if n, ok := n0.(*ast.Int); ok {
comp.addConst(ctx, n.Pos, n.Ident)
}
return true
})
comp.desc.Walk(extractIntConsts)
for _, decl := range comp.desc.Nodes {
pos, _, _ := decl.Info()
info := ctx.getConstInfo(pos)
switch n := decl.(type) {
case *ast.Include:
info.includeArray = append(info.includeArray, n.File.Value)
case *ast.Incdir:
info.incdirArray = append(info.incdirArray, n.Dir.Value)
case *ast.Define:
v := fmt.Sprint(n.Value.Value)
switch {
case n.Value.CExpr != "":
v = n.Value.CExpr
case n.Value.Ident != "":
v = n.Value.Ident
}
name := n.Name.Name
if _, builtin := comp.builtinConsts[name]; builtin {
comp.error(pos, "redefining builtin const %v", name)
}
info.defines[name] = v
ctx.addConst(pos, name, false)
case *ast.Call:
if comp.target.HasCallNumber(n.CallName) {
comp.addConst(ctx, pos, comp.target.SyscallPrefix+n.CallName)
}
for _, attr := range n.Attrs {
if callAttrs[attr.Ident].Type == intAttr {
comp.addConst(ctx, attr.Pos, attr.Args[0].Ident)
}
}
case *ast.Struct:
// The instantionStack allows to add consts that are used in template structs
// to all files that use the template. Without this we would add these consts
// to only one random file, which would leads to flaky changes in const files.
ctx.instantionStack = append(ctx.instantionStack, comp.structFiles[n])
for _, attr := range n.Attrs {
attrDesc := structOrUnionAttrs(n)[attr.Ident]
if attrDesc.Type == intAttr {
comp.addConst(ctx, attr.Pos, attr.Args[0].Ident)
}
}
foreachFieldAttrConst(n, func(t *ast.Type) {
comp.addConst(ctx, t.Pos, t.Ident)
})
extractIntConsts(n)
comp.extractTypeConsts(ctx, decl)
ctx.instantionStack = ctx.instantionStack[:len(ctx.instantionStack)-1]
}
switch decl.(type) {
case *ast.Call, *ast.Resource, *ast.TypeDef:
comp.extractTypeConsts(ctx, decl)
}
}
return convertConstInfo(ctx, comp.fileMetas)
}
func foreachFieldAttrConst(n *ast.Struct, cb func(*ast.Type)) {
for _, field := range n.Fields {
for _, attr := range field.Attrs {
attrDesc := structOrUnionFieldAttrs(n)[attr.Ident]
if attrDesc == nil {
return
}
if attrDesc.Type != exprAttr {
// For now, only these field attrs may have consts.
return
}
ast.Recursive(func(n ast.Node) bool {
t, ok := n.(*ast.Type)
if !ok || t.Expression != nil {
return true
}
if t.Ident != valueIdent {
cb(t)
}
return false
})(attr.Args[0])
}
}
}
func (comp *compiler) extractTypeConsts(ctx *constContext, n ast.Node) {
comp.foreachType(n, func(t *ast.Type, desc *typeDesc, args []*ast.Type, _ prog.IntTypeCommon) {
for i, arg := range args {
if desc.Args[i].Type.Kind&kindInt != 0 {
if arg.Ident != "" {
comp.addConst(ctx, arg.Pos, arg.Ident)
}
for _, col := range arg.Colon {
if col.Ident != "" {
comp.addConst(ctx, col.Pos, col.Ident)
}
}
}
}
})
}
func (comp *compiler) addConst(ctx *constContext, pos ast.Pos, name string) {
if name == "" {
return
}
if _, builtin := comp.builtinConsts[name]; builtin {
return
}
// In case of intN[identA], identA may refer to a constant or to a set of
// flags. To avoid marking all flags as constants, we must check here
// whether identA refers to a flag. We have a check in the compiler to
// ensure an identifier can never refer to both a constant and flags.
if _, isFlag := comp.intFlags[name]; isFlag {
return
}
ctx.addConst(pos, name, true)
for _, instantions := range ctx.instantionStack {
for _, pos1 := range instantions {
ctx.addConst(pos1, name, true)
}
}
}
type constInfo struct {
consts map[string]*Const
defines map[string]string
includeArray []string
incdirArray []string
}
func (ctx *constContext) addConst(pos ast.Pos, name string, used bool) {
info := ctx.getConstInfo(pos)
if c := info.consts[name]; c != nil && c.Used {
used = true
}
info.consts[name] = &Const{
Pos: pos,
Name: name,
Used: used,
}
}
func (ctx *constContext) getConstInfo(pos ast.Pos) *constInfo {
info := ctx.infos[pos.File]
if info == nil {
info = &constInfo{
consts: make(map[string]*Const),
defines: make(map[string]string),
}
ctx.infos[pos.File] = info
}
return info
}
func convertConstInfo(ctx *constContext, metas map[string]Meta) map[string]*ConstInfo {
res := make(map[string]*ConstInfo)
for file, info := range ctx.infos {
if file == ast.BuiltinFile {
continue
}
var allConsts []*Const
for _, val := range info.consts {
allConsts = append(allConsts, val)
}
sort.Slice(allConsts, func(i, j int) bool {
return allConsts[i].Name < allConsts[j].Name
})
res[file] = &ConstInfo{
Consts: allConsts,
Includes: info.includeArray,
Incdirs: info.incdirArray,
Defines: info.defines,
}
}
return res
}
// assignSyscallNumbers assigns syscall numbers, discards unsupported syscalls.
func (comp *compiler) assignSyscallNumbers(consts map[string]uint64) {
for _, decl := range comp.desc.Nodes {
c, ok := decl.(*ast.Call)
if !ok || strings.HasPrefix(c.CallName, "syz_") {
continue
}
str := comp.target.SyscallPrefix + c.CallName
nr, ok := consts[str]
if ok {
c.NR = nr
continue
}
c.NR = ^uint64(0) // mark as unused to not generate it
name := "syscall " + c.CallName
if !comp.unsupported[name] {
comp.unsupported[name] = true
comp.warning(c.Pos, "unsupported syscall: %v due to missing const %v",
c.CallName, str)
}
}
}
// patchConsts replaces all symbolic consts with their numeric values taken from consts map.
// Updates desc and returns set of unsupported syscalls and flags.
func (comp *compiler) patchConsts(consts0 map[string]uint64) {
consts := make(map[string]uint64)
for name, val := range consts0 {
consts[name] = val
}
for name, val := range comp.builtinConsts {
if _, ok := consts[name]; ok {
panic(fmt.Sprintf("builtin const %v already defined", name))
}
consts[name] = val
}
for _, decl := range comp.desc.Nodes {
switch n := decl.(type) {
case *ast.IntFlags:
// Unsupported flag values are dropped.
var values []*ast.Int
for _, v := range n.Values {
if comp.patchIntConst(v, consts, nil) {
values = append(values, v)
}
}
n.Values = values
case *ast.Resource, *ast.Struct, *ast.Call, *ast.TypeDef:
// Walk whole tree and replace consts in Type's and Int's.
missing := ""
comp.foreachType(decl, func(_ *ast.Type, desc *typeDesc,
args []*ast.Type, _ prog.IntTypeCommon) {
for i, arg := range args {
if desc.Args[i].Type.Kind&kindInt != 0 {
comp.patchTypeConst(arg, consts, &missing)
}
}
})
switch n := decl.(type) {
case *ast.Resource:
for _, v := range n.Values {
comp.patchIntConst(v, consts, &missing)
}
case *ast.Call:
for _, attr := range n.Attrs {
if callAttrs[attr.Ident].Type == intAttr {
comp.patchTypeConst(attr.Args[0], consts, &missing)
}
}
case *ast.Struct:
for _, attr := range n.Attrs {
attrDesc := structOrUnionAttrs(n)[attr.Ident]
if attrDesc.Type == intAttr {
comp.patchTypeConst(attr.Args[0], consts, &missing)
}
}
foreachFieldAttrConst(n, func(t *ast.Type) {
comp.patchTypeConst(t, consts, &missing)
})
}
if missing == "" {
continue
}
// Produce a warning about unsupported syscall/resource/struct.
// TODO(dvyukov): we should transitively remove everything that
// depends on unsupported things. Potentially we still can get,
// say, a bad int range error due to the wrong const value.
// However, if we have a union where one of the options is
// arch-specific and does not have a const value, it's probably
// better to remove just that option. But then if we get to 0
// options in the union, we still need to remove it entirely.
pos, typ, name := decl.Info()
if id := typ + " " + name; !comp.unsupported[id] {
comp.unsupported[id] = true
comp.warning(pos, "unsupported %v: %v due to missing const %v",
typ, name, missing)
}
if c, ok := decl.(*ast.Call); ok {
c.NR = ^uint64(0) // mark as unused to not generate it
}
}
}
}
func (comp *compiler) patchIntConst(n *ast.Int, consts map[string]uint64, missing *string) bool {
return comp.patchConst(&n.Value, &n.Ident, consts, missing, false)
}
func (comp *compiler) patchTypeConst(n *ast.Type, consts map[string]uint64, missing *string) {
comp.patchConst(&n.Value, &n.Ident, consts, missing, true)
for _, col := range n.Colon {
comp.patchConst(&col.Value, &col.Ident, consts, missing, true)
}
}
func (comp *compiler) patchConst(val *uint64, id *string, consts map[string]uint64, missing *string, reset bool) bool {
if *id == "" {
return true
}
if v, ok := consts[*id]; ok {
if reset {
*id = ""
}
*val = v
return true
}
// This check is necessary because in intN[identA], identA may be a
// constant or a set of flags.
if _, isFlag := comp.intFlags[*id]; isFlag {
return true
}
if missing != nil && *missing == "" {
*missing = *id
}
// 1 is slightly safer than 0 and allows to work-around e.g. an array size
// that comes from a const missing on an arch. Also see the TODO in patchConsts.
*val = 1
return false
}
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package compiler
import (
"github.com/google/syzkaller/pkg/ast"
"github.com/google/syzkaller/sys/targets"
)
func Fuzz(data []byte) int {
eh := func(pos ast.Pos, msg string) {}
desc := ast.Parse(data, "", eh)
if desc == nil {
return 0
}
prog := Compile(desc, fuzzConsts, fuzzTarget, eh)
if prog == nil {
return 0
}
return 1
}
var (
fuzzTarget = targets.Get(targets.TestOS, targets.TestArch64)
fuzzConsts = map[string]uint64{"A": 1, "B": 2, "C": 3, "SYS_A": 4, "SYS_B": 5, "SYS_C": 6}
)
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package compiler
import (
"bytes"
"fmt"
"reflect"
"sort"
"github.com/google/syzkaller/pkg/ast"
"github.com/google/syzkaller/pkg/serializer"
"github.com/google/syzkaller/prog"
)
const sizeUnassigned = ^uint64(0)
func (comp *compiler) genResources() []*prog.ResourceDesc {
var resources []*prog.ResourceDesc
for name, n := range comp.resources {
if !comp.used[name] {
continue
}
resources = append(resources, comp.genResource(n))
}
sort.Slice(resources, func(i, j int) bool {
return resources[i].Name < resources[j].Name
})
return resources
}
func (comp *compiler) genResource(n *ast.Resource) *prog.ResourceDesc {
res := &prog.ResourceDesc{
Name: n.Name.Name,
}
for n != nil {
res.Values = append(genIntArray(n.Values), res.Values...)
res.Kind = append([]string{n.Name.Name}, res.Kind...)
n = comp.resources[n.Base.Ident]
}
if len(res.Values) == 0 {
res.Values = []uint64{0}
}
return res
}
func (comp *compiler) collectCallArgSizes() map[string][]uint64 {
argPos := make(map[string]ast.Pos)
callArgSizes := make(map[string][]uint64)
for _, decl := range comp.desc.Nodes {
n, ok := decl.(*ast.Call)
if !ok {
continue
}
// Figure out number of arguments and their sizes for each syscall.
// For example, we may have:
// ioctl(fd fd, cmd int32, arg intptr)
// ioctl$FOO(fd fd, cmd const[FOO])
// Here we will figure out that ioctl$FOO have 3 args, even that
// only 2 are specified and that size of cmd is 4 even that
// normally we would assume it's 8 (intptr).
argSizes := callArgSizes[n.CallName]
for i, arg := range n.Args {
if len(argSizes) <= i {
argSizes = append(argSizes, comp.ptrSize)
}
desc, _, _ := comp.getArgsBase(arg.Type, true)
typ := comp.genField(arg, comp.ptrSize, prog.DirInOut)
// Ignore all types with base (const, flags). We don't have base in syscall args.
// Also ignore resources and pointers because fd can be 32-bits and pointer 64-bits,
// and then there is no way to fix this.
// The only relevant types left is plain int types.
if desc != typeInt {
continue
}
if !comp.target.Int64SyscallArgs && typ.Size() > comp.ptrSize {
comp.error(arg.Pos, "%v arg %v is larger than pointer size", n.Name.Name, arg.Name.Name)
continue
}
argID := fmt.Sprintf("%v|%v", comp.getCallName(n), i)
if _, ok := argPos[argID]; !ok {
argSizes[i] = typ.Size()
argPos[argID] = arg.Pos
continue
}
if argSizes[i] != typ.Size() {
comp.error(arg.Pos, "%v arg %v is redeclared with size %v, previously declared with size %v at %v",
n.Name.Name, arg.Name.Name, typ.Size(), argSizes[i], argPos[argID])
continue
}
}
callArgSizes[comp.getCallName(n)] = argSizes
}
return callArgSizes
}
func (comp *compiler) getCallName(n *ast.Call) string {
// getCallName is used for checking that all variants of the same syscall have same argument sizes
// for matching arguments. Automatically-generated syscalls may violate that condition,
// so for them we use full syscall name. As the result manual and automatic variants
// of the same syscall are not checked against each other.
if comp.fileMeta(n.Pos).Automatic {
return n.Name.Name
}
return n.CallName
}
func (comp *compiler) genSyscalls() []*prog.Syscall {
callArgSizes := comp.collectCallArgSizes()
var calls []*prog.Syscall
for _, decl := range comp.desc.Nodes {
if n, ok := decl.(*ast.Call); ok && n.NR != ^uint64(0) {
calls = append(calls, comp.genSyscall(n, callArgSizes[comp.getCallName(n)]))
}
}
// We assign SquashableElem here rather than during pointer type generation
// because during pointer generation recursive struct types may not be fully
// generated yet, thus ForeachArgType won't observe all types.
prog.ForeachTypePost(calls, func(typ prog.Type, ctx *prog.TypeCtx) {
if ptr, ok := typ.(*prog.PtrType); ok {
ptr.SquashableElem = isSquashableElem(ptr.Elem, ptr.ElemDir)
}
})
sort.Slice(calls, func(i, j int) bool {
return calls[i].Name < calls[j].Name
})
return calls
}
func (comp *compiler) genSyscall(n *ast.Call, argSizes []uint64) *prog.Syscall {
var ret prog.Type
if n.Ret != nil {
ret = comp.genType(n.Ret, comp.ptrSize)
}
var attrs prog.SyscallAttrs
attrs.Automatic = comp.fileMeta(n.Pos).Automatic
intAttrs, _, stringAttrs := comp.parseAttrs(callAttrs, n, n.Attrs)
for desc, val := range intAttrs {
fld := reflect.ValueOf(&attrs).Elem().FieldByName(desc.Name)
switch desc.Type {
case intAttr:
fld.SetUint(val)
case flagAttr:
fld.SetBool(val != 0)
default:
panic(fmt.Sprintf("unexpected attrDesc type: %q", desc.Type))
}
}
for desc, val := range stringAttrs {
fld := reflect.ValueOf(&attrs).Elem().FieldByName(desc.Name)
switch desc.Type {
case stringAttr:
fld.SetString(val)
default:
panic(fmt.Sprintf("unexpected attrDesc type: %q", desc.Type))
}
}
fields, _ := comp.genFieldArray(n.Args, argSizes)
return &prog.Syscall{
Name: n.Name.Name,
CallName: n.CallName,
NR: n.NR,
MissingArgs: len(argSizes) - len(n.Args),
Args: fields,
Ret: ret,
Attrs: attrs,
}
}
type typeProxy struct {
typ prog.Type
id string
ref prog.Ref
locations []*prog.Type
}
func (comp *compiler) generateTypes(syscalls []*prog.Syscall) []prog.Type {
// Replace all Type's in the descriptions with Ref's
// and prepare a sorted array of corresponding real types.
proxies := make(map[string]*typeProxy)
prog.ForeachTypePost(syscalls, func(typ prog.Type, ctx *prog.TypeCtx) {
if _, ok := typ.(prog.Ref); ok {
return
}
if !typ.Varlen() && typ.Size() == sizeUnassigned {
panic("unassigned size")
}
id := typ.Name()
switch typ.(type) {
case *prog.StructType, *prog.UnionType:
// There types can be uniquely identified with the name.
default:
buf := new(bytes.Buffer)
serializer.Write(buf, typ)
id = buf.String()
}
proxy := proxies[id]
if proxy == nil {
proxy = &typeProxy{
typ: typ,
id: id,
ref: prog.Ref(len(proxies)),
}
proxies[id] = proxy
}
*ctx.Ptr = proxy.ref
proxy.locations = append(proxy.locations, ctx.Ptr)
})
array := make([]*typeProxy, 0, len(proxies))
for _, proxy := range proxies {
array = append(array, proxy)
}
sort.Slice(array, func(i, j int) bool {
return array[i].id < array[j].id
})
types := make([]prog.Type, len(array))
for i, proxy := range array {
types[i] = proxy.typ
for _, loc := range proxy.locations {
*loc = prog.Ref(i)
}
}
return types
}
func (comp *compiler) layoutTypes(syscalls []*prog.Syscall) {
// Calculate struct/union/array sizes, add padding to structs, mark bitfields.
padded := make(map[prog.Type]bool)
prog.ForeachTypePost(syscalls, func(typ prog.Type, _ *prog.TypeCtx) {
comp.layoutType(typ, padded)
})
}
func (comp *compiler) layoutType(typ prog.Type, padded map[prog.Type]bool) {
if padded[typ] {
return
}
padded[typ] = true
switch t := typ.(type) {
case *prog.ArrayType:
comp.layoutType(t.Elem, padded)
comp.layoutArray(t)
case *prog.StructType:
for _, f := range t.Fields {
comp.layoutType(f.Type, padded)
}
comp.layoutStruct(t)
case *prog.UnionType:
for _, f := range t.Fields {
comp.layoutType(f.Type, padded)
}
comp.layoutUnion(t)
default:
return
}
if !typ.Varlen() && typ.Size() == sizeUnassigned {
panic("size unassigned")
}
}
func (comp *compiler) layoutArray(t *prog.ArrayType) {
t.TypeSize = 0
if t.Kind == prog.ArrayRangeLen && t.RangeBegin == t.RangeEnd && !t.Elem.Varlen() {
t.TypeSize = t.RangeBegin * t.Elem.Size()
}
t.TypeAlign = t.Elem.Alignment()
}
func (comp *compiler) layoutUnion(t *prog.UnionType) {
for _, fld := range t.Fields {
t.TypeAlign = max(t.TypeAlign, fld.Alignment())
}
t.TypeSize = 0
structNode := comp.structs[t.TypeName]
if structNode == conditionalFieldWrapper {
return
}
attrs := comp.parseIntAttrs(unionAttrs, structNode, structNode.Attrs)
if attrs[attrVarlen] != 0 {
return
}
sizeAttr, hasSize := attrs[attrSize]
for i, fld := range t.Fields {
sz := fld.Size()
if hasSize && sz > sizeAttr {
comp.error(structNode.Fields[i].Pos, "union %v has size attribute %v"+
" which is less than field %v size %v",
structNode.Name.Name, sizeAttr, fld.Type.Name(), sz)
}
t.TypeSize = max(t.TypeSize, sz)
}
if hasSize {
t.TypeSize = sizeAttr
}
}
func (comp *compiler) layoutStruct(t *prog.StructType) {
// Add paddings, calculate size, mark bitfields.
structNode := comp.structs[t.TypeName]
varlen := false
for _, f := range t.Fields {
if f.Varlen() {
varlen = true
}
}
attrs := comp.parseIntAttrs(structAttrs, structNode, structNode.Attrs)
t.AlignAttr = attrs[attrAlign]
comp.layoutStructFields(t, varlen, attrs[attrPacked] != 0)
if align := attrs[attrAlign]; align != 0 {
t.TypeAlign = align
} else if attrs[attrPacked] != 0 {
t.TypeAlign = 1
} else {
for _, f := range t.Fields {
t.TypeAlign = max(t.TypeAlign, f.Alignment())
}
}
t.TypeSize = 0
if !varlen {
var size uint64
for i, f := range t.Fields {
if i == t.OverlayField {
size = 0
}
size += f.Size()
t.TypeSize = max(t.TypeSize, size)
}
sizeAttr, hasSize := attrs[attrSize]
if hasSize {
if t.TypeSize > sizeAttr {
comp.error(structNode.Attrs[0].Pos, "struct %v has size attribute %v"+
" which is less than struct size %v",
structNode.Name.Name, sizeAttr, t.TypeSize)
}
if pad := sizeAttr - t.TypeSize; pad != 0 {
t.Fields = append(t.Fields, genPad(pad))
}
t.TypeSize = sizeAttr
}
}
}
func (comp *compiler) layoutStructFields(t *prog.StructType, varlen, packed bool) {
var newFields []prog.Field
overlayField0 := t.OverlayField
var structAlign, byteOffset, bitOffset uint64
for i, field := range t.Fields {
f := field.Type
if i == overlayField0 {
// We layout fields before overlay and the overlay fields effectively as 2 independent structs.
// So if we starting overlay, add any trailign padding/finalize bitfield layout and reset state.
newFields = comp.finalizeStructFields(t, newFields, varlen, structAlign, byteOffset, bitOffset)
t.OverlayField = len(newFields) // update overlay field index after we added paddings
structAlign, byteOffset, bitOffset = 0, 0, 0
}
fieldAlign := uint64(1)
if !packed {
fieldAlign = f.Alignment()
structAlign = max(structAlign, fieldAlign)
}
fullBitOffset := byteOffset*8 + bitOffset
var fieldOffset uint64
if f.IsBitfield() {
unitAlign := f.UnitSize()
if packed {
unitAlign = 1
}
fieldOffset = rounddown(fullBitOffset/8, unitAlign)
unitBits := f.UnitSize() * 8
occupiedBits := fullBitOffset - fieldOffset*8
remainBits := unitBits - occupiedBits
if remainBits < f.BitfieldLength() {
fieldOffset = roundup(roundup(fullBitOffset, 8)/8, unitAlign)
fullBitOffset, bitOffset = 0, 0
} else if fieldOffset*8 >= fullBitOffset {
fullBitOffset, bitOffset = fieldOffset*8, 0
}
fieldBitOffset := (fullBitOffset - fieldOffset*8) % unitBits
setBitfieldOffset(f, fieldBitOffset)
} else {
fieldOffset = roundup(roundup(fullBitOffset, 8)/8, fieldAlign)
bitOffset = 0
}
if fieldOffset > byteOffset {
pad := fieldOffset - byteOffset
byteOffset += pad
if i != 0 && t.Fields[i-1].IsBitfield() {
setBitfieldTypeSize(t.Fields[i-1].Type, pad)
if bitOffset >= 8*pad {
// The padding is due to bitfields, so consume the bitOffset.
bitOffset -= 8 * pad
} else if bitOffset >= 8 {
// Unclear is this is a bug or not and what to do in this case.
// But since we don't have any descriptions that trigger this,
// let's just guard with the panic.
panic(fmt.Sprintf("bad bitOffset: %v.%v pad=%v bitOffset=%v",
t.Name(), field.Name, pad, bitOffset))
}
} else {
newFields = append(newFields, genPad(pad))
}
}
if f.IsBitfield() {
if byteOffset > fieldOffset {
unitOffset := byteOffset - fieldOffset
setBitfieldUnitOffset(f, unitOffset)
}
}
newFields = append(newFields, field)
if f.IsBitfield() {
bitOffset += f.BitfieldLength()
} else if !f.Varlen() {
// Increase offset if the current field except when it's
// the last field in a struct and has variable length.
byteOffset += f.Size()
}
}
t.Fields = comp.finalizeStructFields(t, newFields, varlen, structAlign, byteOffset, bitOffset)
}
func (comp *compiler) finalizeStructFields(t *prog.StructType, fields []prog.Field, varlen bool,
structAlign, byteOffset, bitOffset uint64) []prog.Field {
if bitOffset != 0 {
pad := roundup(bitOffset, 8) / 8
byteOffset += pad
i := len(fields)
if i != 0 && fields[i-1].IsBitfield() {
setBitfieldTypeSize(fields[i-1].Type, pad)
} else {
fields = append(fields, genPad(pad))
}
}
if t.AlignAttr != 0 {
structAlign = t.AlignAttr
}
if !varlen && structAlign != 0 && byteOffset%structAlign != 0 {
pad := structAlign - byteOffset%structAlign
fields = append(fields, genPad(pad))
}
return fields
}
func roundup(v, a uint64) uint64 {
return rounddown(v+a-1, a)
}
func rounddown(v, a uint64) uint64 {
if (a & (a - 1)) != 0 {
panic(fmt.Sprintf("rounddown(%v)", a))
}
return v & ^(a - 1)
}
func bitfieldFields(t0 prog.Type) (*uint64, *uint64, *uint64) {
switch t := t0.(type) {
case *prog.IntType:
return &t.TypeSize, &t.BitfieldOff, &t.BitfieldUnitOff
case *prog.ConstType:
return &t.TypeSize, &t.BitfieldOff, &t.BitfieldUnitOff
case *prog.LenType:
return &t.TypeSize, &t.BitfieldOff, &t.BitfieldUnitOff
case *prog.FlagsType:
return &t.TypeSize, &t.BitfieldOff, &t.BitfieldUnitOff
case *prog.ProcType:
return &t.TypeSize, &t.BitfieldOff, &t.BitfieldUnitOff
default:
panic(fmt.Sprintf("type %#v can't be a bitfield", t))
}
}
func setBitfieldTypeSize(t prog.Type, v uint64) {
p, _, _ := bitfieldFields(t)
*p = v
}
func setBitfieldOffset(t prog.Type, v uint64) {
_, p, _ := bitfieldFields(t)
*p = v
}
func setBitfieldUnitOffset(t prog.Type, v uint64) {
_, _, p := bitfieldFields(t)
*p = v
}
func genPad(size uint64) prog.Field {
return prog.Field{
Type: &prog.ConstType{
IntTypeCommon: genIntCommon(genCommon("pad", size, false), 0, false),
IsPad: true,
},
}
}
func (comp *compiler) genFieldArray(fields []*ast.Field, argSizes []uint64) ([]prog.Field, int) {
outOverlay := -1
for i, f := range fields {
intAttrs := comp.parseIntAttrs(structFieldAttrs, f, f.Attrs)
if intAttrs[attrOutOverlay] > 0 {
outOverlay = i
}
}
var res []prog.Field
for i, f := range fields {
overlayDir := prog.DirInOut
if outOverlay != -1 {
overlayDir = prog.DirIn
if i >= outOverlay {
overlayDir = prog.DirOut
}
}
res = append(res, comp.genField(f, argSizes[i], overlayDir))
}
return res, outOverlay
}
func (comp *compiler) genFieldDir(attrs map[*attrDesc]uint64) (prog.Dir, bool) {
switch {
case attrs[attrIn] != 0:
return prog.DirIn, true
case attrs[attrOut] != 0:
return prog.DirOut, true
case attrs[attrInOut] != 0:
return prog.DirInOut, true
default:
return prog.DirIn, false
}
}
func (comp *compiler) genField(f *ast.Field, argSize uint64, overlayDir prog.Dir) prog.Field {
intAttrs, exprAttrs, _ := comp.parseAttrs(structFieldAttrs, f, f.Attrs)
dir, hasDir := overlayDir, true
if overlayDir == prog.DirInOut {
dir, hasDir = comp.genFieldDir(intAttrs)
}
return prog.Field{
Name: f.Name.Name,
Type: comp.genType(f.Type, argSize),
HasDirection: hasDir,
Direction: dir,
Condition: exprAttrs[attrIf],
}
}
var conditionalFieldWrapper = &ast.Struct{}
// For structs, we wrap conditional fields in anonymous unions with a @void field.
func (comp *compiler) wrapConditionalField(name string, field prog.Field) prog.Field {
common := genCommon(fmt.Sprintf("_%s_%s_wrapper", name, field.Name), sizeUnassigned, false)
common.IsVarlen = true
common.TypeAlign = field.Type.Alignment()
// Fake the corresponding ast.Struct.
comp.structs[common.TypeName] = conditionalFieldWrapper
voidBase := genIntCommon(genCommon("void", sizeUnassigned, false), 0, false)
voidType := typeVoid.Gen(comp, nil, nil, voidBase)
var newCondition prog.Expression
if field.Condition != nil {
newCondition = field.Condition.Clone()
// Prepend "parent:".
newCondition.ForEachValue(func(val *prog.Value) {
if len(val.Path) == 0 {
return
}
if val.Path[0] == prog.ParentRef {
val.Path = append([]string{prog.ParentRef}, val.Path...)
} else {
// Single "parent:" would not change anything.
val.Path = append([]string{prog.ParentRef, prog.ParentRef}, val.Path...)
}
})
}
return prog.Field{
Name: field.Name,
Type: &prog.UnionType{
TypeCommon: common,
Fields: []prog.Field{
{
Name: "value",
Type: field.Type,
HasDirection: field.HasDirection,
Direction: field.Direction,
Condition: newCondition,
},
{
Name: "void",
Type: voidType,
Condition: &prog.BinaryExpression{
Operator: prog.OperatorCompareEq,
Left: newCondition,
Right: &prog.Value{Value: 0x0, Path: nil},
},
},
},
},
}
}
func (comp *compiler) genType(t *ast.Type, argSize uint64) prog.Type {
desc, args, base := comp.getArgsBase(t, argSize != 0)
if desc.Gen == nil {
panic(fmt.Sprintf("no gen for %v %#v", t.Ident, t))
}
if argSize != 0 {
// Now that we know a more precise size, patch the type.
// This is somewhat hacky. Ideally we figure out the size earlier,
// store it somewhere and use during generation of the arg base type.
base.TypeSize = argSize
if desc.CheckConsts != nil {
desc.CheckConsts(comp, t, args, base)
}
}
base.IsVarlen = desc.Varlen != nil && desc.Varlen(comp, t, args)
return desc.Gen(comp, t, args, base)
}
const valueIdent = "value"
var binaryOperatorMap = map[ast.Operator]prog.BinaryOperator{
ast.OperatorCompareEq: prog.OperatorCompareEq,
ast.OperatorCompareNeq: prog.OperatorCompareNeq,
ast.OperatorBinaryAnd: prog.OperatorBinaryAnd,
ast.OperatorOr: prog.OperatorOr,
}
func (comp *compiler) genExpression(t *ast.Type) prog.Expression {
if binary := t.Expression; binary != nil {
operator, ok := binaryOperatorMap[binary.Operator]
if !ok {
comp.error(binary.Pos, "unknown binary operator")
return nil
}
return &prog.BinaryExpression{
Operator: operator,
Left: comp.genExpression(binary.Left),
Right: comp.genExpression(binary.Right),
}
} else {
return comp.genValue(t)
}
}
func (comp *compiler) genValue(val *ast.Type) *prog.Value {
if val.Ident == valueIdent {
if len(val.Args) != 1 {
comp.error(val.Pos, "value reference must have only one argument")
return nil
}
arg := val.Args[0]
if arg.Args != nil {
comp.error(val.Pos, "value aguments must not have any further arguments")
return nil
}
path := []string{arg.Ident}
for _, elem := range arg.Colon {
if elem.Args != nil {
comp.error(arg.Pos, "value path elements must not have any attributes")
return nil
}
path = append(path, elem.Ident)
}
return &prog.Value{Path: path}
}
if val.Expression != nil || val.HasString {
comp.error(val.Pos, "the token must be either an integer or an identifier")
return nil
}
if len(val.Args) != 0 {
comp.error(val.Pos, "consts in expressions must not have any arguments")
return nil
}
return &prog.Value{
Value: val.Value,
}
}
func genCommon(name string, size uint64, opt bool) prog.TypeCommon {
return prog.TypeCommon{
TypeName: name,
TypeSize: size,
IsOptional: opt,
}
}
func genIntCommon(com prog.TypeCommon, bitLen uint64, bigEndian bool) prog.IntTypeCommon {
bf := prog.FormatNative
if bigEndian {
bf = prog.FormatBigEndian
}
bfUnit := uint64(0)
if bitLen != 0 {
bfUnit = com.TypeSize
com.TypeSize = 0
}
return prog.IntTypeCommon{
TypeCommon: com,
ArgFormat: bf,
BitfieldLen: bitLen,
BitfieldUnit: bfUnit,
}
}
func genIntArray(a []*ast.Int) []uint64 {
r := make([]uint64, len(a))
for i, v := range a {
r[i] = v.Value
}
return r
}
func genStrArray(a []*ast.String) []string {
r := make([]string, len(a))
for i, v := range a {
r[i] = v.Value
}
return r
}
// Copyright 2022 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package compiler
import (
"path/filepath"
"github.com/google/syzkaller/pkg/ast"
"github.com/google/syzkaller/sys/targets"
)
type Meta struct {
Automatic bool // automatically-generated descriptions
NoExtract bool // do not run syz-extract on the descriptions by default
Arches map[string]bool
}
func (meta Meta) SupportsArch(arch string) bool {
return len(meta.Arches) == 0 || meta.Arches[arch]
}
func FileList(desc *ast.Description, OS string, eh ast.ErrorHandler) map[string]Meta {
// Use any target for this OS.
for _, target := range targets.List[OS] {
return createCompiler(desc, target, eh).fileList()
}
return nil
}
func (comp *compiler) fileMeta(pos ast.Pos) Meta {
if comp.fileMetas == nil {
comp.fileMetas = comp.fileList()
}
return comp.fileMetas[filepath.Base(pos.File)]
}
func (comp *compiler) fileList() map[string]Meta {
files := make(map[string]Meta)
for _, n := range comp.desc.Nodes {
pos, _, _ := n.Info()
file := filepath.Base(pos.File)
if file == ast.BuiltinFile {
continue
}
meta := files[file]
switch n := n.(type) {
case *ast.Meta:
errors0 := comp.errors
comp.checkTypeImpl(checkCtx{}, n.Value, metaTypes[n.Value.Ident], 0)
if errors0 != comp.errors {
break
}
switch n.Value.Ident {
case metaAutomatic.Names[0]:
meta.Automatic = true
case metaNoExtract.Names[0]:
meta.NoExtract = true
case metaArches.Names[0]:
meta.Arches = make(map[string]bool)
for _, arg := range n.Value.Args {
meta.Arches[arg.String] = true
}
}
}
files[file] = meta
}
return files
}
var metaTypes = map[string]*typeDesc{
metaAutomatic.Names[0]: metaAutomatic,
metaNoExtract.Names[0]: metaNoExtract,
metaArches.Names[0]: metaArches,
}
var metaAutomatic = &typeDesc{
Names: []string{"automatic"},
CantBeOpt: true,
}
var metaNoExtract = &typeDesc{
Names: []string{"noextract"},
CantBeOpt: true,
}
var metaArches = &typeDesc{
Names: []string{"arches"},
CantBeOpt: true,
OptArgs: 8,
Args: []namedArg{metaArch, metaArch, metaArch, metaArch, metaArch, metaArch, metaArch, metaArch},
}
var metaArch = namedArg{Name: "arch", Type: &typeArg{
Kind: kindString,
Check: func(comp *compiler, t *ast.Type) {
if targets.List[comp.target.OS][t.String] == nil {
comp.error(t.Pos, "unknown arch %v", t.String)
}
},
}}
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package compiler
import (
"bytes"
"encoding/binary"
"fmt"
"sort"
"strconv"
"github.com/google/syzkaller/pkg/ast"
"github.com/google/syzkaller/prog"
)
// typeDesc is arg/field type descriptor.
type typeDesc struct {
Names []string
CanBeTypedef bool // can be type alias target?
CantBeOpt bool // can't be marked as opt?
CantBeOut bool // can't be used as an explicitly output argument?
CantHaveOut bool // everything inside can only be in
NeedBase bool // needs base type when used as field?
MaxColon int // max number of colons (int8:2) on fields
OptArgs int // number of optional arguments in Args array
Args []namedArg // type arguments
RequiresCallAttrs map[string]bool // calls using this type must have these attrs.
// CanBeArgRet returns if this type can be syscall argument/return (false if nil).
CanBeArgRet func(comp *compiler, t *ast.Type) (bool, bool)
// CanBeResourceBase returns if this type can be a resource base type (false if nil.
CanBeResourceBase func(comp *compiler, t *ast.Type) bool
// Check does custom verification of the type (optional, consts are not patched yet).
Check func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon)
// CheckConsts does custom verification of the type (optional, consts are patched).
CheckConsts func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon)
// Varlen returns if the type is variable-length (false if not set).
Varlen func(comp *compiler, t *ast.Type, args []*ast.Type) bool
// ZeroSize returns if the type has static 0 size (false if not set).
ZeroSize func(comp *compiler, t *ast.Type, args []*ast.Type) bool
// Gen generates corresponding prog.Type.
Gen func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type
}
// typeArg describes a type argument.
type typeArg struct {
Names []string
Kind int // int/ident/string
MaxArgs int // maxiumum number of subargs
MaxColon int // max number of colons (2:3:4)
// Check does custom verification of the arg (optional).
Check func(comp *compiler, t *ast.Type)
CheckConsts func(comp *compiler, t *ast.Type)
}
type namedArg struct {
Name string
Type *typeArg
IsArg bool // does not need base type
}
const (
kindAny = 0
kindInt = 1 << iota
kindIdent
kindString
)
func canBeArg(comp *compiler, t *ast.Type) (bool, bool) { return true, false }
func canBeArgRet(comp *compiler, t *ast.Type) (bool, bool) { return true, true }
var typeInt = &typeDesc{
Names: typeArgBase.Type.Names,
CanBeArgRet: canBeArg,
CanBeTypedef: true,
MaxColon: 1,
OptArgs: 2,
Args: []namedArg{
{Name: "value", Type: typeArgIntValue},
{Name: "align", Type: typeArgIntAlign},
},
CanBeResourceBase: func(comp *compiler, t *ast.Type) bool {
// Big-endian resources can always be converted to non-big-endian,
// since we will always revert bytes during copyout and during copyin,
// so the result is the same as not reverting at all.
// Big-endian resources are also not implemented and don't have tests.
_, be := comp.parseIntType(t.Ident)
return !be
},
Check: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) {
typeArgBase.Type.Check(comp, t)
if len(args) > 1 && len(args[0].Colon) == 0 {
comp.error(args[1].Pos, "align argument of %v is not supported unless first argument is a range",
t.Ident)
}
},
CheckConsts: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) {
if len(args) > 0 && len(args[0].Colon) != 0 {
begin := args[0].Value
end := args[0].Colon[0].Value
size, _ := comp.parseIntType(t.Ident)
size = size * 8
if len(t.Colon) != 0 {
// Integer is bitfield.
size = t.Colon[0].Value
}
maxUInt := uint64(1<<size - 1)
maxSInt := uint64(1<<(size-1) - 1)
if len(args) > 1 && begin == 0 && int64(end) == -1 {
// intN[0:-1, align] is a special value for 'all possible values', but aligned.
end = maxUInt
} else if end-begin > 1<<64-1<<32 {
comp.error(args[0].Pos, "bad int range [%v:%v]", begin, end)
return
}
// The range fits into the size if treated as unsigned [0:MAX_UINT].
inUnsignedBase := begin <= maxUInt && end <= maxUInt
// The range fits into the size if treated as signed [-MIN_SINT:MAX_SINT].
inSignedBase := begin+maxSInt <= maxUInt && end+maxSInt <= maxUInt
if size < 64 && !inUnsignedBase && !inSignedBase {
comp.error(args[0].Colon[0].Pos, "int range [%v:%v] is too large for base type of size %v",
begin, end, size)
return
}
if len(args) > 1 && args[1].Value != 0 && (end-begin)/args[1].Value == 0 {
comp.error(args[1].Pos, "int alignment %v is too large for range [%v:%v]",
args[1].Value, begin, end)
}
}
},
Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
size, be := comp.parseIntType(t.Ident)
var bitLen uint64
if len(t.Colon) != 0 {
bitLen = t.Colon[0].Value
}
base.TypeSize = size
base.TypeAlign = getIntAlignment(comp, base)
base = genIntCommon(base.TypeCommon, bitLen, be)
kind, rangeBegin, rangeEnd, align := prog.IntPlain, uint64(0), uint64(0), uint64(0)
if len(args) > 0 {
rangeArg := args[0]
if _, isIntFlag := comp.intFlags[rangeArg.Ident]; isIntFlag {
return generateFlagsType(comp, base, rangeArg.Ident)
}
if len(rangeArg.Colon) == 0 {
// If we have an argument that is not a range, then it's a const.
return &prog.ConstType{
IntTypeCommon: base,
Val: args[0].Value,
}
}
kind, rangeBegin, rangeEnd = prog.IntRange, rangeArg.Value, rangeArg.Colon[0].Value
if len(args) > 1 {
align = args[1].Value
}
}
return &prog.IntType{
IntTypeCommon: base,
Kind: kind,
RangeBegin: rangeBegin,
RangeEnd: rangeEnd,
Align: align,
}
},
}
func generateFlagsType(comp *compiler, base prog.IntTypeCommon, name string) prog.Type {
base.TypeName = name
f := comp.intFlags[name]
values := genIntArray(f.Values)
if len(values) == 0 || len(values) == 1 && values[0] == 0 {
// We can get this if all values are unsupported consts.
// Also generate const[0] if we have only 1 flags value which is 0,
// this is the intention in all existing cases (e.g. an enum with types
// of something, but there is really only 1 type exists).
return &prog.ConstType{
IntTypeCommon: base,
Val: 0,
}
}
sort.Slice(values, func(i, j int) bool {
return values[i] < values[j]
})
return &prog.FlagsType{
IntTypeCommon: base,
Vals: values,
BitMask: isBitmask(values),
}
}
func getIntAlignment(comp *compiler, base prog.IntTypeCommon) uint64 {
align := base.UnitSize()
if align == 8 && comp.target.Int64Alignment != 0 {
align = comp.target.Int64Alignment
}
return align
}
var typePtr = &typeDesc{
Names: []string{"ptr", "ptr64"},
CanBeArgRet: canBeArg,
CantBeOut: true,
CanBeTypedef: true,
Args: []namedArg{{Name: "direction", Type: typeArgDir}, {Name: "type", Type: typeArgType}},
Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
base.TypeSize = comp.ptrSize
if t.Ident == "ptr64" {
base.TypeSize = 8
}
base.TypeAlign = getIntAlignment(comp, base)
elem := comp.genType(args[1], 0)
elemDir := genDir(args[0])
return &prog.PtrType{
TypeCommon: base.TypeCommon,
Elem: elem,
ElemDir: elemDir,
}
},
}
func isSquashableElem(elem prog.Type, dir prog.Dir) bool {
if dir != prog.DirIn {
return false
}
// Check if the pointer element contains something that can be complex, and does not contain
// anything unsupported we don't want to sqaush. Prog package later checks at runtime
// if a concrete arg actually contains something complex. But we look at the whole type
// to understand if it contains anything unsupported b/c a union may contain e.g. a complex struct
// and a filename we don't want to squash, or an array may contain something unsupported,
// but has 0 size in a concrete argument.
complex, unsupported := false, false
prog.ForeachArgType(elem, func(t prog.Type, ctx *prog.TypeCtx) {
switch typ := t.(type) {
case *prog.StructType:
if typ.Varlen() {
complex = true
}
if typ.OverlayField != 0 {
// Squashing of structs with out_overlay is not supported.
// If we do it, we need to be careful to either squash out part as well,
// or remove any resources in the out part from the prog.
unsupported = true
}
case *prog.UnionType:
if typ.Varlen() && len(typ.Fields) > 5 {
complex = true
}
case *prog.PtrType:
// Squashing of pointers is not supported b/c if we do it
// we will pass random garbage as pointers.
unsupported = true
case *prog.BufferType:
switch typ.Kind {
case prog.BufferFilename, prog.BufferGlob, prog.BufferCompressed:
// Squashing file names may lead to unwanted escaping paths (e.g. "/"),
// squashing compressed buffers is not useful since we uncompress them ourselves
// (not the kernel).
unsupported = true
}
}
ctx.Stop = unsupported
})
return complex && !unsupported
}
var typeVoid = &typeDesc{
Names: []string{"void"},
CantBeOpt: true,
ZeroSize: func(comp *compiler, t *ast.Type, args []*ast.Type) bool {
return true
},
Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
base.TypeSize = 0 // the only type with static size 0
base.TypeAlign = 1
return &prog.BufferType{
TypeCommon: base.TypeCommon,
Kind: prog.BufferBlobRange,
RangeBegin: 0,
RangeEnd: 0,
}
},
}
var typeArray = &typeDesc{
Names: []string{"array"},
CanBeTypedef: true,
CantBeOpt: true,
OptArgs: 1,
Args: []namedArg{{Name: "type", Type: typeArgType}, {Name: "size", Type: typeArgSizeRange}},
CheckConsts: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) {
if len(args) > 1 && args[1].Value == 0 && (len(args[1].Colon) == 0 || args[1].Colon[0].Value == 0) {
comp.error(args[1].Pos, "arrays of size 0 are not supported")
}
},
Varlen: func(comp *compiler, t *ast.Type, args []*ast.Type) bool {
if comp.isZeroSize(args[0]) {
return false
}
if comp.isVarlen(args[0]) {
return true
}
if len(args) > 1 {
return len(args[1].Colon) != 0 && args[1].Value != args[1].Colon[0].Value
}
return true
},
ZeroSize: func(comp *compiler, t *ast.Type, args []*ast.Type) bool {
return comp.isZeroSize(args[0])
},
Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
elemType := comp.genType(args[0], 0)
kind, begin, end := prog.ArrayRandLen, uint64(0), uint64(0)
if len(args) > 1 {
kind, begin, end = prog.ArrayRangeLen, args[1].Value, args[1].Value
if len(args[1].Colon) != 0 {
end = args[1].Colon[0].Value
}
}
if it, ok := elemType.(*prog.IntType); ok && it.Kind == prog.IntPlain && it.TypeSize == 1 {
// Special case: buffer is better mutated.
bufKind := prog.BufferBlobRand
base.TypeSize = 0
if kind == prog.ArrayRangeLen {
bufKind = prog.BufferBlobRange
if begin == end {
base.TypeSize = begin * elemType.Size()
}
}
base.TypeAlign = 1
return &prog.BufferType{
TypeCommon: base.TypeCommon,
Kind: bufKind,
RangeBegin: begin,
RangeEnd: end,
}
}
if ct, ok := elemType.(*prog.ConstType); ok &&
(ct.ArgFormat == prog.FormatNative || ct.ArgFormat == prog.FormatBigEndian) &&
kind == prog.ArrayRangeLen && begin == end {
// Special case: const string takes less space in C programs.
base.TypeSize = begin * ct.Size()
base.TypeAlign = ct.TypeAlign
val := make([]byte, 8)
if ct.ArgFormat == prog.FormatBigEndian {
binary.BigEndian.PutUint64(val, ct.Val)
val = val[8-ct.Size():]
} else {
binary.LittleEndian.PutUint64(val, ct.Val)
val = val[:ct.Size()]
}
val = bytes.Repeat(val, int(begin))
return &prog.BufferType{
TypeCommon: base.TypeCommon,
Kind: prog.BufferString,
Values: []string{string(val)},
NoZ: true,
}
}
// TypeSize/TypeAlign are assigned later in layoutArray.
return &prog.ArrayType{
TypeCommon: base.TypeCommon,
Elem: elemType,
Kind: kind,
RangeBegin: begin,
RangeEnd: end,
}
},
}
var typeLen = &typeDesc{
Names: []string{"len", "bytesize", "bytesize2", "bytesize4", "bytesize8", "bitsize", "offsetof"},
CanBeArgRet: canBeArg,
CantBeOpt: true,
CantBeOut: true,
NeedBase: true,
Args: []namedArg{{Name: "len target", Type: typeArgLenTarget}},
Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
var bitSize uint64
var offset bool
switch t.Ident {
case "bytesize":
bitSize = 8
case "bytesize2", "bytesize4", "bytesize8":
byteSize, _ := strconv.ParseUint(t.Ident[8:], 10, 8)
bitSize = byteSize * 8
case "bitsize":
bitSize = 1
case "offsetof":
bitSize = 8
offset = true
}
path := []string{args[0].Ident}
for _, col := range args[0].Colon {
path = append(path, col.Ident)
}
base.TypeAlign = getIntAlignment(comp, base)
return &prog.LenType{
IntTypeCommon: base,
Path: path,
BitSize: bitSize,
Offset: offset,
}
},
}
var typeConst = &typeDesc{
Names: []string{"const"},
CanBeArgRet: canBeArg,
CanBeTypedef: true,
CantBeOpt: true,
CantBeOut: true,
NeedBase: true,
Args: []namedArg{{Name: "value", Type: typeArgInt}},
CheckConsts: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) {
v := args[0].Value
bitSize := base.TypeBitSize()
if constOverflowsBase(v, base) {
comp.error(args[0].Pos, "const val 0x%x does not fit into %v bits", v, bitSize)
}
args[0].Value = v & (uint64(1)<<bitSize - 1)
},
Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
base.TypeAlign = getIntAlignment(comp, base)
return &prog.ConstType{
IntTypeCommon: base,
Val: args[0].Value,
}
},
}
func constOverflowsBase(v uint64, base prog.IntTypeCommon) bool {
size := base.TypeBitSize()
if size == 64 {
return false
}
mask := uint64(1)<<size - 1
v1 := v & mask
if int64(v1<<(64-size)) < 0 && int64(v) < 0 {
v1 |= ^mask
}
return v1 != v
}
var typeArgLenTarget = &typeArg{
Kind: kindIdent,
MaxColon: 10,
}
var typeFlags = &typeDesc{
Names: []string{"flags"},
CanBeArgRet: canBeArg,
CanBeTypedef: true,
CantBeOpt: true,
CantBeOut: true,
NeedBase: true,
Args: []namedArg{{Name: "flags", Type: typeArgFlags}},
CheckConsts: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) {
name := args[0].Ident
if name == "xdp_mmap_offsets" && comp.ptrSize == 4 {
// TODO(dvyukov): this sucks a lot. It seems that out 32-bit mmap is wrong.
// The syscall accepts number of pages as int32, but we pass offset in bytes.
// As the result large XDP consts don't fit into the arg.
return
}
f := comp.intFlags[name]
for _, val := range f.Values {
if constOverflowsBase(val.Value, base) {
comp.error(args[0].Pos, "%v %v=0x%x doesn't fit into %v bits",
name, val.Ident, val.Value, base.TypeBitSize())
}
}
},
Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
base.TypeAlign = getIntAlignment(comp, base)
return generateFlagsType(comp, base, args[0].Ident)
},
}
func isBitmask(values []uint64) bool {
if values[0] == 0 {
// 0 can't be part of bitmask, this helps to handle important
// case like "0, 1" and "0, 1, 2" that would be detected
// as bitmask otherwise.
return false
}
var combined uint64
for _, v := range values {
if v&combined != 0 {
return false
}
combined |= v
}
return true
}
var typeArgFlags = &typeArg{
Kind: kindIdent,
Check: func(comp *compiler, t *ast.Type) {
if comp.intFlags[t.Ident] == nil {
comp.error(t.Pos, "unknown flags %v", t.Ident)
return
}
},
}
var typeVMA = &typeDesc{
Names: []string{"vma", "vma64"},
CanBeArgRet: canBeArg,
OptArgs: 1,
Args: []namedArg{{Name: "size range", Type: typeArgSizeRange}},
Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
var begin, end uint64
if len(args) > 0 {
begin, end = args[0].Value, args[0].Value
if len(args[0].Colon) != 0 {
end = args[0].Colon[0].Value
}
}
base.TypeSize = comp.ptrSize
if t.Ident == "vma64" {
base.TypeSize = 8
}
base.TypeAlign = getIntAlignment(comp, base)
return &prog.VmaType{
TypeCommon: base.TypeCommon,
RangeBegin: begin,
RangeEnd: end,
}
},
}
var typeCsum = &typeDesc{
Names: []string{"csum"},
NeedBase: true,
CantBeOpt: true,
CantBeOut: true,
OptArgs: 1,
Args: []namedArg{
{Name: "csum target", Type: typeArgLenTarget},
{Name: "kind", Type: typeArgCsumType},
{Name: "proto", Type: typeArgInt},
},
Check: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) {
if len(args) > 2 && genCsumKind(args[1]) != prog.CsumPseudo {
comp.error(args[2].Pos, "only pseudo csum can have proto")
}
if len(args[0].Colon) != 0 {
comp.error(args[0].Colon[0].Pos, "path expressions are not implemented for csum")
}
},
Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
var proto uint64
if len(args) > 2 {
proto = args[2].Value
}
base.TypeAlign = getIntAlignment(comp, base)
return &prog.CsumType{
IntTypeCommon: base,
Buf: args[0].Ident,
Kind: genCsumKind(args[1]),
Protocol: proto,
}
},
}
var typeArgCsumType = &typeArg{
Kind: kindIdent,
Names: []string{"inet", "pseudo"},
}
func genCsumKind(t *ast.Type) prog.CsumKind {
switch t.Ident {
case "inet":
return prog.CsumInet
case "pseudo":
return prog.CsumPseudo
default:
panic(fmt.Sprintf("unknown csum kind %q", t.Ident))
}
}
var typeProc = &typeDesc{
Names: []string{"proc"},
CanBeArgRet: canBeArg,
CantBeOut: true,
CanBeTypedef: true,
NeedBase: true,
Args: []namedArg{
{Name: "range start", Type: typeArgInt},
{Name: "per-proc values", Type: typeArgInt},
},
CheckConsts: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) {
start := args[0].Value
perProc := args[1].Value
if perProc == 0 {
comp.error(args[1].Pos, "proc per-process values must not be 0")
return
}
size := base.TypeSize * 8
max := uint64(1) << size
if size == 64 {
max = ^uint64(0)
}
if start >= max {
comp.error(args[0].Pos, "values starting from %v overflow base type", start)
} else if perProc > (max-start)/prog.MaxPids {
comp.error(args[0].Pos, "values starting from %v with step %v overflow base type for %v procs",
start, perProc, prog.MaxPids)
}
},
Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
base.TypeAlign = getIntAlignment(comp, base)
return &prog.ProcType{
IntTypeCommon: base,
ValuesStart: args[0].Value,
ValuesPerProc: args[1].Value,
}
},
}
var typeText = &typeDesc{
Names: []string{"text"},
CantBeOpt: true,
CantBeOut: true,
Args: []namedArg{{Name: "kind", Type: typeArgTextType}},
Varlen: func(comp *compiler, t *ast.Type, args []*ast.Type) bool {
return true
},
Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
base.TypeSize = 0
base.TypeAlign = 1
return &prog.BufferType{
TypeCommon: base.TypeCommon,
Kind: prog.BufferText,
Text: genTextType(args[0]),
}
},
}
var typeArgTextType = &typeArg{
Kind: kindIdent,
Names: []string{"target", "x86_real", "x86_16", "x86_32", "x86_64", "arm64", "ppc64"},
}
func genTextType(t *ast.Type) prog.TextKind {
switch t.Ident {
case "target":
return prog.TextTarget
case "x86_real":
return prog.TextX86Real
case "x86_16":
return prog.TextX86bit16
case "x86_32":
return prog.TextX86bit32
case "x86_64":
return prog.TextX86bit64
case "arm64":
return prog.TextArm64
case "ppc64":
return prog.TextPpc64
default:
panic(fmt.Sprintf("unknown text type %q", t.Ident))
}
}
const (
stringnoz = "stringnoz"
glob = "glob"
)
var typeString = &typeDesc{
Names: []string{"string", glob, stringnoz},
CanBeTypedef: true,
OptArgs: 2,
Args: []namedArg{
{Name: "literal or flags", Type: typeArgStringFlags},
{Name: "size", Type: typeArgInt},
},
Check: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) {
if t.Ident == stringnoz && len(args) > 1 {
comp.error(args[0].Pos, "fixed-size string can't be non-zero-terminated")
}
if t.Ident == glob && len(args) != 1 {
comp.error(t.Pos, "glob only accepts 1 arg, provided %v", len(args))
}
},
CheckConsts: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) {
if len(args) > 1 {
size := args[1].Value
vals := comp.genStrings(t, args)
for _, s := range vals {
if uint64(len(s)) > size {
comp.error(args[0].Pos, "string value %q exceeds buffer length %v",
s, size)
}
}
}
},
Varlen: func(comp *compiler, t *ast.Type, args []*ast.Type) bool {
if t.Ident == glob {
return true
}
return comp.stringSize(t, args) == varlenString
},
ZeroSize: func(comp *compiler, t *ast.Type, args []*ast.Type) bool {
return comp.stringSize(t, args) == 0
},
Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
base.TypeAlign = 1
if len(args) > 0 && args[0].Ident == "filename" {
base.TypeName = "filename"
base.TypeSize = 0
if len(args) >= 2 {
base.TypeSize = args[1].Value
}
return &prog.BufferType{
TypeCommon: base.TypeCommon,
Kind: prog.BufferFilename,
NoZ: t.Ident == stringnoz,
}
}
if len(args) > 0 && t.Ident == glob {
base.TypeSize = 0
return &prog.BufferType{
TypeCommon: base.TypeCommon,
Kind: prog.BufferGlob,
SubKind: args[0].String,
NoZ: false,
}
}
subkind := ""
if len(args) > 0 && args[0].Ident != "" {
subkind = args[0].Ident
}
vals := comp.genStrings(t, args)
base.TypeSize = comp.stringSize(t, args)
if base.TypeSize == varlenString {
base.TypeSize = 0
}
return &prog.BufferType{
TypeCommon: base.TypeCommon,
Kind: prog.BufferString,
SubKind: subkind,
Values: vals,
NoZ: t.Ident == stringnoz,
}
},
}
func (comp *compiler) genStrings(t *ast.Type, args []*ast.Type) []string {
var vals []string
if len(args) > 0 {
if args[0].HasString {
vals = append(vals, args[0].String)
} else {
vals = genStrArray(comp.strFlags[args[0].Ident].Values)
}
}
if t.Ident == stringnoz {
return vals
}
var size uint64
if len(args) > 1 {
size = args[1].Value
}
for i, s := range vals {
s += "\x00"
for uint64(len(s)) < size {
s += "\x00"
}
vals[i] = s
}
return vals
}
const varlenString = ^uint64(0)
// stringSize returns static string size, or varlenString if it is variable length.
func (comp *compiler) stringSize(t *ast.Type, args []*ast.Type) uint64 {
switch len(args) {
case 0:
return varlenString // a random string
case 1:
var z uint64
if t.Ident == "string" {
z = 1
}
if args[0].HasString {
return uint64(len(args[0].String)) + z // string constant
}
size := varlenString
for _, s := range comp.strFlags[args[0].Ident].Values {
s1 := uint64(len(s.Value)) + z
if size != varlenString && size != s1 {
return varlenString // strings of different lengths
}
size = s1
}
return size // all strings have the same length
case 2:
return args[1].Value // have explicit length
default:
panic("too many string args")
}
}
var typeArgStringFlags = &typeArg{
Kind: kindIdent | kindString,
Check: func(comp *compiler, t *ast.Type) {
if t.Ident != "" && comp.strFlags[t.Ident] == nil {
comp.error(t.Pos, "unknown string flags %v", t.Ident)
return
}
},
}
var typeFmt = &typeDesc{
Names: []string{"fmt"},
CanBeTypedef: true,
CantBeOpt: true,
CantBeOut: true,
CantHaveOut: true,
Args: []namedArg{
{Name: "format", Type: typeFmtFormat},
{Name: "value", Type: typeArgType, IsArg: true},
},
Check: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) {
desc, _, _ := comp.getArgsBase(args[1], true)
switch desc {
case typeResource, typeInt, typeLen, typeFlags, typeProc:
default:
comp.error(t.Pos, "bad fmt value %v, expect an integer", args[1].Ident)
return
}
},
Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
var format prog.BinaryFormat
var size uint64
switch args[0].Ident {
case "dec":
format = prog.FormatStrDec
size = 20
case "hex":
format = prog.FormatStrHex
size = 18
case "oct":
format = prog.FormatStrOct
size = 23
}
typ := comp.genType(args[1], comp.ptrSize)
switch t := typ.(type) {
case *prog.ResourceType:
t.ArgFormat = format
t.TypeSize = size
t.TypeAlign = 1
case *prog.IntType:
t.ArgFormat = format
t.TypeSize = size
t.TypeAlign = 1
case *prog.LenType:
t.ArgFormat = format
t.TypeSize = size
t.TypeAlign = 1
case *prog.FlagsType:
t.ArgFormat = format
t.TypeSize = size
t.TypeAlign = 1
case *prog.ProcType:
t.ArgFormat = format
t.TypeSize = size
t.TypeAlign = 1
case *prog.ConstType:
// We don't allow fmt[const] directly, but flags with only 1 value
// are transformed to ConstType.
t.ArgFormat = format
t.TypeSize = size
t.TypeAlign = 1
default:
panic(fmt.Sprintf("unexpected type: %#v", typ))
}
return typ
},
}
var typeFmtFormat = &typeArg{
Names: []string{"dec", "hex", "oct"},
Kind: kindIdent,
}
// typeCompressedImage is used for compressed disk images.
var typeCompressedImage = &typeDesc{
Names: []string{"compressed_image"},
CantBeOpt: true,
CantBeOut: true,
RequiresCallAttrs: map[string]bool{
"no_generate": true,
"no_minimize": true,
},
CanBeArgRet: func(comp *compiler, t *ast.Type) (bool, bool) {
return true, false
},
Varlen: func(comp *compiler, t *ast.Type, args []*ast.Type) bool {
return true
},
Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
base.TypeSize = 0
base.TypeAlign = 1
return &prog.BufferType{
TypeCommon: base.TypeCommon,
Kind: prog.BufferCompressed,
}
},
}
// typeArgType is used as placeholder for any type (e.g. ptr target type).
var typeArgType = &typeArg{}
var typeResource = &typeDesc{
// No Names, but getTypeDesc knows how to match it.
CanBeArgRet: canBeArgRet,
CanBeResourceBase: func(comp *compiler, t *ast.Type) bool {
return true
},
// Gen is assigned below to avoid initialization loop.
}
func init() {
typeResource.Gen = func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
// Find and generate base type to get its size.
var baseType *ast.Type
for r := comp.resources[t.Ident]; r != nil; {
baseType = r.Base
r = comp.resources[r.Base.Ident]
}
baseProgType := comp.genType(baseType, 0)
base.TypeSize = baseProgType.Size()
base.TypeAlign = getIntAlignment(comp, base)
return &prog.ResourceType{
TypeCommon: base.TypeCommon,
ArgFormat: baseProgType.Format(),
}
}
}
var typeStruct = &typeDesc{
// No Names, but getTypeDesc knows how to match it.
CantBeOpt: true,
CanBeTypedef: true,
// Varlen/Gen are assigned below due to initialization cycle.
}
func init() {
typeStruct.CanBeArgRet = func(comp *compiler, t *ast.Type) (bool, bool) {
// Allow unions to be arg if all options can be arg.
s := comp.structs[t.Ident]
if !s.IsUnion {
return false, false
}
canBeArg := true
for _, fld := range s.Fields {
desc := comp.getTypeDesc(fld.Type)
if desc == nil || desc == typeStruct || desc.CanBeArgRet == nil {
return false, false
}
canBeArg1, _ := desc.CanBeArgRet(comp, fld.Type)
if !canBeArg1 {
canBeArg = false
}
}
return canBeArg, false
}
typeStruct.Varlen = func(comp *compiler, t *ast.Type, args []*ast.Type) bool {
return comp.structIsVarlen(t.Ident)
}
typeStruct.ZeroSize = func(comp *compiler, t *ast.Type, args []*ast.Type) bool {
for _, fld := range comp.structs[t.Ident].Fields {
if !comp.isZeroSize(fld.Type) {
return false
}
}
return true
}
typeStruct.Gen = func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
if typ := comp.structTypes[t.Ident]; typ != nil {
return typ
}
s := comp.structs[t.Ident]
common := genCommon(t.Ident, sizeUnassigned, false)
common.IsVarlen = typeStruct.Varlen(comp, t, args)
var typ prog.Type
if s.IsUnion {
typ = &prog.UnionType{
TypeCommon: common,
}
} else {
typ = &prog.StructType{
TypeCommon: common,
}
}
// Need to cache type in structTypes before generating fields to break recursion.
comp.structTypes[t.Ident] = typ
fields, overlayField := comp.genFieldArray(s.Fields, make([]uint64, len(s.Fields)))
switch typ1 := typ.(type) {
case *prog.UnionType:
typ1.Fields = fields
case *prog.StructType:
typ1.Fields = fields
for i, field := range fields {
if field.Condition != nil {
fields[i] = comp.wrapConditionalField(t.Ident, field)
}
}
if overlayField >= 0 {
typ1.OverlayField = overlayField
}
}
// TypeSize/TypeAlign are assigned later in layoutStruct.
return typ
}
}
var typeTypedef = &typeDesc{
// No Names, but getTypeDesc knows how to match it.
Check: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) {
panic("must not be called")
},
}
var typeArgDir = &typeArg{
Kind: kindIdent,
Names: []string{"in", "out", "inout"},
}
func genDir(t *ast.Type) prog.Dir {
switch t.Ident {
case "in":
return prog.DirIn
case "out":
return prog.DirOut
case "inout":
return prog.DirInOut
default:
panic(fmt.Sprintf("unknown direction %q", t.Ident))
}
}
var typeArgInt = &typeArg{
Kind: kindInt,
}
var typeArgIntValue = &typeArg{
Kind: kindInt | kindIdent,
MaxColon: 1,
CheckConsts: func(comp *compiler, t *ast.Type) {
// If the first arg is not a range, then it should be a valid flags.
if len(t.Colon) == 0 && t.Ident != "" && comp.intFlags[t.Ident] == nil {
comp.error(t.Pos, "unknown flags %v", t.Ident)
return
}
},
}
var typeArgIntAlign = &typeArg{
Kind: kindInt,
MaxColon: 0,
CheckConsts: func(comp *compiler, t *ast.Type) {
if t.Value <= 1 {
comp.error(t.Pos, "bad int alignment %v", t.Value)
}
},
}
// Size of array and vma's.
var typeArgSizeRange = &typeArg{
Kind: kindInt,
MaxColon: 1,
CheckConsts: func(comp *compiler, t *ast.Type) {
end := t.Value
if len(t.Colon) != 0 {
end = t.Colon[0].Value
}
const maxVal = 1e6
if t.Value > end || t.Value > maxVal || end > maxVal {
comp.error(t.Pos, "bad size range [%v:%v]", t.Value, end)
}
},
}
// Base type of const/len/etc. Same as typeInt, but can't have range.
var typeArgBase = namedArg{
Name: "base type",
Type: &typeArg{
Names: []string{"int8", "int16", "int32", "int64", "int16be", "int32be", "int64be", "intptr"},
MaxColon: 1,
Check: func(comp *compiler, t *ast.Type) {
if len(t.Colon) != 0 {
col := t.Colon[0]
if col.Ident != "" {
comp.error(col.Pos, "literal const bitfield sizes are not supported")
return
}
if col.Value == 0 {
// This was not supported historically
// and does not work the way C bitfields of size 0 work.
// We could allow this, but then we need to make
// this work the way C bitfields work.
comp.error(col.Pos, "bitfields of size 0 are not supported")
}
size, _ := comp.parseIntType(t.Ident)
if col.Value > size*8 {
comp.error(col.Pos, "bitfield of size %v is too large for base type of size %v",
col.Value, size*8)
}
}
},
},
}
var (
builtinTypes = make(map[string]*typeDesc)
builtinDescs *ast.Description
// To avoid weird cases like ptr[in, in] and ptr[out, opt].
reservedName = map[string]bool{
"opt": true,
"in": true,
"out": true,
"inout": true,
}
)
const builtinDefs = `
type bool8 int8[0:1]
type bool16 int16[0:1]
type bool32 int32[0:1]
type bool64 int64[0:1]
type boolptr intptr[0:1]
type fileoff[BASE] BASE
type filename string[filename]
filename = "", "."
type buffer[DIR] ptr[DIR, array[int8]]
type optional[T] [
val T
void void
] [varlen]
# prog/any.go knows layout of these types.
ANYUNION [
ANYBLOB array[int8]
ANYRES8 ANYRES8
ANYRES16 ANYRES16
ANYRES32 ANYRES32
ANYRES64 ANYRES64
ANYRESDEC fmt[dec, ANYRES64] (in)
ANYRESHEX fmt[hex, ANYRES64] (in)
ANYRESOCT fmt[oct, ANYRES64] (in)
] [varlen]
ANYPTRS [
ANYPTR ptr[inout, array[ANYUNION]]
ANYPTR64 ptr64[inout, array[ANYUNION]]
]
resource ANYRES8[int8]: -1, 0
resource ANYRES16[int16]: -1, 0
resource ANYRES32[int32]: -1, 0
resource ANYRES64[int64]: -1, 0
syz_builtin0(a ptr[in, ANYPTRS]) (disabled)
syz_builtin1(a ptr[inout, ANYUNION]) (disabled)
syz_builtin2() ANYRES8 (disabled)
syz_builtin3() ANYRES16 (disabled)
syz_builtin4() ANYRES32 (disabled)
syz_builtin5() ANYRES64 (disabled)
`
func init() {
builtins := []*typeDesc{
typeInt,
typePtr,
typeVoid,
typeArray,
typeLen,
typeConst,
typeFlags,
typeVMA,
typeCsum,
typeProc,
typeText,
typeString,
typeFmt,
typeCompressedImage,
}
for _, desc := range builtins {
for _, name := range desc.Names {
if builtinTypes[name] != nil {
panic(fmt.Sprintf("duplicate builtin type %q", name))
}
builtinTypes[name] = desc
}
}
builtinDescs = ast.Parse([]byte(builtinDefs), ast.BuiltinFile, func(pos ast.Pos, msg string) {
panic(fmt.Sprintf("failed to parse builtins: %v: %v", pos, msg))
})
}
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package config
import (
"bytes"
"encoding/json"
"fmt"
"os"
"regexp"
"github.com/google/syzkaller/pkg/osutil"
)
func LoadFile(filename string, cfg interface{}) error {
if filename == "" {
return fmt.Errorf("no config file specified")
}
data, err := os.ReadFile(filename)
if err != nil {
return fmt.Errorf("failed to read config file: %w", err)
}
return LoadData(data, cfg)
}
func LoadData(data []byte, cfg interface{}) error {
// Remove comment lines starting with #.
data = regexp.MustCompile(`(^|\n)\s*#[^\n]*`).ReplaceAll(data, nil)
dec := json.NewDecoder(bytes.NewReader(data))
dec.DisallowUnknownFields()
if err := dec.Decode(cfg); err != nil {
return fmt.Errorf("failed to parse config file: %w", err)
}
return nil
}
func SaveFile(filename string, cfg interface{}) error {
data, err := json.MarshalIndent(cfg, "", "\t")
if err != nil {
return err
}
return osutil.WriteFile(filename, data)
}
// Copyright 2021 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package config
import (
"encoding/json"
)
// Unfortunately, if we want to apply a JSON patch to some configuration, we cannot just unmarshal
// it twice - in that case json.RawMessage objects will be completely replaced, but not merged.
func MergeJSONs(left, right []byte) ([]byte, error) {
vLeft, err := parseFragment(left)
if err != nil {
return nil, err
}
vRight, err := parseFragment(right)
if err != nil {
return nil, err
}
return json.Marshal(mergeRecursive(vLeft, vRight))
}
// Recursively apply a patch to a raw JSON data.
// Patch is supposed to be a map, which possibly nests other map objects.
func PatchJSON(left []byte, patch map[string]interface{}) ([]byte, error) {
vLeft, err := parseFragment(left)
if err != nil {
return nil, err
}
return json.Marshal(mergeRecursive(vLeft, patch))
}
func parseFragment(input []byte) (parsed interface{}, err error) {
if len(input) == 0 {
// For convenience, we allow empty strings to be passed to the function that merges JSONs.
return
}
err = json.Unmarshal(json.RawMessage(input), &parsed)
return
}
// If one of the elements is not a map, use the new one.
// Otherwise, recursively merge map elements.
func mergeRecursive(left, right interface{}) interface{} {
if left == nil {
return right
}
if right == nil {
return left
}
mLeft, okLeft := left.(map[string]interface{})
mRight, okRight := right.(map[string]interface{})
if !okLeft || !okRight {
return right
}
for key, val := range mRight {
valLeft, ok := mLeft[key]
if ok {
mLeft[key] = mergeRecursive(valLeft, val)
} else {
mLeft[key] = val
}
}
return mLeft
}
// Copyright 2020 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package backend
import (
"fmt"
"github.com/google/syzkaller/pkg/mgrconfig"
"github.com/google/syzkaller/pkg/vminfo"
"github.com/google/syzkaller/sys/targets"
)
type Impl struct {
Units []*CompileUnit
Symbols []*Symbol
Frames []*Frame
Symbolize func(pcs map[*vminfo.KernelModule][]uint64) ([]*Frame, error)
CallbackPoints []uint64
PreciseCoverage bool
}
type CompileUnit struct {
ObjectUnit
Path string
Module *vminfo.KernelModule
}
type Symbol struct {
ObjectUnit
Module *vminfo.KernelModule
Unit *CompileUnit
Start uint64
End uint64
Symbolized bool
}
// ObjectUnit represents either CompileUnit or Symbol.
type ObjectUnit struct {
Name string
PCs []uint64 // PCs we can get in coverage callbacks for this unit.
CMPs []uint64 // PCs we can get in comparison interception callbacks for this unit.
}
type Frame struct {
Module *vminfo.KernelModule
PC uint64
Name string
FuncName string
Path string
Inline bool
Range
}
type Range struct {
StartLine int
StartCol int
EndLine int
EndCol int
}
type SecRange struct {
Start uint64
End uint64
}
const LineEnd = 1 << 30
func Make(cfg *mgrconfig.Config, modules []*vminfo.KernelModule) (*Impl, error) {
kernelDirs := cfg.KernelDirs()
target := cfg.SysTarget
moduleObj := cfg.ModuleObj
vm := cfg.Type
if kernelDirs.Obj == "" {
return nil, fmt.Errorf("kernel obj directory is not specified")
}
if target.OS == targets.Darwin {
return makeMachO(target, kernelDirs, moduleObj, modules)
}
if vm == targets.GVisor {
return makeGvisor(target, kernelDirs, modules)
}
var delimiters []string
if cfg.AndroidSplitBuild {
// Path prefixes used by Android Pixel kernels. See
// https://source.android.com/docs/setup/build/building-pixel-kernels for more
// details.
delimiters = []string{"/aosp/", "/private/"}
}
return makeELF(target, kernelDirs, delimiters, moduleObj, modules)
}
func GetPCBase(cfg *mgrconfig.Config) (uint64, error) {
if cfg.Target.OS == targets.Linux && cfg.Type != targets.GVisor && cfg.Type != targets.Starnix {
return getLinuxPCBase(cfg)
}
return 0, nil
}
// Copyright 2021 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package backend
import (
"bufio"
"bytes"
"debug/dwarf"
"debug/elf"
"encoding/binary"
"fmt"
"io"
"path/filepath"
"regexp"
"runtime"
"sort"
"strconv"
"strings"
"github.com/google/syzkaller/pkg/log"
"github.com/google/syzkaller/pkg/mgrconfig"
"github.com/google/syzkaller/pkg/osutil"
"github.com/google/syzkaller/pkg/symbolizer"
"github.com/google/syzkaller/pkg/vminfo"
"github.com/google/syzkaller/sys/targets"
)
type dwarfParams struct {
target *targets.Target
kernelDirs *mgrconfig.KernelDirs
splitBuildDelimiters []string
moduleObj []string
hostModules []*vminfo.KernelModule
readSymbols func(*vminfo.KernelModule, *symbolInfo) ([]*Symbol, error)
readTextData func(*vminfo.KernelModule) ([]byte, error)
readModuleCoverPoints func(*targets.Target, *vminfo.KernelModule, *symbolInfo) ([2][]uint64, error)
readTextRanges func(*vminfo.KernelModule) ([]pcRange, []*CompileUnit, error)
getCompilerVersion func(string) string
}
type Arch struct {
scanSize int
callLen int
relaOffset uint64
callRelocType uint64
isCallInsn func(arch *Arch, insn []byte) bool
callTarget func(arch *Arch, insn []byte, pc uint64) uint64
}
var arches = map[string]*Arch{
targets.AMD64: {
scanSize: 1,
callLen: 5,
relaOffset: 1,
callRelocType: uint64(elf.R_X86_64_PLT32),
isCallInsn: func(arch *Arch, insn []byte) bool {
return insn[0] == 0xe8
},
callTarget: func(arch *Arch, insn []byte, pc uint64) uint64 {
off := uint64(int64(int32(binary.LittleEndian.Uint32(insn[1:]))))
return pc + off + uint64(arch.callLen)
},
},
targets.ARM64: {
scanSize: 4,
callLen: 4,
callRelocType: uint64(elf.R_AARCH64_CALL26),
isCallInsn: func(arch *Arch, insn []byte) bool {
const mask = uint32(0xfc000000)
const opc = uint32(0x94000000)
return binary.LittleEndian.Uint32(insn)&mask == opc
},
callTarget: func(arch *Arch, insn []byte, pc uint64) uint64 {
off26 := binary.LittleEndian.Uint32(insn) & 0x3ffffff
sign := off26 >> 25
off := uint64(off26)
// Sign-extend the 26-bit offset stored in the instruction.
if sign == 1 {
off |= 0xfffffffffc000000
}
return pc + 4*off
},
},
targets.S390x: {
scanSize: 1,
callLen: 6,
callRelocType: uint64(elf.R_390_PLT32DBL),
isCallInsn: func(arch *Arch, insn []byte) bool {
return insn[0] == 0xc0 && insn[1] == 0xe5
},
callTarget: func(arch *Arch, insn []byte, pc uint64) uint64 {
off := uint64(int64(int32(binary.BigEndian.Uint32(insn[2:]))))
return pc + 2*off
},
},
}
func makeDWARF(params *dwarfParams) (impl *Impl, err error) {
defer func() {
// It turns out that the DWARF-parsing library in Go crashes while parsing DWARF 5 data.
// As GCC11 uses DWARF 5 by default, we can expect larger number of problems with
// syzkallers compiled using old go versions.
// So we just catch the panic and turn it into a meaningful error message.
if recErr := recover(); recErr != nil {
impl = nil
err = fmt.Errorf("panic occurred while parsing DWARF "+
"(possible remedy: use go1.16+ which support DWARF 5 debug data): %s", recErr)
}
}()
impl, err = makeDWARFUnsafe(params)
return
}
type Result struct {
CoverPoints [2][]uint64
Symbols []*Symbol
}
func processModule(params *dwarfParams, module *vminfo.KernelModule, info *symbolInfo,
target *targets.Target) (*Result, error) {
symbols, err := params.readSymbols(module, info)
if err != nil {
return nil, err
}
var data []byte
var coverPoints [2][]uint64
if _, ok := arches[target.Arch]; !ok {
coverPoints, err = objdump(target, module)
} else if module.Name == "" {
data, err = params.readTextData(module)
if err != nil {
return nil, err
}
coverPoints, err = readCoverPoints(target, info, data)
} else {
coverPoints, err = params.readModuleCoverPoints(target, module, info)
}
if err != nil {
return nil, err
}
result := &Result{
Symbols: symbols,
CoverPoints: coverPoints,
}
return result, nil
}
func makeDWARFUnsafe(params *dwarfParams) (*Impl, error) {
target := params.target
kernelDirs := params.kernelDirs
splitBuildDelimiters := params.splitBuildDelimiters
modules := params.hostModules
// Here and below index 0 refers to coverage callbacks (__sanitizer_cov_trace_pc(_guard))
// and index 1 refers to comparison callbacks (__sanitizer_cov_trace_cmp*).
var allCoverPoints [2][]uint64
var allSymbols []*Symbol
var allRanges []pcRange
var allUnits []*CompileUnit
preciseCoverage := true
type binResult struct {
symbols []*Symbol
coverPoints [2][]uint64
ranges []pcRange
units []*CompileUnit
err error
}
binC := make(chan binResult, len(modules))
for _, module := range modules {
go func() {
info := &symbolInfo{
tracePC: make(map[uint64]bool),
traceCmp: make(map[uint64]bool),
tracePCIdx: make(map[int]bool),
traceCmpIdx: make(map[int]bool),
}
result, err := processModule(params, module, info, target)
if err != nil {
binC <- binResult{err: err}
return
}
if module.Name == "" && len(result.CoverPoints[0]) == 0 {
err = fmt.Errorf("%v doesn't contain coverage callbacks (set CONFIG_KCOV=y on linux)", module.Path)
binC <- binResult{err: err}
return
}
ranges, units, err := params.readTextRanges(module)
if err != nil {
binC <- binResult{err: err}
return
}
binC <- binResult{symbols: result.Symbols, coverPoints: result.CoverPoints, ranges: ranges, units: units}
}()
if isKcovBrokenInCompiler(params.getCompilerVersion(module.Path)) {
preciseCoverage = false
}
}
for range modules {
result := <-binC
if err := result.err; err != nil {
return nil, err
}
allSymbols = append(allSymbols, result.symbols...)
allCoverPoints[0] = append(allCoverPoints[0], result.coverPoints[0]...)
allCoverPoints[1] = append(allCoverPoints[1], result.coverPoints[1]...)
allRanges = append(allRanges, result.ranges...)
allUnits = append(allUnits, result.units...)
}
log.Logf(1, "discovered %v source files, %v symbols", len(allUnits), len(allSymbols))
// TODO: need better way to remove symbols having the same Start
uniqSymbs := make(map[uint64]*Symbol)
for _, sym := range allSymbols {
if _, ok := uniqSymbs[sym.Start]; !ok {
uniqSymbs[sym.Start] = sym
}
}
allSymbols = []*Symbol{}
for _, sym := range uniqSymbs {
allSymbols = append(allSymbols, sym)
}
sort.Slice(allSymbols, func(i, j int) bool {
return allSymbols[i].Start < allSymbols[j].Start
})
sort.Slice(allRanges, func(i, j int) bool {
return allRanges[i].start < allRanges[j].start
})
for k := range allCoverPoints {
sort.Slice(allCoverPoints[k], func(i, j int) bool {
return allCoverPoints[k][i] < allCoverPoints[k][j]
})
}
allSymbols = buildSymbols(allSymbols, allRanges, allCoverPoints)
nunit := 0
for _, unit := range allUnits {
if len(unit.PCs) == 0 {
continue // drop the unit
}
// TODO: objDir won't work for out-of-tree modules.
unit.Name, unit.Path = CleanPath(unit.Name, kernelDirs, splitBuildDelimiters)
allUnits[nunit] = unit
nunit++
}
allUnits = allUnits[:nunit]
if len(allSymbols) == 0 || len(allUnits) == 0 {
return nil, fmt.Errorf("failed to parse DWARF (set CONFIG_DEBUG_INFO=y on linux)")
}
var interner symbolizer.Interner
impl := &Impl{
Units: allUnits,
Symbols: allSymbols,
Symbolize: func(pcs map[*vminfo.KernelModule][]uint64) ([]*Frame, error) {
return symbolize(target, &interner, kernelDirs, splitBuildDelimiters, pcs)
},
CallbackPoints: allCoverPoints[0],
PreciseCoverage: preciseCoverage,
}
return impl, nil
}
func buildSymbols(symbols []*Symbol, ranges []pcRange, coverPoints [2][]uint64) []*Symbol {
// Assign coverage point PCs to symbols.
// Both symbols and coverage points are sorted, so we do it one pass over both.
selectPCs := func(u *ObjectUnit, typ int) *[]uint64 {
return [2]*[]uint64{&u.PCs, &u.CMPs}[typ]
}
for pcType := range coverPoints {
pcs := coverPoints[pcType]
var curSymbol *Symbol
firstSymbolPC, symbolIdx := -1, 0
for i := 0; i < len(pcs); i++ {
pc := pcs[i]
for ; symbolIdx < len(symbols) && pc >= symbols[symbolIdx].End; symbolIdx++ {
}
var symb *Symbol
if symbolIdx < len(symbols) && pc >= symbols[symbolIdx].Start && pc < symbols[symbolIdx].End {
symb = symbols[symbolIdx]
}
if curSymbol != nil && curSymbol != symb {
*selectPCs(&curSymbol.ObjectUnit, pcType) = pcs[firstSymbolPC:i]
firstSymbolPC = -1
}
curSymbol = symb
if symb != nil && firstSymbolPC == -1 {
firstSymbolPC = i
}
}
if curSymbol != nil {
*selectPCs(&curSymbol.ObjectUnit, pcType) = pcs[firstSymbolPC:]
}
}
// Assign compile units to symbols based on unit pc ranges.
// Do it one pass as both are sorted.
nsymbol := 0
rangeIndex := 0
for _, s := range symbols {
for ; rangeIndex < len(ranges) && ranges[rangeIndex].end <= s.Start; rangeIndex++ {
}
if rangeIndex == len(ranges) || s.Start < ranges[rangeIndex].start || len(s.PCs) == 0 {
continue // drop the symbol
}
unit := ranges[rangeIndex].unit
s.Unit = unit
symbols[nsymbol] = s
nsymbol++
}
symbols = symbols[:nsymbol]
for pcType := range coverPoints {
for _, s := range symbols {
symbPCs := selectPCs(&s.ObjectUnit, pcType)
unitPCs := selectPCs(&s.Unit.ObjectUnit, pcType)
pos := len(*unitPCs)
*unitPCs = append(*unitPCs, *symbPCs...)
*symbPCs = (*unitPCs)[pos:]
}
}
return symbols
}
// Regexps to parse compiler version string in isKcovBrokenInCompiler.
// Some targets (e.g. NetBSD) use g++ instead of gcc.
var gccRE = regexp.MustCompile(`gcc|GCC|g\+\+`)
var gccVersionRE = regexp.MustCompile(`(gcc|GCC|g\+\+).* ([0-9]{1,2})\.[0-9]+\.[0-9]+`)
// GCC < 14 incorrectly tail-calls kcov callbacks, which does not let syzkaller
// verify that collected coverage points have matching callbacks.
// See https://github.com/google/syzkaller/issues/4447 for more information.
func isKcovBrokenInCompiler(versionStr string) bool {
if !gccRE.MatchString(versionStr) {
return false
}
groups := gccVersionRE.FindStringSubmatch(versionStr)
if len(groups) > 0 {
version, err := strconv.Atoi(groups[2])
if err == nil {
return version < 14
}
}
return true
}
type symbolInfo struct {
textAddr uint64
// Set of addresses that correspond to __sanitizer_cov_trace_pc or its trampolines.
tracePC map[uint64]bool
traceCmp map[uint64]bool
tracePCIdx map[int]bool
traceCmpIdx map[int]bool
}
type pcRange struct {
// [start; end)
start uint64
end uint64
unit *CompileUnit
}
type pcFixFn = (func([2]uint64) ([2]uint64, bool))
func readTextRanges(debugInfo *dwarf.Data, module *vminfo.KernelModule, pcFix pcFixFn) (
[]pcRange, []*CompileUnit, error) {
var ranges []pcRange
unitMap := map[string]*CompileUnit{}
addRange := func(r [2]uint64, fileName string) {
if pcFix != nil {
var filtered bool
r, filtered = pcFix(r)
if filtered {
return
}
}
unit, ok := unitMap[fileName]
if !ok {
unit = &CompileUnit{
ObjectUnit: ObjectUnit{
Name: fileName,
},
Module: module,
}
unitMap[fileName] = unit
}
if module.Name == "" {
ranges = append(ranges, pcRange{r[0], r[1], unit})
} else {
ranges = append(ranges, pcRange{r[0] + module.Addr, r[1] + module.Addr, unit})
}
}
for r := debugInfo.Reader(); ; {
ent, err := r.Next()
if err != nil {
return nil, nil, err
}
if ent == nil {
break
}
if ent.Tag != dwarf.TagCompileUnit {
return nil, nil, fmt.Errorf("found unexpected tag %v on top level", ent.Tag)
}
attrName, ok := ent.Val(dwarf.AttrName).(string)
if !ok {
continue
}
attrCompDir, _ := ent.Val(dwarf.AttrCompDir).(string)
const languageRust = 28
if language, ok := ent.Val(dwarf.AttrLanguage).(int64); ok && language == languageRust {
rawRanges, err := rustRanges(debugInfo, ent)
if err != nil {
return nil, nil, fmt.Errorf("failed to query Rust PC ranges: %w", err)
}
for _, r := range rawRanges {
addRange([2]uint64{r.start, r.end}, r.file)
}
} else {
// Compile unit names are relative to the compilation dir,
// while per-line info isn't.
// attrName could be an absolute path for out-of-tree modules.
unitName := attrName
if !filepath.IsAbs(attrName) {
unitName = filepath.Join(attrCompDir, attrName)
}
ranges1, err := debugInfo.Ranges(ent)
if err != nil {
return nil, nil, err
}
for _, r := range ranges1 {
addRange(r, unitName)
}
}
r.SkipChildren()
}
var units []*CompileUnit
for _, unit := range unitMap {
units = append(units, unit)
}
return ranges, units, nil
}
type rustRange struct {
// [start; end)
start uint64
end uint64
file string
}
func rustRanges(debugInfo *dwarf.Data, ent *dwarf.Entry) ([]rustRange, error) {
// For Rust, a single compilation unit may comprise all .rs files that belong to the crate.
// To properly render the coverage, we need to somehow infer the ranges that belong to
// those individual .rs files.
// For simplicity, let's create fake ranges by looking at the DWARF line information.
var ret []rustRange
lr, err := debugInfo.LineReader(ent)
if err != nil {
return nil, fmt.Errorf("failed to query line reader: %w", err)
}
var startPC uint64
var files []string
for {
var entry dwarf.LineEntry
if err = lr.Next(&entry); err != nil {
if err == io.EOF {
break
}
return nil, fmt.Errorf("failed to parse next line entry: %w", err)
}
if startPC == 0 || entry.Address != startPC {
for _, file := range files {
ret = append(ret, rustRange{
start: startPC,
end: entry.Address,
file: file,
})
}
files = files[:0]
startPC = entry.Address
}
// Keep on collecting file names that are covered by the range.
files = append(files, entry.File.Name)
}
if startPC != 0 {
// We don't know the end PC for these, but let's still add them to the ranges.
for _, file := range files {
ret = append(ret, rustRange{
start: startPC,
end: startPC + 1,
file: file,
})
}
}
return ret, nil
}
func symbolizeModule(target *targets.Target, interner *symbolizer.Interner, kernelDirs *mgrconfig.KernelDirs,
splitBuildDelimiters []string, mod *vminfo.KernelModule, pcs []uint64) ([]*Frame, error) {
procs := min(runtime.GOMAXPROCS(0)/2, len(pcs)/1000)
const (
minProcs = 1
maxProcs = 4
)
// addr2line on a beefy vmlinux takes up to 1.6GB of RAM, so don't create too many of them.
procs = min(procs, maxProcs)
procs = max(procs, minProcs)
type symbolizerResult struct {
frames []symbolizer.Frame
err error
}
symbolizerC := make(chan symbolizerResult, procs)
pcchan := make(chan []uint64, procs)
for p := 0; p < procs; p++ {
go func() {
symb := symbolizer.Make(target)
defer symb.Close()
var res symbolizerResult
for pcs := range pcchan {
for i, pc := range pcs {
if mod.Name == "" {
pcs[i] = pc
} else {
pcs[i] = pc - mod.Addr
}
}
frames, err := symb.Symbolize(mod.Path, pcs...)
if err != nil {
res.err = fmt.Errorf("failed to symbolize: %w", err)
}
res.frames = append(res.frames, frames...)
}
symbolizerC <- res
}()
}
for i := 0; i < len(pcs); {
end := min(i+100, len(pcs))
pcchan <- pcs[i:end]
i = end
}
close(pcchan)
var err0 error
var frames []*Frame
for p := 0; p < procs; p++ {
res := <-symbolizerC
if res.err != nil {
err0 = res.err
}
for _, frame := range res.frames {
name, path := CleanPath(frame.File, kernelDirs, splitBuildDelimiters)
pc := frame.PC
if mod.Name != "" {
pc = frame.PC + mod.Addr
}
frames = append(frames, &Frame{
Module: mod,
PC: pc,
Name: interner.Do(name),
FuncName: frame.Func,
Path: interner.Do(path),
Inline: frame.Inline,
Range: Range{
StartLine: frame.Line,
StartCol: 0,
EndLine: frame.Line,
EndCol: LineEnd,
},
})
}
}
if err0 != nil {
return nil, err0
}
return frames, nil
}
func symbolize(target *targets.Target, interner *symbolizer.Interner, kernelDirs *mgrconfig.KernelDirs,
splitBuildDelimiters []string, pcs map[*vminfo.KernelModule][]uint64) ([]*Frame, error) {
var frames []*Frame
type frameResult struct {
frames []*Frame
err error
}
frameC := make(chan frameResult, len(pcs))
for mod, pcs1 := range pcs {
go func(mod *vminfo.KernelModule, pcs []uint64) {
frames, err := symbolizeModule(target, interner, kernelDirs, splitBuildDelimiters, mod, pcs)
frameC <- frameResult{frames: frames, err: err}
}(mod, pcs1)
}
for range pcs {
res := <-frameC
if res.err != nil {
return nil, res.err
}
frames = append(frames, res.frames...)
}
return frames, nil
}
// nextCallTarget finds the next call instruction in data[] starting at *pos and returns that
// instruction's target and pc.
func nextCallTarget(arch *Arch, textAddr uint64, data []byte, pos *int) (uint64, uint64) {
for *pos < len(data) {
i := *pos
if i+arch.callLen > len(data) {
break
}
*pos += arch.scanSize
insn := data[i : i+arch.callLen]
if !arch.isCallInsn(arch, insn) {
continue
}
pc := textAddr + uint64(i)
callTarget := arch.callTarget(arch, insn, pc)
*pos = i + arch.scanSize
return callTarget, pc
}
return 0, 0
}
// readCoverPoints finds all coverage points (calls of __sanitizer_cov_trace_*) in the object file.
// Currently it is [amd64|arm64]-specific: looks for opcode and correct offset.
// Running objdump on the whole object file is too slow.
func readCoverPoints(target *targets.Target, info *symbolInfo, data []byte) ([2][]uint64, error) {
var pcs [2][]uint64
if len(info.tracePC) == 0 {
return pcs, fmt.Errorf("no __sanitizer_cov_trace_pc symbol in the object file")
}
i := 0
arch := arches[target.Arch]
for {
callTarget, pc := nextCallTarget(arch, info.textAddr, data, &i)
if callTarget == 0 {
break
}
if info.tracePC[callTarget] {
pcs[0] = append(pcs[0], pc)
} else if info.traceCmp[callTarget] {
pcs[1] = append(pcs[1], pc)
}
}
return pcs, nil
}
// Source files for Android may be split between two subdirectories: the common AOSP kernel
// and the device-specific drivers: https://source.android.com/docs/setup/build/building-pixel-kernels.
// Android build system references these subdirectories in various ways, which often results in
// paths to non-existent files being recorded in the debug info.
//
// cleanPathAndroid() assumes that the subdirectories reside in `srcDir`, with their names being listed in
// `delimiters`.
// If one of the `delimiters` occurs in the `path`, it is stripped together with the path prefix, and the
// remaining file path is appended to `srcDir + delimiter`.
// If none of the `delimiters` occur in the `path`, `path` is treated as a relative path that needs to be
// looked up in `srcDir + delimiters[i]`.
func cleanPathAndroid(path, srcDir string, delimiters []string, existFn func(string) bool) (string, string) {
if len(delimiters) == 0 {
return "", ""
}
reStr := "(" + strings.Join(delimiters, "|") + ")(.*)"
re := regexp.MustCompile(reStr)
match := re.FindStringSubmatch(path)
if match != nil {
delimiter := match[1]
filename := match[2]
path := filepath.Clean(srcDir + delimiter + filename)
return filename, path
}
// None of the delimiters found in `path`: it is probably a relative path to the source file.
// Try to look it up in every subdirectory of srcDir.
for _, delimiter := range delimiters {
absPath := filepath.Clean(srcDir + delimiter + path)
if existFn(absPath) {
return path, absPath
}
}
return "", ""
}
func CleanPath(path string, kernelDirs *mgrconfig.KernelDirs, splitBuildDelimiters []string) (string, string) {
filename := ""
path = filepath.Clean(path)
aname, apath := cleanPathAndroid(path, kernelDirs.Src, splitBuildDelimiters, osutil.IsExist)
if aname != "" {
return aname, apath
}
absPath := osutil.Abs(path)
switch {
case strings.HasPrefix(absPath, kernelDirs.Obj):
// Assume the file was built there.
path = strings.TrimPrefix(absPath, kernelDirs.Obj)
filename = filepath.Join(kernelDirs.Obj, path)
case strings.HasPrefix(absPath, kernelDirs.BuildSrc):
// Assume the file was moved from buildDir to srcDir.
path = strings.TrimPrefix(absPath, kernelDirs.BuildSrc)
filename = filepath.Join(kernelDirs.Src, path)
default:
// Assume this is relative path.
filename = filepath.Join(kernelDirs.Src, path)
}
return strings.TrimLeft(filepath.Clean(path), "/\\"), filename
}
// objdump is an old, slow way of finding coverage points.
// amd64 uses faster option of parsing binary directly (readCoverPoints).
// TODO: use the faster approach for all other arches and drop this.
func objdump(target *targets.Target, mod *vminfo.KernelModule) ([2][]uint64, error) {
var pcs [2][]uint64
cmd := osutil.Command(target.Objdump, "-d", "--no-show-raw-insn", mod.Path)
stdout, err := cmd.StdoutPipe()
if err != nil {
return pcs, err
}
defer stdout.Close()
stderr, err := cmd.StderrPipe()
if err != nil {
return pcs, err
}
defer stderr.Close()
if err := cmd.Start(); err != nil {
return pcs, fmt.Errorf("failed to run objdump on %v: %w", mod.Path, err)
}
defer func() {
cmd.Process.Kill()
cmd.Wait()
}()
s := bufio.NewScanner(stdout)
callInsns, traceFuncs := archCallInsn(target)
for s.Scan() {
if pc := parseLine(callInsns, traceFuncs, s.Bytes()); pc != 0 {
if mod.Name != "" {
pc = pc + mod.Addr
}
pcs[0] = append(pcs[0], pc)
}
}
stderrOut, _ := io.ReadAll(stderr)
if err := cmd.Wait(); err != nil {
return pcs, fmt.Errorf("failed to run objdump on %v: %w\n%s", mod.Path, err, stderrOut)
}
if err := s.Err(); err != nil {
return pcs, fmt.Errorf("failed to run objdump on %v: %w\n%s", mod.Path, err, stderrOut)
}
return pcs, nil
}
func parseLine(callInsns, traceFuncs [][]byte, ln []byte) uint64 {
pos := -1
for _, callInsn := range callInsns {
if pos = bytes.Index(ln, callInsn); pos != -1 {
break
}
}
if pos == -1 {
return 0
}
hasCall := false
for _, traceFunc := range traceFuncs {
if hasCall = bytes.Contains(ln[pos:], traceFunc); hasCall {
break
}
}
if !hasCall {
return 0
}
for len(ln) != 0 && ln[0] == ' ' {
ln = ln[1:]
}
colon := bytes.IndexByte(ln, ':')
if colon == -1 {
return 0
}
pc, err := strconv.ParseUint(string(ln[:colon]), 16, 64)
if err != nil {
return 0
}
return pc
}
func archCallInsn(target *targets.Target) ([][]byte, [][]byte) {
callName := [][]byte{[]byte(" <__sanitizer_cov_trace_pc>")}
switch target.Arch {
case targets.I386:
// c1000102: call c10001f0 <__sanitizer_cov_trace_pc>
return [][]byte{[]byte("\tcall ")}, callName
case targets.ARM64:
// ffff0000080d9cc0: bl ffff00000820f478 <__sanitizer_cov_trace_pc>
return [][]byte{[]byte("\tbl ")}, [][]byte{
[]byte("<__sanitizer_cov_trace_pc>"),
[]byte("<____sanitizer_cov_trace_pc_veneer>"),
}
case targets.ARM:
// 8010252c: bl 801c3280 <__sanitizer_cov_trace_pc>
return [][]byte{[]byte("\tbl\t")}, callName
case targets.PPC64LE:
// c00000000006d904: bl c000000000350780 <.__sanitizer_cov_trace_pc>
// This is only known to occur in the test:
// 838: bl 824 <__sanitizer_cov_trace_pc+0x8>
// This occurs on PPC64LE:
// c0000000001c21a8: bl c0000000002df4a0 <__sanitizer_cov_trace_pc>
return [][]byte{[]byte("\tbl ")}, [][]byte{
[]byte("<__sanitizer_cov_trace_pc>"),
[]byte("<__sanitizer_cov_trace_pc+0x8>"),
[]byte(" <.__sanitizer_cov_trace_pc>"),
}
case targets.MIPS64LE:
// ffffffff80100420: jal ffffffff80205880 <__sanitizer_cov_trace_pc>
// This is only known to occur in the test:
// b58: bal b30 <__sanitizer_cov_trace_pc>
return [][]byte{[]byte("\tjal\t"), []byte("\tbal\t")}, callName
case targets.S390x:
// 1001de: brasl %r14,2bc090 <__sanitizer_cov_trace_pc>
return [][]byte{[]byte("\tbrasl\t")}, callName
case targets.RiscV64:
// ffffffe000200018: jal ra,ffffffe0002935b0 <__sanitizer_cov_trace_pc>
// ffffffe0000010da: jalr 1242(ra) # ffffffe0002935b0 <__sanitizer_cov_trace_pc>
return [][]byte{[]byte("\tjal\t"), []byte("\tjalr\t")}, callName
default:
panic(fmt.Sprintf("unknown arch %q", target.Arch))
}
}
// Copyright 2020 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package backend
import (
"debug/elf"
"encoding/binary"
"fmt"
"io"
"path/filepath"
"strings"
"github.com/google/syzkaller/pkg/log"
"github.com/google/syzkaller/pkg/mgrconfig"
"github.com/google/syzkaller/pkg/vminfo"
"github.com/google/syzkaller/sys/targets"
)
func makeELF(target *targets.Target, kernelDirs *mgrconfig.KernelDirs, splitBuildDelimiters, moduleObj []string,
hostModules []*vminfo.KernelModule) (*Impl, error) {
return makeDWARF(&dwarfParams{
target: target,
kernelDirs: kernelDirs,
splitBuildDelimiters: splitBuildDelimiters,
moduleObj: moduleObj,
hostModules: hostModules,
readSymbols: elfReadSymbols,
readTextData: elfReadTextData,
readModuleCoverPoints: elfReadModuleCoverPoints,
readTextRanges: elfReadTextRanges,
getCompilerVersion: elfGetCompilerVersion,
})
}
const (
TraceCbNone int = iota
TraceCbPc
TraceCbCmp
)
// Normally, -fsanitize-coverage=trace-pc inserts calls to __sanitizer_cov_trace_pc() at the
// beginning of every basic block. -fsanitize-coverage=trace-cmp adds calls to other functions,
// like __sanitizer_cov_trace_cmp1() or __sanitizer_cov_trace_const_cmp4().
//
// On ARM64 there can be additional symbol names inserted by the linker. By default, BL instruction
// can only target addresses within the +/-128M range from PC. To target farther addresses, the
// ARM64 linker inserts so-called veneers that act as trampolines for functions. We count calls to
// such veneers as normal calls to __sanitizer_cov_trace_XXX.
func getTraceCallbackType(name string) int {
if name == "__sanitizer_cov_trace_pc" || name == "____sanitizer_cov_trace_pc_veneer" {
return TraceCbPc
}
if strings.HasPrefix(name, "__sanitizer_cov_trace_") ||
(strings.HasPrefix(name, "____sanitizer_cov_trace_") && strings.HasSuffix(name, "_veneer")) {
return TraceCbCmp
}
return TraceCbNone
}
func elfReadSymbols(module *vminfo.KernelModule, info *symbolInfo) ([]*Symbol, error) {
file, err := elf.Open(module.Path)
if err != nil {
return nil, err
}
defer file.Close()
text := file.Section(".text")
if text == nil {
return nil, fmt.Errorf("no .text section in the object file")
}
allSymbols, err := file.Symbols()
if err != nil {
return nil, fmt.Errorf("failed to read ELF symbols: %w", err)
}
info.textAddr = text.Addr
var symbols []*Symbol
for i, symb := range allSymbols {
if symb.Info&0xf != uint8(elf.STT_FUNC) && symb.Info&0xf != uint8(elf.STT_NOTYPE) {
// Only save STT_FUNC, STT_NONE otherwise some symb range inside another symb range.
continue
}
text := symb.Value >= text.Addr && symb.Value+symb.Size <= text.Addr+text.Size
if text && symb.Size != 0 {
start := symb.Value
if module.Name != "" {
start += module.Addr
}
symbols = append(symbols, &Symbol{
Module: module,
ObjectUnit: ObjectUnit{
Name: symb.Name,
},
Start: start,
End: start + symb.Size,
})
}
switch getTraceCallbackType(symb.Name) {
case TraceCbPc:
info.tracePCIdx[i] = true
if text {
info.tracePC[symb.Value] = true
}
case TraceCbCmp:
info.traceCmpIdx[i] = true
if text {
info.traceCmp[symb.Value] = true
}
}
}
return symbols, nil
}
func elfReadTextRanges(module *vminfo.KernelModule) ([]pcRange, []*CompileUnit, error) {
file, err := elf.Open(module.Path)
if err != nil {
return nil, nil, err
}
defer file.Close()
text := file.Section(".text")
if text == nil {
return nil, nil, fmt.Errorf("no .text section in the object file")
}
kaslr := file.Section(".rela.text") != nil
debugInfo, err := file.DWARF()
if err != nil {
if module.Name != "" {
log.Logf(0, "ignoring module %v without DEBUG_INFO", module.Name)
return nil, nil, nil
}
return nil, nil, fmt.Errorf("failed to parse DWARF: %w (set CONFIG_DEBUG_INFO=y on linux)", err)
}
var pcFix pcFixFn
if kaslr {
pcFix = func(r [2]uint64) ([2]uint64, bool) {
if r[0] >= r[1] || r[0] < text.Addr || r[1] > text.Addr+text.Size {
// Linux kernel binaries with CONFIG_RANDOMIZE_BASE=y are strange.
// .text starts at 0xffffffff81000000 and symbols point there as
// well, but PC ranges point to addresses around 0.
// So try to add text offset and retry the check.
// It's unclear if we also need some offset on top of text.Addr,
// it gives approximately correct addresses, but not necessary
// precisely correct addresses.
r[0] += text.Addr
r[1] += text.Addr
if r[0] >= r[1] || r[0] < text.Addr || r[1] > text.Addr+text.Size {
return r, true
}
}
return r, false
}
}
return readTextRanges(debugInfo, module, pcFix)
}
func elfReadTextData(module *vminfo.KernelModule) ([]byte, error) {
file, err := elf.Open(module.Path)
if err != nil {
return nil, err
}
defer file.Close()
text := file.Section(".text")
if text == nil {
return nil, fmt.Errorf("no .text section in the object file")
}
return text.Data()
}
func elfReadModuleCoverPoints(target *targets.Target, module *vminfo.KernelModule, info *symbolInfo) ([2][]uint64,
error) {
var pcs [2][]uint64
file, err := elf.Open(module.Path)
if err != nil {
return pcs, err
}
defer file.Close()
callRelocType := arches[target.Arch].callRelocType
relaOffset := arches[target.Arch].relaOffset
for _, s := range file.Sections {
if s.Type != elf.SHT_RELA { // nolint: misspell
continue
}
rel := new(elf.Rela64)
for r := s.Open(); ; {
if err := binary.Read(r, binary.LittleEndian, rel); err != nil {
if err == io.EOF {
break
}
return pcs, err
}
if (rel.Info & 0xffffffff) != callRelocType {
continue
}
pc := module.Addr + rel.Off - relaOffset
index := int(elf.R_SYM64(rel.Info)) - 1
if info.tracePCIdx[index] {
pcs[0] = append(pcs[0], pc)
} else if info.traceCmpIdx[index] {
pcs[1] = append(pcs[1], pc)
}
}
}
return pcs, nil
}
func elfGetCompilerVersion(path string) string {
file, err := elf.Open(path)
if err != nil {
return ""
}
defer file.Close()
sec := file.Section(".comment")
if sec == nil {
return ""
}
data, err := sec.Data()
if err != nil {
return ""
}
return string(data[:])
}
func elfReadTextSecRange(module *vminfo.KernelModule) (*SecRange, error) {
text, err := elfReadTextSec(module)
if err != nil {
return nil, err
}
r := &SecRange{
Start: text.Addr,
End: text.Addr + text.Size,
}
return r, nil
}
func elfReadTextSec(module *vminfo.KernelModule) (*elf.Section, error) {
file, err := elf.Open(module.Path)
if err != nil {
return nil, err
}
defer file.Close()
text := file.Section(".text")
if text == nil {
return nil, fmt.Errorf("no .text section in the object file")
}
return text, nil
}
func getLinuxPCBase(cfg *mgrconfig.Config) (uint64, error) {
bin := filepath.Join(cfg.KernelObj, cfg.SysTarget.KernelObject)
file, err := elf.Open(bin)
if err != nil {
return 0, err
}
defer file.Close()
allSymbols, err := file.Symbols()
if err != nil {
return 0, err
}
for _, sym := range allSymbols {
if sym.Name == "_stext" {
return sym.Value, nil
}
}
return 0, fmt.Errorf("no _stext symbol")
}
// Copyright 2020 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package backend
import (
"bufio"
"fmt"
"path/filepath"
"regexp"
"strconv"
"github.com/google/syzkaller/pkg/mgrconfig"
"github.com/google/syzkaller/pkg/osutil"
"github.com/google/syzkaller/pkg/vminfo"
"github.com/google/syzkaller/sys/targets"
)
func makeGvisor(target *targets.Target, kernelDirs *mgrconfig.KernelDirs, modules []*vminfo.KernelModule) (*Impl,
error) {
if len(modules) != 0 {
return nil, fmt.Errorf("gvisor coverage does not support modules")
}
bin := filepath.Join(kernelDirs.Obj, target.KernelObject)
// pkg/build stores runsc as 'vmlinux' (we pretent to be linux), but a local build will have it as 'runsc'.
if !osutil.IsExist(bin) {
bin = filepath.Join(filepath.Dir(bin), "runsc")
}
frames, err := gvisorSymbolize(bin, kernelDirs.Src)
if err != nil {
return nil, err
}
unitMap := make(map[string]*CompileUnit)
for _, frame := range frames {
unit := unitMap[frame.Name]
if unit == nil {
unit = &CompileUnit{
ObjectUnit: ObjectUnit{
Name: frame.Name,
},
Path: frame.Path,
}
unitMap[frame.Name] = unit
}
unit.PCs = append(unit.PCs, frame.PC)
}
var units []*CompileUnit
for _, unit := range unitMap {
units = append(units, unit)
}
impl := &Impl{
Units: units,
Frames: frames,
}
return impl, nil
}
func gvisorSymbolize(bin, srcDir string) ([]*Frame, error) {
cmd := osutil.Command(bin, "symbolize", "-all")
stdout, err := cmd.StdoutPipe()
if err != nil {
return nil, err
}
defer stdout.Close()
if err := cmd.Start(); err != nil {
return nil, err
}
defer cmd.Wait()
defer cmd.Process.Kill()
var frames []*Frame
s := bufio.NewScanner(stdout)
for s.Scan() {
frame, err := gvisorParseLine(s)
if err != nil {
return nil, err
}
frame.Path = filepath.Join(srcDir, frame.Name)
if !osutil.IsExist(frame.Path) {
// Try to locate auto-generated files.
// Note: some files are only present under some hashed path,
// e.g. bazel-out/k8-fastbuild-ST-4c64f0b3d5c7/bin/pkg/usermem/addr_range.go,
// it's unclear how we can locate them. In a local run that may be under objDir,
// but this is not the case for syz-ci.
path := filepath.Join(srcDir, "bazel-out", "k8-fastbuild", "bin", frame.Name)
if osutil.IsExist(path) {
frame.Path = path
}
}
frames = append(frames, frame)
}
if err := s.Err(); err != nil {
return nil, err
}
return frames, nil
}
func gvisorParseLine(s *bufio.Scanner) (*Frame, error) {
pc, err := strconv.ParseUint(s.Text(), 0, 64)
if err != nil {
return nil, fmt.Errorf("read pc %q, but no line info", pc)
}
if !s.Scan() {
return nil, fmt.Errorf("read pc %q, but no line info", pc)
}
match := gvisorLineRe.FindStringSubmatch(s.Text())
if match == nil {
return nil, fmt.Errorf("failed to parse line: %q", s.Text())
}
var ints [4]int
for i := range ints {
x, err := strconv.ParseUint(match[i+3], 0, 32)
if err != nil {
return nil, fmt.Errorf("failed to parse number %q: %w", match[i+3], err)
}
ints[i] = int(x)
}
frame := &Frame{
PC: pc,
Name: match[2],
Range: Range{
StartLine: ints[0],
StartCol: ints[1],
EndLine: ints[2],
EndCol: ints[3],
},
}
return frame, nil
}
var gvisorLineRe = regexp.MustCompile(`^(.*/)?(pkg/[^:]+):([0-9]+).([0-9]+),([0-9]+).([0-9]+)$`)
// Copyright 2020 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package backend
import (
"debug/macho"
"fmt"
"path/filepath"
"sort"
"strings"
"github.com/google/syzkaller/pkg/mgrconfig"
"github.com/google/syzkaller/pkg/vminfo"
"github.com/google/syzkaller/sys/targets"
)
func makeMachO(target *targets.Target, kernelDirs *mgrconfig.KernelDirs,
moduleObj []string, hostModules []*vminfo.KernelModule) (*Impl, error) {
return makeDWARF(&dwarfParams{
target: target,
kernelDirs: kernelDirs,
moduleObj: moduleObj,
hostModules: hostModules,
readSymbols: machoReadSymbols,
readTextData: machoReadTextData,
readModuleCoverPoints: machoReadModuleCoverPoints,
readTextRanges: machoReadTextRanges,
})
}
func machoReadSymbols(module *vminfo.KernelModule, info *symbolInfo) ([]*Symbol, error) {
file, err := macho.Open(module.Path)
if err != nil {
return nil, err
}
text := file.Section("__text")
if text == nil {
return nil, fmt.Errorf("no __text section in the object file")
}
if file.Symtab == nil {
return nil, fmt.Errorf("failed to read Mach-O symbols")
}
info.textAddr = text.Addr
// We don't get symbol lengths or symbol ends in Mach-O symbols. So we
// guesstimate them by taking the next symbols beginning -1. That only
// works after we have sorted them.
sort.Slice(file.Symtab.Syms, func(i, j int) bool {
return file.Symtab.Syms[i].Value < file.Symtab.Syms[j].Value
})
var symbols []*Symbol
for i, symb := range file.Symtab.Syms {
// Mach-Os doesn't contain the Symbol size like in ELF
symbEnd := text.Addr + text.Size
if i < len(file.Symtab.Syms)-1 {
symbEnd = file.Symtab.Syms[i+1].Value
}
text := symb.Value >= text.Addr && symbEnd <= text.Addr+text.Size
if text {
symbStart := symb.Value + module.Addr
symbols = append(symbols, &Symbol{
Module: module,
ObjectUnit: ObjectUnit{
Name: symb.Name,
},
Start: symbStart,
End: symbEnd,
})
}
if strings.HasPrefix(symb.Name, "___sanitizer_cov_trace_") {
if symb.Name == "___sanitizer_cov_trace_pc_guard" {
info.tracePCIdx[i] = true
if text {
info.tracePC[symb.Value] = true
}
} else {
info.traceCmpIdx[i] = true
if text {
info.traceCmp[symb.Value] = true
}
}
}
}
return symbols, nil
}
func machoReadTextRanges(module *vminfo.KernelModule) ([]pcRange, []*CompileUnit, error) {
dir, kernel := filepath.Split(module.Path)
dSYMPath := filepath.Join(dir, fmt.Sprintf(
"%[1]s.dSYM/Contents/Resources/DWARF/%[1]s", kernel))
dSYM, err := macho.Open(dSYMPath)
if err != nil {
return nil, nil, err
}
debugInfo, err := dSYM.DWARF()
if err != nil {
return nil, nil, fmt.Errorf("failed to parse DWARF: %w", err)
}
return readTextRanges(debugInfo, module, nil)
}
func machoReadTextData(module *vminfo.KernelModule) ([]byte, error) {
file, err := macho.Open(module.Path)
if err != nil {
return nil, err
}
text := file.Section("__text")
if text == nil {
return nil, fmt.Errorf("no __text section in the object file")
}
return text.Data()
}
func machoReadModuleCoverPoints(target *targets.Target, module *vminfo.KernelModule, info *symbolInfo) ([2][]uint64,
error) {
// TODO: Linux/ELF supports module symbols. We should probably also do that
// for XNU/Mach-O. To maximize code re-use we already have a lot of the
// plumbing for module support. I think we mainly miss an equivalent to
// discoverModules and this function at the moment.
return [2][]uint64{}, fmt.Errorf("machoReadModuleCoverPoints not implemented")
}
// Copyright 2021 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package backend
import (
"bytes"
"debug/elf"
"fmt"
"io/fs"
"path/filepath"
"strings"
"github.com/google/syzkaller/pkg/log"
"github.com/google/syzkaller/pkg/vminfo"
"github.com/google/syzkaller/sys/targets"
)
func DiscoverModules(target *targets.Target, objDir string, moduleObj []string) (
[]*vminfo.KernelModule, error) {
module := &vminfo.KernelModule{
Path: filepath.Join(objDir, target.KernelObject),
}
textRange, err := elfReadTextSecRange(module)
if err != nil {
return nil, err
}
modules := []*vminfo.KernelModule{
// A dummy module representing the kernel itself.
{
Path: module.Path,
Size: textRange.End - textRange.Start,
},
}
if target.OS == targets.Linux {
modules1, err := discoverModulesLinux(append([]string{objDir}, moduleObj...))
if err != nil {
return nil, err
}
modules = append(modules, modules1...)
} else if len(modules) != 1 {
return nil, fmt.Errorf("%v coverage does not support modules", target.OS)
}
return modules, nil
}
func discoverModulesLinux(dirs []string) ([]*vminfo.KernelModule, error) {
paths, err := locateModules(dirs)
if err != nil {
return nil, err
}
var modules []*vminfo.KernelModule
for name, path := range paths {
if path == "" {
continue
}
log.Logf(2, "module %v -> %v", name, path)
module := &vminfo.KernelModule{
Name: name,
Path: path,
}
textRange, err := elfReadTextSecRange(module)
if err != nil {
return nil, err
}
module.Size = textRange.End - textRange.Start
modules = append(modules, module)
}
return modules, nil
}
func locateModules(dirs []string) (map[string]string, error) {
paths := make(map[string]string)
for _, dir := range dirs {
err := filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error {
if err != nil || filepath.Ext(path) != ".ko" {
return err
}
name, err := getModuleName(path)
if err != nil {
// Extracting module name involves parsing ELF and binary data,
// let's not fail on it, we still have the file name,
// which is usually the right module name.
log.Logf(0, "failed to get %v module name: %v", path, err)
name = strings.TrimSuffix(filepath.Base(path), "."+filepath.Ext(path))
}
// Order of dirs determine priority, so don't overwrite already discovered names.
if name != "" && paths[name] == "" {
paths[name] = path
}
return nil
})
if err != nil {
return nil, err
}
}
return paths, nil
}
func getModuleName(path string) (string, error) {
file, err := elf.Open(path)
if err != nil {
return "", err
}
defer file.Close()
section := file.Section(".modinfo")
if section == nil {
return "", fmt.Errorf("no .modinfo section")
}
data, err := section.Data()
if err != nil {
return "", fmt.Errorf("failed to read .modinfo: %w", err)
}
if name := searchModuleName(data); name != "" {
return name, nil
}
section = file.Section(".gnu.linkonce.this_module")
if section == nil {
return "", fmt.Errorf("no .gnu.linkonce.this_module section")
}
data, err = section.Data()
if err != nil {
return "", fmt.Errorf("failed to read .gnu.linkonce.this_module: %w", err)
}
return string(data), nil
}
func searchModuleName(data []byte) string {
data = append([]byte{0}, data...)
key := []byte("\x00name=")
pos := bytes.Index(data, key)
if pos == -1 {
return ""
}
end := bytes.IndexByte(data[pos+len(key):], 0)
if end == -1 {
return ""
}
end = pos + len(key) + end
if end > len(data) {
return ""
}
return string(data[pos+len(key) : end])
}
func getKaslrOffset(modules []*vminfo.KernelModule, pcBase uint64) uint64 {
for _, mod := range modules {
if mod.Name == "" {
return mod.Addr - pcBase
}
}
return 0
}
// when CONFIG_RANDOMIZE_BASE=y, pc from kcov already removed kaslr_offset.
func FixModules(localModules, modules []*vminfo.KernelModule, pcBase uint64) []*vminfo.KernelModule {
kaslrOffset := getKaslrOffset(modules, pcBase)
var modules1 []*vminfo.KernelModule
for _, mod := range modules {
size := uint64(0)
path := ""
for _, modA := range localModules {
if modA.Name == mod.Name {
size = modA.Size
path = modA.Path
break
}
}
if path == "" {
continue
}
addr := mod.Addr - kaslrOffset
modules1 = append(modules1, &vminfo.KernelModule{
Name: mod.Name,
Size: size,
Addr: addr,
Path: path,
})
}
return modules1
}
// Copyright 2020 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package backend
import (
"fmt"
"github.com/google/syzkaller/sys/targets"
)
func PreviousInstructionPC(target *targets.Target, vm string, pc uint64) uint64 {
if vm == targets.GVisor {
// gVisor coverage returns real PCs that don't need adjustment.
return pc
}
offset := instructionLen(target.Arch)
pc -= offset
// THUMB instructions are 2 or 4 bytes with low bit set.
// ARM instructions are always 4 bytes.
if target.Arch == targets.ARM {
return pc & ^uint64(1)
}
return pc
}
func NextInstructionPC(target *targets.Target, vm string, pc uint64) uint64 {
if vm == targets.GVisor {
return pc
}
offset := instructionLen(target.Arch)
pc += offset
// THUMB instructions are 2 or 4 bytes with low bit set.
// ARM instructions are always 4 bytes.
if target.Arch == targets.ARM {
return pc & ^uint64(1)
}
return pc
}
func instructionLen(arch string) uint64 {
switch arch {
case targets.AMD64:
return 5
case targets.I386:
return 5
case targets.ARM64:
return 4
case targets.ARM:
return 3
case targets.PPC64LE:
return 4
case targets.MIPS64LE:
return 8
case targets.S390x:
return 6
case targets.RiscV64:
return 4
case targets.TestArch64:
return 0
default:
panic(fmt.Sprintf("unknown arch %q", arch))
}
}
// Copyright 2020 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package debugtracer
import (
"fmt"
"io"
"path/filepath"
"testing"
"time"
"github.com/google/syzkaller/pkg/osutil"
)
type DebugTracer interface {
Log(msg string, args ...interface{})
SaveFile(filename string, data []byte)
}
type GenericTracer struct {
WithTime bool
TraceWriter io.Writer
OutDir string
}
type TestTracer struct {
T *testing.T
}
type NullTracer struct {
}
func (gt *GenericTracer) Log(msg string, args ...interface{}) {
if gt.WithTime {
timeStr := time.Now().Format("02-Jan-2006 15:04:05")
newArgs := append([]interface{}{timeStr}, args...)
fmt.Fprintf(gt.TraceWriter, "%s: "+msg+"\n", newArgs...)
} else {
fmt.Fprintf(gt.TraceWriter, msg+"\n", args...)
}
}
func (gt *GenericTracer) SaveFile(filename string, data []byte) {
if gt.OutDir == "" {
return
}
osutil.MkdirAll(gt.OutDir)
osutil.WriteFile(filepath.Join(gt.OutDir, filename), data)
}
func (tt *TestTracer) Log(msg string, args ...interface{}) {
tt.T.Log(msg, args)
}
func (tt *TestTracer) SaveFile(filename string, data []byte) {
// Not implemented.
}
func (nt *NullTracer) Log(msg string, args ...interface{}) {
// Not implemented.
}
func (nt *NullTracer) SaveFile(filename string, data []byte) {
// Not implemented.
}
// Copyright 2024 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package flatrpc
import (
"context"
"errors"
"fmt"
"io"
"net"
"reflect"
"slices"
"sync"
"unsafe"
flatbuffers "github.com/google/flatbuffers/go"
"github.com/google/syzkaller/pkg/log"
"github.com/google/syzkaller/pkg/stat"
"golang.org/x/sync/errgroup"
)
var (
statSent = stat.New("rpc sent", "Outbound RPC traffic",
stat.Graph("traffic"), stat.Rate{}, stat.FormatMB)
statRecv = stat.New("rpc recv", "Inbound RPC traffic",
stat.Graph("traffic"), stat.Rate{}, stat.FormatMB)
)
type Serv struct {
Addr *net.TCPAddr
ln net.Listener
}
func Listen(addr string) (*Serv, error) {
ln, err := net.Listen("tcp", addr)
if err != nil {
return nil, err
}
return &Serv{
Addr: ln.Addr().(*net.TCPAddr),
ln: ln,
}, nil
}
// Serve accepts incoming connections and calls handler for each of them.
// An error returned from the handler stops the server and aborts the whole processing.
func (s *Serv) Serve(baseCtx context.Context, handler func(context.Context, *Conn) error) error {
eg, ctx := errgroup.WithContext(baseCtx)
go func() {
// If the context is cancelled, stop the server.
<-ctx.Done()
s.Close()
}()
for {
conn, err := s.ln.Accept()
if err != nil && errors.Is(err, net.ErrClosed) {
break
}
if err != nil {
var netErr *net.OpError
if errors.As(err, &netErr) && !netErr.Temporary() {
return fmt.Errorf("flatrpc: failed to accept: %w", err)
}
log.Logf(0, "flatrpc: failed to accept: %v", err)
continue
}
eg.Go(func() error {
connCtx, cancel := context.WithCancel(ctx)
defer cancel()
c := NewConn(conn)
// Closing the server does not automatically close all the connections.
go func() {
<-connCtx.Done()
c.Close()
}()
return handler(connCtx, c)
})
}
return eg.Wait()
}
func (s *Serv) Close() error {
return s.ln.Close()
}
type Conn struct {
conn net.Conn
sendMu sync.Mutex
builder *flatbuffers.Builder
data []byte
hasData int
lastMsg int
}
func NewConn(conn net.Conn) *Conn {
return &Conn{
conn: conn,
builder: flatbuffers.NewBuilder(0),
}
}
func (c *Conn) Close() error {
return c.conn.Close()
}
type sendMsg interface {
Pack(*flatbuffers.Builder) flatbuffers.UOffsetT
}
// Send sends an RPC message.
// The type T is supposed to be an "object API" type ending with T (e.g. ConnectRequestT).
// Sending can be done from multiple goroutines concurrently.
func Send[T sendMsg](c *Conn, msg T) error {
c.sendMu.Lock()
defer c.sendMu.Unlock()
off := msg.Pack(c.builder)
c.builder.FinishSizePrefixed(off)
data := c.builder.FinishedBytes()
_, err := c.conn.Write(data)
c.builder.Reset()
statSent.Add(len(data))
if err != nil {
return fmt.Errorf("failed to send %T: %w", msg, err)
}
return nil
}
type RecvType[T any] interface {
UnPack() *T
flatbuffers.FlatBuffer
}
// Recv receives an RPC message.
// The type T is supposed to be a pointer to a normal flatbuffers type (not ending with T, e.g. *ConnectRequestRaw).
// Receiving should be done from a single goroutine, the received message is valid
// only until the next Recv call (messages share the same underlying receive buffer).
func Recv[Raw RecvType[T], T any](c *Conn) (res *T, err0 error) {
// First, discard the previous message.
// For simplicity we copy any data from the next message to the beginning of the buffer.
// Theoretically we could something more efficient, e.g. don't copy if we already
// have a full next message.
if c.hasData > c.lastMsg {
copy(c.data, c.data[c.lastMsg:c.hasData])
}
c.hasData -= c.lastMsg
c.lastMsg = 0
const (
sizePrefixSize = flatbuffers.SizeUint32
maxMessageSize = 64 << 20
)
// Then, receive at least the size prefix (4 bytes).
// And then the full message, if we have not got it yet.
if err := c.recv(sizePrefixSize); err != nil {
return nil, fmt.Errorf("failed to recv %T: %w", (*T)(nil), err)
}
size := int(flatbuffers.GetSizePrefix(c.data, 0))
if size > maxMessageSize {
return nil, fmt.Errorf("message %T has too large size %v", (*T)(nil), size)
}
c.lastMsg = sizePrefixSize + size
if err := c.recv(c.lastMsg); err != nil {
return nil, fmt.Errorf("failed to recv %T: %w", (*T)(nil), err)
}
return Parse[Raw](c.data[sizePrefixSize:c.lastMsg])
}
// recv ensures that we have at least 'size' bytes received in c.data.
func (c *Conn) recv(size int) error {
need := size - c.hasData
if need <= 0 {
return nil
}
if grow := size - len(c.data) + c.hasData; grow > 0 {
c.data = slices.Grow(c.data, grow)[:len(c.data)+grow]
}
n, err := io.ReadAtLeast(c.conn, c.data[c.hasData:], need)
if err != nil {
return err
}
c.hasData += n
return nil
}
func Parse[Raw RecvType[T], T any](data []byte) (res *T, err0 error) {
defer func() {
if err := recover(); err != nil {
err0 = fmt.Errorf("%v", err)
}
}()
statRecv.Add(len(data))
// This probably can be expressed w/o reflect as "new U" where U is *T,
// but I failed to express that as generic constraints.
var msg Raw
msg = reflect.New(reflect.TypeOf(msg).Elem()).Interface().(Raw)
msg.Init(data, flatbuffers.GetUOffsetT(data))
if err := verify(msg, len(data)); err != nil {
return nil, err
}
return msg.UnPack(), nil
}
func verify(raw any, rawSize int) error {
switch msg := raw.(type) {
case *ExecutorMessageRaw:
return verifyExecutorMessage(msg, rawSize)
}
return nil
}
func verifyExecutorMessage(raw *ExecutorMessageRaw, rawSize int) error {
// We receive the message into raw (non object API) type and carefully verify
// because the message from the test machine can be corrupted in all possible ways.
// Recovering from panics handles most corruptions (since flatbuffers does not use unsafe
// and panics on any OOB references). But it's still possible that UnPack may try to allocate
// unbounded amount of memory and crash with OOM. To prevent that we check that arrays have
// reasonable size. We don't need to check []byte/string b/c for them flatbuffers use
// Table.ByteVector which directly references the underlying byte slice and also panics
// if size is OOB. But we need to check all other arrays b/c for them flatbuffers will
// first do make([]T, size), filling that array later will panic, but it's already too late
// since the make will kill the process with OOM.
switch typ := raw.MsgType(); typ {
case ExecutorMessagesRawExecResult,
ExecutorMessagesRawExecuting,
ExecutorMessagesRawState:
default:
return fmt.Errorf("bad executor message type %v", typ)
}
var tab flatbuffers.Table
if !raw.Msg(&tab) {
return errors.New("received no message")
}
// Only ExecResult has arrays.
if raw.MsgType() == ExecutorMessagesRawExecResult {
var res ExecResultRaw
res.Init(tab.Bytes, tab.Pos)
return verifyExecResult(&res, rawSize)
}
return nil
}
func verifyExecResult(res *ExecResultRaw, rawSize int) error {
info := res.Info(nil)
if info == nil {
return nil
}
var tmp ComparisonRaw
// It's hard to impose good limit on each individual signal/cover/comps array,
// so instead we count total memory size for all calls and check that it's not
// larger than the total message size.
callSize := func(call *CallInfoRaw) int {
// Cap array size at 1G to prevent overflows during multiplication by size and addition.
const maxSize = 1 << 30
size := 0
if call.SignalLength() != 0 {
size += min(maxSize, call.SignalLength()) * int(unsafe.Sizeof(call.Signal(0)))
}
if call.CoverLength() != 0 {
size += min(maxSize, call.CoverLength()) * int(unsafe.Sizeof(call.Cover(0)))
}
if call.CompsLength() != 0 {
size += min(maxSize, call.CompsLength()) * int(unsafe.Sizeof(call.Comps(&tmp, 0)))
}
return size
}
size := 0
var call CallInfoRaw
for i := 0; i < info.CallsLength(); i++ {
if info.Calls(&call, i) {
size += callSize(&call)
}
}
for i := 0; i < info.ExtraRawLength(); i++ {
if info.ExtraRaw(&call, i) {
size += callSize(&call)
}
}
if info.Extra(&call) != nil {
size += callSize(&call)
}
if size > rawSize {
return fmt.Errorf("corrupted message: total size %v, size of elements %v",
rawSize, size)
}
return nil
}
// Code generated by the FlatBuffers compiler. DO NOT EDIT.
package flatrpc
import (
"strconv"
flatbuffers "github.com/google/flatbuffers/go"
)
type Const uint64
const (
ConstSnapshotDoorbellSize Const = 4096
ConstMaxInputSize Const = 4198400
ConstMaxOutputSize Const = 14680064
ConstSnapshotShmemSize Const = 33554432
)
var EnumNamesConst = map[Const]string{
ConstSnapshotDoorbellSize: "SnapshotDoorbellSize",
ConstMaxInputSize: "MaxInputSize",
ConstMaxOutputSize: "MaxOutputSize",
ConstSnapshotShmemSize: "SnapshotShmemSize",
}
var EnumValuesConst = map[string]Const{
"SnapshotDoorbellSize": ConstSnapshotDoorbellSize,
"MaxInputSize": ConstMaxInputSize,
"MaxOutputSize": ConstMaxOutputSize,
"SnapshotShmemSize": ConstSnapshotShmemSize,
}
func (v Const) String() string {
if s, ok := EnumNamesConst[v]; ok {
return s
}
return "Const(" + strconv.FormatInt(int64(v), 10) + ")"
}
type Feature uint64
const (
FeatureCoverage Feature = 1
FeatureComparisons Feature = 2
FeatureExtraCoverage Feature = 4
FeatureDelayKcovMmap Feature = 8
FeatureSandboxNone Feature = 16
FeatureSandboxSetuid Feature = 32
FeatureSandboxNamespace Feature = 64
FeatureSandboxAndroid Feature = 128
FeatureFault Feature = 256
FeatureLeak Feature = 512
FeatureNetInjection Feature = 1024
FeatureNetDevices Feature = 2048
FeatureKCSAN Feature = 4096
FeatureDevlinkPCI Feature = 8192
FeatureNicVF Feature = 16384
FeatureUSBEmulation Feature = 32768
FeatureVhciInjection Feature = 65536
FeatureWifiEmulation Feature = 131072
FeatureLRWPANEmulation Feature = 262144
FeatureBinFmtMisc Feature = 524288
FeatureSwap Feature = 1048576
)
var EnumNamesFeature = map[Feature]string{
FeatureCoverage: "Coverage",
FeatureComparisons: "Comparisons",
FeatureExtraCoverage: "ExtraCoverage",
FeatureDelayKcovMmap: "DelayKcovMmap",
FeatureSandboxNone: "SandboxNone",
FeatureSandboxSetuid: "SandboxSetuid",
FeatureSandboxNamespace: "SandboxNamespace",
FeatureSandboxAndroid: "SandboxAndroid",
FeatureFault: "Fault",
FeatureLeak: "Leak",
FeatureNetInjection: "NetInjection",
FeatureNetDevices: "NetDevices",
FeatureKCSAN: "KCSAN",
FeatureDevlinkPCI: "DevlinkPCI",
FeatureNicVF: "NicVF",
FeatureUSBEmulation: "USBEmulation",
FeatureVhciInjection: "VhciInjection",
FeatureWifiEmulation: "WifiEmulation",
FeatureLRWPANEmulation: "LRWPANEmulation",
FeatureBinFmtMisc: "BinFmtMisc",
FeatureSwap: "Swap",
}
var EnumValuesFeature = map[string]Feature{
"Coverage": FeatureCoverage,
"Comparisons": FeatureComparisons,
"ExtraCoverage": FeatureExtraCoverage,
"DelayKcovMmap": FeatureDelayKcovMmap,
"SandboxNone": FeatureSandboxNone,
"SandboxSetuid": FeatureSandboxSetuid,
"SandboxNamespace": FeatureSandboxNamespace,
"SandboxAndroid": FeatureSandboxAndroid,
"Fault": FeatureFault,
"Leak": FeatureLeak,
"NetInjection": FeatureNetInjection,
"NetDevices": FeatureNetDevices,
"KCSAN": FeatureKCSAN,
"DevlinkPCI": FeatureDevlinkPCI,
"NicVF": FeatureNicVF,
"USBEmulation": FeatureUSBEmulation,
"VhciInjection": FeatureVhciInjection,
"WifiEmulation": FeatureWifiEmulation,
"LRWPANEmulation": FeatureLRWPANEmulation,
"BinFmtMisc": FeatureBinFmtMisc,
"Swap": FeatureSwap,
}
func (v Feature) String() string {
if s, ok := EnumNamesFeature[v]; ok {
return s
}
return "Feature(" + strconv.FormatInt(int64(v), 10) + ")"
}
type HostMessagesRaw byte
const (
HostMessagesRawNONE HostMessagesRaw = 0
HostMessagesRawExecRequest HostMessagesRaw = 1
HostMessagesRawSignalUpdate HostMessagesRaw = 2
HostMessagesRawCorpusTriaged HostMessagesRaw = 3
HostMessagesRawStateRequest HostMessagesRaw = 4
)
var EnumNamesHostMessagesRaw = map[HostMessagesRaw]string{
HostMessagesRawNONE: "NONE",
HostMessagesRawExecRequest: "ExecRequest",
HostMessagesRawSignalUpdate: "SignalUpdate",
HostMessagesRawCorpusTriaged: "CorpusTriaged",
HostMessagesRawStateRequest: "StateRequest",
}
var EnumValuesHostMessagesRaw = map[string]HostMessagesRaw{
"NONE": HostMessagesRawNONE,
"ExecRequest": HostMessagesRawExecRequest,
"SignalUpdate": HostMessagesRawSignalUpdate,
"CorpusTriaged": HostMessagesRawCorpusTriaged,
"StateRequest": HostMessagesRawStateRequest,
}
func (v HostMessagesRaw) String() string {
if s, ok := EnumNamesHostMessagesRaw[v]; ok {
return s
}
return "HostMessagesRaw(" + strconv.FormatInt(int64(v), 10) + ")"
}
type HostMessagesRawT struct {
Type HostMessagesRaw
Value interface{}
}
func (t *HostMessagesRawT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
if t == nil {
return 0
}
switch t.Type {
case HostMessagesRawExecRequest:
return t.Value.(*ExecRequestRawT).Pack(builder)
case HostMessagesRawSignalUpdate:
return t.Value.(*SignalUpdateRawT).Pack(builder)
case HostMessagesRawCorpusTriaged:
return t.Value.(*CorpusTriagedRawT).Pack(builder)
case HostMessagesRawStateRequest:
return t.Value.(*StateRequestRawT).Pack(builder)
}
return 0
}
func (rcv HostMessagesRaw) UnPack(table flatbuffers.Table) *HostMessagesRawT {
switch rcv {
case HostMessagesRawExecRequest:
x := ExecRequestRaw{_tab: table}
return &HostMessagesRawT{Type: HostMessagesRawExecRequest, Value: x.UnPack()}
case HostMessagesRawSignalUpdate:
x := SignalUpdateRaw{_tab: table}
return &HostMessagesRawT{Type: HostMessagesRawSignalUpdate, Value: x.UnPack()}
case HostMessagesRawCorpusTriaged:
x := CorpusTriagedRaw{_tab: table}
return &HostMessagesRawT{Type: HostMessagesRawCorpusTriaged, Value: x.UnPack()}
case HostMessagesRawStateRequest:
x := StateRequestRaw{_tab: table}
return &HostMessagesRawT{Type: HostMessagesRawStateRequest, Value: x.UnPack()}
}
return nil
}
type ExecutorMessagesRaw byte
const (
ExecutorMessagesRawNONE ExecutorMessagesRaw = 0
ExecutorMessagesRawExecResult ExecutorMessagesRaw = 1
ExecutorMessagesRawExecuting ExecutorMessagesRaw = 2
ExecutorMessagesRawState ExecutorMessagesRaw = 3
)
var EnumNamesExecutorMessagesRaw = map[ExecutorMessagesRaw]string{
ExecutorMessagesRawNONE: "NONE",
ExecutorMessagesRawExecResult: "ExecResult",
ExecutorMessagesRawExecuting: "Executing",
ExecutorMessagesRawState: "State",
}
var EnumValuesExecutorMessagesRaw = map[string]ExecutorMessagesRaw{
"NONE": ExecutorMessagesRawNONE,
"ExecResult": ExecutorMessagesRawExecResult,
"Executing": ExecutorMessagesRawExecuting,
"State": ExecutorMessagesRawState,
}
func (v ExecutorMessagesRaw) String() string {
if s, ok := EnumNamesExecutorMessagesRaw[v]; ok {
return s
}
return "ExecutorMessagesRaw(" + strconv.FormatInt(int64(v), 10) + ")"
}
type ExecutorMessagesRawT struct {
Type ExecutorMessagesRaw
Value interface{}
}
func (t *ExecutorMessagesRawT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
if t == nil {
return 0
}
switch t.Type {
case ExecutorMessagesRawExecResult:
return t.Value.(*ExecResultRawT).Pack(builder)
case ExecutorMessagesRawExecuting:
return t.Value.(*ExecutingMessageRawT).Pack(builder)
case ExecutorMessagesRawState:
return t.Value.(*StateResultRawT).Pack(builder)
}
return 0
}
func (rcv ExecutorMessagesRaw) UnPack(table flatbuffers.Table) *ExecutorMessagesRawT {
switch rcv {
case ExecutorMessagesRawExecResult:
x := ExecResultRaw{_tab: table}
return &ExecutorMessagesRawT{Type: ExecutorMessagesRawExecResult, Value: x.UnPack()}
case ExecutorMessagesRawExecuting:
x := ExecutingMessageRaw{_tab: table}
return &ExecutorMessagesRawT{Type: ExecutorMessagesRawExecuting, Value: x.UnPack()}
case ExecutorMessagesRawState:
x := StateResultRaw{_tab: table}
return &ExecutorMessagesRawT{Type: ExecutorMessagesRawState, Value: x.UnPack()}
}
return nil
}
type RequestType uint64
const (
RequestTypeProgram RequestType = 0
RequestTypeBinary RequestType = 1
RequestTypeGlob RequestType = 2
)
var EnumNamesRequestType = map[RequestType]string{
RequestTypeProgram: "Program",
RequestTypeBinary: "Binary",
RequestTypeGlob: "Glob",
}
var EnumValuesRequestType = map[string]RequestType{
"Program": RequestTypeProgram,
"Binary": RequestTypeBinary,
"Glob": RequestTypeGlob,
}
func (v RequestType) String() string {
if s, ok := EnumNamesRequestType[v]; ok {
return s
}
return "RequestType(" + strconv.FormatInt(int64(v), 10) + ")"
}
type RequestFlag uint64
const (
RequestFlagReturnOutput RequestFlag = 1
RequestFlagReturnError RequestFlag = 2
)
var EnumNamesRequestFlag = map[RequestFlag]string{
RequestFlagReturnOutput: "ReturnOutput",
RequestFlagReturnError: "ReturnError",
}
var EnumValuesRequestFlag = map[string]RequestFlag{
"ReturnOutput": RequestFlagReturnOutput,
"ReturnError": RequestFlagReturnError,
}
func (v RequestFlag) String() string {
if s, ok := EnumNamesRequestFlag[v]; ok {
return s
}
return "RequestFlag(" + strconv.FormatInt(int64(v), 10) + ")"
}
type ExecEnv uint64
const (
ExecEnvDebug ExecEnv = 1
ExecEnvSignal ExecEnv = 2
ExecEnvResetState ExecEnv = 4
ExecEnvSandboxNone ExecEnv = 8
ExecEnvSandboxSetuid ExecEnv = 16
ExecEnvSandboxNamespace ExecEnv = 32
ExecEnvSandboxAndroid ExecEnv = 64
ExecEnvExtraCover ExecEnv = 128
ExecEnvEnableTun ExecEnv = 256
ExecEnvEnableNetDev ExecEnv = 512
ExecEnvEnableNetReset ExecEnv = 1024
ExecEnvEnableCgroups ExecEnv = 2048
ExecEnvEnableCloseFds ExecEnv = 4096
ExecEnvEnableDevlinkPCI ExecEnv = 8192
ExecEnvEnableVhciInjection ExecEnv = 16384
ExecEnvEnableWifi ExecEnv = 32768
ExecEnvDelayKcovMmap ExecEnv = 65536
ExecEnvEnableNicVF ExecEnv = 131072
)
var EnumNamesExecEnv = map[ExecEnv]string{
ExecEnvDebug: "Debug",
ExecEnvSignal: "Signal",
ExecEnvResetState: "ResetState",
ExecEnvSandboxNone: "SandboxNone",
ExecEnvSandboxSetuid: "SandboxSetuid",
ExecEnvSandboxNamespace: "SandboxNamespace",
ExecEnvSandboxAndroid: "SandboxAndroid",
ExecEnvExtraCover: "ExtraCover",
ExecEnvEnableTun: "EnableTun",
ExecEnvEnableNetDev: "EnableNetDev",
ExecEnvEnableNetReset: "EnableNetReset",
ExecEnvEnableCgroups: "EnableCgroups",
ExecEnvEnableCloseFds: "EnableCloseFds",
ExecEnvEnableDevlinkPCI: "EnableDevlinkPCI",
ExecEnvEnableVhciInjection: "EnableVhciInjection",
ExecEnvEnableWifi: "EnableWifi",
ExecEnvDelayKcovMmap: "DelayKcovMmap",
ExecEnvEnableNicVF: "EnableNicVF",
}
var EnumValuesExecEnv = map[string]ExecEnv{
"Debug": ExecEnvDebug,
"Signal": ExecEnvSignal,
"ResetState": ExecEnvResetState,
"SandboxNone": ExecEnvSandboxNone,
"SandboxSetuid": ExecEnvSandboxSetuid,
"SandboxNamespace": ExecEnvSandboxNamespace,
"SandboxAndroid": ExecEnvSandboxAndroid,
"ExtraCover": ExecEnvExtraCover,
"EnableTun": ExecEnvEnableTun,
"EnableNetDev": ExecEnvEnableNetDev,
"EnableNetReset": ExecEnvEnableNetReset,
"EnableCgroups": ExecEnvEnableCgroups,
"EnableCloseFds": ExecEnvEnableCloseFds,
"EnableDevlinkPCI": ExecEnvEnableDevlinkPCI,
"EnableVhciInjection": ExecEnvEnableVhciInjection,
"EnableWifi": ExecEnvEnableWifi,
"DelayKcovMmap": ExecEnvDelayKcovMmap,
"EnableNicVF": ExecEnvEnableNicVF,
}
func (v ExecEnv) String() string {
if s, ok := EnumNamesExecEnv[v]; ok {
return s
}
return "ExecEnv(" + strconv.FormatInt(int64(v), 10) + ")"
}
type ExecFlag uint64
const (
ExecFlagCollectSignal ExecFlag = 1
ExecFlagCollectCover ExecFlag = 2
ExecFlagDedupCover ExecFlag = 4
ExecFlagCollectComps ExecFlag = 8
ExecFlagThreaded ExecFlag = 16
)
var EnumNamesExecFlag = map[ExecFlag]string{
ExecFlagCollectSignal: "CollectSignal",
ExecFlagCollectCover: "CollectCover",
ExecFlagDedupCover: "DedupCover",
ExecFlagCollectComps: "CollectComps",
ExecFlagThreaded: "Threaded",
}
var EnumValuesExecFlag = map[string]ExecFlag{
"CollectSignal": ExecFlagCollectSignal,
"CollectCover": ExecFlagCollectCover,
"DedupCover": ExecFlagDedupCover,
"CollectComps": ExecFlagCollectComps,
"Threaded": ExecFlagThreaded,
}
func (v ExecFlag) String() string {
if s, ok := EnumNamesExecFlag[v]; ok {
return s
}
return "ExecFlag(" + strconv.FormatInt(int64(v), 10) + ")"
}
type CallFlag byte
const (
CallFlagExecuted CallFlag = 1
CallFlagFinished CallFlag = 2
CallFlagBlocked CallFlag = 4
CallFlagFaultInjected CallFlag = 8
CallFlagCoverageOverflow CallFlag = 16
)
var EnumNamesCallFlag = map[CallFlag]string{
CallFlagExecuted: "Executed",
CallFlagFinished: "Finished",
CallFlagBlocked: "Blocked",
CallFlagFaultInjected: "FaultInjected",
CallFlagCoverageOverflow: "CoverageOverflow",
}
var EnumValuesCallFlag = map[string]CallFlag{
"Executed": CallFlagExecuted,
"Finished": CallFlagFinished,
"Blocked": CallFlagBlocked,
"FaultInjected": CallFlagFaultInjected,
"CoverageOverflow": CallFlagCoverageOverflow,
}
func (v CallFlag) String() string {
if s, ok := EnumNamesCallFlag[v]; ok {
return s
}
return "CallFlag(" + strconv.FormatInt(int64(v), 10) + ")"
}
type SnapshotState uint64
const (
SnapshotStateInitial SnapshotState = 0
SnapshotStateHandshake SnapshotState = 1
SnapshotStateReady SnapshotState = 2
SnapshotStateSnapshotted SnapshotState = 3
SnapshotStateExecute SnapshotState = 4
SnapshotStateExecuted SnapshotState = 5
SnapshotStateFailed SnapshotState = 6
)
var EnumNamesSnapshotState = map[SnapshotState]string{
SnapshotStateInitial: "Initial",
SnapshotStateHandshake: "Handshake",
SnapshotStateReady: "Ready",
SnapshotStateSnapshotted: "Snapshotted",
SnapshotStateExecute: "Execute",
SnapshotStateExecuted: "Executed",
SnapshotStateFailed: "Failed",
}
var EnumValuesSnapshotState = map[string]SnapshotState{
"Initial": SnapshotStateInitial,
"Handshake": SnapshotStateHandshake,
"Ready": SnapshotStateReady,
"Snapshotted": SnapshotStateSnapshotted,
"Execute": SnapshotStateExecute,
"Executed": SnapshotStateExecuted,
"Failed": SnapshotStateFailed,
}
func (v SnapshotState) String() string {
if s, ok := EnumNamesSnapshotState[v]; ok {
return s
}
return "SnapshotState(" + strconv.FormatInt(int64(v), 10) + ")"
}
type ConnectHelloRawT struct {
Cookie uint64 `json:"cookie"`
}
func (t *ConnectHelloRawT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
if t == nil {
return 0
}
ConnectHelloRawStart(builder)
ConnectHelloRawAddCookie(builder, t.Cookie)
return ConnectHelloRawEnd(builder)
}
func (rcv *ConnectHelloRaw) UnPackTo(t *ConnectHelloRawT) {
t.Cookie = rcv.Cookie()
}
func (rcv *ConnectHelloRaw) UnPack() *ConnectHelloRawT {
if rcv == nil {
return nil
}
t := &ConnectHelloRawT{}
rcv.UnPackTo(t)
return t
}
type ConnectHelloRaw struct {
_tab flatbuffers.Table
}
func GetRootAsConnectHelloRaw(buf []byte, offset flatbuffers.UOffsetT) *ConnectHelloRaw {
n := flatbuffers.GetUOffsetT(buf[offset:])
x := &ConnectHelloRaw{}
x.Init(buf, n+offset)
return x
}
func GetSizePrefixedRootAsConnectHelloRaw(buf []byte, offset flatbuffers.UOffsetT) *ConnectHelloRaw {
n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])
x := &ConnectHelloRaw{}
x.Init(buf, n+offset+flatbuffers.SizeUint32)
return x
}
func (rcv *ConnectHelloRaw) Init(buf []byte, i flatbuffers.UOffsetT) {
rcv._tab.Bytes = buf
rcv._tab.Pos = i
}
func (rcv *ConnectHelloRaw) Table() flatbuffers.Table {
return rcv._tab
}
func (rcv *ConnectHelloRaw) Cookie() uint64 {
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
if o != 0 {
return rcv._tab.GetUint64(o + rcv._tab.Pos)
}
return 0
}
func (rcv *ConnectHelloRaw) MutateCookie(n uint64) bool {
return rcv._tab.MutateUint64Slot(4, n)
}
func ConnectHelloRawStart(builder *flatbuffers.Builder) {
builder.StartObject(1)
}
func ConnectHelloRawAddCookie(builder *flatbuffers.Builder, cookie uint64) {
builder.PrependUint64Slot(0, cookie, 0)
}
func ConnectHelloRawEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
return builder.EndObject()
}
type ConnectRequestRawT struct {
Cookie uint64 `json:"cookie"`
Id int64 `json:"id"`
Arch string `json:"arch"`
GitRevision string `json:"git_revision"`
SyzRevision string `json:"syz_revision"`
}
func (t *ConnectRequestRawT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
if t == nil {
return 0
}
archOffset := builder.CreateString(t.Arch)
gitRevisionOffset := builder.CreateString(t.GitRevision)
syzRevisionOffset := builder.CreateString(t.SyzRevision)
ConnectRequestRawStart(builder)
ConnectRequestRawAddCookie(builder, t.Cookie)
ConnectRequestRawAddId(builder, t.Id)
ConnectRequestRawAddArch(builder, archOffset)
ConnectRequestRawAddGitRevision(builder, gitRevisionOffset)
ConnectRequestRawAddSyzRevision(builder, syzRevisionOffset)
return ConnectRequestRawEnd(builder)
}
func (rcv *ConnectRequestRaw) UnPackTo(t *ConnectRequestRawT) {
t.Cookie = rcv.Cookie()
t.Id = rcv.Id()
t.Arch = string(rcv.Arch())
t.GitRevision = string(rcv.GitRevision())
t.SyzRevision = string(rcv.SyzRevision())
}
func (rcv *ConnectRequestRaw) UnPack() *ConnectRequestRawT {
if rcv == nil {
return nil
}
t := &ConnectRequestRawT{}
rcv.UnPackTo(t)
return t
}
type ConnectRequestRaw struct {
_tab flatbuffers.Table
}
func GetRootAsConnectRequestRaw(buf []byte, offset flatbuffers.UOffsetT) *ConnectRequestRaw {
n := flatbuffers.GetUOffsetT(buf[offset:])
x := &ConnectRequestRaw{}
x.Init(buf, n+offset)
return x
}
func GetSizePrefixedRootAsConnectRequestRaw(buf []byte, offset flatbuffers.UOffsetT) *ConnectRequestRaw {
n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])
x := &ConnectRequestRaw{}
x.Init(buf, n+offset+flatbuffers.SizeUint32)
return x
}
func (rcv *ConnectRequestRaw) Init(buf []byte, i flatbuffers.UOffsetT) {
rcv._tab.Bytes = buf
rcv._tab.Pos = i
}
func (rcv *ConnectRequestRaw) Table() flatbuffers.Table {
return rcv._tab
}
func (rcv *ConnectRequestRaw) Cookie() uint64 {
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
if o != 0 {
return rcv._tab.GetUint64(o + rcv._tab.Pos)
}
return 0
}
func (rcv *ConnectRequestRaw) MutateCookie(n uint64) bool {
return rcv._tab.MutateUint64Slot(4, n)
}
func (rcv *ConnectRequestRaw) Id() int64 {
o := flatbuffers.UOffsetT(rcv._tab.Offset(6))
if o != 0 {
return rcv._tab.GetInt64(o + rcv._tab.Pos)
}
return 0
}
func (rcv *ConnectRequestRaw) MutateId(n int64) bool {
return rcv._tab.MutateInt64Slot(6, n)
}
func (rcv *ConnectRequestRaw) Arch() []byte {
o := flatbuffers.UOffsetT(rcv._tab.Offset(8))
if o != 0 {
return rcv._tab.ByteVector(o + rcv._tab.Pos)
}
return nil
}
func (rcv *ConnectRequestRaw) GitRevision() []byte {
o := flatbuffers.UOffsetT(rcv._tab.Offset(10))
if o != 0 {
return rcv._tab.ByteVector(o + rcv._tab.Pos)
}
return nil
}
func (rcv *ConnectRequestRaw) SyzRevision() []byte {
o := flatbuffers.UOffsetT(rcv._tab.Offset(12))
if o != 0 {
return rcv._tab.ByteVector(o + rcv._tab.Pos)
}
return nil
}
func ConnectRequestRawStart(builder *flatbuffers.Builder) {
builder.StartObject(5)
}
func ConnectRequestRawAddCookie(builder *flatbuffers.Builder, cookie uint64) {
builder.PrependUint64Slot(0, cookie, 0)
}
func ConnectRequestRawAddId(builder *flatbuffers.Builder, id int64) {
builder.PrependInt64Slot(1, id, 0)
}
func ConnectRequestRawAddArch(builder *flatbuffers.Builder, arch flatbuffers.UOffsetT) {
builder.PrependUOffsetTSlot(2, flatbuffers.UOffsetT(arch), 0)
}
func ConnectRequestRawAddGitRevision(builder *flatbuffers.Builder, gitRevision flatbuffers.UOffsetT) {
builder.PrependUOffsetTSlot(3, flatbuffers.UOffsetT(gitRevision), 0)
}
func ConnectRequestRawAddSyzRevision(builder *flatbuffers.Builder, syzRevision flatbuffers.UOffsetT) {
builder.PrependUOffsetTSlot(4, flatbuffers.UOffsetT(syzRevision), 0)
}
func ConnectRequestRawEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
return builder.EndObject()
}
type ConnectReplyRawT struct {
Debug bool `json:"debug"`
Cover bool `json:"cover"`
CoverEdges bool `json:"cover_edges"`
Kernel64Bit bool `json:"kernel_64_bit"`
Procs int32 `json:"procs"`
Slowdown int32 `json:"slowdown"`
SyscallTimeoutMs int32 `json:"syscall_timeout_ms"`
ProgramTimeoutMs int32 `json:"program_timeout_ms"`
LeakFrames []string `json:"leak_frames"`
RaceFrames []string `json:"race_frames"`
Features Feature `json:"features"`
Files []string `json:"files"`
}
func (t *ConnectReplyRawT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
if t == nil {
return 0
}
leakFramesOffset := flatbuffers.UOffsetT(0)
if t.LeakFrames != nil {
leakFramesLength := len(t.LeakFrames)
leakFramesOffsets := make([]flatbuffers.UOffsetT, leakFramesLength)
for j := 0; j < leakFramesLength; j++ {
leakFramesOffsets[j] = builder.CreateString(t.LeakFrames[j])
}
ConnectReplyRawStartLeakFramesVector(builder, leakFramesLength)
for j := leakFramesLength - 1; j >= 0; j-- {
builder.PrependUOffsetT(leakFramesOffsets[j])
}
leakFramesOffset = builder.EndVector(leakFramesLength)
}
raceFramesOffset := flatbuffers.UOffsetT(0)
if t.RaceFrames != nil {
raceFramesLength := len(t.RaceFrames)
raceFramesOffsets := make([]flatbuffers.UOffsetT, raceFramesLength)
for j := 0; j < raceFramesLength; j++ {
raceFramesOffsets[j] = builder.CreateString(t.RaceFrames[j])
}
ConnectReplyRawStartRaceFramesVector(builder, raceFramesLength)
for j := raceFramesLength - 1; j >= 0; j-- {
builder.PrependUOffsetT(raceFramesOffsets[j])
}
raceFramesOffset = builder.EndVector(raceFramesLength)
}
filesOffset := flatbuffers.UOffsetT(0)
if t.Files != nil {
filesLength := len(t.Files)
filesOffsets := make([]flatbuffers.UOffsetT, filesLength)
for j := 0; j < filesLength; j++ {
filesOffsets[j] = builder.CreateString(t.Files[j])
}
ConnectReplyRawStartFilesVector(builder, filesLength)
for j := filesLength - 1; j >= 0; j-- {
builder.PrependUOffsetT(filesOffsets[j])
}
filesOffset = builder.EndVector(filesLength)
}
ConnectReplyRawStart(builder)
ConnectReplyRawAddDebug(builder, t.Debug)
ConnectReplyRawAddCover(builder, t.Cover)
ConnectReplyRawAddCoverEdges(builder, t.CoverEdges)
ConnectReplyRawAddKernel64Bit(builder, t.Kernel64Bit)
ConnectReplyRawAddProcs(builder, t.Procs)
ConnectReplyRawAddSlowdown(builder, t.Slowdown)
ConnectReplyRawAddSyscallTimeoutMs(builder, t.SyscallTimeoutMs)
ConnectReplyRawAddProgramTimeoutMs(builder, t.ProgramTimeoutMs)
ConnectReplyRawAddLeakFrames(builder, leakFramesOffset)
ConnectReplyRawAddRaceFrames(builder, raceFramesOffset)
ConnectReplyRawAddFeatures(builder, t.Features)
ConnectReplyRawAddFiles(builder, filesOffset)
return ConnectReplyRawEnd(builder)
}
func (rcv *ConnectReplyRaw) UnPackTo(t *ConnectReplyRawT) {
t.Debug = rcv.Debug()
t.Cover = rcv.Cover()
t.CoverEdges = rcv.CoverEdges()
t.Kernel64Bit = rcv.Kernel64Bit()
t.Procs = rcv.Procs()
t.Slowdown = rcv.Slowdown()
t.SyscallTimeoutMs = rcv.SyscallTimeoutMs()
t.ProgramTimeoutMs = rcv.ProgramTimeoutMs()
leakFramesLength := rcv.LeakFramesLength()
t.LeakFrames = make([]string, leakFramesLength)
for j := 0; j < leakFramesLength; j++ {
t.LeakFrames[j] = string(rcv.LeakFrames(j))
}
raceFramesLength := rcv.RaceFramesLength()
t.RaceFrames = make([]string, raceFramesLength)
for j := 0; j < raceFramesLength; j++ {
t.RaceFrames[j] = string(rcv.RaceFrames(j))
}
t.Features = rcv.Features()
filesLength := rcv.FilesLength()
t.Files = make([]string, filesLength)
for j := 0; j < filesLength; j++ {
t.Files[j] = string(rcv.Files(j))
}
}
func (rcv *ConnectReplyRaw) UnPack() *ConnectReplyRawT {
if rcv == nil {
return nil
}
t := &ConnectReplyRawT{}
rcv.UnPackTo(t)
return t
}
type ConnectReplyRaw struct {
_tab flatbuffers.Table
}
func GetRootAsConnectReplyRaw(buf []byte, offset flatbuffers.UOffsetT) *ConnectReplyRaw {
n := flatbuffers.GetUOffsetT(buf[offset:])
x := &ConnectReplyRaw{}
x.Init(buf, n+offset)
return x
}
func GetSizePrefixedRootAsConnectReplyRaw(buf []byte, offset flatbuffers.UOffsetT) *ConnectReplyRaw {
n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])
x := &ConnectReplyRaw{}
x.Init(buf, n+offset+flatbuffers.SizeUint32)
return x
}
func (rcv *ConnectReplyRaw) Init(buf []byte, i flatbuffers.UOffsetT) {
rcv._tab.Bytes = buf
rcv._tab.Pos = i
}
func (rcv *ConnectReplyRaw) Table() flatbuffers.Table {
return rcv._tab
}
func (rcv *ConnectReplyRaw) Debug() bool {
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
if o != 0 {
return rcv._tab.GetBool(o + rcv._tab.Pos)
}
return false
}
func (rcv *ConnectReplyRaw) MutateDebug(n bool) bool {
return rcv._tab.MutateBoolSlot(4, n)
}
func (rcv *ConnectReplyRaw) Cover() bool {
o := flatbuffers.UOffsetT(rcv._tab.Offset(6))
if o != 0 {
return rcv._tab.GetBool(o + rcv._tab.Pos)
}
return false
}
func (rcv *ConnectReplyRaw) MutateCover(n bool) bool {
return rcv._tab.MutateBoolSlot(6, n)
}
func (rcv *ConnectReplyRaw) CoverEdges() bool {
o := flatbuffers.UOffsetT(rcv._tab.Offset(8))
if o != 0 {
return rcv._tab.GetBool(o + rcv._tab.Pos)
}
return false
}
func (rcv *ConnectReplyRaw) MutateCoverEdges(n bool) bool {
return rcv._tab.MutateBoolSlot(8, n)
}
func (rcv *ConnectReplyRaw) Kernel64Bit() bool {
o := flatbuffers.UOffsetT(rcv._tab.Offset(10))
if o != 0 {
return rcv._tab.GetBool(o + rcv._tab.Pos)
}
return false
}
func (rcv *ConnectReplyRaw) MutateKernel64Bit(n bool) bool {
return rcv._tab.MutateBoolSlot(10, n)
}
func (rcv *ConnectReplyRaw) Procs() int32 {
o := flatbuffers.UOffsetT(rcv._tab.Offset(12))
if o != 0 {
return rcv._tab.GetInt32(o + rcv._tab.Pos)
}
return 0
}
func (rcv *ConnectReplyRaw) MutateProcs(n int32) bool {
return rcv._tab.MutateInt32Slot(12, n)
}
func (rcv *ConnectReplyRaw) Slowdown() int32 {
o := flatbuffers.UOffsetT(rcv._tab.Offset(14))
if o != 0 {
return rcv._tab.GetInt32(o + rcv._tab.Pos)
}
return 0
}
func (rcv *ConnectReplyRaw) MutateSlowdown(n int32) bool {
return rcv._tab.MutateInt32Slot(14, n)
}
func (rcv *ConnectReplyRaw) SyscallTimeoutMs() int32 {
o := flatbuffers.UOffsetT(rcv._tab.Offset(16))
if o != 0 {
return rcv._tab.GetInt32(o + rcv._tab.Pos)
}
return 0
}
func (rcv *ConnectReplyRaw) MutateSyscallTimeoutMs(n int32) bool {
return rcv._tab.MutateInt32Slot(16, n)
}
func (rcv *ConnectReplyRaw) ProgramTimeoutMs() int32 {
o := flatbuffers.UOffsetT(rcv._tab.Offset(18))
if o != 0 {
return rcv._tab.GetInt32(o + rcv._tab.Pos)
}
return 0
}
func (rcv *ConnectReplyRaw) MutateProgramTimeoutMs(n int32) bool {
return rcv._tab.MutateInt32Slot(18, n)
}
func (rcv *ConnectReplyRaw) LeakFrames(j int) []byte {
o := flatbuffers.UOffsetT(rcv._tab.Offset(20))
if o != 0 {
a := rcv._tab.Vector(o)
return rcv._tab.ByteVector(a + flatbuffers.UOffsetT(j*4))
}
return nil
}
func (rcv *ConnectReplyRaw) LeakFramesLength() int {
o := flatbuffers.UOffsetT(rcv._tab.Offset(20))
if o != 0 {
return rcv._tab.VectorLen(o)
}
return 0
}
func (rcv *ConnectReplyRaw) RaceFrames(j int) []byte {
o := flatbuffers.UOffsetT(rcv._tab.Offset(22))
if o != 0 {
a := rcv._tab.Vector(o)
return rcv._tab.ByteVector(a + flatbuffers.UOffsetT(j*4))
}
return nil
}
func (rcv *ConnectReplyRaw) RaceFramesLength() int {
o := flatbuffers.UOffsetT(rcv._tab.Offset(22))
if o != 0 {
return rcv._tab.VectorLen(o)
}
return 0
}
func (rcv *ConnectReplyRaw) Features() Feature {
o := flatbuffers.UOffsetT(rcv._tab.Offset(24))
if o != 0 {
return Feature(rcv._tab.GetUint64(o + rcv._tab.Pos))
}
return 0
}
func (rcv *ConnectReplyRaw) MutateFeatures(n Feature) bool {
return rcv._tab.MutateUint64Slot(24, uint64(n))
}
func (rcv *ConnectReplyRaw) Files(j int) []byte {
o := flatbuffers.UOffsetT(rcv._tab.Offset(26))
if o != 0 {
a := rcv._tab.Vector(o)
return rcv._tab.ByteVector(a + flatbuffers.UOffsetT(j*4))
}
return nil
}
func (rcv *ConnectReplyRaw) FilesLength() int {
o := flatbuffers.UOffsetT(rcv._tab.Offset(26))
if o != 0 {
return rcv._tab.VectorLen(o)
}
return 0
}
func ConnectReplyRawStart(builder *flatbuffers.Builder) {
builder.StartObject(12)
}
func ConnectReplyRawAddDebug(builder *flatbuffers.Builder, debug bool) {
builder.PrependBoolSlot(0, debug, false)
}
func ConnectReplyRawAddCover(builder *flatbuffers.Builder, cover bool) {
builder.PrependBoolSlot(1, cover, false)
}
func ConnectReplyRawAddCoverEdges(builder *flatbuffers.Builder, coverEdges bool) {
builder.PrependBoolSlot(2, coverEdges, false)
}
func ConnectReplyRawAddKernel64Bit(builder *flatbuffers.Builder, kernel64Bit bool) {
builder.PrependBoolSlot(3, kernel64Bit, false)
}
func ConnectReplyRawAddProcs(builder *flatbuffers.Builder, procs int32) {
builder.PrependInt32Slot(4, procs, 0)
}
func ConnectReplyRawAddSlowdown(builder *flatbuffers.Builder, slowdown int32) {
builder.PrependInt32Slot(5, slowdown, 0)
}
func ConnectReplyRawAddSyscallTimeoutMs(builder *flatbuffers.Builder, syscallTimeoutMs int32) {
builder.PrependInt32Slot(6, syscallTimeoutMs, 0)
}
func ConnectReplyRawAddProgramTimeoutMs(builder *flatbuffers.Builder, programTimeoutMs int32) {
builder.PrependInt32Slot(7, programTimeoutMs, 0)
}
func ConnectReplyRawAddLeakFrames(builder *flatbuffers.Builder, leakFrames flatbuffers.UOffsetT) {
builder.PrependUOffsetTSlot(8, flatbuffers.UOffsetT(leakFrames), 0)
}
func ConnectReplyRawStartLeakFramesVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT {
return builder.StartVector(4, numElems, 4)
}
func ConnectReplyRawAddRaceFrames(builder *flatbuffers.Builder, raceFrames flatbuffers.UOffsetT) {
builder.PrependUOffsetTSlot(9, flatbuffers.UOffsetT(raceFrames), 0)
}
func ConnectReplyRawStartRaceFramesVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT {
return builder.StartVector(4, numElems, 4)
}
func ConnectReplyRawAddFeatures(builder *flatbuffers.Builder, features Feature) {
builder.PrependUint64Slot(10, uint64(features), 0)
}
func ConnectReplyRawAddFiles(builder *flatbuffers.Builder, files flatbuffers.UOffsetT) {
builder.PrependUOffsetTSlot(11, flatbuffers.UOffsetT(files), 0)
}
func ConnectReplyRawStartFilesVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT {
return builder.StartVector(4, numElems, 4)
}
func ConnectReplyRawEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
return builder.EndObject()
}
type InfoRequestRawT struct {
Error string `json:"error"`
Features []*FeatureInfoRawT `json:"features"`
Files []*FileInfoRawT `json:"files"`
}
func (t *InfoRequestRawT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
if t == nil {
return 0
}
errorOffset := builder.CreateString(t.Error)
featuresOffset := flatbuffers.UOffsetT(0)
if t.Features != nil {
featuresLength := len(t.Features)
featuresOffsets := make([]flatbuffers.UOffsetT, featuresLength)
for j := 0; j < featuresLength; j++ {
featuresOffsets[j] = t.Features[j].Pack(builder)
}
InfoRequestRawStartFeaturesVector(builder, featuresLength)
for j := featuresLength - 1; j >= 0; j-- {
builder.PrependUOffsetT(featuresOffsets[j])
}
featuresOffset = builder.EndVector(featuresLength)
}
filesOffset := flatbuffers.UOffsetT(0)
if t.Files != nil {
filesLength := len(t.Files)
filesOffsets := make([]flatbuffers.UOffsetT, filesLength)
for j := 0; j < filesLength; j++ {
filesOffsets[j] = t.Files[j].Pack(builder)
}
InfoRequestRawStartFilesVector(builder, filesLength)
for j := filesLength - 1; j >= 0; j-- {
builder.PrependUOffsetT(filesOffsets[j])
}
filesOffset = builder.EndVector(filesLength)
}
InfoRequestRawStart(builder)
InfoRequestRawAddError(builder, errorOffset)
InfoRequestRawAddFeatures(builder, featuresOffset)
InfoRequestRawAddFiles(builder, filesOffset)
return InfoRequestRawEnd(builder)
}
func (rcv *InfoRequestRaw) UnPackTo(t *InfoRequestRawT) {
t.Error = string(rcv.Error())
featuresLength := rcv.FeaturesLength()
t.Features = make([]*FeatureInfoRawT, featuresLength)
for j := 0; j < featuresLength; j++ {
x := FeatureInfoRaw{}
rcv.Features(&x, j)
t.Features[j] = x.UnPack()
}
filesLength := rcv.FilesLength()
t.Files = make([]*FileInfoRawT, filesLength)
for j := 0; j < filesLength; j++ {
x := FileInfoRaw{}
rcv.Files(&x, j)
t.Files[j] = x.UnPack()
}
}
func (rcv *InfoRequestRaw) UnPack() *InfoRequestRawT {
if rcv == nil {
return nil
}
t := &InfoRequestRawT{}
rcv.UnPackTo(t)
return t
}
type InfoRequestRaw struct {
_tab flatbuffers.Table
}
func GetRootAsInfoRequestRaw(buf []byte, offset flatbuffers.UOffsetT) *InfoRequestRaw {
n := flatbuffers.GetUOffsetT(buf[offset:])
x := &InfoRequestRaw{}
x.Init(buf, n+offset)
return x
}
func GetSizePrefixedRootAsInfoRequestRaw(buf []byte, offset flatbuffers.UOffsetT) *InfoRequestRaw {
n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])
x := &InfoRequestRaw{}
x.Init(buf, n+offset+flatbuffers.SizeUint32)
return x
}
func (rcv *InfoRequestRaw) Init(buf []byte, i flatbuffers.UOffsetT) {
rcv._tab.Bytes = buf
rcv._tab.Pos = i
}
func (rcv *InfoRequestRaw) Table() flatbuffers.Table {
return rcv._tab
}
func (rcv *InfoRequestRaw) Error() []byte {
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
if o != 0 {
return rcv._tab.ByteVector(o + rcv._tab.Pos)
}
return nil
}
func (rcv *InfoRequestRaw) Features(obj *FeatureInfoRaw, j int) bool {
o := flatbuffers.UOffsetT(rcv._tab.Offset(6))
if o != 0 {
x := rcv._tab.Vector(o)
x += flatbuffers.UOffsetT(j) * 4
x = rcv._tab.Indirect(x)
obj.Init(rcv._tab.Bytes, x)
return true
}
return false
}
func (rcv *InfoRequestRaw) FeaturesLength() int {
o := flatbuffers.UOffsetT(rcv._tab.Offset(6))
if o != 0 {
return rcv._tab.VectorLen(o)
}
return 0
}
func (rcv *InfoRequestRaw) Files(obj *FileInfoRaw, j int) bool {
o := flatbuffers.UOffsetT(rcv._tab.Offset(8))
if o != 0 {
x := rcv._tab.Vector(o)
x += flatbuffers.UOffsetT(j) * 4
x = rcv._tab.Indirect(x)
obj.Init(rcv._tab.Bytes, x)
return true
}
return false
}
func (rcv *InfoRequestRaw) FilesLength() int {
o := flatbuffers.UOffsetT(rcv._tab.Offset(8))
if o != 0 {
return rcv._tab.VectorLen(o)
}
return 0
}
func InfoRequestRawStart(builder *flatbuffers.Builder) {
builder.StartObject(3)
}
func InfoRequestRawAddError(builder *flatbuffers.Builder, error flatbuffers.UOffsetT) {
builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(error), 0)
}
func InfoRequestRawAddFeatures(builder *flatbuffers.Builder, features flatbuffers.UOffsetT) {
builder.PrependUOffsetTSlot(1, flatbuffers.UOffsetT(features), 0)
}
func InfoRequestRawStartFeaturesVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT {
return builder.StartVector(4, numElems, 4)
}
func InfoRequestRawAddFiles(builder *flatbuffers.Builder, files flatbuffers.UOffsetT) {
builder.PrependUOffsetTSlot(2, flatbuffers.UOffsetT(files), 0)
}
func InfoRequestRawStartFilesVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT {
return builder.StartVector(4, numElems, 4)
}
func InfoRequestRawEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
return builder.EndObject()
}
type InfoReplyRawT struct {
CoverFilter []uint64 `json:"cover_filter"`
}
func (t *InfoReplyRawT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
if t == nil {
return 0
}
coverFilterOffset := flatbuffers.UOffsetT(0)
if t.CoverFilter != nil {
coverFilterLength := len(t.CoverFilter)
InfoReplyRawStartCoverFilterVector(builder, coverFilterLength)
for j := coverFilterLength - 1; j >= 0; j-- {
builder.PrependUint64(t.CoverFilter[j])
}
coverFilterOffset = builder.EndVector(coverFilterLength)
}
InfoReplyRawStart(builder)
InfoReplyRawAddCoverFilter(builder, coverFilterOffset)
return InfoReplyRawEnd(builder)
}
func (rcv *InfoReplyRaw) UnPackTo(t *InfoReplyRawT) {
coverFilterLength := rcv.CoverFilterLength()
t.CoverFilter = make([]uint64, coverFilterLength)
for j := 0; j < coverFilterLength; j++ {
t.CoverFilter[j] = rcv.CoverFilter(j)
}
}
func (rcv *InfoReplyRaw) UnPack() *InfoReplyRawT {
if rcv == nil {
return nil
}
t := &InfoReplyRawT{}
rcv.UnPackTo(t)
return t
}
type InfoReplyRaw struct {
_tab flatbuffers.Table
}
func GetRootAsInfoReplyRaw(buf []byte, offset flatbuffers.UOffsetT) *InfoReplyRaw {
n := flatbuffers.GetUOffsetT(buf[offset:])
x := &InfoReplyRaw{}
x.Init(buf, n+offset)
return x
}
func GetSizePrefixedRootAsInfoReplyRaw(buf []byte, offset flatbuffers.UOffsetT) *InfoReplyRaw {
n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])
x := &InfoReplyRaw{}
x.Init(buf, n+offset+flatbuffers.SizeUint32)
return x
}
func (rcv *InfoReplyRaw) Init(buf []byte, i flatbuffers.UOffsetT) {
rcv._tab.Bytes = buf
rcv._tab.Pos = i
}
func (rcv *InfoReplyRaw) Table() flatbuffers.Table {
return rcv._tab
}
func (rcv *InfoReplyRaw) CoverFilter(j int) uint64 {
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
if o != 0 {
a := rcv._tab.Vector(o)
return rcv._tab.GetUint64(a + flatbuffers.UOffsetT(j*8))
}
return 0
}
func (rcv *InfoReplyRaw) CoverFilterLength() int {
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
if o != 0 {
return rcv._tab.VectorLen(o)
}
return 0
}
func (rcv *InfoReplyRaw) MutateCoverFilter(j int, n uint64) bool {
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
if o != 0 {
a := rcv._tab.Vector(o)
return rcv._tab.MutateUint64(a+flatbuffers.UOffsetT(j*8), n)
}
return false
}
func InfoReplyRawStart(builder *flatbuffers.Builder) {
builder.StartObject(1)
}
func InfoReplyRawAddCoverFilter(builder *flatbuffers.Builder, coverFilter flatbuffers.UOffsetT) {
builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(coverFilter), 0)
}
func InfoReplyRawStartCoverFilterVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT {
return builder.StartVector(8, numElems, 8)
}
func InfoReplyRawEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
return builder.EndObject()
}
type FileInfoRawT struct {
Name string `json:"name"`
Exists bool `json:"exists"`
Error string `json:"error"`
Data []byte `json:"data"`
}
func (t *FileInfoRawT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
if t == nil {
return 0
}
nameOffset := builder.CreateString(t.Name)
errorOffset := builder.CreateString(t.Error)
dataOffset := flatbuffers.UOffsetT(0)
if t.Data != nil {
dataOffset = builder.CreateByteString(t.Data)
}
FileInfoRawStart(builder)
FileInfoRawAddName(builder, nameOffset)
FileInfoRawAddExists(builder, t.Exists)
FileInfoRawAddError(builder, errorOffset)
FileInfoRawAddData(builder, dataOffset)
return FileInfoRawEnd(builder)
}
func (rcv *FileInfoRaw) UnPackTo(t *FileInfoRawT) {
t.Name = string(rcv.Name())
t.Exists = rcv.Exists()
t.Error = string(rcv.Error())
t.Data = rcv.DataBytes()
}
func (rcv *FileInfoRaw) UnPack() *FileInfoRawT {
if rcv == nil {
return nil
}
t := &FileInfoRawT{}
rcv.UnPackTo(t)
return t
}
type FileInfoRaw struct {
_tab flatbuffers.Table
}
func GetRootAsFileInfoRaw(buf []byte, offset flatbuffers.UOffsetT) *FileInfoRaw {
n := flatbuffers.GetUOffsetT(buf[offset:])
x := &FileInfoRaw{}
x.Init(buf, n+offset)
return x
}
func GetSizePrefixedRootAsFileInfoRaw(buf []byte, offset flatbuffers.UOffsetT) *FileInfoRaw {
n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])
x := &FileInfoRaw{}
x.Init(buf, n+offset+flatbuffers.SizeUint32)
return x
}
func (rcv *FileInfoRaw) Init(buf []byte, i flatbuffers.UOffsetT) {
rcv._tab.Bytes = buf
rcv._tab.Pos = i
}
func (rcv *FileInfoRaw) Table() flatbuffers.Table {
return rcv._tab
}
func (rcv *FileInfoRaw) Name() []byte {
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
if o != 0 {
return rcv._tab.ByteVector(o + rcv._tab.Pos)
}
return nil
}
func (rcv *FileInfoRaw) Exists() bool {
o := flatbuffers.UOffsetT(rcv._tab.Offset(6))
if o != 0 {
return rcv._tab.GetBool(o + rcv._tab.Pos)
}
return false
}
func (rcv *FileInfoRaw) MutateExists(n bool) bool {
return rcv._tab.MutateBoolSlot(6, n)
}
func (rcv *FileInfoRaw) Error() []byte {
o := flatbuffers.UOffsetT(rcv._tab.Offset(8))
if o != 0 {
return rcv._tab.ByteVector(o + rcv._tab.Pos)
}
return nil
}
func (rcv *FileInfoRaw) Data(j int) byte {
o := flatbuffers.UOffsetT(rcv._tab.Offset(10))
if o != 0 {
a := rcv._tab.Vector(o)
return rcv._tab.GetByte(a + flatbuffers.UOffsetT(j*1))
}
return 0
}
func (rcv *FileInfoRaw) DataLength() int {
o := flatbuffers.UOffsetT(rcv._tab.Offset(10))
if o != 0 {
return rcv._tab.VectorLen(o)
}
return 0
}
func (rcv *FileInfoRaw) DataBytes() []byte {
o := flatbuffers.UOffsetT(rcv._tab.Offset(10))
if o != 0 {
return rcv._tab.ByteVector(o + rcv._tab.Pos)
}
return nil
}
func (rcv *FileInfoRaw) MutateData(j int, n byte) bool {
o := flatbuffers.UOffsetT(rcv._tab.Offset(10))
if o != 0 {
a := rcv._tab.Vector(o)
return rcv._tab.MutateByte(a+flatbuffers.UOffsetT(j*1), n)
}
return false
}
func FileInfoRawStart(builder *flatbuffers.Builder) {
builder.StartObject(4)
}
func FileInfoRawAddName(builder *flatbuffers.Builder, name flatbuffers.UOffsetT) {
builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(name), 0)
}
func FileInfoRawAddExists(builder *flatbuffers.Builder, exists bool) {
builder.PrependBoolSlot(1, exists, false)
}
func FileInfoRawAddError(builder *flatbuffers.Builder, error flatbuffers.UOffsetT) {
builder.PrependUOffsetTSlot(2, flatbuffers.UOffsetT(error), 0)
}
func FileInfoRawAddData(builder *flatbuffers.Builder, data flatbuffers.UOffsetT) {
builder.PrependUOffsetTSlot(3, flatbuffers.UOffsetT(data), 0)
}
func FileInfoRawStartDataVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT {
return builder.StartVector(1, numElems, 1)
}
func FileInfoRawEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
return builder.EndObject()
}
type GlobInfoRawT struct {
Name string `json:"name"`
Files []string `json:"files"`
}
func (t *GlobInfoRawT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
if t == nil {
return 0
}
nameOffset := builder.CreateString(t.Name)
filesOffset := flatbuffers.UOffsetT(0)
if t.Files != nil {
filesLength := len(t.Files)
filesOffsets := make([]flatbuffers.UOffsetT, filesLength)
for j := 0; j < filesLength; j++ {
filesOffsets[j] = builder.CreateString(t.Files[j])
}
GlobInfoRawStartFilesVector(builder, filesLength)
for j := filesLength - 1; j >= 0; j-- {
builder.PrependUOffsetT(filesOffsets[j])
}
filesOffset = builder.EndVector(filesLength)
}
GlobInfoRawStart(builder)
GlobInfoRawAddName(builder, nameOffset)
GlobInfoRawAddFiles(builder, filesOffset)
return GlobInfoRawEnd(builder)
}
func (rcv *GlobInfoRaw) UnPackTo(t *GlobInfoRawT) {
t.Name = string(rcv.Name())
filesLength := rcv.FilesLength()
t.Files = make([]string, filesLength)
for j := 0; j < filesLength; j++ {
t.Files[j] = string(rcv.Files(j))
}
}
func (rcv *GlobInfoRaw) UnPack() *GlobInfoRawT {
if rcv == nil {
return nil
}
t := &GlobInfoRawT{}
rcv.UnPackTo(t)
return t
}
type GlobInfoRaw struct {
_tab flatbuffers.Table
}
func GetRootAsGlobInfoRaw(buf []byte, offset flatbuffers.UOffsetT) *GlobInfoRaw {
n := flatbuffers.GetUOffsetT(buf[offset:])
x := &GlobInfoRaw{}
x.Init(buf, n+offset)
return x
}
func GetSizePrefixedRootAsGlobInfoRaw(buf []byte, offset flatbuffers.UOffsetT) *GlobInfoRaw {
n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])
x := &GlobInfoRaw{}
x.Init(buf, n+offset+flatbuffers.SizeUint32)
return x
}
func (rcv *GlobInfoRaw) Init(buf []byte, i flatbuffers.UOffsetT) {
rcv._tab.Bytes = buf
rcv._tab.Pos = i
}
func (rcv *GlobInfoRaw) Table() flatbuffers.Table {
return rcv._tab
}
func (rcv *GlobInfoRaw) Name() []byte {
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
if o != 0 {
return rcv._tab.ByteVector(o + rcv._tab.Pos)
}
return nil
}
func (rcv *GlobInfoRaw) Files(j int) []byte {
o := flatbuffers.UOffsetT(rcv._tab.Offset(6))
if o != 0 {
a := rcv._tab.Vector(o)
return rcv._tab.ByteVector(a + flatbuffers.UOffsetT(j*4))
}
return nil
}
func (rcv *GlobInfoRaw) FilesLength() int {
o := flatbuffers.UOffsetT(rcv._tab.Offset(6))
if o != 0 {
return rcv._tab.VectorLen(o)
}
return 0
}
func GlobInfoRawStart(builder *flatbuffers.Builder) {
builder.StartObject(2)
}
func GlobInfoRawAddName(builder *flatbuffers.Builder, name flatbuffers.UOffsetT) {
builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(name), 0)
}
func GlobInfoRawAddFiles(builder *flatbuffers.Builder, files flatbuffers.UOffsetT) {
builder.PrependUOffsetTSlot(1, flatbuffers.UOffsetT(files), 0)
}
func GlobInfoRawStartFilesVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT {
return builder.StartVector(4, numElems, 4)
}
func GlobInfoRawEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
return builder.EndObject()
}
type FeatureInfoRawT struct {
Id Feature `json:"id"`
NeedSetup bool `json:"need_setup"`
Reason string `json:"reason"`
}
func (t *FeatureInfoRawT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
if t == nil {
return 0
}
reasonOffset := builder.CreateString(t.Reason)
FeatureInfoRawStart(builder)
FeatureInfoRawAddId(builder, t.Id)
FeatureInfoRawAddNeedSetup(builder, t.NeedSetup)
FeatureInfoRawAddReason(builder, reasonOffset)
return FeatureInfoRawEnd(builder)
}
func (rcv *FeatureInfoRaw) UnPackTo(t *FeatureInfoRawT) {
t.Id = rcv.Id()
t.NeedSetup = rcv.NeedSetup()
t.Reason = string(rcv.Reason())
}
func (rcv *FeatureInfoRaw) UnPack() *FeatureInfoRawT {
if rcv == nil {
return nil
}
t := &FeatureInfoRawT{}
rcv.UnPackTo(t)
return t
}
type FeatureInfoRaw struct {
_tab flatbuffers.Table
}
func GetRootAsFeatureInfoRaw(buf []byte, offset flatbuffers.UOffsetT) *FeatureInfoRaw {
n := flatbuffers.GetUOffsetT(buf[offset:])
x := &FeatureInfoRaw{}
x.Init(buf, n+offset)
return x
}
func GetSizePrefixedRootAsFeatureInfoRaw(buf []byte, offset flatbuffers.UOffsetT) *FeatureInfoRaw {
n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])
x := &FeatureInfoRaw{}
x.Init(buf, n+offset+flatbuffers.SizeUint32)
return x
}
func (rcv *FeatureInfoRaw) Init(buf []byte, i flatbuffers.UOffsetT) {
rcv._tab.Bytes = buf
rcv._tab.Pos = i
}
func (rcv *FeatureInfoRaw) Table() flatbuffers.Table {
return rcv._tab
}
func (rcv *FeatureInfoRaw) Id() Feature {
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
if o != 0 {
return Feature(rcv._tab.GetUint64(o + rcv._tab.Pos))
}
return 0
}
func (rcv *FeatureInfoRaw) MutateId(n Feature) bool {
return rcv._tab.MutateUint64Slot(4, uint64(n))
}
func (rcv *FeatureInfoRaw) NeedSetup() bool {
o := flatbuffers.UOffsetT(rcv._tab.Offset(6))
if o != 0 {
return rcv._tab.GetBool(o + rcv._tab.Pos)
}
return false
}
func (rcv *FeatureInfoRaw) MutateNeedSetup(n bool) bool {
return rcv._tab.MutateBoolSlot(6, n)
}
func (rcv *FeatureInfoRaw) Reason() []byte {
o := flatbuffers.UOffsetT(rcv._tab.Offset(8))
if o != 0 {
return rcv._tab.ByteVector(o + rcv._tab.Pos)
}
return nil
}
func FeatureInfoRawStart(builder *flatbuffers.Builder) {
builder.StartObject(3)
}
func FeatureInfoRawAddId(builder *flatbuffers.Builder, id Feature) {
builder.PrependUint64Slot(0, uint64(id), 0)
}
func FeatureInfoRawAddNeedSetup(builder *flatbuffers.Builder, needSetup bool) {
builder.PrependBoolSlot(1, needSetup, false)
}
func FeatureInfoRawAddReason(builder *flatbuffers.Builder, reason flatbuffers.UOffsetT) {
builder.PrependUOffsetTSlot(2, flatbuffers.UOffsetT(reason), 0)
}
func FeatureInfoRawEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
return builder.EndObject()
}
type HostMessageRawT struct {
Msg *HostMessagesRawT `json:"msg"`
}
func (t *HostMessageRawT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
if t == nil {
return 0
}
msgOffset := t.Msg.Pack(builder)
HostMessageRawStart(builder)
if t.Msg != nil {
HostMessageRawAddMsgType(builder, t.Msg.Type)
}
HostMessageRawAddMsg(builder, msgOffset)
return HostMessageRawEnd(builder)
}
func (rcv *HostMessageRaw) UnPackTo(t *HostMessageRawT) {
msgTable := flatbuffers.Table{}
if rcv.Msg(&msgTable) {
t.Msg = rcv.MsgType().UnPack(msgTable)
}
}
func (rcv *HostMessageRaw) UnPack() *HostMessageRawT {
if rcv == nil {
return nil
}
t := &HostMessageRawT{}
rcv.UnPackTo(t)
return t
}
type HostMessageRaw struct {
_tab flatbuffers.Table
}
func GetRootAsHostMessageRaw(buf []byte, offset flatbuffers.UOffsetT) *HostMessageRaw {
n := flatbuffers.GetUOffsetT(buf[offset:])
x := &HostMessageRaw{}
x.Init(buf, n+offset)
return x
}
func GetSizePrefixedRootAsHostMessageRaw(buf []byte, offset flatbuffers.UOffsetT) *HostMessageRaw {
n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])
x := &HostMessageRaw{}
x.Init(buf, n+offset+flatbuffers.SizeUint32)
return x
}
func (rcv *HostMessageRaw) Init(buf []byte, i flatbuffers.UOffsetT) {
rcv._tab.Bytes = buf
rcv._tab.Pos = i
}
func (rcv *HostMessageRaw) Table() flatbuffers.Table {
return rcv._tab
}
func (rcv *HostMessageRaw) MsgType() HostMessagesRaw {
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
if o != 0 {
return HostMessagesRaw(rcv._tab.GetByte(o + rcv._tab.Pos))
}
return 0
}
func (rcv *HostMessageRaw) MutateMsgType(n HostMessagesRaw) bool {
return rcv._tab.MutateByteSlot(4, byte(n))
}
func (rcv *HostMessageRaw) Msg(obj *flatbuffers.Table) bool {
o := flatbuffers.UOffsetT(rcv._tab.Offset(6))
if o != 0 {
rcv._tab.Union(obj, o)
return true
}
return false
}
func HostMessageRawStart(builder *flatbuffers.Builder) {
builder.StartObject(2)
}
func HostMessageRawAddMsgType(builder *flatbuffers.Builder, msgType HostMessagesRaw) {
builder.PrependByteSlot(0, byte(msgType), 0)
}
func HostMessageRawAddMsg(builder *flatbuffers.Builder, msg flatbuffers.UOffsetT) {
builder.PrependUOffsetTSlot(1, flatbuffers.UOffsetT(msg), 0)
}
func HostMessageRawEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
return builder.EndObject()
}
type ExecutorMessageRawT struct {
Msg *ExecutorMessagesRawT `json:"msg"`
}
func (t *ExecutorMessageRawT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
if t == nil {
return 0
}
msgOffset := t.Msg.Pack(builder)
ExecutorMessageRawStart(builder)
if t.Msg != nil {
ExecutorMessageRawAddMsgType(builder, t.Msg.Type)
}
ExecutorMessageRawAddMsg(builder, msgOffset)
return ExecutorMessageRawEnd(builder)
}
func (rcv *ExecutorMessageRaw) UnPackTo(t *ExecutorMessageRawT) {
msgTable := flatbuffers.Table{}
if rcv.Msg(&msgTable) {
t.Msg = rcv.MsgType().UnPack(msgTable)
}
}
func (rcv *ExecutorMessageRaw) UnPack() *ExecutorMessageRawT {
if rcv == nil {
return nil
}
t := &ExecutorMessageRawT{}
rcv.UnPackTo(t)
return t
}
type ExecutorMessageRaw struct {
_tab flatbuffers.Table
}
func GetRootAsExecutorMessageRaw(buf []byte, offset flatbuffers.UOffsetT) *ExecutorMessageRaw {
n := flatbuffers.GetUOffsetT(buf[offset:])
x := &ExecutorMessageRaw{}
x.Init(buf, n+offset)
return x
}
func GetSizePrefixedRootAsExecutorMessageRaw(buf []byte, offset flatbuffers.UOffsetT) *ExecutorMessageRaw {
n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])
x := &ExecutorMessageRaw{}
x.Init(buf, n+offset+flatbuffers.SizeUint32)
return x
}
func (rcv *ExecutorMessageRaw) Init(buf []byte, i flatbuffers.UOffsetT) {
rcv._tab.Bytes = buf
rcv._tab.Pos = i
}
func (rcv *ExecutorMessageRaw) Table() flatbuffers.Table {
return rcv._tab
}
func (rcv *ExecutorMessageRaw) MsgType() ExecutorMessagesRaw {
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
if o != 0 {
return ExecutorMessagesRaw(rcv._tab.GetByte(o + rcv._tab.Pos))
}
return 0
}
func (rcv *ExecutorMessageRaw) MutateMsgType(n ExecutorMessagesRaw) bool {
return rcv._tab.MutateByteSlot(4, byte(n))
}
func (rcv *ExecutorMessageRaw) Msg(obj *flatbuffers.Table) bool {
o := flatbuffers.UOffsetT(rcv._tab.Offset(6))
if o != 0 {
rcv._tab.Union(obj, o)
return true
}
return false
}
func ExecutorMessageRawStart(builder *flatbuffers.Builder) {
builder.StartObject(2)
}
func ExecutorMessageRawAddMsgType(builder *flatbuffers.Builder, msgType ExecutorMessagesRaw) {
builder.PrependByteSlot(0, byte(msgType), 0)
}
func ExecutorMessageRawAddMsg(builder *flatbuffers.Builder, msg flatbuffers.UOffsetT) {
builder.PrependUOffsetTSlot(1, flatbuffers.UOffsetT(msg), 0)
}
func ExecutorMessageRawEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
return builder.EndObject()
}
type ExecOptsRawT struct {
EnvFlags ExecEnv `json:"env_flags"`
ExecFlags ExecFlag `json:"exec_flags"`
SandboxArg int64 `json:"sandbox_arg"`
}
func (t *ExecOptsRawT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
if t == nil {
return 0
}
return CreateExecOptsRaw(builder, t.EnvFlags, t.ExecFlags, t.SandboxArg)
}
func (rcv *ExecOptsRaw) UnPackTo(t *ExecOptsRawT) {
t.EnvFlags = rcv.EnvFlags()
t.ExecFlags = rcv.ExecFlags()
t.SandboxArg = rcv.SandboxArg()
}
func (rcv *ExecOptsRaw) UnPack() *ExecOptsRawT {
if rcv == nil {
return nil
}
t := &ExecOptsRawT{}
rcv.UnPackTo(t)
return t
}
type ExecOptsRaw struct {
_tab flatbuffers.Struct
}
func (rcv *ExecOptsRaw) Init(buf []byte, i flatbuffers.UOffsetT) {
rcv._tab.Bytes = buf
rcv._tab.Pos = i
}
func (rcv *ExecOptsRaw) Table() flatbuffers.Table {
return rcv._tab.Table
}
func (rcv *ExecOptsRaw) EnvFlags() ExecEnv {
return ExecEnv(rcv._tab.GetUint64(rcv._tab.Pos + flatbuffers.UOffsetT(0)))
}
func (rcv *ExecOptsRaw) MutateEnvFlags(n ExecEnv) bool {
return rcv._tab.MutateUint64(rcv._tab.Pos+flatbuffers.UOffsetT(0), uint64(n))
}
func (rcv *ExecOptsRaw) ExecFlags() ExecFlag {
return ExecFlag(rcv._tab.GetUint64(rcv._tab.Pos + flatbuffers.UOffsetT(8)))
}
func (rcv *ExecOptsRaw) MutateExecFlags(n ExecFlag) bool {
return rcv._tab.MutateUint64(rcv._tab.Pos+flatbuffers.UOffsetT(8), uint64(n))
}
func (rcv *ExecOptsRaw) SandboxArg() int64 {
return rcv._tab.GetInt64(rcv._tab.Pos + flatbuffers.UOffsetT(16))
}
func (rcv *ExecOptsRaw) MutateSandboxArg(n int64) bool {
return rcv._tab.MutateInt64(rcv._tab.Pos+flatbuffers.UOffsetT(16), n)
}
func CreateExecOptsRaw(builder *flatbuffers.Builder, envFlags ExecEnv, execFlags ExecFlag, sandboxArg int64) flatbuffers.UOffsetT {
builder.Prep(8, 24)
builder.PrependInt64(sandboxArg)
builder.PrependUint64(uint64(execFlags))
builder.PrependUint64(uint64(envFlags))
return builder.Offset()
}
type ExecRequestRawT struct {
Id int64 `json:"id"`
Type RequestType `json:"type"`
Avoid uint64 `json:"avoid"`
Data []byte `json:"data"`
ExecOpts *ExecOptsRawT `json:"exec_opts"`
Flags RequestFlag `json:"flags"`
AllSignal []int32 `json:"all_signal"`
}
func (t *ExecRequestRawT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
if t == nil {
return 0
}
dataOffset := flatbuffers.UOffsetT(0)
if t.Data != nil {
dataOffset = builder.CreateByteString(t.Data)
}
allSignalOffset := flatbuffers.UOffsetT(0)
if t.AllSignal != nil {
allSignalLength := len(t.AllSignal)
ExecRequestRawStartAllSignalVector(builder, allSignalLength)
for j := allSignalLength - 1; j >= 0; j-- {
builder.PrependInt32(t.AllSignal[j])
}
allSignalOffset = builder.EndVector(allSignalLength)
}
ExecRequestRawStart(builder)
ExecRequestRawAddId(builder, t.Id)
ExecRequestRawAddType(builder, t.Type)
ExecRequestRawAddAvoid(builder, t.Avoid)
ExecRequestRawAddData(builder, dataOffset)
execOptsOffset := t.ExecOpts.Pack(builder)
ExecRequestRawAddExecOpts(builder, execOptsOffset)
ExecRequestRawAddFlags(builder, t.Flags)
ExecRequestRawAddAllSignal(builder, allSignalOffset)
return ExecRequestRawEnd(builder)
}
func (rcv *ExecRequestRaw) UnPackTo(t *ExecRequestRawT) {
t.Id = rcv.Id()
t.Type = rcv.Type()
t.Avoid = rcv.Avoid()
t.Data = rcv.DataBytes()
t.ExecOpts = rcv.ExecOpts(nil).UnPack()
t.Flags = rcv.Flags()
allSignalLength := rcv.AllSignalLength()
t.AllSignal = make([]int32, allSignalLength)
for j := 0; j < allSignalLength; j++ {
t.AllSignal[j] = rcv.AllSignal(j)
}
}
func (rcv *ExecRequestRaw) UnPack() *ExecRequestRawT {
if rcv == nil {
return nil
}
t := &ExecRequestRawT{}
rcv.UnPackTo(t)
return t
}
type ExecRequestRaw struct {
_tab flatbuffers.Table
}
func GetRootAsExecRequestRaw(buf []byte, offset flatbuffers.UOffsetT) *ExecRequestRaw {
n := flatbuffers.GetUOffsetT(buf[offset:])
x := &ExecRequestRaw{}
x.Init(buf, n+offset)
return x
}
func GetSizePrefixedRootAsExecRequestRaw(buf []byte, offset flatbuffers.UOffsetT) *ExecRequestRaw {
n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])
x := &ExecRequestRaw{}
x.Init(buf, n+offset+flatbuffers.SizeUint32)
return x
}
func (rcv *ExecRequestRaw) Init(buf []byte, i flatbuffers.UOffsetT) {
rcv._tab.Bytes = buf
rcv._tab.Pos = i
}
func (rcv *ExecRequestRaw) Table() flatbuffers.Table {
return rcv._tab
}
func (rcv *ExecRequestRaw) Id() int64 {
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
if o != 0 {
return rcv._tab.GetInt64(o + rcv._tab.Pos)
}
return 0
}
func (rcv *ExecRequestRaw) MutateId(n int64) bool {
return rcv._tab.MutateInt64Slot(4, n)
}
func (rcv *ExecRequestRaw) Type() RequestType {
o := flatbuffers.UOffsetT(rcv._tab.Offset(6))
if o != 0 {
return RequestType(rcv._tab.GetUint64(o + rcv._tab.Pos))
}
return 0
}
func (rcv *ExecRequestRaw) MutateType(n RequestType) bool {
return rcv._tab.MutateUint64Slot(6, uint64(n))
}
func (rcv *ExecRequestRaw) Avoid() uint64 {
o := flatbuffers.UOffsetT(rcv._tab.Offset(8))
if o != 0 {
return rcv._tab.GetUint64(o + rcv._tab.Pos)
}
return 0
}
func (rcv *ExecRequestRaw) MutateAvoid(n uint64) bool {
return rcv._tab.MutateUint64Slot(8, n)
}
func (rcv *ExecRequestRaw) Data(j int) byte {
o := flatbuffers.UOffsetT(rcv._tab.Offset(10))
if o != 0 {
a := rcv._tab.Vector(o)
return rcv._tab.GetByte(a + flatbuffers.UOffsetT(j*1))
}
return 0
}
func (rcv *ExecRequestRaw) DataLength() int {
o := flatbuffers.UOffsetT(rcv._tab.Offset(10))
if o != 0 {
return rcv._tab.VectorLen(o)
}
return 0
}
func (rcv *ExecRequestRaw) DataBytes() []byte {
o := flatbuffers.UOffsetT(rcv._tab.Offset(10))
if o != 0 {
return rcv._tab.ByteVector(o + rcv._tab.Pos)
}
return nil
}
func (rcv *ExecRequestRaw) MutateData(j int, n byte) bool {
o := flatbuffers.UOffsetT(rcv._tab.Offset(10))
if o != 0 {
a := rcv._tab.Vector(o)
return rcv._tab.MutateByte(a+flatbuffers.UOffsetT(j*1), n)
}
return false
}
func (rcv *ExecRequestRaw) ExecOpts(obj *ExecOptsRaw) *ExecOptsRaw {
o := flatbuffers.UOffsetT(rcv._tab.Offset(12))
if o != 0 {
x := o + rcv._tab.Pos
if obj == nil {
obj = new(ExecOptsRaw)
}
obj.Init(rcv._tab.Bytes, x)
return obj
}
return nil
}
func (rcv *ExecRequestRaw) Flags() RequestFlag {
o := flatbuffers.UOffsetT(rcv._tab.Offset(14))
if o != 0 {
return RequestFlag(rcv._tab.GetUint64(o + rcv._tab.Pos))
}
return 0
}
func (rcv *ExecRequestRaw) MutateFlags(n RequestFlag) bool {
return rcv._tab.MutateUint64Slot(14, uint64(n))
}
func (rcv *ExecRequestRaw) AllSignal(j int) int32 {
o := flatbuffers.UOffsetT(rcv._tab.Offset(16))
if o != 0 {
a := rcv._tab.Vector(o)
return rcv._tab.GetInt32(a + flatbuffers.UOffsetT(j*4))
}
return 0
}
func (rcv *ExecRequestRaw) AllSignalLength() int {
o := flatbuffers.UOffsetT(rcv._tab.Offset(16))
if o != 0 {
return rcv._tab.VectorLen(o)
}
return 0
}
func (rcv *ExecRequestRaw) MutateAllSignal(j int, n int32) bool {
o := flatbuffers.UOffsetT(rcv._tab.Offset(16))
if o != 0 {
a := rcv._tab.Vector(o)
return rcv._tab.MutateInt32(a+flatbuffers.UOffsetT(j*4), n)
}
return false
}
func ExecRequestRawStart(builder *flatbuffers.Builder) {
builder.StartObject(7)
}
func ExecRequestRawAddId(builder *flatbuffers.Builder, id int64) {
builder.PrependInt64Slot(0, id, 0)
}
func ExecRequestRawAddType(builder *flatbuffers.Builder, type_ RequestType) {
builder.PrependUint64Slot(1, uint64(type_), 0)
}
func ExecRequestRawAddAvoid(builder *flatbuffers.Builder, avoid uint64) {
builder.PrependUint64Slot(2, avoid, 0)
}
func ExecRequestRawAddData(builder *flatbuffers.Builder, data flatbuffers.UOffsetT) {
builder.PrependUOffsetTSlot(3, flatbuffers.UOffsetT(data), 0)
}
func ExecRequestRawStartDataVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT {
return builder.StartVector(1, numElems, 1)
}
func ExecRequestRawAddExecOpts(builder *flatbuffers.Builder, execOpts flatbuffers.UOffsetT) {
builder.PrependStructSlot(4, flatbuffers.UOffsetT(execOpts), 0)
}
func ExecRequestRawAddFlags(builder *flatbuffers.Builder, flags RequestFlag) {
builder.PrependUint64Slot(5, uint64(flags), 0)
}
func ExecRequestRawAddAllSignal(builder *flatbuffers.Builder, allSignal flatbuffers.UOffsetT) {
builder.PrependUOffsetTSlot(6, flatbuffers.UOffsetT(allSignal), 0)
}
func ExecRequestRawStartAllSignalVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT {
return builder.StartVector(4, numElems, 4)
}
func ExecRequestRawEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
return builder.EndObject()
}
type SignalUpdateRawT struct {
NewMax []uint64 `json:"new_max"`
}
func (t *SignalUpdateRawT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
if t == nil {
return 0
}
newMaxOffset := flatbuffers.UOffsetT(0)
if t.NewMax != nil {
newMaxLength := len(t.NewMax)
SignalUpdateRawStartNewMaxVector(builder, newMaxLength)
for j := newMaxLength - 1; j >= 0; j-- {
builder.PrependUint64(t.NewMax[j])
}
newMaxOffset = builder.EndVector(newMaxLength)
}
SignalUpdateRawStart(builder)
SignalUpdateRawAddNewMax(builder, newMaxOffset)
return SignalUpdateRawEnd(builder)
}
func (rcv *SignalUpdateRaw) UnPackTo(t *SignalUpdateRawT) {
newMaxLength := rcv.NewMaxLength()
t.NewMax = make([]uint64, newMaxLength)
for j := 0; j < newMaxLength; j++ {
t.NewMax[j] = rcv.NewMax(j)
}
}
func (rcv *SignalUpdateRaw) UnPack() *SignalUpdateRawT {
if rcv == nil {
return nil
}
t := &SignalUpdateRawT{}
rcv.UnPackTo(t)
return t
}
type SignalUpdateRaw struct {
_tab flatbuffers.Table
}
func GetRootAsSignalUpdateRaw(buf []byte, offset flatbuffers.UOffsetT) *SignalUpdateRaw {
n := flatbuffers.GetUOffsetT(buf[offset:])
x := &SignalUpdateRaw{}
x.Init(buf, n+offset)
return x
}
func GetSizePrefixedRootAsSignalUpdateRaw(buf []byte, offset flatbuffers.UOffsetT) *SignalUpdateRaw {
n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])
x := &SignalUpdateRaw{}
x.Init(buf, n+offset+flatbuffers.SizeUint32)
return x
}
func (rcv *SignalUpdateRaw) Init(buf []byte, i flatbuffers.UOffsetT) {
rcv._tab.Bytes = buf
rcv._tab.Pos = i
}
func (rcv *SignalUpdateRaw) Table() flatbuffers.Table {
return rcv._tab
}
func (rcv *SignalUpdateRaw) NewMax(j int) uint64 {
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
if o != 0 {
a := rcv._tab.Vector(o)
return rcv._tab.GetUint64(a + flatbuffers.UOffsetT(j*8))
}
return 0
}
func (rcv *SignalUpdateRaw) NewMaxLength() int {
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
if o != 0 {
return rcv._tab.VectorLen(o)
}
return 0
}
func (rcv *SignalUpdateRaw) MutateNewMax(j int, n uint64) bool {
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
if o != 0 {
a := rcv._tab.Vector(o)
return rcv._tab.MutateUint64(a+flatbuffers.UOffsetT(j*8), n)
}
return false
}
func SignalUpdateRawStart(builder *flatbuffers.Builder) {
builder.StartObject(1)
}
func SignalUpdateRawAddNewMax(builder *flatbuffers.Builder, newMax flatbuffers.UOffsetT) {
builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(newMax), 0)
}
func SignalUpdateRawStartNewMaxVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT {
return builder.StartVector(8, numElems, 8)
}
func SignalUpdateRawEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
return builder.EndObject()
}
type CorpusTriagedRawT struct {
}
func (t *CorpusTriagedRawT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
if t == nil {
return 0
}
CorpusTriagedRawStart(builder)
return CorpusTriagedRawEnd(builder)
}
func (rcv *CorpusTriagedRaw) UnPackTo(t *CorpusTriagedRawT) {
}
func (rcv *CorpusTriagedRaw) UnPack() *CorpusTriagedRawT {
if rcv == nil {
return nil
}
t := &CorpusTriagedRawT{}
rcv.UnPackTo(t)
return t
}
type CorpusTriagedRaw struct {
_tab flatbuffers.Table
}
func GetRootAsCorpusTriagedRaw(buf []byte, offset flatbuffers.UOffsetT) *CorpusTriagedRaw {
n := flatbuffers.GetUOffsetT(buf[offset:])
x := &CorpusTriagedRaw{}
x.Init(buf, n+offset)
return x
}
func GetSizePrefixedRootAsCorpusTriagedRaw(buf []byte, offset flatbuffers.UOffsetT) *CorpusTriagedRaw {
n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])
x := &CorpusTriagedRaw{}
x.Init(buf, n+offset+flatbuffers.SizeUint32)
return x
}
func (rcv *CorpusTriagedRaw) Init(buf []byte, i flatbuffers.UOffsetT) {
rcv._tab.Bytes = buf
rcv._tab.Pos = i
}
func (rcv *CorpusTriagedRaw) Table() flatbuffers.Table {
return rcv._tab
}
func CorpusTriagedRawStart(builder *flatbuffers.Builder) {
builder.StartObject(0)
}
func CorpusTriagedRawEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
return builder.EndObject()
}
type StateRequestRawT struct {
}
func (t *StateRequestRawT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
if t == nil {
return 0
}
StateRequestRawStart(builder)
return StateRequestRawEnd(builder)
}
func (rcv *StateRequestRaw) UnPackTo(t *StateRequestRawT) {
}
func (rcv *StateRequestRaw) UnPack() *StateRequestRawT {
if rcv == nil {
return nil
}
t := &StateRequestRawT{}
rcv.UnPackTo(t)
return t
}
type StateRequestRaw struct {
_tab flatbuffers.Table
}
func GetRootAsStateRequestRaw(buf []byte, offset flatbuffers.UOffsetT) *StateRequestRaw {
n := flatbuffers.GetUOffsetT(buf[offset:])
x := &StateRequestRaw{}
x.Init(buf, n+offset)
return x
}
func GetSizePrefixedRootAsStateRequestRaw(buf []byte, offset flatbuffers.UOffsetT) *StateRequestRaw {
n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])
x := &StateRequestRaw{}
x.Init(buf, n+offset+flatbuffers.SizeUint32)
return x
}
func (rcv *StateRequestRaw) Init(buf []byte, i flatbuffers.UOffsetT) {
rcv._tab.Bytes = buf
rcv._tab.Pos = i
}
func (rcv *StateRequestRaw) Table() flatbuffers.Table {
return rcv._tab
}
func StateRequestRawStart(builder *flatbuffers.Builder) {
builder.StartObject(0)
}
func StateRequestRawEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
return builder.EndObject()
}
type ExecutingMessageRawT struct {
Id int64 `json:"id"`
ProcId int32 `json:"proc_id"`
Try int32 `json:"try"`
WaitDuration int64 `json:"wait_duration"`
}
func (t *ExecutingMessageRawT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
if t == nil {
return 0
}
ExecutingMessageRawStart(builder)
ExecutingMessageRawAddId(builder, t.Id)
ExecutingMessageRawAddProcId(builder, t.ProcId)
ExecutingMessageRawAddTry(builder, t.Try)
ExecutingMessageRawAddWaitDuration(builder, t.WaitDuration)
return ExecutingMessageRawEnd(builder)
}
func (rcv *ExecutingMessageRaw) UnPackTo(t *ExecutingMessageRawT) {
t.Id = rcv.Id()
t.ProcId = rcv.ProcId()
t.Try = rcv.Try()
t.WaitDuration = rcv.WaitDuration()
}
func (rcv *ExecutingMessageRaw) UnPack() *ExecutingMessageRawT {
if rcv == nil {
return nil
}
t := &ExecutingMessageRawT{}
rcv.UnPackTo(t)
return t
}
type ExecutingMessageRaw struct {
_tab flatbuffers.Table
}
func GetRootAsExecutingMessageRaw(buf []byte, offset flatbuffers.UOffsetT) *ExecutingMessageRaw {
n := flatbuffers.GetUOffsetT(buf[offset:])
x := &ExecutingMessageRaw{}
x.Init(buf, n+offset)
return x
}
func GetSizePrefixedRootAsExecutingMessageRaw(buf []byte, offset flatbuffers.UOffsetT) *ExecutingMessageRaw {
n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])
x := &ExecutingMessageRaw{}
x.Init(buf, n+offset+flatbuffers.SizeUint32)
return x
}
func (rcv *ExecutingMessageRaw) Init(buf []byte, i flatbuffers.UOffsetT) {
rcv._tab.Bytes = buf
rcv._tab.Pos = i
}
func (rcv *ExecutingMessageRaw) Table() flatbuffers.Table {
return rcv._tab
}
func (rcv *ExecutingMessageRaw) Id() int64 {
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
if o != 0 {
return rcv._tab.GetInt64(o + rcv._tab.Pos)
}
return 0
}
func (rcv *ExecutingMessageRaw) MutateId(n int64) bool {
return rcv._tab.MutateInt64Slot(4, n)
}
func (rcv *ExecutingMessageRaw) ProcId() int32 {
o := flatbuffers.UOffsetT(rcv._tab.Offset(6))
if o != 0 {
return rcv._tab.GetInt32(o + rcv._tab.Pos)
}
return 0
}
func (rcv *ExecutingMessageRaw) MutateProcId(n int32) bool {
return rcv._tab.MutateInt32Slot(6, n)
}
func (rcv *ExecutingMessageRaw) Try() int32 {
o := flatbuffers.UOffsetT(rcv._tab.Offset(8))
if o != 0 {
return rcv._tab.GetInt32(o + rcv._tab.Pos)
}
return 0
}
func (rcv *ExecutingMessageRaw) MutateTry(n int32) bool {
return rcv._tab.MutateInt32Slot(8, n)
}
func (rcv *ExecutingMessageRaw) WaitDuration() int64 {
o := flatbuffers.UOffsetT(rcv._tab.Offset(10))
if o != 0 {
return rcv._tab.GetInt64(o + rcv._tab.Pos)
}
return 0
}
func (rcv *ExecutingMessageRaw) MutateWaitDuration(n int64) bool {
return rcv._tab.MutateInt64Slot(10, n)
}
func ExecutingMessageRawStart(builder *flatbuffers.Builder) {
builder.StartObject(4)
}
func ExecutingMessageRawAddId(builder *flatbuffers.Builder, id int64) {
builder.PrependInt64Slot(0, id, 0)
}
func ExecutingMessageRawAddProcId(builder *flatbuffers.Builder, procId int32) {
builder.PrependInt32Slot(1, procId, 0)
}
func ExecutingMessageRawAddTry(builder *flatbuffers.Builder, try int32) {
builder.PrependInt32Slot(2, try, 0)
}
func ExecutingMessageRawAddWaitDuration(builder *flatbuffers.Builder, waitDuration int64) {
builder.PrependInt64Slot(3, waitDuration, 0)
}
func ExecutingMessageRawEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
return builder.EndObject()
}
type CallInfoRawT struct {
Flags CallFlag `json:"flags"`
Error int32 `json:"error"`
Signal []uint64 `json:"signal"`
Cover []uint64 `json:"cover"`
Comps []*ComparisonRawT `json:"comps"`
}
func (t *CallInfoRawT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
if t == nil {
return 0
}
signalOffset := flatbuffers.UOffsetT(0)
if t.Signal != nil {
signalLength := len(t.Signal)
CallInfoRawStartSignalVector(builder, signalLength)
for j := signalLength - 1; j >= 0; j-- {
builder.PrependUint64(t.Signal[j])
}
signalOffset = builder.EndVector(signalLength)
}
coverOffset := flatbuffers.UOffsetT(0)
if t.Cover != nil {
coverLength := len(t.Cover)
CallInfoRawStartCoverVector(builder, coverLength)
for j := coverLength - 1; j >= 0; j-- {
builder.PrependUint64(t.Cover[j])
}
coverOffset = builder.EndVector(coverLength)
}
compsOffset := flatbuffers.UOffsetT(0)
if t.Comps != nil {
compsLength := len(t.Comps)
CallInfoRawStartCompsVector(builder, compsLength)
for j := compsLength - 1; j >= 0; j-- {
t.Comps[j].Pack(builder)
}
compsOffset = builder.EndVector(compsLength)
}
CallInfoRawStart(builder)
CallInfoRawAddFlags(builder, t.Flags)
CallInfoRawAddError(builder, t.Error)
CallInfoRawAddSignal(builder, signalOffset)
CallInfoRawAddCover(builder, coverOffset)
CallInfoRawAddComps(builder, compsOffset)
return CallInfoRawEnd(builder)
}
func (rcv *CallInfoRaw) UnPackTo(t *CallInfoRawT) {
t.Flags = rcv.Flags()
t.Error = rcv.Error()
signalLength := rcv.SignalLength()
t.Signal = make([]uint64, signalLength)
for j := 0; j < signalLength; j++ {
t.Signal[j] = rcv.Signal(j)
}
coverLength := rcv.CoverLength()
t.Cover = make([]uint64, coverLength)
for j := 0; j < coverLength; j++ {
t.Cover[j] = rcv.Cover(j)
}
compsLength := rcv.CompsLength()
t.Comps = make([]*ComparisonRawT, compsLength)
for j := 0; j < compsLength; j++ {
x := ComparisonRaw{}
rcv.Comps(&x, j)
t.Comps[j] = x.UnPack()
}
}
func (rcv *CallInfoRaw) UnPack() *CallInfoRawT {
if rcv == nil {
return nil
}
t := &CallInfoRawT{}
rcv.UnPackTo(t)
return t
}
type CallInfoRaw struct {
_tab flatbuffers.Table
}
func GetRootAsCallInfoRaw(buf []byte, offset flatbuffers.UOffsetT) *CallInfoRaw {
n := flatbuffers.GetUOffsetT(buf[offset:])
x := &CallInfoRaw{}
x.Init(buf, n+offset)
return x
}
func GetSizePrefixedRootAsCallInfoRaw(buf []byte, offset flatbuffers.UOffsetT) *CallInfoRaw {
n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])
x := &CallInfoRaw{}
x.Init(buf, n+offset+flatbuffers.SizeUint32)
return x
}
func (rcv *CallInfoRaw) Init(buf []byte, i flatbuffers.UOffsetT) {
rcv._tab.Bytes = buf
rcv._tab.Pos = i
}
func (rcv *CallInfoRaw) Table() flatbuffers.Table {
return rcv._tab
}
func (rcv *CallInfoRaw) Flags() CallFlag {
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
if o != 0 {
return CallFlag(rcv._tab.GetByte(o + rcv._tab.Pos))
}
return 0
}
func (rcv *CallInfoRaw) MutateFlags(n CallFlag) bool {
return rcv._tab.MutateByteSlot(4, byte(n))
}
func (rcv *CallInfoRaw) Error() int32 {
o := flatbuffers.UOffsetT(rcv._tab.Offset(6))
if o != 0 {
return rcv._tab.GetInt32(o + rcv._tab.Pos)
}
return 0
}
func (rcv *CallInfoRaw) MutateError(n int32) bool {
return rcv._tab.MutateInt32Slot(6, n)
}
func (rcv *CallInfoRaw) Signal(j int) uint64 {
o := flatbuffers.UOffsetT(rcv._tab.Offset(8))
if o != 0 {
a := rcv._tab.Vector(o)
return rcv._tab.GetUint64(a + flatbuffers.UOffsetT(j*8))
}
return 0
}
func (rcv *CallInfoRaw) SignalLength() int {
o := flatbuffers.UOffsetT(rcv._tab.Offset(8))
if o != 0 {
return rcv._tab.VectorLen(o)
}
return 0
}
func (rcv *CallInfoRaw) MutateSignal(j int, n uint64) bool {
o := flatbuffers.UOffsetT(rcv._tab.Offset(8))
if o != 0 {
a := rcv._tab.Vector(o)
return rcv._tab.MutateUint64(a+flatbuffers.UOffsetT(j*8), n)
}
return false
}
func (rcv *CallInfoRaw) Cover(j int) uint64 {
o := flatbuffers.UOffsetT(rcv._tab.Offset(10))
if o != 0 {
a := rcv._tab.Vector(o)
return rcv._tab.GetUint64(a + flatbuffers.UOffsetT(j*8))
}
return 0
}
func (rcv *CallInfoRaw) CoverLength() int {
o := flatbuffers.UOffsetT(rcv._tab.Offset(10))
if o != 0 {
return rcv._tab.VectorLen(o)
}
return 0
}
func (rcv *CallInfoRaw) MutateCover(j int, n uint64) bool {
o := flatbuffers.UOffsetT(rcv._tab.Offset(10))
if o != 0 {
a := rcv._tab.Vector(o)
return rcv._tab.MutateUint64(a+flatbuffers.UOffsetT(j*8), n)
}
return false
}
func (rcv *CallInfoRaw) Comps(obj *ComparisonRaw, j int) bool {
o := flatbuffers.UOffsetT(rcv._tab.Offset(12))
if o != 0 {
x := rcv._tab.Vector(o)
x += flatbuffers.UOffsetT(j) * 32
obj.Init(rcv._tab.Bytes, x)
return true
}
return false
}
func (rcv *CallInfoRaw) CompsLength() int {
o := flatbuffers.UOffsetT(rcv._tab.Offset(12))
if o != 0 {
return rcv._tab.VectorLen(o)
}
return 0
}
func CallInfoRawStart(builder *flatbuffers.Builder) {
builder.StartObject(5)
}
func CallInfoRawAddFlags(builder *flatbuffers.Builder, flags CallFlag) {
builder.PrependByteSlot(0, byte(flags), 0)
}
func CallInfoRawAddError(builder *flatbuffers.Builder, error int32) {
builder.PrependInt32Slot(1, error, 0)
}
func CallInfoRawAddSignal(builder *flatbuffers.Builder, signal flatbuffers.UOffsetT) {
builder.PrependUOffsetTSlot(2, flatbuffers.UOffsetT(signal), 0)
}
func CallInfoRawStartSignalVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT {
return builder.StartVector(8, numElems, 8)
}
func CallInfoRawAddCover(builder *flatbuffers.Builder, cover flatbuffers.UOffsetT) {
builder.PrependUOffsetTSlot(3, flatbuffers.UOffsetT(cover), 0)
}
func CallInfoRawStartCoverVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT {
return builder.StartVector(8, numElems, 8)
}
func CallInfoRawAddComps(builder *flatbuffers.Builder, comps flatbuffers.UOffsetT) {
builder.PrependUOffsetTSlot(4, flatbuffers.UOffsetT(comps), 0)
}
func CallInfoRawStartCompsVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT {
return builder.StartVector(32, numElems, 8)
}
func CallInfoRawEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
return builder.EndObject()
}
type ComparisonRawT struct {
Pc uint64 `json:"pc"`
Op1 uint64 `json:"op1"`
Op2 uint64 `json:"op2"`
IsConst bool `json:"is_const"`
}
func (t *ComparisonRawT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
if t == nil {
return 0
}
return CreateComparisonRaw(builder, t.Pc, t.Op1, t.Op2, t.IsConst)
}
func (rcv *ComparisonRaw) UnPackTo(t *ComparisonRawT) {
t.Pc = rcv.Pc()
t.Op1 = rcv.Op1()
t.Op2 = rcv.Op2()
t.IsConst = rcv.IsConst()
}
func (rcv *ComparisonRaw) UnPack() *ComparisonRawT {
if rcv == nil {
return nil
}
t := &ComparisonRawT{}
rcv.UnPackTo(t)
return t
}
type ComparisonRaw struct {
_tab flatbuffers.Struct
}
func (rcv *ComparisonRaw) Init(buf []byte, i flatbuffers.UOffsetT) {
rcv._tab.Bytes = buf
rcv._tab.Pos = i
}
func (rcv *ComparisonRaw) Table() flatbuffers.Table {
return rcv._tab.Table
}
func (rcv *ComparisonRaw) Pc() uint64 {
return rcv._tab.GetUint64(rcv._tab.Pos + flatbuffers.UOffsetT(0))
}
func (rcv *ComparisonRaw) MutatePc(n uint64) bool {
return rcv._tab.MutateUint64(rcv._tab.Pos+flatbuffers.UOffsetT(0), n)
}
func (rcv *ComparisonRaw) Op1() uint64 {
return rcv._tab.GetUint64(rcv._tab.Pos + flatbuffers.UOffsetT(8))
}
func (rcv *ComparisonRaw) MutateOp1(n uint64) bool {
return rcv._tab.MutateUint64(rcv._tab.Pos+flatbuffers.UOffsetT(8), n)
}
func (rcv *ComparisonRaw) Op2() uint64 {
return rcv._tab.GetUint64(rcv._tab.Pos + flatbuffers.UOffsetT(16))
}
func (rcv *ComparisonRaw) MutateOp2(n uint64) bool {
return rcv._tab.MutateUint64(rcv._tab.Pos+flatbuffers.UOffsetT(16), n)
}
func (rcv *ComparisonRaw) IsConst() bool {
return rcv._tab.GetBool(rcv._tab.Pos + flatbuffers.UOffsetT(24))
}
func (rcv *ComparisonRaw) MutateIsConst(n bool) bool {
return rcv._tab.MutateBool(rcv._tab.Pos+flatbuffers.UOffsetT(24), n)
}
func CreateComparisonRaw(builder *flatbuffers.Builder, pc uint64, op1 uint64, op2 uint64, isConst bool) flatbuffers.UOffsetT {
builder.Prep(8, 32)
builder.Pad(7)
builder.PrependBool(isConst)
builder.PrependUint64(op2)
builder.PrependUint64(op1)
builder.PrependUint64(pc)
return builder.Offset()
}
type ProgInfoRawT struct {
Calls []*CallInfoRawT `json:"calls"`
ExtraRaw []*CallInfoRawT `json:"extra_raw"`
Extra *CallInfoRawT `json:"extra"`
Elapsed uint64 `json:"elapsed"`
Freshness uint64 `json:"freshness"`
}
func (t *ProgInfoRawT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
if t == nil {
return 0
}
callsOffset := flatbuffers.UOffsetT(0)
if t.Calls != nil {
callsLength := len(t.Calls)
callsOffsets := make([]flatbuffers.UOffsetT, callsLength)
for j := 0; j < callsLength; j++ {
callsOffsets[j] = t.Calls[j].Pack(builder)
}
ProgInfoRawStartCallsVector(builder, callsLength)
for j := callsLength - 1; j >= 0; j-- {
builder.PrependUOffsetT(callsOffsets[j])
}
callsOffset = builder.EndVector(callsLength)
}
extraRawOffset := flatbuffers.UOffsetT(0)
if t.ExtraRaw != nil {
extraRawLength := len(t.ExtraRaw)
extraRawOffsets := make([]flatbuffers.UOffsetT, extraRawLength)
for j := 0; j < extraRawLength; j++ {
extraRawOffsets[j] = t.ExtraRaw[j].Pack(builder)
}
ProgInfoRawStartExtraRawVector(builder, extraRawLength)
for j := extraRawLength - 1; j >= 0; j-- {
builder.PrependUOffsetT(extraRawOffsets[j])
}
extraRawOffset = builder.EndVector(extraRawLength)
}
extraOffset := t.Extra.Pack(builder)
ProgInfoRawStart(builder)
ProgInfoRawAddCalls(builder, callsOffset)
ProgInfoRawAddExtraRaw(builder, extraRawOffset)
ProgInfoRawAddExtra(builder, extraOffset)
ProgInfoRawAddElapsed(builder, t.Elapsed)
ProgInfoRawAddFreshness(builder, t.Freshness)
return ProgInfoRawEnd(builder)
}
func (rcv *ProgInfoRaw) UnPackTo(t *ProgInfoRawT) {
callsLength := rcv.CallsLength()
t.Calls = make([]*CallInfoRawT, callsLength)
for j := 0; j < callsLength; j++ {
x := CallInfoRaw{}
rcv.Calls(&x, j)
t.Calls[j] = x.UnPack()
}
extraRawLength := rcv.ExtraRawLength()
t.ExtraRaw = make([]*CallInfoRawT, extraRawLength)
for j := 0; j < extraRawLength; j++ {
x := CallInfoRaw{}
rcv.ExtraRaw(&x, j)
t.ExtraRaw[j] = x.UnPack()
}
t.Extra = rcv.Extra(nil).UnPack()
t.Elapsed = rcv.Elapsed()
t.Freshness = rcv.Freshness()
}
func (rcv *ProgInfoRaw) UnPack() *ProgInfoRawT {
if rcv == nil {
return nil
}
t := &ProgInfoRawT{}
rcv.UnPackTo(t)
return t
}
type ProgInfoRaw struct {
_tab flatbuffers.Table
}
func GetRootAsProgInfoRaw(buf []byte, offset flatbuffers.UOffsetT) *ProgInfoRaw {
n := flatbuffers.GetUOffsetT(buf[offset:])
x := &ProgInfoRaw{}
x.Init(buf, n+offset)
return x
}
func GetSizePrefixedRootAsProgInfoRaw(buf []byte, offset flatbuffers.UOffsetT) *ProgInfoRaw {
n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])
x := &ProgInfoRaw{}
x.Init(buf, n+offset+flatbuffers.SizeUint32)
return x
}
func (rcv *ProgInfoRaw) Init(buf []byte, i flatbuffers.UOffsetT) {
rcv._tab.Bytes = buf
rcv._tab.Pos = i
}
func (rcv *ProgInfoRaw) Table() flatbuffers.Table {
return rcv._tab
}
func (rcv *ProgInfoRaw) Calls(obj *CallInfoRaw, j int) bool {
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
if o != 0 {
x := rcv._tab.Vector(o)
x += flatbuffers.UOffsetT(j) * 4
x = rcv._tab.Indirect(x)
obj.Init(rcv._tab.Bytes, x)
return true
}
return false
}
func (rcv *ProgInfoRaw) CallsLength() int {
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
if o != 0 {
return rcv._tab.VectorLen(o)
}
return 0
}
func (rcv *ProgInfoRaw) ExtraRaw(obj *CallInfoRaw, j int) bool {
o := flatbuffers.UOffsetT(rcv._tab.Offset(6))
if o != 0 {
x := rcv._tab.Vector(o)
x += flatbuffers.UOffsetT(j) * 4
x = rcv._tab.Indirect(x)
obj.Init(rcv._tab.Bytes, x)
return true
}
return false
}
func (rcv *ProgInfoRaw) ExtraRawLength() int {
o := flatbuffers.UOffsetT(rcv._tab.Offset(6))
if o != 0 {
return rcv._tab.VectorLen(o)
}
return 0
}
func (rcv *ProgInfoRaw) Extra(obj *CallInfoRaw) *CallInfoRaw {
o := flatbuffers.UOffsetT(rcv._tab.Offset(8))
if o != 0 {
x := rcv._tab.Indirect(o + rcv._tab.Pos)
if obj == nil {
obj = new(CallInfoRaw)
}
obj.Init(rcv._tab.Bytes, x)
return obj
}
return nil
}
func (rcv *ProgInfoRaw) Elapsed() uint64 {
o := flatbuffers.UOffsetT(rcv._tab.Offset(10))
if o != 0 {
return rcv._tab.GetUint64(o + rcv._tab.Pos)
}
return 0
}
func (rcv *ProgInfoRaw) MutateElapsed(n uint64) bool {
return rcv._tab.MutateUint64Slot(10, n)
}
func (rcv *ProgInfoRaw) Freshness() uint64 {
o := flatbuffers.UOffsetT(rcv._tab.Offset(12))
if o != 0 {
return rcv._tab.GetUint64(o + rcv._tab.Pos)
}
return 0
}
func (rcv *ProgInfoRaw) MutateFreshness(n uint64) bool {
return rcv._tab.MutateUint64Slot(12, n)
}
func ProgInfoRawStart(builder *flatbuffers.Builder) {
builder.StartObject(5)
}
func ProgInfoRawAddCalls(builder *flatbuffers.Builder, calls flatbuffers.UOffsetT) {
builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(calls), 0)
}
func ProgInfoRawStartCallsVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT {
return builder.StartVector(4, numElems, 4)
}
func ProgInfoRawAddExtraRaw(builder *flatbuffers.Builder, extraRaw flatbuffers.UOffsetT) {
builder.PrependUOffsetTSlot(1, flatbuffers.UOffsetT(extraRaw), 0)
}
func ProgInfoRawStartExtraRawVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT {
return builder.StartVector(4, numElems, 4)
}
func ProgInfoRawAddExtra(builder *flatbuffers.Builder, extra flatbuffers.UOffsetT) {
builder.PrependUOffsetTSlot(2, flatbuffers.UOffsetT(extra), 0)
}
func ProgInfoRawAddElapsed(builder *flatbuffers.Builder, elapsed uint64) {
builder.PrependUint64Slot(3, elapsed, 0)
}
func ProgInfoRawAddFreshness(builder *flatbuffers.Builder, freshness uint64) {
builder.PrependUint64Slot(4, freshness, 0)
}
func ProgInfoRawEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
return builder.EndObject()
}
type ExecResultRawT struct {
Id int64 `json:"id"`
Proc int32 `json:"proc"`
Output []byte `json:"output"`
Hanged bool `json:"hanged"`
Error string `json:"error"`
Info *ProgInfoRawT `json:"info"`
}
func (t *ExecResultRawT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
if t == nil {
return 0
}
outputOffset := flatbuffers.UOffsetT(0)
if t.Output != nil {
outputOffset = builder.CreateByteString(t.Output)
}
errorOffset := builder.CreateString(t.Error)
infoOffset := t.Info.Pack(builder)
ExecResultRawStart(builder)
ExecResultRawAddId(builder, t.Id)
ExecResultRawAddProc(builder, t.Proc)
ExecResultRawAddOutput(builder, outputOffset)
ExecResultRawAddHanged(builder, t.Hanged)
ExecResultRawAddError(builder, errorOffset)
ExecResultRawAddInfo(builder, infoOffset)
return ExecResultRawEnd(builder)
}
func (rcv *ExecResultRaw) UnPackTo(t *ExecResultRawT) {
t.Id = rcv.Id()
t.Proc = rcv.Proc()
t.Output = rcv.OutputBytes()
t.Hanged = rcv.Hanged()
t.Error = string(rcv.Error())
t.Info = rcv.Info(nil).UnPack()
}
func (rcv *ExecResultRaw) UnPack() *ExecResultRawT {
if rcv == nil {
return nil
}
t := &ExecResultRawT{}
rcv.UnPackTo(t)
return t
}
type ExecResultRaw struct {
_tab flatbuffers.Table
}
func GetRootAsExecResultRaw(buf []byte, offset flatbuffers.UOffsetT) *ExecResultRaw {
n := flatbuffers.GetUOffsetT(buf[offset:])
x := &ExecResultRaw{}
x.Init(buf, n+offset)
return x
}
func GetSizePrefixedRootAsExecResultRaw(buf []byte, offset flatbuffers.UOffsetT) *ExecResultRaw {
n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])
x := &ExecResultRaw{}
x.Init(buf, n+offset+flatbuffers.SizeUint32)
return x
}
func (rcv *ExecResultRaw) Init(buf []byte, i flatbuffers.UOffsetT) {
rcv._tab.Bytes = buf
rcv._tab.Pos = i
}
func (rcv *ExecResultRaw) Table() flatbuffers.Table {
return rcv._tab
}
func (rcv *ExecResultRaw) Id() int64 {
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
if o != 0 {
return rcv._tab.GetInt64(o + rcv._tab.Pos)
}
return 0
}
func (rcv *ExecResultRaw) MutateId(n int64) bool {
return rcv._tab.MutateInt64Slot(4, n)
}
func (rcv *ExecResultRaw) Proc() int32 {
o := flatbuffers.UOffsetT(rcv._tab.Offset(6))
if o != 0 {
return rcv._tab.GetInt32(o + rcv._tab.Pos)
}
return 0
}
func (rcv *ExecResultRaw) MutateProc(n int32) bool {
return rcv._tab.MutateInt32Slot(6, n)
}
func (rcv *ExecResultRaw) Output(j int) byte {
o := flatbuffers.UOffsetT(rcv._tab.Offset(8))
if o != 0 {
a := rcv._tab.Vector(o)
return rcv._tab.GetByte(a + flatbuffers.UOffsetT(j*1))
}
return 0
}
func (rcv *ExecResultRaw) OutputLength() int {
o := flatbuffers.UOffsetT(rcv._tab.Offset(8))
if o != 0 {
return rcv._tab.VectorLen(o)
}
return 0
}
func (rcv *ExecResultRaw) OutputBytes() []byte {
o := flatbuffers.UOffsetT(rcv._tab.Offset(8))
if o != 0 {
return rcv._tab.ByteVector(o + rcv._tab.Pos)
}
return nil
}
func (rcv *ExecResultRaw) MutateOutput(j int, n byte) bool {
o := flatbuffers.UOffsetT(rcv._tab.Offset(8))
if o != 0 {
a := rcv._tab.Vector(o)
return rcv._tab.MutateByte(a+flatbuffers.UOffsetT(j*1), n)
}
return false
}
func (rcv *ExecResultRaw) Hanged() bool {
o := flatbuffers.UOffsetT(rcv._tab.Offset(10))
if o != 0 {
return rcv._tab.GetBool(o + rcv._tab.Pos)
}
return false
}
func (rcv *ExecResultRaw) MutateHanged(n bool) bool {
return rcv._tab.MutateBoolSlot(10, n)
}
func (rcv *ExecResultRaw) Error() []byte {
o := flatbuffers.UOffsetT(rcv._tab.Offset(12))
if o != 0 {
return rcv._tab.ByteVector(o + rcv._tab.Pos)
}
return nil
}
func (rcv *ExecResultRaw) Info(obj *ProgInfoRaw) *ProgInfoRaw {
o := flatbuffers.UOffsetT(rcv._tab.Offset(14))
if o != 0 {
x := rcv._tab.Indirect(o + rcv._tab.Pos)
if obj == nil {
obj = new(ProgInfoRaw)
}
obj.Init(rcv._tab.Bytes, x)
return obj
}
return nil
}
func ExecResultRawStart(builder *flatbuffers.Builder) {
builder.StartObject(6)
}
func ExecResultRawAddId(builder *flatbuffers.Builder, id int64) {
builder.PrependInt64Slot(0, id, 0)
}
func ExecResultRawAddProc(builder *flatbuffers.Builder, proc int32) {
builder.PrependInt32Slot(1, proc, 0)
}
func ExecResultRawAddOutput(builder *flatbuffers.Builder, output flatbuffers.UOffsetT) {
builder.PrependUOffsetTSlot(2, flatbuffers.UOffsetT(output), 0)
}
func ExecResultRawStartOutputVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT {
return builder.StartVector(1, numElems, 1)
}
func ExecResultRawAddHanged(builder *flatbuffers.Builder, hanged bool) {
builder.PrependBoolSlot(3, hanged, false)
}
func ExecResultRawAddError(builder *flatbuffers.Builder, error flatbuffers.UOffsetT) {
builder.PrependUOffsetTSlot(4, flatbuffers.UOffsetT(error), 0)
}
func ExecResultRawAddInfo(builder *flatbuffers.Builder, info flatbuffers.UOffsetT) {
builder.PrependUOffsetTSlot(5, flatbuffers.UOffsetT(info), 0)
}
func ExecResultRawEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
return builder.EndObject()
}
type StateResultRawT struct {
Data []byte `json:"data"`
}
func (t *StateResultRawT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
if t == nil {
return 0
}
dataOffset := flatbuffers.UOffsetT(0)
if t.Data != nil {
dataOffset = builder.CreateByteString(t.Data)
}
StateResultRawStart(builder)
StateResultRawAddData(builder, dataOffset)
return StateResultRawEnd(builder)
}
func (rcv *StateResultRaw) UnPackTo(t *StateResultRawT) {
t.Data = rcv.DataBytes()
}
func (rcv *StateResultRaw) UnPack() *StateResultRawT {
if rcv == nil {
return nil
}
t := &StateResultRawT{}
rcv.UnPackTo(t)
return t
}
type StateResultRaw struct {
_tab flatbuffers.Table
}
func GetRootAsStateResultRaw(buf []byte, offset flatbuffers.UOffsetT) *StateResultRaw {
n := flatbuffers.GetUOffsetT(buf[offset:])
x := &StateResultRaw{}
x.Init(buf, n+offset)
return x
}
func GetSizePrefixedRootAsStateResultRaw(buf []byte, offset flatbuffers.UOffsetT) *StateResultRaw {
n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])
x := &StateResultRaw{}
x.Init(buf, n+offset+flatbuffers.SizeUint32)
return x
}
func (rcv *StateResultRaw) Init(buf []byte, i flatbuffers.UOffsetT) {
rcv._tab.Bytes = buf
rcv._tab.Pos = i
}
func (rcv *StateResultRaw) Table() flatbuffers.Table {
return rcv._tab
}
func (rcv *StateResultRaw) Data(j int) byte {
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
if o != 0 {
a := rcv._tab.Vector(o)
return rcv._tab.GetByte(a + flatbuffers.UOffsetT(j*1))
}
return 0
}
func (rcv *StateResultRaw) DataLength() int {
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
if o != 0 {
return rcv._tab.VectorLen(o)
}
return 0
}
func (rcv *StateResultRaw) DataBytes() []byte {
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
if o != 0 {
return rcv._tab.ByteVector(o + rcv._tab.Pos)
}
return nil
}
func (rcv *StateResultRaw) MutateData(j int, n byte) bool {
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
if o != 0 {
a := rcv._tab.Vector(o)
return rcv._tab.MutateByte(a+flatbuffers.UOffsetT(j*1), n)
}
return false
}
func StateResultRawStart(builder *flatbuffers.Builder) {
builder.StartObject(1)
}
func StateResultRawAddData(builder *flatbuffers.Builder, data flatbuffers.UOffsetT) {
builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(data), 0)
}
func StateResultRawStartDataVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT {
return builder.StartVector(1, numElems, 1)
}
func StateResultRawEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
return builder.EndObject()
}
type SnapshotHeaderT struct {
State SnapshotState `json:"state"`
OutputOffset uint32 `json:"output_offset"`
OutputSize uint32 `json:"output_size"`
}
func (t *SnapshotHeaderT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
if t == nil {
return 0
}
SnapshotHeaderStart(builder)
SnapshotHeaderAddState(builder, t.State)
SnapshotHeaderAddOutputOffset(builder, t.OutputOffset)
SnapshotHeaderAddOutputSize(builder, t.OutputSize)
return SnapshotHeaderEnd(builder)
}
func (rcv *SnapshotHeader) UnPackTo(t *SnapshotHeaderT) {
t.State = rcv.State()
t.OutputOffset = rcv.OutputOffset()
t.OutputSize = rcv.OutputSize()
}
func (rcv *SnapshotHeader) UnPack() *SnapshotHeaderT {
if rcv == nil {
return nil
}
t := &SnapshotHeaderT{}
rcv.UnPackTo(t)
return t
}
type SnapshotHeader struct {
_tab flatbuffers.Table
}
func GetRootAsSnapshotHeader(buf []byte, offset flatbuffers.UOffsetT) *SnapshotHeader {
n := flatbuffers.GetUOffsetT(buf[offset:])
x := &SnapshotHeader{}
x.Init(buf, n+offset)
return x
}
func GetSizePrefixedRootAsSnapshotHeader(buf []byte, offset flatbuffers.UOffsetT) *SnapshotHeader {
n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])
x := &SnapshotHeader{}
x.Init(buf, n+offset+flatbuffers.SizeUint32)
return x
}
func (rcv *SnapshotHeader) Init(buf []byte, i flatbuffers.UOffsetT) {
rcv._tab.Bytes = buf
rcv._tab.Pos = i
}
func (rcv *SnapshotHeader) Table() flatbuffers.Table {
return rcv._tab
}
func (rcv *SnapshotHeader) State() SnapshotState {
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
if o != 0 {
return SnapshotState(rcv._tab.GetUint64(o + rcv._tab.Pos))
}
return 0
}
func (rcv *SnapshotHeader) MutateState(n SnapshotState) bool {
return rcv._tab.MutateUint64Slot(4, uint64(n))
}
func (rcv *SnapshotHeader) OutputOffset() uint32 {
o := flatbuffers.UOffsetT(rcv._tab.Offset(6))
if o != 0 {
return rcv._tab.GetUint32(o + rcv._tab.Pos)
}
return 0
}
func (rcv *SnapshotHeader) MutateOutputOffset(n uint32) bool {
return rcv._tab.MutateUint32Slot(6, n)
}
func (rcv *SnapshotHeader) OutputSize() uint32 {
o := flatbuffers.UOffsetT(rcv._tab.Offset(8))
if o != 0 {
return rcv._tab.GetUint32(o + rcv._tab.Pos)
}
return 0
}
func (rcv *SnapshotHeader) MutateOutputSize(n uint32) bool {
return rcv._tab.MutateUint32Slot(8, n)
}
func SnapshotHeaderStart(builder *flatbuffers.Builder) {
builder.StartObject(3)
}
func SnapshotHeaderAddState(builder *flatbuffers.Builder, state SnapshotState) {
builder.PrependUint64Slot(0, uint64(state), 0)
}
func SnapshotHeaderAddOutputOffset(builder *flatbuffers.Builder, outputOffset uint32) {
builder.PrependUint32Slot(1, outputOffset, 0)
}
func SnapshotHeaderAddOutputSize(builder *flatbuffers.Builder, outputSize uint32) {
builder.PrependUint32Slot(2, outputSize, 0)
}
func SnapshotHeaderEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
return builder.EndObject()
}
type SnapshotHandshakeT struct {
CoverEdges bool `json:"cover_edges"`
Kernel64Bit bool `json:"kernel_64_bit"`
Slowdown int32 `json:"slowdown"`
SyscallTimeoutMs int32 `json:"syscall_timeout_ms"`
ProgramTimeoutMs int32 `json:"program_timeout_ms"`
Features Feature `json:"features"`
EnvFlags ExecEnv `json:"env_flags"`
SandboxArg int64 `json:"sandbox_arg"`
}
func (t *SnapshotHandshakeT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
if t == nil {
return 0
}
SnapshotHandshakeStart(builder)
SnapshotHandshakeAddCoverEdges(builder, t.CoverEdges)
SnapshotHandshakeAddKernel64Bit(builder, t.Kernel64Bit)
SnapshotHandshakeAddSlowdown(builder, t.Slowdown)
SnapshotHandshakeAddSyscallTimeoutMs(builder, t.SyscallTimeoutMs)
SnapshotHandshakeAddProgramTimeoutMs(builder, t.ProgramTimeoutMs)
SnapshotHandshakeAddFeatures(builder, t.Features)
SnapshotHandshakeAddEnvFlags(builder, t.EnvFlags)
SnapshotHandshakeAddSandboxArg(builder, t.SandboxArg)
return SnapshotHandshakeEnd(builder)
}
func (rcv *SnapshotHandshake) UnPackTo(t *SnapshotHandshakeT) {
t.CoverEdges = rcv.CoverEdges()
t.Kernel64Bit = rcv.Kernel64Bit()
t.Slowdown = rcv.Slowdown()
t.SyscallTimeoutMs = rcv.SyscallTimeoutMs()
t.ProgramTimeoutMs = rcv.ProgramTimeoutMs()
t.Features = rcv.Features()
t.EnvFlags = rcv.EnvFlags()
t.SandboxArg = rcv.SandboxArg()
}
func (rcv *SnapshotHandshake) UnPack() *SnapshotHandshakeT {
if rcv == nil {
return nil
}
t := &SnapshotHandshakeT{}
rcv.UnPackTo(t)
return t
}
type SnapshotHandshake struct {
_tab flatbuffers.Table
}
func GetRootAsSnapshotHandshake(buf []byte, offset flatbuffers.UOffsetT) *SnapshotHandshake {
n := flatbuffers.GetUOffsetT(buf[offset:])
x := &SnapshotHandshake{}
x.Init(buf, n+offset)
return x
}
func GetSizePrefixedRootAsSnapshotHandshake(buf []byte, offset flatbuffers.UOffsetT) *SnapshotHandshake {
n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])
x := &SnapshotHandshake{}
x.Init(buf, n+offset+flatbuffers.SizeUint32)
return x
}
func (rcv *SnapshotHandshake) Init(buf []byte, i flatbuffers.UOffsetT) {
rcv._tab.Bytes = buf
rcv._tab.Pos = i
}
func (rcv *SnapshotHandshake) Table() flatbuffers.Table {
return rcv._tab
}
func (rcv *SnapshotHandshake) CoverEdges() bool {
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
if o != 0 {
return rcv._tab.GetBool(o + rcv._tab.Pos)
}
return false
}
func (rcv *SnapshotHandshake) MutateCoverEdges(n bool) bool {
return rcv._tab.MutateBoolSlot(4, n)
}
func (rcv *SnapshotHandshake) Kernel64Bit() bool {
o := flatbuffers.UOffsetT(rcv._tab.Offset(6))
if o != 0 {
return rcv._tab.GetBool(o + rcv._tab.Pos)
}
return false
}
func (rcv *SnapshotHandshake) MutateKernel64Bit(n bool) bool {
return rcv._tab.MutateBoolSlot(6, n)
}
func (rcv *SnapshotHandshake) Slowdown() int32 {
o := flatbuffers.UOffsetT(rcv._tab.Offset(8))
if o != 0 {
return rcv._tab.GetInt32(o + rcv._tab.Pos)
}
return 0
}
func (rcv *SnapshotHandshake) MutateSlowdown(n int32) bool {
return rcv._tab.MutateInt32Slot(8, n)
}
func (rcv *SnapshotHandshake) SyscallTimeoutMs() int32 {
o := flatbuffers.UOffsetT(rcv._tab.Offset(10))
if o != 0 {
return rcv._tab.GetInt32(o + rcv._tab.Pos)
}
return 0
}
func (rcv *SnapshotHandshake) MutateSyscallTimeoutMs(n int32) bool {
return rcv._tab.MutateInt32Slot(10, n)
}
func (rcv *SnapshotHandshake) ProgramTimeoutMs() int32 {
o := flatbuffers.UOffsetT(rcv._tab.Offset(12))
if o != 0 {
return rcv._tab.GetInt32(o + rcv._tab.Pos)
}
return 0
}
func (rcv *SnapshotHandshake) MutateProgramTimeoutMs(n int32) bool {
return rcv._tab.MutateInt32Slot(12, n)
}
func (rcv *SnapshotHandshake) Features() Feature {
o := flatbuffers.UOffsetT(rcv._tab.Offset(14))
if o != 0 {
return Feature(rcv._tab.GetUint64(o + rcv._tab.Pos))
}
return 0
}
func (rcv *SnapshotHandshake) MutateFeatures(n Feature) bool {
return rcv._tab.MutateUint64Slot(14, uint64(n))
}
func (rcv *SnapshotHandshake) EnvFlags() ExecEnv {
o := flatbuffers.UOffsetT(rcv._tab.Offset(16))
if o != 0 {
return ExecEnv(rcv._tab.GetUint64(o + rcv._tab.Pos))
}
return 0
}
func (rcv *SnapshotHandshake) MutateEnvFlags(n ExecEnv) bool {
return rcv._tab.MutateUint64Slot(16, uint64(n))
}
func (rcv *SnapshotHandshake) SandboxArg() int64 {
o := flatbuffers.UOffsetT(rcv._tab.Offset(18))
if o != 0 {
return rcv._tab.GetInt64(o + rcv._tab.Pos)
}
return 0
}
func (rcv *SnapshotHandshake) MutateSandboxArg(n int64) bool {
return rcv._tab.MutateInt64Slot(18, n)
}
func SnapshotHandshakeStart(builder *flatbuffers.Builder) {
builder.StartObject(8)
}
func SnapshotHandshakeAddCoverEdges(builder *flatbuffers.Builder, coverEdges bool) {
builder.PrependBoolSlot(0, coverEdges, false)
}
func SnapshotHandshakeAddKernel64Bit(builder *flatbuffers.Builder, kernel64Bit bool) {
builder.PrependBoolSlot(1, kernel64Bit, false)
}
func SnapshotHandshakeAddSlowdown(builder *flatbuffers.Builder, slowdown int32) {
builder.PrependInt32Slot(2, slowdown, 0)
}
func SnapshotHandshakeAddSyscallTimeoutMs(builder *flatbuffers.Builder, syscallTimeoutMs int32) {
builder.PrependInt32Slot(3, syscallTimeoutMs, 0)
}
func SnapshotHandshakeAddProgramTimeoutMs(builder *flatbuffers.Builder, programTimeoutMs int32) {
builder.PrependInt32Slot(4, programTimeoutMs, 0)
}
func SnapshotHandshakeAddFeatures(builder *flatbuffers.Builder, features Feature) {
builder.PrependUint64Slot(5, uint64(features), 0)
}
func SnapshotHandshakeAddEnvFlags(builder *flatbuffers.Builder, envFlags ExecEnv) {
builder.PrependUint64Slot(6, uint64(envFlags), 0)
}
func SnapshotHandshakeAddSandboxArg(builder *flatbuffers.Builder, sandboxArg int64) {
builder.PrependInt64Slot(7, sandboxArg, 0)
}
func SnapshotHandshakeEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
return builder.EndObject()
}
type SnapshotRequestT struct {
ExecFlags ExecFlag `json:"exec_flags"`
NumCalls int32 `json:"num_calls"`
AllCallSignal uint64 `json:"all_call_signal"`
AllExtraSignal bool `json:"all_extra_signal"`
ProgData []byte `json:"prog_data"`
}
func (t *SnapshotRequestT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
if t == nil {
return 0
}
progDataOffset := flatbuffers.UOffsetT(0)
if t.ProgData != nil {
progDataOffset = builder.CreateByteString(t.ProgData)
}
SnapshotRequestStart(builder)
SnapshotRequestAddExecFlags(builder, t.ExecFlags)
SnapshotRequestAddNumCalls(builder, t.NumCalls)
SnapshotRequestAddAllCallSignal(builder, t.AllCallSignal)
SnapshotRequestAddAllExtraSignal(builder, t.AllExtraSignal)
SnapshotRequestAddProgData(builder, progDataOffset)
return SnapshotRequestEnd(builder)
}
func (rcv *SnapshotRequest) UnPackTo(t *SnapshotRequestT) {
t.ExecFlags = rcv.ExecFlags()
t.NumCalls = rcv.NumCalls()
t.AllCallSignal = rcv.AllCallSignal()
t.AllExtraSignal = rcv.AllExtraSignal()
t.ProgData = rcv.ProgDataBytes()
}
func (rcv *SnapshotRequest) UnPack() *SnapshotRequestT {
if rcv == nil {
return nil
}
t := &SnapshotRequestT{}
rcv.UnPackTo(t)
return t
}
type SnapshotRequest struct {
_tab flatbuffers.Table
}
func GetRootAsSnapshotRequest(buf []byte, offset flatbuffers.UOffsetT) *SnapshotRequest {
n := flatbuffers.GetUOffsetT(buf[offset:])
x := &SnapshotRequest{}
x.Init(buf, n+offset)
return x
}
func GetSizePrefixedRootAsSnapshotRequest(buf []byte, offset flatbuffers.UOffsetT) *SnapshotRequest {
n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])
x := &SnapshotRequest{}
x.Init(buf, n+offset+flatbuffers.SizeUint32)
return x
}
func (rcv *SnapshotRequest) Init(buf []byte, i flatbuffers.UOffsetT) {
rcv._tab.Bytes = buf
rcv._tab.Pos = i
}
func (rcv *SnapshotRequest) Table() flatbuffers.Table {
return rcv._tab
}
func (rcv *SnapshotRequest) ExecFlags() ExecFlag {
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
if o != 0 {
return ExecFlag(rcv._tab.GetUint64(o + rcv._tab.Pos))
}
return 0
}
func (rcv *SnapshotRequest) MutateExecFlags(n ExecFlag) bool {
return rcv._tab.MutateUint64Slot(4, uint64(n))
}
func (rcv *SnapshotRequest) NumCalls() int32 {
o := flatbuffers.UOffsetT(rcv._tab.Offset(6))
if o != 0 {
return rcv._tab.GetInt32(o + rcv._tab.Pos)
}
return 0
}
func (rcv *SnapshotRequest) MutateNumCalls(n int32) bool {
return rcv._tab.MutateInt32Slot(6, n)
}
func (rcv *SnapshotRequest) AllCallSignal() uint64 {
o := flatbuffers.UOffsetT(rcv._tab.Offset(8))
if o != 0 {
return rcv._tab.GetUint64(o + rcv._tab.Pos)
}
return 0
}
func (rcv *SnapshotRequest) MutateAllCallSignal(n uint64) bool {
return rcv._tab.MutateUint64Slot(8, n)
}
func (rcv *SnapshotRequest) AllExtraSignal() bool {
o := flatbuffers.UOffsetT(rcv._tab.Offset(10))
if o != 0 {
return rcv._tab.GetBool(o + rcv._tab.Pos)
}
return false
}
func (rcv *SnapshotRequest) MutateAllExtraSignal(n bool) bool {
return rcv._tab.MutateBoolSlot(10, n)
}
func (rcv *SnapshotRequest) ProgData(j int) byte {
o := flatbuffers.UOffsetT(rcv._tab.Offset(12))
if o != 0 {
a := rcv._tab.Vector(o)
return rcv._tab.GetByte(a + flatbuffers.UOffsetT(j*1))
}
return 0
}
func (rcv *SnapshotRequest) ProgDataLength() int {
o := flatbuffers.UOffsetT(rcv._tab.Offset(12))
if o != 0 {
return rcv._tab.VectorLen(o)
}
return 0
}
func (rcv *SnapshotRequest) ProgDataBytes() []byte {
o := flatbuffers.UOffsetT(rcv._tab.Offset(12))
if o != 0 {
return rcv._tab.ByteVector(o + rcv._tab.Pos)
}
return nil
}
func (rcv *SnapshotRequest) MutateProgData(j int, n byte) bool {
o := flatbuffers.UOffsetT(rcv._tab.Offset(12))
if o != 0 {
a := rcv._tab.Vector(o)
return rcv._tab.MutateByte(a+flatbuffers.UOffsetT(j*1), n)
}
return false
}
func SnapshotRequestStart(builder *flatbuffers.Builder) {
builder.StartObject(5)
}
func SnapshotRequestAddExecFlags(builder *flatbuffers.Builder, execFlags ExecFlag) {
builder.PrependUint64Slot(0, uint64(execFlags), 0)
}
func SnapshotRequestAddNumCalls(builder *flatbuffers.Builder, numCalls int32) {
builder.PrependInt32Slot(1, numCalls, 0)
}
func SnapshotRequestAddAllCallSignal(builder *flatbuffers.Builder, allCallSignal uint64) {
builder.PrependUint64Slot(2, allCallSignal, 0)
}
func SnapshotRequestAddAllExtraSignal(builder *flatbuffers.Builder, allExtraSignal bool) {
builder.PrependBoolSlot(3, allExtraSignal, false)
}
func SnapshotRequestAddProgData(builder *flatbuffers.Builder, progData flatbuffers.UOffsetT) {
builder.PrependUOffsetTSlot(4, flatbuffers.UOffsetT(progData), 0)
}
func SnapshotRequestStartProgDataVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT {
return builder.StartVector(1, numElems, 1)
}
func SnapshotRequestEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
return builder.EndObject()
}
// Copyright 2024 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package flatrpc
import (
"fmt"
"slices"
"sync/atomic"
"syscall"
"unsafe"
"github.com/google/syzkaller/prog"
)
const AllFeatures = ^Feature(0)
// Flatbuffers compiler adds T suffix to object API types, which are actual structs representing types.
// This leads to non-idiomatic Go code, e.g. we would have to use []FileInfoT in Go code.
// So we use Raw suffix for all flatbuffers tables and rename object API types here to idiomatic names.
type ConnectHello = ConnectHelloRawT
type ConnectRequest = ConnectRequestRawT
type ConnectReply = ConnectReplyRawT
type InfoRequest = InfoRequestRawT
type InfoReply = InfoReplyRawT
type FileInfo = FileInfoRawT
type GlobInfo = GlobInfoRawT
type FeatureInfo = FeatureInfoRawT
type HostMessages = HostMessagesRawT
type HostMessage = HostMessageRawT
type ExecutorMessages = ExecutorMessagesRawT
type ExecutorMessage = ExecutorMessageRawT
type ExecRequest = ExecRequestRawT
type StateRequest = StateRequestRawT
type SignalUpdate = SignalUpdateRawT
type CorpusTriaged = CorpusTriagedRawT
type ExecutingMessage = ExecutingMessageRawT
type CallInfo = CallInfoRawT
type Comparison = ComparisonRawT
type ExecOpts = ExecOptsRawT
type ProgInfo = ProgInfoRawT
type ExecResult = ExecResultRawT
type StateResult = StateResultRawT
func init() {
var req ExecRequest
if prog.MaxPids > unsafe.Sizeof(req.Avoid)*8 {
panic("all procs won't fit ito ExecRequest.Avoid")
}
}
func (pi *ProgInfo) Clone() *ProgInfo {
if pi == nil {
return nil
}
ret := *pi
ret.Extra = ret.Extra.clone()
ret.Calls = make([]*CallInfo, len(pi.Calls))
for i, call := range pi.Calls {
ret.Calls[i] = call.clone()
}
return &ret
}
func (ci *CallInfo) clone() *CallInfo {
if ci == nil {
return nil
}
ret := *ci
ret.Signal = slices.Clone(ret.Signal)
ret.Cover = slices.Clone(ret.Cover)
ret.Comps = slices.Clone(ret.Comps)
return &ret
}
func EmptyProgInfo(calls int) *ProgInfo {
info := &ProgInfo{}
for i := 0; i < calls; i++ {
info.Calls = append(info.Calls, &CallInfo{
// Store some unsuccessful errno in the case we won't get any result.
// It also won't have CallExecuted flag, but it's handy to make it
// look failed based on errno as well.
Error: int32(syscall.ENOSYS),
})
}
return info
}
func SandboxToFlags(sandbox string) (ExecEnv, error) {
switch sandbox {
case "none":
return ExecEnvSandboxNone, nil
case "setuid":
return ExecEnvSandboxSetuid, nil
case "namespace":
return ExecEnvSandboxNamespace, nil
case "android":
return ExecEnvSandboxAndroid, nil
default:
return 0, fmt.Errorf("sandbox must contain one of none/setuid/namespace/android")
}
}
func (hdr *SnapshotHeaderT) UpdateState(state SnapshotState) {
atomic.StoreUint64((*uint64)(unsafe.Pointer(&hdr.State)), uint64(state))
}
func (hdr *SnapshotHeaderT) LoadState() SnapshotState {
return SnapshotState(atomic.LoadUint64((*uint64)(unsafe.Pointer(&hdr.State))))
}
// Copyright 2024 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package queue
import (
"sync"
"sync/atomic"
"github.com/google/syzkaller/pkg/stat"
)
// Distributor distributes requests to different VMs during input triage
// (allows to avoid already used VMs).
type Distributor struct {
source Source
seq atomic.Uint64
empty atomic.Bool
active atomic.Pointer[[]atomic.Uint64]
mu sync.Mutex
queue []*Request
statDelayed *stat.Val
statUndelayed *stat.Val
statViolated *stat.Val
}
func Distribute(source Source) *Distributor {
return &Distributor{
source: source,
statDelayed: stat.New("distributor delayed", "Number of test programs delayed due to VM avoidance",
stat.Graph("distributor")),
statUndelayed: stat.New("distributor undelayed", "Number of test programs undelayed for VM avoidance",
stat.Graph("distributor")),
statViolated: stat.New("distributor violated", "Number of test programs violated VM avoidance",
stat.Graph("distributor")),
}
}
// Next returns the next request to execute on the given vm.
func (dist *Distributor) Next(vm int) *Request {
dist.noteActive(vm)
if req := dist.delayed(vm); req != nil {
return req
}
for {
req := dist.source.Next()
if req == nil || !contains(req.Avoid, vm) || !dist.hasOtherActive(req.Avoid) {
return req
}
dist.delay(req)
}
}
func (dist *Distributor) delay(req *Request) {
dist.mu.Lock()
defer dist.mu.Unlock()
req.delayedSince = dist.seq.Load()
dist.queue = append(dist.queue, req)
dist.statDelayed.Add(1)
dist.empty.Store(false)
}
func (dist *Distributor) delayed(vm int) *Request {
if dist.empty.Load() {
return nil
}
dist.mu.Lock()
defer dist.mu.Unlock()
seq := dist.seq.Load()
for i, req := range dist.queue {
violation := contains(req.Avoid, vm)
// The delayedSince check protects from a situation when we had another VM available,
// and delayed a request, but then the VM was taken for reproduction and does not
// serve requests any more. If we could not dispatch a request in 1000 attempts,
// we gave up and give it to any VM.
if violation && req.delayedSince+1000 > seq {
continue
}
dist.statUndelayed.Add(1)
if violation {
dist.statViolated.Add(1)
}
last := len(dist.queue) - 1
dist.queue[i] = dist.queue[last]
dist.queue[last] = nil
dist.queue = dist.queue[:last]
dist.empty.Store(len(dist.queue) == 0)
return req
}
return nil
}
func (dist *Distributor) noteActive(vm int) {
active := dist.active.Load()
if active == nil || len(*active) <= vm {
dist.mu.Lock()
active = dist.active.Load()
if active == nil || len(*active) <= vm {
tmp := make([]atomic.Uint64, vm+10)
active = &tmp
dist.active.Store(active)
}
dist.mu.Unlock()
}
(*active)[vm].Store(dist.seq.Add(1))
}
// hasOtherActive says if we recently seen activity from VMs not in the set.
func (dist *Distributor) hasOtherActive(set []ExecutorID) bool {
seq := dist.seq.Load()
active := *dist.active.Load()
for vm := range active {
if contains(set, vm) {
continue
}
// 1000 is semi-random notion of recency.
if active[vm].Load()+1000 < seq {
continue
}
return true
}
return false
}
func contains(set []ExecutorID, vm int) bool {
for _, id := range set {
if id.VM == vm {
return true
}
}
return false
}
// Copyright 2024 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package queue
import (
"container/heap"
)
type priorityQueueOps[T any] struct {
impl priorityQueueImpl[T]
}
func (pq *priorityQueueOps[T]) Len() int {
return pq.impl.Len()
}
func (pq *priorityQueueOps[T]) Push(item T, prio int) {
heap.Push(&pq.impl, &priorityQueueItem[T]{item, prio})
}
func (pq *priorityQueueOps[T]) Pop() T {
if len(pq.impl) == 0 {
var def T
return def
}
return heap.Pop(&pq.impl).(*priorityQueueItem[T]).value
}
// The implementation below is based on the example provided
// by https://pkg.go.dev/container/heap.
type priorityQueueItem[T any] struct {
value T
prio int
}
type priorityQueueImpl[T any] []*priorityQueueItem[T]
func (pq priorityQueueImpl[T]) Len() int { return len(pq) }
func (pq priorityQueueImpl[T]) Less(i, j int) bool {
// We want Pop to give us the lowest priority.
return pq[i].prio < pq[j].prio
}
func (pq priorityQueueImpl[T]) Swap(i, j int) {
pq[i], pq[j] = pq[j], pq[i]
}
func (pq *priorityQueueImpl[T]) Push(x any) {
*pq = append(*pq, x.(*priorityQueueItem[T]))
}
func (pq *priorityQueueImpl[T]) Pop() any {
n := len(*pq)
item := (*pq)[n-1]
(*pq)[n-1] = nil
*pq = (*pq)[:n-1]
return item
}
// Copyright 2024 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package queue
import (
"bytes"
"context"
"encoding/gob"
"errors"
"fmt"
"math/rand"
"strings"
"sync"
"sync/atomic"
"github.com/google/syzkaller/pkg/flatrpc"
"github.com/google/syzkaller/pkg/hash"
"github.com/google/syzkaller/pkg/stat"
"github.com/google/syzkaller/prog"
)
type Request struct {
// Type of the request.
// RequestTypeProgram executes Prog, and is used by most requests (also the default zero value).
// RequestTypeBinary executes binary with file name stored in Data.
// RequestTypeGlob expands glob pattern stored in Data.
Type flatrpc.RequestType
ExecOpts flatrpc.ExecOpts
Prog *prog.Prog // for RequestTypeProgram
BinaryFile string // for RequestTypeBinary
GlobPattern string // for RequestTypeGlob
// Return all signal for these calls instead of new signal.
ReturnAllSignal []int
ReturnError bool
ReturnOutput bool
// This stat will be incremented on request completion.
Stat *stat.Val
// Important requests will be retried even from crashed VMs.
Important bool
// Avoid specifies set of executors that are preferable to avoid when executing this request.
// The restriction is soft since there can be only one executor at all or available right now.
Avoid []ExecutorID
// The callback will be called on request completion in the LIFO order.
// If it returns false, all further processing will be stopped.
// It allows wrappers to intercept Done() requests.
callback DoneCallback
onceCrashed bool
delayedSince uint64
mu sync.Mutex
result *Result
done chan struct{}
}
type ExecutorID struct {
VM int
Proc int
}
type DoneCallback func(*Request, *Result) bool
func (r *Request) OnDone(cb DoneCallback) {
oldCallback := r.callback
r.callback = func(req *Request, res *Result) bool {
r.callback = oldCallback
if !cb(req, res) {
return false
}
if oldCallback == nil {
return true
}
return oldCallback(req, res)
}
}
func (r *Request) Done(res *Result) {
if r.callback != nil {
if !r.callback(r, res) {
return
}
}
if r.Stat != nil {
r.Stat.Add(1)
}
r.initChannel()
r.result = res
close(r.done)
}
var ErrRequestAborted = errors.New("context closed while waiting the result")
// Wait() blocks until we have the result.
func (r *Request) Wait(ctx context.Context) *Result {
r.initChannel()
select {
case <-ctx.Done():
return &Result{Status: ExecFailure, Err: ErrRequestAborted}
case <-r.done:
return r.result
}
}
// Risky() returns true if there's a substantial risk of the input crashing the VM.
func (r *Request) Risky() bool {
return r.onceCrashed
}
func (r *Request) Validate() error {
collectSignal := r.ExecOpts.ExecFlags&flatrpc.ExecFlagCollectSignal > 0
if len(r.ReturnAllSignal) != 0 && !collectSignal {
return fmt.Errorf("ReturnAllSignal is set, but FlagCollectSignal is not")
}
collectComps := r.ExecOpts.ExecFlags&flatrpc.ExecFlagCollectComps > 0
collectCover := r.ExecOpts.ExecFlags&flatrpc.ExecFlagCollectCover > 0
if (collectComps) && (collectSignal || collectCover) {
return fmt.Errorf("hint collection is mutually exclusive with signal/coverage")
}
switch r.Type {
case flatrpc.RequestTypeProgram:
if r.Prog == nil {
return fmt.Errorf("program is not set")
}
sandboxes := flatrpc.ExecEnvSandboxNone | flatrpc.ExecEnvSandboxSetuid |
flatrpc.ExecEnvSandboxNamespace | flatrpc.ExecEnvSandboxAndroid
if r.ExecOpts.EnvFlags&sandboxes == 0 {
return fmt.Errorf("no sandboxes set")
}
case flatrpc.RequestTypeBinary:
if r.BinaryFile == "" {
return fmt.Errorf("binary file name is not set")
}
case flatrpc.RequestTypeGlob:
if r.GlobPattern == "" {
return fmt.Errorf("glob pattern is not set")
}
default:
return fmt.Errorf("unknown request type")
}
return nil
}
func (r *Request) hash() hash.Sig {
buf := new(bytes.Buffer)
enc := gob.NewEncoder(buf)
if err := enc.Encode(r.Type); err != nil {
panic(err)
}
if err := enc.Encode(r.ExecOpts); err != nil {
panic(err)
}
var data []byte
switch r.Type {
case flatrpc.RequestTypeProgram:
data = r.Prog.Serialize()
case flatrpc.RequestTypeBinary:
data = []byte(r.BinaryFile)
case flatrpc.RequestTypeGlob:
data = []byte(r.GlobPattern)
default:
panic("unknown request type")
}
return hash.Hash(data, buf.Bytes())
}
func (r *Request) initChannel() {
r.mu.Lock()
if r.done == nil {
r.done = make(chan struct{})
}
r.mu.Unlock()
}
type Result struct {
Info *flatrpc.ProgInfo
Executor ExecutorID
Output []byte
Status Status
Err error // More details in case of ExecFailure.
}
func (r *Result) clone() *Result {
ret := *r
ret.Info = ret.Info.Clone()
return &ret
}
func (r *Result) Stop() bool {
switch r.Status {
case Success, Restarted:
return false
case ExecFailure, Crashed, Hanged:
return true
default:
panic(fmt.Sprintf("unhandled status %v", r.Status))
}
}
// Globs returns result of RequestTypeGlob.
func (r *Result) GlobFiles() []string {
out := strings.Trim(string(r.Output), "\000")
if out == "" {
return nil
}
return strings.Split(out, "\000")
}
type Status int
//go:generate go run golang.org/x/tools/cmd/stringer -type Status
const (
Success Status = iota
ExecFailure // For e.g. serialization errors.
Crashed // The VM crashed holding the request.
Restarted // The VM was restarted holding the request.
Hanged // The program has hanged (can't be killed/waited).
)
// Executor describes the interface wanted by the producers of requests.
// After a Request is submitted, it's expected that the consumer will eventually
// take it and report the execution result via Done().
type Executor interface {
Submit(req *Request)
}
// Source describes the interface wanted by the consumers of requests.
type Source interface {
Next() *Request
}
// PlainQueue is a straighforward thread-safe Request queue implementation.
type PlainQueue struct {
mu sync.Mutex
queue []*Request
pos int
}
func Plain() *PlainQueue {
return &PlainQueue{}
}
func (pq *PlainQueue) Len() int {
pq.mu.Lock()
defer pq.mu.Unlock()
return len(pq.queue) - pq.pos
}
func (pq *PlainQueue) Submit(req *Request) {
pq.mu.Lock()
defer pq.mu.Unlock()
// It doesn't make sense to compact the queue too often.
const minSizeToCompact = 128
if pq.pos > len(pq.queue)/2 && len(pq.queue) >= minSizeToCompact {
copy(pq.queue, pq.queue[pq.pos:])
for pq.pos > 0 {
newLen := len(pq.queue) - 1
pq.queue[newLen] = nil
pq.queue = pq.queue[:newLen]
pq.pos--
}
}
pq.queue = append(pq.queue, req)
}
func (pq *PlainQueue) Next() *Request {
pq.mu.Lock()
defer pq.mu.Unlock()
return pq.nextLocked()
}
func (pq *PlainQueue) tryNext() *Request {
if !pq.mu.TryLock() {
return nil
}
defer pq.mu.Unlock()
return pq.nextLocked()
}
func (pq *PlainQueue) nextLocked() *Request {
if pq.pos == len(pq.queue) {
return nil
}
ret := pq.queue[pq.pos]
pq.queue[pq.pos] = nil
pq.pos++
return ret
}
// Order combines several different sources in a particular order.
type orderImpl struct {
sources []Source
}
func Order(sources ...Source) Source {
return &orderImpl{sources: sources}
}
func (o *orderImpl) Next() *Request {
for _, s := range o.sources {
req := s.Next()
if req != nil {
return req
}
}
return nil
}
type callback struct {
cb func() *Request
}
// Callback produces a source that calls the callback to serve every Next() request.
func Callback(cb func() *Request) Source {
return &callback{cb}
}
func (cb *callback) Next() *Request {
return cb.cb()
}
type alternate struct {
base Source
nth int
seq atomic.Int64
}
// Alternate proxies base, but returns nil every nth Next() call.
func Alternate(base Source, nth int) Source {
return &alternate{
base: base,
nth: nth,
}
}
func (a *alternate) Next() *Request {
if a.seq.Add(1)%int64(a.nth) == 0 {
return nil
}
return a.base.Next()
}
type DynamicOrderer struct {
mu sync.Mutex
currPrio int
ops *priorityQueueOps[*Request]
}
// DynamicOrder() can be used to form nested queues dynamically.
// That is, if
// q1 := pq.Append()
// q2 := pq.Append()
// All elements added via q2.Submit() will always have a *lower* priority
// than all elements added via q1.Submit().
func DynamicOrder() *DynamicOrderer {
return &DynamicOrderer{
ops: &priorityQueueOps[*Request]{},
}
}
func (do *DynamicOrderer) Append() Executor {
do.mu.Lock()
defer do.mu.Unlock()
do.currPrio++
return &dynamicOrdererItem{
parent: do,
prio: do.currPrio,
}
}
func (do *DynamicOrderer) submit(req *Request, prio int) {
do.mu.Lock()
defer do.mu.Unlock()
do.ops.Push(req, prio)
}
func (do *DynamicOrderer) Next() *Request {
do.mu.Lock()
defer do.mu.Unlock()
return do.ops.Pop()
}
type dynamicOrdererItem struct {
parent *DynamicOrderer
prio int
}
func (doi *dynamicOrdererItem) Submit(req *Request) {
doi.parent.submit(req, doi.prio)
}
type DynamicSourceCtl struct {
value atomic.Pointer[Source]
}
// DynamicSource is assumed never to point to nil.
func DynamicSource(source Source) *DynamicSourceCtl {
var ret DynamicSourceCtl
ret.Store(source)
return &ret
}
func (ds *DynamicSourceCtl) Store(source Source) {
ds.value.Store(&source)
}
func (ds *DynamicSourceCtl) Next() *Request {
return (*ds.value.Load()).Next()
}
// Deduplicator() keeps track of the previously run requests to avoid re-running them.
type Deduplicator struct {
mu sync.Mutex
source Source
mm map[hash.Sig]*duplicateState
}
type duplicateState struct {
res *Result
queued []*Request // duplicate requests waiting for the result.
}
func Deduplicate(source Source) Source {
return &Deduplicator{
source: source,
mm: map[hash.Sig]*duplicateState{},
}
}
func (d *Deduplicator) Next() *Request {
for {
req := d.source.Next()
if req == nil {
return nil
}
hash := req.hash()
d.mu.Lock()
entry, ok := d.mm[hash]
if !ok {
d.mm[hash] = &duplicateState{}
} else if entry.res == nil {
// There's no result yet, put the request to the queue.
entry.queued = append(entry.queued, req)
} else {
// We already know the result.
req.Done(entry.res.clone())
}
d.mu.Unlock()
if !ok {
// This is the first time we see such a request.
req.OnDone(d.onDone)
return req
}
}
}
func (d *Deduplicator) onDone(req *Request, res *Result) bool {
hash := req.hash()
clonedRes := res.clone()
d.mu.Lock()
entry := d.mm[hash]
queued := entry.queued
entry.queued = nil
entry.res = clonedRes
d.mu.Unlock()
// Broadcast the result.
for _, waitingReq := range queued {
waitingReq.Done(res.clone())
}
return true
}
// DefaultOpts applies opts to all requests in source.
func DefaultOpts(source Source, opts flatrpc.ExecOpts) Source {
return &defaultOpts{source, opts}
}
type defaultOpts struct {
source Source
opts flatrpc.ExecOpts
}
func (do *defaultOpts) Next() *Request {
req := do.source.Next()
if req == nil {
return nil
}
req.ExecOpts.ExecFlags |= do.opts.ExecFlags
req.ExecOpts.EnvFlags |= do.opts.EnvFlags
req.ExecOpts.SandboxArg = do.opts.SandboxArg
return req
}
// RandomQueue holds up to |size| elements.
// Next() evicts a random one.
// On Submit(), if the queue is full, a random element is replaced.
type RandomQueue struct {
mu sync.Mutex
queue []*Request
maxSize int
rnd *rand.Rand
}
func NewRandomQueue(size int, rnd *rand.Rand) *RandomQueue {
return &RandomQueue{
maxSize: size,
rnd: rnd,
}
}
func (rq *RandomQueue) Next() *Request {
rq.mu.Lock()
defer rq.mu.Unlock()
if len(rq.queue) == 0 {
return nil
}
pos := rq.rnd.Intn(len(rq.queue))
item := rq.queue[pos]
last := len(rq.queue) - 1
rq.queue[pos] = rq.queue[last]
rq.queue[last] = nil
rq.queue = rq.queue[0 : len(rq.queue)-1]
return item
}
var errEvictedFromQueue = errors.New("evicted from the random queue")
func (rq *RandomQueue) Submit(req *Request) {
rq.mu.Lock()
defer rq.mu.Unlock()
if len(rq.queue) < rq.maxSize {
rq.queue = append(rq.queue, req)
} else {
pos := rq.rnd.Intn(rq.maxSize + 1)
if pos < len(rq.queue) {
rq.queue[pos].Done(&Result{
Status: ExecFailure,
Err: errEvictedFromQueue,
})
rq.queue[pos] = req
}
}
}
type tee struct {
queue Executor
src Source
}
func Tee(src Source, queue Executor) Source {
return &tee{src: src, queue: queue}
}
func (t *tee) Next() *Request {
req := t.src.Next()
if req == nil {
return nil
}
t.queue.Submit(&Request{
Prog: req.Prog.Clone(),
})
return req
}
// Copyright 2024 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package queue
import (
"fmt"
)
type retryer struct {
pq *PlainQueue
base Source
}
// Retry adds a layer that resends results with Status=Restarted.
func Retry(base Source) Source {
return &retryer{
base: base,
pq: Plain(),
}
}
func (r *retryer) Next() *Request {
req := r.pq.tryNext()
if req == nil {
req = r.base.Next()
}
if req != nil {
req.OnDone(r.done)
}
return req
}
func (r *retryer) done(req *Request, res *Result) bool {
switch res.Status {
case Success, ExecFailure, Hanged:
return true
case Restarted:
// The input was on a restarted VM.
r.pq.Submit(req)
return false
case Crashed:
// Retry important requests from crashed VMs once.
if req.Important && !req.onceCrashed {
req.onceCrashed = true
r.pq.Submit(req)
return false
}
return true
default:
panic(fmt.Sprintf("unhandled status %v", res.Status))
}
}
// Code generated by "stringer -type Status"; DO NOT EDIT.
package queue
import "strconv"
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[Success-0]
_ = x[ExecFailure-1]
_ = x[Crashed-2]
_ = x[Restarted-3]
_ = x[Hanged-4]
}
const _Status_name = "SuccessExecFailureCrashedRestartedHanged"
var _Status_index = [...]uint8{0, 7, 18, 25, 34, 40}
func (i Status) String() string {
if i < 0 || i >= Status(len(_Status_index)-1) {
return "Status(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _Status_name[_Status_index[i]:_Status_index[i+1]]
}
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
// Package gcs provides wrappers around Google Cloud Storage (GCS) APIs.
// Package uses Application Default Credentials assuming that the program runs on GCE.
//
// See the following links for details and API reference:
// https://cloud.google.com/go/getting-started/using-cloud-storage
// https://godoc.org/cloud.google.com/go/storage
package gcs
import (
"context"
"errors"
"fmt"
"io"
"strings"
"time"
"cloud.google.com/go/storage"
"google.golang.org/api/iterator"
)
type Client interface {
Close() error
FileReader(path string) (io.ReadCloser, error)
FileWriter(path string, contentType string, contentEncoding string) (io.WriteCloser, error)
DeleteFile(path string) error
FileExists(path string) (bool, error)
ListObjects(path string) ([]*Object, error)
Publish(path string) error
}
type UploadOptions struct {
Publish bool
ContentEncoding string
GCSClientMock Client
}
func UploadFile(ctx context.Context, srcFile io.Reader, destURL string, opts UploadOptions) error {
destURL = strings.TrimPrefix(destURL, "gs://")
var err error
gcsClient := opts.GCSClientMock
if gcsClient == nil {
if gcsClient, err = NewClient(ctx); err != nil {
return fmt.Errorf("func NewClient: %w", err)
}
}
defer gcsClient.Close()
gcsWriter, err := gcsClient.FileWriter(destURL, "", opts.ContentEncoding)
if err != nil {
return fmt.Errorf("client.FileWriter: %w", err)
}
if _, err := io.Copy(gcsWriter, srcFile); err != nil {
gcsWriter.Close()
return fmt.Errorf("io.Copy: %w", err)
}
if err := gcsWriter.Close(); err != nil {
return fmt.Errorf("gcsWriter.Close: %w", err)
}
if opts.Publish {
return gcsClient.Publish(destURL)
}
return nil
}
type client struct {
client *storage.Client
ctx context.Context
}
func NewClient(ctx context.Context) (Client, error) {
storageClient, err := storage.NewClient(ctx)
if err != nil {
return nil, err
}
c := &client{
client: storageClient,
ctx: ctx,
}
return c, nil
}
func (c *client) Close() error {
return c.client.Close()
}
func (c *client) FileReader(gcsFile string) (io.ReadCloser, error) {
bucket, filename, err := split(gcsFile)
if err != nil {
return nil, err
}
bkt := c.client.Bucket(bucket)
f := bkt.Object(filename)
attrs, err := f.Attrs(c.ctx)
if err != nil {
return nil, fmt.Errorf("failed to read %v attributes: %w", gcsFile, err)
}
if !attrs.Deleted.IsZero() {
return nil, fmt.Errorf("file %v is deleted", gcsFile)
}
handle := f.If(storage.Conditions{
GenerationMatch: attrs.Generation,
MetagenerationMatch: attrs.Metageneration,
})
return handle.NewReader(c.ctx)
}
func (c *client) FileWriter(gcsFile, contentType, contentEncoding string) (io.WriteCloser, error) {
bucket, filename, err := split(gcsFile)
if err != nil {
return nil, err
}
bkt := c.client.Bucket(bucket)
f := bkt.Object(filename)
w := f.NewWriter(c.ctx)
if contentType != "" {
w.ContentType = contentType
}
if contentEncoding != "" {
w.ContentEncoding = contentEncoding
}
return w, nil
}
// Publish lets any user read gcsFile.
func (c *client) Publish(gcsFile string) error {
bucket, filename, err := split(gcsFile)
if err != nil {
return err
}
obj := c.client.Bucket(bucket).Object(filename)
return obj.ACL().Set(c.ctx, storage.AllUsers, storage.RoleReader)
}
var ErrFileNotFound = errors.New("the requested files does not exist")
func (c *client) DeleteFile(gcsFile string) error {
bucket, filename, err := split(gcsFile)
if err != nil {
return err
}
err = c.client.Bucket(bucket).Object(filename).Delete(c.ctx)
if errors.Is(err, storage.ErrObjectNotExist) {
return ErrFileNotFound
}
return err
}
func (c *client) FileExists(gcsFile string) (bool, error) {
bucket, filename, err := split(gcsFile)
if err != nil {
return false, err
}
_, err = c.client.Bucket(bucket).Object(filename).Attrs(c.ctx)
if errors.Is(err, storage.ErrObjectNotExist) {
return false, nil
} else if err != nil {
return false, err
}
return true, nil
}
// Where things get published.
const (
PublicPrefix = "https://storage.googleapis.com/"
AuthenticatedPrefix = "https://storage.cloud.google.com/"
)
func GetDownloadURL(gcsFile string, publicURL bool) string {
gcsFile = strings.TrimPrefix(gcsFile, "/")
if publicURL {
return PublicPrefix + gcsFile
}
return AuthenticatedPrefix + gcsFile
}
type Object struct {
Path string
CreatedAt time.Time
}
// ListObjects expects "bucket/path" or "bucket" as input.
func (c *client) ListObjects(bucketObjectPath string) ([]*Object, error) {
bucket, objectPath, err := split(bucketObjectPath)
if err != nil { // no path specified
bucket = bucketObjectPath
}
query := &storage.Query{Prefix: objectPath}
it := c.client.Bucket(bucket).Objects(c.ctx, query)
ret := []*Object{}
for {
objAttrs, err := it.Next()
if err == iterator.Done {
break
}
if err != nil {
return nil, fmt.Errorf("failed to query GCS objects: %w", err)
}
ret = append(ret, &Object{
Path: objAttrs.Name,
CreatedAt: objAttrs.Created,
})
}
return ret, nil
}
func split(file string) (bucket, filename string, err error) {
pos := strings.IndexByte(file, '/')
if pos == -1 {
return "", "", fmt.Errorf("invalid GCS file name: %v", file)
}
return file[:pos], file[pos+1:], nil
}
// Copyright 2016 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package hash
import (
"bytes"
"crypto/sha1"
"encoding/binary"
"encoding/hex"
"fmt"
)
type Sig [sha1.Size]byte
func Hash(pieces ...any) Sig {
h := sha1.New()
for _, data := range pieces {
binary.Write(h, binary.LittleEndian, data)
}
var sig Sig
copy(sig[:], h.Sum(nil))
return sig
}
func String(pieces ...any) string {
sig := Hash(pieces...)
return sig.String()
}
func (sig *Sig) String() string {
return hex.EncodeToString((*sig)[:])
}
// Truncate64 returns first 64 bits of the hash as int64.
func (sig *Sig) Truncate64() int64 {
var v int64
if err := binary.Read(bytes.NewReader((*sig)[:]), binary.LittleEndian, &v); err != nil {
panic(fmt.Sprintf("failed convert hash to id: %v", err))
}
return v
}
// Copyright 2024 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
//go:generate go run gen/gen.go gen/json/arm64.json generated/insns.go
// Package arm64 allows to generate and mutate arm64 machine code.
package arm64
import (
"encoding/binary"
"fmt"
"math/rand"
"github.com/google/syzkaller/pkg/ifuzz/iset"
)
type InsnField struct {
Name string
Start uint // Little endian bit order.
Length uint
}
type Insn struct {
Name string
OpcodeMask uint32
Opcode uint32
Fields []InsnField
AsUInt32 uint32
Operands []uint32
Pseudo bool
Priv bool
Generator func(cfg *iset.Config, r *rand.Rand) []byte // for pseudo instructions
}
type InsnSet struct {
modeInsns iset.ModeInsns
Insns []*Insn
}
func Register(insns []*Insn) {
if len(insns) == 0 {
panic("no instructions")
}
insnset := &InsnSet{
Insns: append(insns, pseudo...),
}
for _, insn := range insnset.Insns {
insnset.modeInsns.Add(insn)
}
iset.Arches[iset.ArchArm64] = insnset
templates = insns
}
func (insnset *InsnSet) GetInsns(mode iset.Mode, typ iset.Type) []iset.Insn {
return insnset.modeInsns[mode][typ]
}
func (insn *Insn) Info() (string, iset.Mode, bool, bool) {
return insn.Name, 1 << iset.ModeLong64, insn.Pseudo, insn.Priv
}
func (insn *Insn) Encode(cfg *iset.Config, r *rand.Rand) []byte {
if insn.Pseudo {
return insn.Generator(cfg, r)
}
ret := make([]byte, 4)
binary.LittleEndian.PutUint32(ret, insn.AsUInt32)
return ret
}
func (insnset *InsnSet) Decode(mode iset.Mode, text []byte) (int, error) {
if len(text) < 4 {
return 0, fmt.Errorf("must be at least 4 bytes")
}
opcode := binary.LittleEndian.Uint32(text[:4])
_, err := ParseInsn(opcode)
if err != nil {
return 0, fmt.Errorf("failed to decode %x", opcode)
}
return 4, nil
}
func (insnset *InsnSet) DecodeExt(mode iset.Mode, text []byte) (int, error) {
return 0, fmt.Errorf("no external decoder")
}
var templates []*Insn
func (insn *Insn) initFromValue(val uint32) {
operands := []uint32{}
for _, field := range insn.Fields {
extracted := extractBits(val, field.Start, field.Length)
operands = append(operands, extracted)
}
insn.Operands = operands
insn.AsUInt32 = val
}
func (insn *Insn) matchesValue(val uint32) bool {
opcode := val & insn.OpcodeMask
return opcode == insn.Opcode
}
func ParseInsn(val uint32) (Insn, error) {
for _, tmpl := range templates {
if tmpl.matchesValue(val) {
newInsn := *tmpl
newInsn.initFromValue(val)
return newInsn, nil
}
}
unknown := Insn{
Name: "unknown",
}
return unknown, fmt.Errorf("unrecognized instruction: %08x", val)
}
// Code generated by pkg/ifuzz/gen. DO NOT EDIT.
// go:build !codeanalysis
package generated
import (
. "github.com/google/syzkaller/pkg/ifuzz/arm64"
)
func init() {
Register(insns_arm64)
}
var insns_arm64 = []*Insn{
{Name: "ADC", OpcodeMask: 4292934656, Opcode: 436207616, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 436207616, Generator: nil},
{Name: "ADC", OpcodeMask: 4292934656, Opcode: 2583691264, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2583691264, Generator: nil},
{Name: "ADCS", OpcodeMask: 4292934656, Opcode: 973078528, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 973078528, Generator: nil},
{Name: "ADCS", OpcodeMask: 4292934656, Opcode: 3120562176, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 3120562176, Generator: nil},
{Name: "ADD (extended register)", OpcodeMask: 4292870144, Opcode: 186646528, Fields: []InsnField{
{"Rm", 20, 5},
{"option", 15, 3},
{"imm3", 12, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 186646528, Generator: nil},
{Name: "ADD (extended register)", OpcodeMask: 4292870144, Opcode: 2334130176, Fields: []InsnField{
{"Rm", 20, 5},
{"option", 15, 3},
{"imm3", 12, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2334130176, Generator: nil},
{Name: "ADD (immediate)", OpcodeMask: 4278190080, Opcode: 285212672, Fields: []InsnField{
{"shift", 23, 2},
{"imm12", 21, 12},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 285212672, Generator: nil},
{Name: "ADD (immediate)", OpcodeMask: 4278190080, Opcode: 2432696320, Fields: []InsnField{
{"shift", 23, 2},
{"imm12", 21, 12},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2432696320, Generator: nil},
{Name: "ADD (shifted register)", OpcodeMask: 4280287232, Opcode: 184549376, Fields: []InsnField{
{"shift", 23, 2},
{"Rm", 20, 5},
{"imm6", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 184549376, Generator: nil},
{Name: "ADD (shifted register)", OpcodeMask: 4280287232, Opcode: 2332033024, Fields: []InsnField{
{"shift", 23, 2},
{"Rm", 20, 5},
{"imm6", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2332033024, Generator: nil},
{Name: "ADDS (extended register)", OpcodeMask: 4292870144, Opcode: 723517440, Fields: []InsnField{
{"Rm", 20, 5},
{"option", 15, 3},
{"imm3", 12, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 723517440, Generator: nil},
{Name: "ADDS (extended register)", OpcodeMask: 4292870144, Opcode: 2871001088, Fields: []InsnField{
{"Rm", 20, 5},
{"option", 15, 3},
{"imm3", 12, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2871001088, Generator: nil},
{Name: "ADDS (immediate)", OpcodeMask: 4278190080, Opcode: 822083584, Fields: []InsnField{
{"shift", 23, 2},
{"imm12", 21, 12},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 822083584, Generator: nil},
{Name: "ADDS (immediate)", OpcodeMask: 4278190080, Opcode: 2969567232, Fields: []InsnField{
{"shift", 23, 2},
{"imm12", 21, 12},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2969567232, Generator: nil},
{Name: "ADDS (shifted register)", OpcodeMask: 4280287232, Opcode: 721420288, Fields: []InsnField{
{"shift", 23, 2},
{"Rm", 20, 5},
{"imm6", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 721420288, Generator: nil},
{Name: "ADDS (shifted register)", OpcodeMask: 4280287232, Opcode: 2868903936, Fields: []InsnField{
{"shift", 23, 2},
{"Rm", 20, 5},
{"imm6", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2868903936, Generator: nil},
{Name: "ADR", OpcodeMask: 2667577344, Opcode: 268435456, Fields: []InsnField{
{"immlo", 30, 2},
{"immhi", 23, 19},
{"Rd", 4, 5},
}, AsUInt32: 268435456, Generator: nil},
{Name: "ADRP", OpcodeMask: 2667577344, Opcode: 2415919104, Fields: []InsnField{
{"immlo", 30, 2},
{"immhi", 23, 19},
{"Rd", 4, 5},
}, AsUInt32: 2415919104, Generator: nil},
{Name: "AND (immediate)", OpcodeMask: 4290772992, Opcode: 301989888, Fields: []InsnField{
{"immr", 21, 6},
{"imms", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 301989888, Generator: nil},
{Name: "AND (immediate)", OpcodeMask: 4286578688, Opcode: 2449473536, Fields: []InsnField{
{"N", 22, 1},
{"immr", 21, 6},
{"imms", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2449473536, Generator: nil},
{Name: "AND (shifted register)", OpcodeMask: 4280287232, Opcode: 167772160, Fields: []InsnField{
{"shift", 23, 2},
{"Rm", 20, 5},
{"imm6", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 167772160, Generator: nil},
{Name: "AND (shifted register)", OpcodeMask: 4280287232, Opcode: 2315255808, Fields: []InsnField{
{"shift", 23, 2},
{"Rm", 20, 5},
{"imm6", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2315255808, Generator: nil},
{Name: "ANDS (immediate)", OpcodeMask: 4290772992, Opcode: 1912602624, Fields: []InsnField{
{"immr", 21, 6},
{"imms", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1912602624, Generator: nil},
{Name: "ANDS (immediate)", OpcodeMask: 4286578688, Opcode: 4060086272, Fields: []InsnField{
{"N", 22, 1},
{"immr", 21, 6},
{"imms", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 4060086272, Generator: nil},
{Name: "ANDS (shifted register)", OpcodeMask: 4280287232, Opcode: 1778384896, Fields: []InsnField{
{"shift", 23, 2},
{"Rm", 20, 5},
{"imm6", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1778384896, Generator: nil},
{Name: "ANDS (shifted register)", OpcodeMask: 4280287232, Opcode: 3925868544, Fields: []InsnField{
{"shift", 23, 2},
{"Rm", 20, 5},
{"imm6", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 3925868544, Generator: nil},
{Name: "ASR (register)", OpcodeMask: 4292934656, Opcode: 448800768, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 448800768, Generator: nil},
{Name: "ASR (register)", OpcodeMask: 4292934656, Opcode: 2596284416, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2596284416, Generator: nil},
{Name: "ASR (immediate)", OpcodeMask: 4290837504, Opcode: 318798848, Fields: []InsnField{
{"immr", 21, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 318798848, Generator: nil},
{Name: "ASR (immediate)", OpcodeMask: 4290837504, Opcode: 2470509568, Fields: []InsnField{
{"immr", 21, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2470509568, Generator: nil},
{Name: "ASRV", OpcodeMask: 4292934656, Opcode: 448800768, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 448800768, Generator: nil},
{Name: "ASRV", OpcodeMask: 4292934656, Opcode: 2596284416, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2596284416, Generator: nil},
{Name: "AT", OpcodeMask: 4294504448, Opcode: 3574099968, Fields: []InsnField{
{"op1", 18, 3},
{"CRm", 11, 4},
{"op2", 7, 3},
{"Rt", 4, 5},
}, AsUInt32: 3574099968, Priv: true, Generator: nil},
{Name: "B.cond", OpcodeMask: 4278190096, Opcode: 1409286144, Fields: []InsnField{
{"imm19", 23, 19},
{"cond", 3, 4},
}, AsUInt32: 1409286144, Generator: nil},
{Name: "B", OpcodeMask: 4227858432, Opcode: 335544320, Fields: []InsnField{
{"imm26", 25, 26},
}, AsUInt32: 335544320, Generator: nil},
{Name: "BFI", OpcodeMask: 4290772992, Opcode: 855638016, Fields: []InsnField{
{"immr", 21, 6},
{"imms", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 855638016, Generator: nil},
{Name: "BFI", OpcodeMask: 4290772992, Opcode: 3007315968, Fields: []InsnField{
{"immr", 21, 6},
{"imms", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 3007315968, Generator: nil},
{Name: "BFM", OpcodeMask: 4290772992, Opcode: 855638016, Fields: []InsnField{
{"immr", 21, 6},
{"imms", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 855638016, Generator: nil},
{Name: "BFM", OpcodeMask: 4290772992, Opcode: 3007315968, Fields: []InsnField{
{"immr", 21, 6},
{"imms", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 3007315968, Generator: nil},
{Name: "BFXIL", OpcodeMask: 4290772992, Opcode: 855638016, Fields: []InsnField{
{"immr", 21, 6},
{"imms", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 855638016, Generator: nil},
{Name: "BFXIL", OpcodeMask: 4290772992, Opcode: 3007315968, Fields: []InsnField{
{"immr", 21, 6},
{"imms", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 3007315968, Generator: nil},
{Name: "BIC (shifted register)", OpcodeMask: 4280287232, Opcode: 169869312, Fields: []InsnField{
{"shift", 23, 2},
{"Rm", 20, 5},
{"imm6", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 169869312, Generator: nil},
{Name: "BIC (shifted register)", OpcodeMask: 4280287232, Opcode: 2317352960, Fields: []InsnField{
{"shift", 23, 2},
{"Rm", 20, 5},
{"imm6", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2317352960, Generator: nil},
{Name: "BICS (shifted register)", OpcodeMask: 4280287232, Opcode: 1780482048, Fields: []InsnField{
{"shift", 23, 2},
{"Rm", 20, 5},
{"imm6", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1780482048, Generator: nil},
{Name: "BICS (shifted register)", OpcodeMask: 4280287232, Opcode: 3927965696, Fields: []InsnField{
{"shift", 23, 2},
{"Rm", 20, 5},
{"imm6", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 3927965696, Generator: nil},
{Name: "BL", OpcodeMask: 4227858432, Opcode: 2483027968, Fields: []InsnField{
{"imm26", 25, 26},
}, AsUInt32: 2483027968, Generator: nil},
{Name: "BLR", OpcodeMask: 4294966303, Opcode: 3594452992, Fields: []InsnField{
{"Rn", 9, 5},
}, AsUInt32: 3594452992, Generator: nil},
{Name: "BR", OpcodeMask: 4294966303, Opcode: 3592355840, Fields: []InsnField{
{"Rn", 9, 5},
}, AsUInt32: 3592355840, Generator: nil},
{Name: "BRK", OpcodeMask: 4292870175, Opcode: 3558866944, Fields: []InsnField{
{"imm16", 20, 16},
}, AsUInt32: 3558866944, Generator: nil},
{Name: "CBNZ", OpcodeMask: 4278190080, Opcode: 889192448, Fields: []InsnField{
{"imm19", 23, 19},
{"Rt", 4, 5},
}, AsUInt32: 889192448, Generator: nil},
{Name: "CBNZ", OpcodeMask: 4278190080, Opcode: 3036676096, Fields: []InsnField{
{"imm19", 23, 19},
{"Rt", 4, 5},
}, AsUInt32: 3036676096, Generator: nil},
{Name: "CBZ", OpcodeMask: 4278190080, Opcode: 872415232, Fields: []InsnField{
{"imm19", 23, 19},
{"Rt", 4, 5},
}, AsUInt32: 872415232, Generator: nil},
{Name: "CBZ", OpcodeMask: 4278190080, Opcode: 3019898880, Fields: []InsnField{
{"imm19", 23, 19},
{"Rt", 4, 5},
}, AsUInt32: 3019898880, Generator: nil},
{Name: "CCMN (immediate)", OpcodeMask: 4292873232, Opcode: 977274880, Fields: []InsnField{
{"imm5", 20, 5},
{"cond", 15, 4},
{"Rn", 9, 5},
{"nzcv", 3, 4},
}, AsUInt32: 977274880, Generator: nil},
{Name: "CCMN (immediate)", OpcodeMask: 4292873232, Opcode: 3124758528, Fields: []InsnField{
{"imm5", 20, 5},
{"cond", 15, 4},
{"Rn", 9, 5},
{"nzcv", 3, 4},
}, AsUInt32: 3124758528, Generator: nil},
{Name: "CCMN (register)", OpcodeMask: 4292873232, Opcode: 977272832, Fields: []InsnField{
{"Rm", 20, 5},
{"cond", 15, 4},
{"Rn", 9, 5},
{"nzcv", 3, 4},
}, AsUInt32: 977272832, Generator: nil},
{Name: "CCMN (register)", OpcodeMask: 4292873232, Opcode: 3124756480, Fields: []InsnField{
{"Rm", 20, 5},
{"cond", 15, 4},
{"Rn", 9, 5},
{"nzcv", 3, 4},
}, AsUInt32: 3124756480, Generator: nil},
{Name: "CCMP (immediate)", OpcodeMask: 4292873232, Opcode: 2051016704, Fields: []InsnField{
{"imm5", 20, 5},
{"cond", 15, 4},
{"Rn", 9, 5},
{"nzcv", 3, 4},
}, AsUInt32: 2051016704, Generator: nil},
{Name: "CCMP (immediate)", OpcodeMask: 4292873232, Opcode: 4198500352, Fields: []InsnField{
{"imm5", 20, 5},
{"cond", 15, 4},
{"Rn", 9, 5},
{"nzcv", 3, 4},
}, AsUInt32: 4198500352, Generator: nil},
{Name: "CCMP (register)", OpcodeMask: 4292873232, Opcode: 2051014656, Fields: []InsnField{
{"Rm", 20, 5},
{"cond", 15, 4},
{"Rn", 9, 5},
{"nzcv", 3, 4},
}, AsUInt32: 2051014656, Generator: nil},
{Name: "CCMP (register)", OpcodeMask: 4292873232, Opcode: 4198498304, Fields: []InsnField{
{"Rm", 20, 5},
{"cond", 15, 4},
{"Rn", 9, 5},
{"nzcv", 3, 4},
}, AsUInt32: 4198498304, Generator: nil},
{Name: "CINC", OpcodeMask: 4292873216, Opcode: 444597248, Fields: []InsnField{
{"Rm", 20, 5},
{"cond", 15, 4},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 444597248, Generator: nil},
{Name: "CINC", OpcodeMask: 4292873216, Opcode: 2592080896, Fields: []InsnField{
{"Rm", 20, 5},
{"cond", 15, 4},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2592080896, Generator: nil},
{Name: "CINV", OpcodeMask: 4292873216, Opcode: 1518338048, Fields: []InsnField{
{"Rm", 20, 5},
{"cond", 15, 4},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1518338048, Generator: nil},
{Name: "CINV", OpcodeMask: 4292873216, Opcode: 3665821696, Fields: []InsnField{
{"Rm", 20, 5},
{"cond", 15, 4},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 3665821696, Generator: nil},
{Name: "CLREX", OpcodeMask: 4294963455, Opcode: 3573755999, Fields: []InsnField{
{"CRm", 11, 4},
}, AsUInt32: 3573755999, Generator: nil},
{Name: "CLS", OpcodeMask: 4294966272, Opcode: 1522537472, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1522537472, Generator: nil},
{Name: "CLS", OpcodeMask: 4294966272, Opcode: 3670021120, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 3670021120, Generator: nil},
{Name: "CLZ", OpcodeMask: 4294966272, Opcode: 1522536448, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1522536448, Generator: nil},
{Name: "CLZ", OpcodeMask: 4294966272, Opcode: 3670020096, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 3670020096, Generator: nil},
{Name: "CMN (extended register)", OpcodeMask: 4292870175, Opcode: 723517471, Fields: []InsnField{
{"Rm", 20, 5},
{"option", 15, 3},
{"imm3", 12, 3},
{"Rn", 9, 5},
}, AsUInt32: 723517471, Generator: nil},
{Name: "CMN (extended register)", OpcodeMask: 4292870175, Opcode: 2871001119, Fields: []InsnField{
{"Rm", 20, 5},
{"option", 15, 3},
{"imm3", 12, 3},
{"Rn", 9, 5},
}, AsUInt32: 2871001119, Generator: nil},
{Name: "CMN (immediate)", OpcodeMask: 4278190111, Opcode: 822083615, Fields: []InsnField{
{"shift", 23, 2},
{"imm12", 21, 12},
{"Rn", 9, 5},
}, AsUInt32: 822083615, Generator: nil},
{Name: "CMN (immediate)", OpcodeMask: 4278190111, Opcode: 2969567263, Fields: []InsnField{
{"shift", 23, 2},
{"imm12", 21, 12},
{"Rn", 9, 5},
}, AsUInt32: 2969567263, Generator: nil},
{Name: "CMN (shifted register)", OpcodeMask: 4280287263, Opcode: 721420319, Fields: []InsnField{
{"shift", 23, 2},
{"Rm", 20, 5},
{"imm6", 15, 6},
{"Rn", 9, 5},
}, AsUInt32: 721420319, Generator: nil},
{Name: "CMN (shifted register)", OpcodeMask: 4280287263, Opcode: 2868903967, Fields: []InsnField{
{"shift", 23, 2},
{"Rm", 20, 5},
{"imm6", 15, 6},
{"Rn", 9, 5},
}, AsUInt32: 2868903967, Generator: nil},
{Name: "CMP (extended register)", OpcodeMask: 4292870175, Opcode: 1797259295, Fields: []InsnField{
{"Rm", 20, 5},
{"option", 15, 3},
{"imm3", 12, 3},
{"Rn", 9, 5},
}, AsUInt32: 1797259295, Generator: nil},
{Name: "CMP (extended register)", OpcodeMask: 4292870175, Opcode: 3944742943, Fields: []InsnField{
{"Rm", 20, 5},
{"option", 15, 3},
{"imm3", 12, 3},
{"Rn", 9, 5},
}, AsUInt32: 3944742943, Generator: nil},
{Name: "CMP (immediate)", OpcodeMask: 4278190111, Opcode: 1895825439, Fields: []InsnField{
{"shift", 23, 2},
{"imm12", 21, 12},
{"Rn", 9, 5},
}, AsUInt32: 1895825439, Generator: nil},
{Name: "CMP (immediate)", OpcodeMask: 4278190111, Opcode: 4043309087, Fields: []InsnField{
{"shift", 23, 2},
{"imm12", 21, 12},
{"Rn", 9, 5},
}, AsUInt32: 4043309087, Generator: nil},
{Name: "CMP (shifted register)", OpcodeMask: 4280287263, Opcode: 1795162143, Fields: []InsnField{
{"shift", 23, 2},
{"Rm", 20, 5},
{"imm6", 15, 6},
{"Rn", 9, 5},
}, AsUInt32: 1795162143, Generator: nil},
{Name: "CMP (shifted register)", OpcodeMask: 4280287263, Opcode: 3942645791, Fields: []InsnField{
{"shift", 23, 2},
{"Rm", 20, 5},
{"imm6", 15, 6},
{"Rn", 9, 5},
}, AsUInt32: 3942645791, Generator: nil},
{Name: "CNEG", OpcodeMask: 4292873216, Opcode: 1518339072, Fields: []InsnField{
{"Rm", 20, 5},
{"cond", 15, 4},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1518339072, Generator: nil},
{Name: "CNEG", OpcodeMask: 4292873216, Opcode: 3665822720, Fields: []InsnField{
{"Rm", 20, 5},
{"cond", 15, 4},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 3665822720, Generator: nil},
{Name: "CRC32B, CRC32H, CRC32W, CRC32X", OpcodeMask: 4292934656, Opcode: 448806912, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 448806912, Generator: nil},
{Name: "CRC32B, CRC32H, CRC32W, CRC32X", OpcodeMask: 4292934656, Opcode: 448807936, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 448807936, Generator: nil},
{Name: "CRC32B, CRC32H, CRC32W, CRC32X", OpcodeMask: 4292934656, Opcode: 448808960, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 448808960, Generator: nil},
{Name: "CRC32B, CRC32H, CRC32W, CRC32X", OpcodeMask: 4292934656, Opcode: 2596293632, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2596293632, Generator: nil},
{Name: "CRC32CB, CRC32CH, CRC32CW, CRC32CX", OpcodeMask: 4292934656, Opcode: 448811008, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 448811008, Generator: nil},
{Name: "CRC32CB, CRC32CH, CRC32CW, CRC32CX", OpcodeMask: 4292934656, Opcode: 448812032, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 448812032, Generator: nil},
{Name: "CRC32CB, CRC32CH, CRC32CW, CRC32CX", OpcodeMask: 4292934656, Opcode: 448813056, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 448813056, Generator: nil},
{Name: "CRC32CB, CRC32CH, CRC32CW, CRC32CX", OpcodeMask: 4292934656, Opcode: 2596297728, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2596297728, Generator: nil},
{Name: "CSEL", OpcodeMask: 4292873216, Opcode: 444596224, Fields: []InsnField{
{"Rm", 20, 5},
{"cond", 15, 4},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 444596224, Generator: nil},
{Name: "CSEL", OpcodeMask: 4292873216, Opcode: 2592079872, Fields: []InsnField{
{"Rm", 20, 5},
{"cond", 15, 4},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2592079872, Generator: nil},
{Name: "CSET", OpcodeMask: 4294905824, Opcode: 446629856, Fields: []InsnField{
{"cond", 15, 4},
{"Rd", 4, 5},
}, AsUInt32: 446629856, Generator: nil},
{Name: "CSET", OpcodeMask: 4294905824, Opcode: 2594113504, Fields: []InsnField{
{"cond", 15, 4},
{"Rd", 4, 5},
}, AsUInt32: 2594113504, Generator: nil},
{Name: "CSETM", OpcodeMask: 4294905824, Opcode: 1520370656, Fields: []InsnField{
{"cond", 15, 4},
{"Rd", 4, 5},
}, AsUInt32: 1520370656, Generator: nil},
{Name: "CSETM", OpcodeMask: 4294905824, Opcode: 3667854304, Fields: []InsnField{
{"cond", 15, 4},
{"Rd", 4, 5},
}, AsUInt32: 3667854304, Generator: nil},
{Name: "CSINC", OpcodeMask: 4292873216, Opcode: 444597248, Fields: []InsnField{
{"Rm", 20, 5},
{"cond", 15, 4},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 444597248, Generator: nil},
{Name: "CSINC", OpcodeMask: 4292873216, Opcode: 2592080896, Fields: []InsnField{
{"Rm", 20, 5},
{"cond", 15, 4},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2592080896, Generator: nil},
{Name: "CSINV", OpcodeMask: 4292873216, Opcode: 1518338048, Fields: []InsnField{
{"Rm", 20, 5},
{"cond", 15, 4},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1518338048, Generator: nil},
{Name: "CSINV", OpcodeMask: 4292873216, Opcode: 3665821696, Fields: []InsnField{
{"Rm", 20, 5},
{"cond", 15, 4},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 3665821696, Generator: nil},
{Name: "CSNEG", OpcodeMask: 4292873216, Opcode: 1518339072, Fields: []InsnField{
{"Rm", 20, 5},
{"cond", 15, 4},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1518339072, Generator: nil},
{Name: "CSNEG", OpcodeMask: 4292873216, Opcode: 3665822720, Fields: []InsnField{
{"Rm", 20, 5},
{"cond", 15, 4},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 3665822720, Generator: nil},
{Name: "DC", OpcodeMask: 4294504448, Opcode: 3574099968, Fields: []InsnField{
{"op1", 18, 3},
{"CRm", 11, 4},
{"op2", 7, 3},
{"Rt", 4, 5},
}, AsUInt32: 3574099968, Priv: true, Generator: nil},
{Name: "DCPS1", OpcodeMask: 4292870175, Opcode: 3567255553, Fields: []InsnField{
{"imm16", 20, 16},
}, AsUInt32: 3567255553, Generator: nil},
{Name: "DCPS2", OpcodeMask: 4292870175, Opcode: 3567255554, Fields: []InsnField{
{"imm16", 20, 16},
}, AsUInt32: 3567255554, Generator: nil},
{Name: "DCPS3", OpcodeMask: 4292870175, Opcode: 3567255555, Fields: []InsnField{
{"imm16", 20, 16},
}, AsUInt32: 3567255555, Generator: nil},
{Name: "DMB", OpcodeMask: 4294963455, Opcode: 3573756095, Fields: []InsnField{
{"CRm", 11, 4},
}, AsUInt32: 3573756095, Generator: nil},
{Name: "DRPS", OpcodeMask: 4294967295, Opcode: 3602842592, AsUInt32: 3602842592, Generator: nil},
{Name: "DSB", OpcodeMask: 4294963455, Opcode: 3573756063, Fields: []InsnField{
{"CRm", 11, 4},
}, AsUInt32: 3573756063, Generator: nil},
{Name: "EON (shifted register)", OpcodeMask: 4280287232, Opcode: 1243611136, Fields: []InsnField{
{"shift", 23, 2},
{"Rm", 20, 5},
{"imm6", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1243611136, Generator: nil},
{Name: "EON (shifted register)", OpcodeMask: 4280287232, Opcode: 3391094784, Fields: []InsnField{
{"shift", 23, 2},
{"Rm", 20, 5},
{"imm6", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 3391094784, Generator: nil},
{Name: "EOR (immediate)", OpcodeMask: 4290772992, Opcode: 1375731712, Fields: []InsnField{
{"immr", 21, 6},
{"imms", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1375731712, Generator: nil},
{Name: "EOR (immediate)", OpcodeMask: 4286578688, Opcode: 3523215360, Fields: []InsnField{
{"N", 22, 1},
{"immr", 21, 6},
{"imms", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 3523215360, Generator: nil},
{Name: "EOR (shifted register)", OpcodeMask: 4280287232, Opcode: 1241513984, Fields: []InsnField{
{"shift", 23, 2},
{"Rm", 20, 5},
{"imm6", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1241513984, Generator: nil},
{Name: "EOR (shifted register)", OpcodeMask: 4280287232, Opcode: 3388997632, Fields: []InsnField{
{"shift", 23, 2},
{"Rm", 20, 5},
{"imm6", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 3388997632, Generator: nil},
{Name: "ERET", OpcodeMask: 4294967295, Opcode: 3600745440, AsUInt32: 3600745440, Generator: nil},
{Name: "EXTR", OpcodeMask: 4292870144, Opcode: 327155712, Fields: []InsnField{
{"Rm", 20, 5},
{"imms", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 327155712, Generator: nil},
{Name: "EXTR", OpcodeMask: 4292870144, Opcode: 2478833664, Fields: []InsnField{
{"Rm", 20, 5},
{"imms", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2478833664, Generator: nil},
{Name: "HINT", OpcodeMask: 4294967071, Opcode: 3573751839, Fields: []InsnField{
{"op2", 7, 3},
}, AsUInt32: 3573751839, Generator: nil},
{Name: "HINT", OpcodeMask: 4294963231, Opcode: 3573751839, Fields: []InsnField{
{"CRm", 11, 4},
{"op2", 7, 3},
}, AsUInt32: 3573751839, Generator: nil},
{Name: "HLT", OpcodeMask: 4292870175, Opcode: 3560964096, Fields: []InsnField{
{"imm16", 20, 16},
}, AsUInt32: 3560964096, Generator: nil},
{Name: "HVC", OpcodeMask: 4292870175, Opcode: 3556769794, Fields: []InsnField{
{"imm16", 20, 16},
}, AsUInt32: 3556769794, Generator: nil},
{Name: "IC", OpcodeMask: 4294504448, Opcode: 3574099968, Fields: []InsnField{
{"op1", 18, 3},
{"CRm", 11, 4},
{"op2", 7, 3},
{"Rt", 4, 5},
}, AsUInt32: 3574099968, Priv: true, Generator: nil},
{Name: "ISB", OpcodeMask: 4294963455, Opcode: 3573756127, Fields: []InsnField{
{"CRm", 11, 4},
}, AsUInt32: 3573756127, Generator: nil},
{Name: "LDAR", OpcodeMask: 4292902912, Opcode: 2294317056, Fields: []InsnField{
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2294317056, Generator: nil},
{Name: "LDAR", OpcodeMask: 4292902912, Opcode: 3368058880, Fields: []InsnField{
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 3368058880, Generator: nil},
{Name: "LDARB", OpcodeMask: 4292902912, Opcode: 146833408, Fields: []InsnField{
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 146833408, Generator: nil},
{Name: "LDARH", OpcodeMask: 4292902912, Opcode: 1220575232, Fields: []InsnField{
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 1220575232, Generator: nil},
{Name: "LDAXP", OpcodeMask: 4292902912, Opcode: 2288025600, Fields: []InsnField{
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2288025600, Generator: nil},
{Name: "LDAXP", OpcodeMask: 4292902912, Opcode: 3361767424, Fields: []InsnField{
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 3361767424, Generator: nil},
{Name: "LDAXR", OpcodeMask: 4292902912, Opcode: 2285928448, Fields: []InsnField{
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2285928448, Generator: nil},
{Name: "LDAXR", OpcodeMask: 4292902912, Opcode: 3359670272, Fields: []InsnField{
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 3359670272, Generator: nil},
{Name: "LDAXRB", OpcodeMask: 4292902912, Opcode: 138444800, Fields: []InsnField{
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 138444800, Generator: nil},
{Name: "LDAXRH", OpcodeMask: 4292902912, Opcode: 1212186624, Fields: []InsnField{
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 1212186624, Generator: nil},
{Name: "LDNP", OpcodeMask: 4290772992, Opcode: 675282944, Fields: []InsnField{
{"imm7", 21, 7},
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 675282944, Generator: nil},
{Name: "LDNP", OpcodeMask: 4290772992, Opcode: 2822766592, Fields: []InsnField{
{"imm7", 21, 7},
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2822766592, Generator: nil},
{Name: "LDP", OpcodeMask: 4290772992, Opcode: 683671552, Fields: []InsnField{
{"imm7", 21, 7},
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 683671552, Generator: nil},
{Name: "LDP", OpcodeMask: 4290772992, Opcode: 2831155200, Fields: []InsnField{
{"imm7", 21, 7},
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2831155200, Generator: nil},
{Name: "LDP", OpcodeMask: 4290772992, Opcode: 700448768, Fields: []InsnField{
{"imm7", 21, 7},
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 700448768, Generator: nil},
{Name: "LDP", OpcodeMask: 4290772992, Opcode: 2847932416, Fields: []InsnField{
{"imm7", 21, 7},
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2847932416, Generator: nil},
{Name: "LDP", OpcodeMask: 4290772992, Opcode: 692060160, Fields: []InsnField{
{"imm7", 21, 7},
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 692060160, Generator: nil},
{Name: "LDP", OpcodeMask: 4290772992, Opcode: 2839543808, Fields: []InsnField{
{"imm7", 21, 7},
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2839543808, Generator: nil},
{Name: "LDPSW", OpcodeMask: 4290772992, Opcode: 1757413376, Fields: []InsnField{
{"imm7", 21, 7},
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 1757413376, Generator: nil},
{Name: "LDPSW", OpcodeMask: 4290772992, Opcode: 1774190592, Fields: []InsnField{
{"imm7", 21, 7},
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 1774190592, Generator: nil},
{Name: "LDPSW", OpcodeMask: 4290772992, Opcode: 1765801984, Fields: []InsnField{
{"imm7", 21, 7},
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 1765801984, Generator: nil},
{Name: "LDR (immediate)", OpcodeMask: 4292873216, Opcode: 3091203072, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 3091203072, Generator: nil},
{Name: "LDR (immediate)", OpcodeMask: 4292873216, Opcode: 4164944896, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 4164944896, Generator: nil},
{Name: "LDR (immediate)", OpcodeMask: 4292873216, Opcode: 3091205120, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 3091205120, Generator: nil},
{Name: "LDR (immediate)", OpcodeMask: 4292873216, Opcode: 4164946944, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 4164946944, Generator: nil},
{Name: "LDR (immediate)", OpcodeMask: 4290772992, Opcode: 3107979264, Fields: []InsnField{
{"imm12", 21, 12},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 3107979264, Generator: nil},
{Name: "LDR (immediate)", OpcodeMask: 4290772992, Opcode: 4181721088, Fields: []InsnField{
{"imm12", 21, 12},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 4181721088, Generator: nil},
{Name: "LDR (literal)", OpcodeMask: 4278190080, Opcode: 402653184, Fields: []InsnField{
{"imm19", 23, 19},
{"Rt", 4, 5},
}, AsUInt32: 402653184, Generator: nil},
{Name: "LDR (literal)", OpcodeMask: 4278190080, Opcode: 1476395008, Fields: []InsnField{
{"imm19", 23, 19},
{"Rt", 4, 5},
}, AsUInt32: 1476395008, Generator: nil},
{Name: "LDR (register)", OpcodeMask: 4292873216, Opcode: 3093301248, Fields: []InsnField{
{"Rm", 20, 5},
{"option", 15, 3},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 3093301248, Generator: nil},
{Name: "LDR (register)", OpcodeMask: 4292873216, Opcode: 4167043072, Fields: []InsnField{
{"Rm", 20, 5},
{"option", 15, 3},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 4167043072, Generator: nil},
{Name: "LDRB (immediate)", OpcodeMask: 4292873216, Opcode: 943719424, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 943719424, Generator: nil},
{Name: "LDRB (immediate)", OpcodeMask: 4292873216, Opcode: 943721472, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 943721472, Generator: nil},
{Name: "LDRB (immediate)", OpcodeMask: 4290772992, Opcode: 960495616, Fields: []InsnField{
{"imm12", 21, 12},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 960495616, Generator: nil},
{Name: "LDRB (register)", OpcodeMask: 4292873216, Opcode: 945817600, Fields: []InsnField{
{"Rm", 20, 5},
{"option", 15, 3},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 945817600, Generator: nil},
{Name: "LDRB (register)", OpcodeMask: 4292930560, Opcode: 945842176, Fields: []InsnField{
{"Rm", 20, 5},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 945842176, Generator: nil},
{Name: "LDRH (immediate)", OpcodeMask: 4292873216, Opcode: 2017461248, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2017461248, Generator: nil},
{Name: "LDRH (immediate)", OpcodeMask: 4292873216, Opcode: 2017463296, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2017463296, Generator: nil},
{Name: "LDRH (immediate)", OpcodeMask: 4290772992, Opcode: 2034237440, Fields: []InsnField{
{"imm12", 21, 12},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2034237440, Generator: nil},
{Name: "LDRH (register)", OpcodeMask: 4292873216, Opcode: 2019559424, Fields: []InsnField{
{"Rm", 20, 5},
{"option", 15, 3},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2019559424, Generator: nil},
{Name: "LDRSB (immediate)", OpcodeMask: 4292873216, Opcode: 952108032, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 952108032, Generator: nil},
{Name: "LDRSB (immediate)", OpcodeMask: 4292873216, Opcode: 947913728, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 947913728, Generator: nil},
{Name: "LDRSB (immediate)", OpcodeMask: 4292873216, Opcode: 952110080, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 952110080, Generator: nil},
{Name: "LDRSB (immediate)", OpcodeMask: 4292873216, Opcode: 947915776, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 947915776, Generator: nil},
{Name: "LDRSB (immediate)", OpcodeMask: 4290772992, Opcode: 968884224, Fields: []InsnField{
{"imm12", 21, 12},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 968884224, Generator: nil},
{Name: "LDRSB (immediate)", OpcodeMask: 4290772992, Opcode: 964689920, Fields: []InsnField{
{"imm12", 21, 12},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 964689920, Generator: nil},
{Name: "LDRSB (register)", OpcodeMask: 4292873216, Opcode: 954206208, Fields: []InsnField{
{"Rm", 20, 5},
{"option", 15, 3},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 954206208, Generator: nil},
{Name: "LDRSB (register)", OpcodeMask: 4292930560, Opcode: 954230784, Fields: []InsnField{
{"Rm", 20, 5},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 954230784, Generator: nil},
{Name: "LDRSB (register)", OpcodeMask: 4292873216, Opcode: 950011904, Fields: []InsnField{
{"Rm", 20, 5},
{"option", 15, 3},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 950011904, Generator: nil},
{Name: "LDRSB (register)", OpcodeMask: 4292930560, Opcode: 950036480, Fields: []InsnField{
{"Rm", 20, 5},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 950036480, Generator: nil},
{Name: "LDRSH (immediate)", OpcodeMask: 4292873216, Opcode: 2025849856, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2025849856, Generator: nil},
{Name: "LDRSH (immediate)", OpcodeMask: 4292873216, Opcode: 2021655552, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2021655552, Generator: nil},
{Name: "LDRSH (immediate)", OpcodeMask: 4292873216, Opcode: 2025851904, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2025851904, Generator: nil},
{Name: "LDRSH (immediate)", OpcodeMask: 4292873216, Opcode: 2021657600, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2021657600, Generator: nil},
{Name: "LDRSH (immediate)", OpcodeMask: 4290772992, Opcode: 2042626048, Fields: []InsnField{
{"imm12", 21, 12},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2042626048, Generator: nil},
{Name: "LDRSH (immediate)", OpcodeMask: 4290772992, Opcode: 2038431744, Fields: []InsnField{
{"imm12", 21, 12},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2038431744, Generator: nil},
{Name: "LDRSH (register)", OpcodeMask: 4292873216, Opcode: 2027948032, Fields: []InsnField{
{"Rm", 20, 5},
{"option", 15, 3},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2027948032, Generator: nil},
{Name: "LDRSH (register)", OpcodeMask: 4292873216, Opcode: 2023753728, Fields: []InsnField{
{"Rm", 20, 5},
{"option", 15, 3},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2023753728, Generator: nil},
{Name: "LDRSW (immediate)", OpcodeMask: 4292873216, Opcode: 3095397376, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 3095397376, Generator: nil},
{Name: "LDRSW (immediate)", OpcodeMask: 4292873216, Opcode: 3095399424, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 3095399424, Generator: nil},
{Name: "LDRSW (immediate)", OpcodeMask: 4290772992, Opcode: 3112173568, Fields: []InsnField{
{"imm12", 21, 12},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 3112173568, Generator: nil},
{Name: "LDRSW (literal)", OpcodeMask: 4278190080, Opcode: 2550136832, Fields: []InsnField{
{"imm19", 23, 19},
{"Rt", 4, 5},
}, AsUInt32: 2550136832, Generator: nil},
{Name: "LDRSW (register)", OpcodeMask: 4292873216, Opcode: 3097495552, Fields: []InsnField{
{"Rm", 20, 5},
{"option", 15, 3},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 3097495552, Generator: nil},
{Name: "LDTR", OpcodeMask: 4292873216, Opcode: 3091204096, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 3091204096, Generator: nil},
{Name: "LDTR", OpcodeMask: 4292873216, Opcode: 4164945920, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 4164945920, Generator: nil},
{Name: "LDTRB", OpcodeMask: 4292873216, Opcode: 943720448, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 943720448, Generator: nil},
{Name: "LDTRH", OpcodeMask: 4292873216, Opcode: 2017462272, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2017462272, Generator: nil},
{Name: "LDTRSB", OpcodeMask: 4292873216, Opcode: 952109056, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 952109056, Generator: nil},
{Name: "LDTRSB", OpcodeMask: 4292873216, Opcode: 947914752, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 947914752, Generator: nil},
{Name: "LDTRSH", OpcodeMask: 4292873216, Opcode: 2025850880, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2025850880, Generator: nil},
{Name: "LDTRSH", OpcodeMask: 4292873216, Opcode: 2021656576, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2021656576, Generator: nil},
{Name: "LDTRSW", OpcodeMask: 4292873216, Opcode: 3095398400, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 3095398400, Generator: nil},
{Name: "LDUR", OpcodeMask: 4292873216, Opcode: 3091202048, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 3091202048, Generator: nil},
{Name: "LDUR", OpcodeMask: 4292873216, Opcode: 4164943872, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 4164943872, Generator: nil},
{Name: "LDURB", OpcodeMask: 4292873216, Opcode: 943718400, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 943718400, Generator: nil},
{Name: "LDURH", OpcodeMask: 4292873216, Opcode: 2017460224, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2017460224, Generator: nil},
{Name: "LDURSB", OpcodeMask: 4292873216, Opcode: 952107008, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 952107008, Generator: nil},
{Name: "LDURSB", OpcodeMask: 4292873216, Opcode: 947912704, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 947912704, Generator: nil},
{Name: "LDURSH", OpcodeMask: 4292873216, Opcode: 2025848832, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2025848832, Generator: nil},
{Name: "LDURSH", OpcodeMask: 4292873216, Opcode: 2021654528, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2021654528, Generator: nil},
{Name: "LDURSW", OpcodeMask: 4292873216, Opcode: 3095396352, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 3095396352, Generator: nil},
{Name: "LDXP", OpcodeMask: 4292902912, Opcode: 2287992832, Fields: []InsnField{
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2287992832, Generator: nil},
{Name: "LDXP", OpcodeMask: 4292902912, Opcode: 3361734656, Fields: []InsnField{
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 3361734656, Generator: nil},
{Name: "LDXR", OpcodeMask: 4292902912, Opcode: 2285895680, Fields: []InsnField{
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2285895680, Generator: nil},
{Name: "LDXR", OpcodeMask: 4292902912, Opcode: 3359637504, Fields: []InsnField{
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 3359637504, Generator: nil},
{Name: "LDXRB", OpcodeMask: 4292902912, Opcode: 138412032, Fields: []InsnField{
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 138412032, Generator: nil},
{Name: "LDXRH", OpcodeMask: 4292902912, Opcode: 1212153856, Fields: []InsnField{
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 1212153856, Generator: nil},
{Name: "LSL (register)", OpcodeMask: 4292934656, Opcode: 448798720, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 448798720, Generator: nil},
{Name: "LSL (register)", OpcodeMask: 4292934656, Opcode: 2596282368, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2596282368, Generator: nil},
{Name: "LSL (immediate)", OpcodeMask: 4290772992, Opcode: 1392508928, Fields: []InsnField{
{"immr", 21, 6},
{"imms", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1392508928, Generator: nil},
{Name: "LSL (immediate)", OpcodeMask: 4290772992, Opcode: 3544186880, Fields: []InsnField{
{"immr", 21, 6},
{"imms", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 3544186880, Generator: nil},
{Name: "LSLV", OpcodeMask: 4292934656, Opcode: 448798720, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 448798720, Generator: nil},
{Name: "LSLV", OpcodeMask: 4292934656, Opcode: 2596282368, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2596282368, Generator: nil},
{Name: "LSR (register)", OpcodeMask: 4292934656, Opcode: 448799744, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 448799744, Generator: nil},
{Name: "LSR (register)", OpcodeMask: 4292934656, Opcode: 2596283392, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2596283392, Generator: nil},
{Name: "LSR (immediate)", OpcodeMask: 4290837504, Opcode: 1392540672, Fields: []InsnField{
{"immr", 21, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1392540672, Generator: nil},
{Name: "LSR (immediate)", OpcodeMask: 4290837504, Opcode: 3544251392, Fields: []InsnField{
{"immr", 21, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 3544251392, Generator: nil},
{Name: "LSRV", OpcodeMask: 4292934656, Opcode: 448799744, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 448799744, Generator: nil},
{Name: "LSRV", OpcodeMask: 4292934656, Opcode: 2596283392, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2596283392, Generator: nil},
{Name: "MADD", OpcodeMask: 4292902912, Opcode: 452984832, Fields: []InsnField{
{"Rm", 20, 5},
{"Ra", 14, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 452984832, Generator: nil},
{Name: "MADD", OpcodeMask: 4292902912, Opcode: 2600468480, Fields: []InsnField{
{"Rm", 20, 5},
{"Ra", 14, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2600468480, Generator: nil},
{Name: "MNEG", OpcodeMask: 4292934656, Opcode: 453049344, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 453049344, Generator: nil},
{Name: "MNEG", OpcodeMask: 4292934656, Opcode: 2600532992, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2600532992, Generator: nil},
{Name: "MOV (to/from SP)", OpcodeMask: 4294966272, Opcode: 285212672, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 285212672, Generator: nil},
{Name: "MOV (to/from SP)", OpcodeMask: 4294966272, Opcode: 2432696320, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2432696320, Generator: nil},
{Name: "MOV (inverted wide immediate)", OpcodeMask: 4286578688, Opcode: 310378496, Fields: []InsnField{
{"hw", 22, 2},
{"imm16", 20, 16},
{"Rd", 4, 5},
}, AsUInt32: 310378496, Generator: nil},
{Name: "MOV (inverted wide immediate)", OpcodeMask: 4286578688, Opcode: 2457862144, Fields: []InsnField{
{"hw", 22, 2},
{"imm16", 20, 16},
{"Rd", 4, 5},
}, AsUInt32: 2457862144, Generator: nil},
{Name: "MOV (wide immediate)", OpcodeMask: 4286578688, Opcode: 1384120320, Fields: []InsnField{
{"hw", 22, 2},
{"imm16", 20, 16},
{"Rd", 4, 5},
}, AsUInt32: 1384120320, Generator: nil},
{Name: "MOV (wide immediate)", OpcodeMask: 4286578688, Opcode: 3531603968, Fields: []InsnField{
{"hw", 22, 2},
{"imm16", 20, 16},
{"Rd", 4, 5},
}, AsUInt32: 3531603968, Generator: nil},
{Name: "MOV (bitmask immediate)", OpcodeMask: 4290773984, Opcode: 838861792, Fields: []InsnField{
{"immr", 21, 6},
{"imms", 15, 6},
{"Rd", 4, 5},
}, AsUInt32: 838861792, Generator: nil},
{Name: "MOV (bitmask immediate)", OpcodeMask: 4286579680, Opcode: 2986345440, Fields: []InsnField{
{"N", 22, 1},
{"immr", 21, 6},
{"imms", 15, 6},
{"Rd", 4, 5},
}, AsUInt32: 2986345440, Generator: nil},
{Name: "MOV (register)", OpcodeMask: 4292935648, Opcode: 704644064, Fields: []InsnField{
{"Rm", 20, 5},
{"Rd", 4, 5},
}, AsUInt32: 704644064, Generator: nil},
{Name: "MOV (register)", OpcodeMask: 4292935648, Opcode: 2852127712, Fields: []InsnField{
{"Rm", 20, 5},
{"Rd", 4, 5},
}, AsUInt32: 2852127712, Generator: nil},
{Name: "MOVK", OpcodeMask: 4286578688, Opcode: 1920991232, Fields: []InsnField{
{"hw", 22, 2},
{"imm16", 20, 16},
{"Rd", 4, 5},
}, AsUInt32: 1920991232, Generator: nil},
{Name: "MOVK", OpcodeMask: 4286578688, Opcode: 4068474880, Fields: []InsnField{
{"hw", 22, 2},
{"imm16", 20, 16},
{"Rd", 4, 5},
}, AsUInt32: 4068474880, Generator: nil},
{Name: "MOVN", OpcodeMask: 4286578688, Opcode: 310378496, Fields: []InsnField{
{"hw", 22, 2},
{"imm16", 20, 16},
{"Rd", 4, 5},
}, AsUInt32: 310378496, Generator: nil},
{Name: "MOVN", OpcodeMask: 4286578688, Opcode: 2457862144, Fields: []InsnField{
{"hw", 22, 2},
{"imm16", 20, 16},
{"Rd", 4, 5},
}, AsUInt32: 2457862144, Generator: nil},
{Name: "MOVZ", OpcodeMask: 4286578688, Opcode: 1384120320, Fields: []InsnField{
{"hw", 22, 2},
{"imm16", 20, 16},
{"Rd", 4, 5},
}, AsUInt32: 1384120320, Generator: nil},
{Name: "MOVZ", OpcodeMask: 4286578688, Opcode: 3531603968, Fields: []InsnField{
{"hw", 22, 2},
{"imm16", 20, 16},
{"Rd", 4, 5},
}, AsUInt32: 3531603968, Generator: nil},
{Name: "MRS", OpcodeMask: 4293918720, Opcode: 3576692736, Fields: []InsnField{
{"o0", 19, 1},
{"op1", 18, 3},
{"CRn", 15, 4},
{"CRm", 11, 4},
{"op2", 7, 3},
{"Rt", 4, 5},
}, AsUInt32: 3576692736, Generator: nil},
{Name: "MSR (immediate)", OpcodeMask: 4294504479, Opcode: 3573563423, Fields: []InsnField{
{"op1", 18, 3},
{"CRm", 11, 4},
{"op2", 7, 3},
}, AsUInt32: 3573563423, Generator: nil},
{Name: "MSR (register)", OpcodeMask: 4293918720, Opcode: 3574595584, Fields: []InsnField{
{"o0", 19, 1},
{"op1", 18, 3},
{"CRn", 15, 4},
{"CRm", 11, 4},
{"op2", 7, 3},
{"Rt", 4, 5},
}, AsUInt32: 3574595584, Generator: nil},
{Name: "MSUB", OpcodeMask: 4292902912, Opcode: 453017600, Fields: []InsnField{
{"Rm", 20, 5},
{"Ra", 14, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 453017600, Generator: nil},
{Name: "MSUB", OpcodeMask: 4292902912, Opcode: 2600501248, Fields: []InsnField{
{"Rm", 20, 5},
{"Ra", 14, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2600501248, Generator: nil},
{Name: "MUL", OpcodeMask: 4292934656, Opcode: 453016576, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 453016576, Generator: nil},
{Name: "MUL", OpcodeMask: 4292934656, Opcode: 2600500224, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2600500224, Generator: nil},
{Name: "MVN", OpcodeMask: 4280288224, Opcode: 706741216, Fields: []InsnField{
{"shift", 23, 2},
{"Rm", 20, 5},
{"imm6", 15, 6},
{"Rd", 4, 5},
}, AsUInt32: 706741216, Generator: nil},
{Name: "MVN", OpcodeMask: 4280288224, Opcode: 2854224864, Fields: []InsnField{
{"shift", 23, 2},
{"Rm", 20, 5},
{"imm6", 15, 6},
{"Rd", 4, 5},
}, AsUInt32: 2854224864, Generator: nil},
{Name: "NEG (shifted register)", OpcodeMask: 4280288224, Opcode: 1258292192, Fields: []InsnField{
{"shift", 23, 2},
{"Rm", 20, 5},
{"imm6", 15, 6},
{"Rd", 4, 5},
}, AsUInt32: 1258292192, Generator: nil},
{Name: "NEG (shifted register)", OpcodeMask: 4280288224, Opcode: 3405775840, Fields: []InsnField{
{"shift", 23, 2},
{"Rm", 20, 5},
{"imm6", 15, 6},
{"Rd", 4, 5},
}, AsUInt32: 3405775840, Generator: nil},
{Name: "NEGS", OpcodeMask: 4280288224, Opcode: 1795163104, Fields: []InsnField{
{"shift", 23, 2},
{"Rm", 20, 5},
{"imm6", 15, 6},
{"Rd", 4, 5},
}, AsUInt32: 1795163104, Generator: nil},
{Name: "NEGS", OpcodeMask: 4280288224, Opcode: 3942646752, Fields: []InsnField{
{"shift", 23, 2},
{"Rm", 20, 5},
{"imm6", 15, 6},
{"Rd", 4, 5},
}, AsUInt32: 3942646752, Generator: nil},
{Name: "NGC", OpcodeMask: 4292935648, Opcode: 1509950432, Fields: []InsnField{
{"Rm", 20, 5},
{"Rd", 4, 5},
}, AsUInt32: 1509950432, Generator: nil},
{Name: "NGC", OpcodeMask: 4292935648, Opcode: 3657434080, Fields: []InsnField{
{"Rm", 20, 5},
{"Rd", 4, 5},
}, AsUInt32: 3657434080, Generator: nil},
{Name: "NGCS", OpcodeMask: 4292935648, Opcode: 2046821344, Fields: []InsnField{
{"Rm", 20, 5},
{"Rd", 4, 5},
}, AsUInt32: 2046821344, Generator: nil},
{Name: "NGCS", OpcodeMask: 4292935648, Opcode: 4194304992, Fields: []InsnField{
{"Rm", 20, 5},
{"Rd", 4, 5},
}, AsUInt32: 4194304992, Generator: nil},
{Name: "NOP", OpcodeMask: 4294967295, Opcode: 3573751839, AsUInt32: 3573751839, Generator: nil},
{Name: "ORN (shifted register)", OpcodeMask: 4280287232, Opcode: 706740224, Fields: []InsnField{
{"shift", 23, 2},
{"Rm", 20, 5},
{"imm6", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 706740224, Generator: nil},
{Name: "ORN (shifted register)", OpcodeMask: 4280287232, Opcode: 2854223872, Fields: []InsnField{
{"shift", 23, 2},
{"Rm", 20, 5},
{"imm6", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2854223872, Generator: nil},
{Name: "ORR (immediate)", OpcodeMask: 4290772992, Opcode: 838860800, Fields: []InsnField{
{"immr", 21, 6},
{"imms", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 838860800, Generator: nil},
{Name: "ORR (immediate)", OpcodeMask: 4286578688, Opcode: 2986344448, Fields: []InsnField{
{"N", 22, 1},
{"immr", 21, 6},
{"imms", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2986344448, Generator: nil},
{Name: "ORR (shifted register)", OpcodeMask: 4280287232, Opcode: 704643072, Fields: []InsnField{
{"shift", 23, 2},
{"Rm", 20, 5},
{"imm6", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 704643072, Generator: nil},
{Name: "ORR (shifted register)", OpcodeMask: 4280287232, Opcode: 2852126720, Fields: []InsnField{
{"shift", 23, 2},
{"Rm", 20, 5},
{"imm6", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2852126720, Generator: nil},
{Name: "PRFM (immediate)", OpcodeMask: 4290772992, Opcode: 4185915392, Fields: []InsnField{
{"imm12", 21, 12},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 4185915392, Generator: nil},
{Name: "PRFM (literal)", OpcodeMask: 4278190080, Opcode: 3623878656, Fields: []InsnField{
{"imm19", 23, 19},
{"Rt", 4, 5},
}, AsUInt32: 3623878656, Generator: nil},
{Name: "PRFM (register)", OpcodeMask: 4292873216, Opcode: 4171237376, Fields: []InsnField{
{"Rm", 20, 5},
{"option", 15, 3},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 4171237376, Generator: nil},
{Name: "PRFM (unscaled offset)", OpcodeMask: 4292873216, Opcode: 4169138176, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 4169138176, Generator: nil},
{Name: "RBIT", OpcodeMask: 4294966272, Opcode: 1522532352, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1522532352, Generator: nil},
{Name: "RBIT", OpcodeMask: 4294966272, Opcode: 3670016000, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 3670016000, Generator: nil},
{Name: "RET", OpcodeMask: 4294966303, Opcode: 3596550144, Fields: []InsnField{
{"Rn", 9, 5},
}, AsUInt32: 3596550144, Generator: nil},
{Name: "REV", OpcodeMask: 4294966272, Opcode: 1522534400, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1522534400, Generator: nil},
{Name: "REV", OpcodeMask: 4294966272, Opcode: 3670019072, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 3670019072, Generator: nil},
{Name: "REV16", OpcodeMask: 4294966272, Opcode: 1522533376, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1522533376, Generator: nil},
{Name: "REV16", OpcodeMask: 4294966272, Opcode: 3670017024, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 3670017024, Generator: nil},
{Name: "REV32", OpcodeMask: 4294966272, Opcode: 3670018048, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 3670018048, Generator: nil},
{Name: "REV64", OpcodeMask: 4294966272, Opcode: 3670019072, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 3670019072, Generator: nil},
{Name: "ROR (immediate)", OpcodeMask: 4292870144, Opcode: 327155712, Fields: []InsnField{
{"Rm", 20, 5},
{"imms", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 327155712, Generator: nil},
{Name: "ROR (immediate)", OpcodeMask: 4292870144, Opcode: 2478833664, Fields: []InsnField{
{"Rm", 20, 5},
{"imms", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2478833664, Generator: nil},
{Name: "ROR (register)", OpcodeMask: 4292934656, Opcode: 448801792, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 448801792, Generator: nil},
{Name: "ROR (register)", OpcodeMask: 4292934656, Opcode: 2596285440, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2596285440, Generator: nil},
{Name: "RORV", OpcodeMask: 4292934656, Opcode: 448801792, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 448801792, Generator: nil},
{Name: "RORV", OpcodeMask: 4292934656, Opcode: 2596285440, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2596285440, Generator: nil},
{Name: "SBC", OpcodeMask: 4292934656, Opcode: 1509949440, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1509949440, Generator: nil},
{Name: "SBC", OpcodeMask: 4292934656, Opcode: 3657433088, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 3657433088, Generator: nil},
{Name: "SBCS", OpcodeMask: 4292934656, Opcode: 2046820352, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2046820352, Generator: nil},
{Name: "SBCS", OpcodeMask: 4292934656, Opcode: 4194304000, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 4194304000, Generator: nil},
{Name: "SBFIZ", OpcodeMask: 4290772992, Opcode: 318767104, Fields: []InsnField{
{"immr", 21, 6},
{"imms", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 318767104, Generator: nil},
{Name: "SBFIZ", OpcodeMask: 4290772992, Opcode: 2470445056, Fields: []InsnField{
{"immr", 21, 6},
{"imms", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2470445056, Generator: nil},
{Name: "SBFM", OpcodeMask: 4290772992, Opcode: 318767104, Fields: []InsnField{
{"immr", 21, 6},
{"imms", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 318767104, Generator: nil},
{Name: "SBFM", OpcodeMask: 4290772992, Opcode: 2470445056, Fields: []InsnField{
{"immr", 21, 6},
{"imms", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2470445056, Generator: nil},
{Name: "SBFX", OpcodeMask: 4290772992, Opcode: 318767104, Fields: []InsnField{
{"immr", 21, 6},
{"imms", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 318767104, Generator: nil},
{Name: "SBFX", OpcodeMask: 4290772992, Opcode: 2470445056, Fields: []InsnField{
{"immr", 21, 6},
{"imms", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2470445056, Generator: nil},
{Name: "SDIV", OpcodeMask: 4292934656, Opcode: 448793600, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 448793600, Generator: nil},
{Name: "SDIV", OpcodeMask: 4292934656, Opcode: 2596277248, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2596277248, Generator: nil},
{Name: "SEV", OpcodeMask: 4294967295, Opcode: 3573751967, AsUInt32: 3573751967, Generator: nil},
{Name: "SEVL", OpcodeMask: 4294967295, Opcode: 3573751999, AsUInt32: 3573751999, Generator: nil},
{Name: "SMADDL", OpcodeMask: 4292902912, Opcode: 2602565632, Fields: []InsnField{
{"Rm", 20, 5},
{"Ra", 14, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2602565632, Generator: nil},
{Name: "SMC", OpcodeMask: 4292870175, Opcode: 3556769795, Fields: []InsnField{
{"imm16", 20, 16},
}, AsUInt32: 3556769795, Generator: nil},
{Name: "SMNEGL", OpcodeMask: 4292934656, Opcode: 2602630144, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2602630144, Generator: nil},
{Name: "SMSUBL", OpcodeMask: 4292902912, Opcode: 2602598400, Fields: []InsnField{
{"Rm", 20, 5},
{"Ra", 14, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2602598400, Generator: nil},
{Name: "SMULH", OpcodeMask: 4292902912, Opcode: 2604662784, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2604662784, Generator: nil},
{Name: "SMULL", OpcodeMask: 4292934656, Opcode: 2602597376, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2602597376, Generator: nil},
{Name: "STLR", OpcodeMask: 4292902912, Opcode: 2290122752, Fields: []InsnField{
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2290122752, Generator: nil},
{Name: "STLR", OpcodeMask: 4292902912, Opcode: 3363864576, Fields: []InsnField{
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 3363864576, Generator: nil},
{Name: "STLRB", OpcodeMask: 4292902912, Opcode: 142639104, Fields: []InsnField{
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 142639104, Generator: nil},
{Name: "STLRH", OpcodeMask: 4292902912, Opcode: 1216380928, Fields: []InsnField{
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 1216380928, Generator: nil},
{Name: "STLXP", OpcodeMask: 4292902912, Opcode: 2283831296, Fields: []InsnField{
{"Rs", 20, 5},
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2283831296, Generator: nil},
{Name: "STLXP", OpcodeMask: 4292902912, Opcode: 3357573120, Fields: []InsnField{
{"Rs", 20, 5},
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 3357573120, Generator: nil},
{Name: "STLXR", OpcodeMask: 4292902912, Opcode: 2281734144, Fields: []InsnField{
{"Rs", 20, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2281734144, Generator: nil},
{Name: "STLXR", OpcodeMask: 4292902912, Opcode: 3355475968, Fields: []InsnField{
{"Rs", 20, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 3355475968, Generator: nil},
{Name: "STLXRB", OpcodeMask: 4292902912, Opcode: 134250496, Fields: []InsnField{
{"Rs", 20, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 134250496, Generator: nil},
{Name: "STLXRH", OpcodeMask: 4292902912, Opcode: 1207992320, Fields: []InsnField{
{"Rs", 20, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 1207992320, Generator: nil},
{Name: "STNP", OpcodeMask: 4290772992, Opcode: 671088640, Fields: []InsnField{
{"imm7", 21, 7},
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 671088640, Generator: nil},
{Name: "STNP", OpcodeMask: 4290772992, Opcode: 2818572288, Fields: []InsnField{
{"imm7", 21, 7},
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2818572288, Generator: nil},
{Name: "STP", OpcodeMask: 4290772992, Opcode: 679477248, Fields: []InsnField{
{"imm7", 21, 7},
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 679477248, Generator: nil},
{Name: "STP", OpcodeMask: 4290772992, Opcode: 2826960896, Fields: []InsnField{
{"imm7", 21, 7},
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2826960896, Generator: nil},
{Name: "STP", OpcodeMask: 4290772992, Opcode: 696254464, Fields: []InsnField{
{"imm7", 21, 7},
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 696254464, Generator: nil},
{Name: "STP", OpcodeMask: 4290772992, Opcode: 2843738112, Fields: []InsnField{
{"imm7", 21, 7},
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2843738112, Generator: nil},
{Name: "STP", OpcodeMask: 4290772992, Opcode: 687865856, Fields: []InsnField{
{"imm7", 21, 7},
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 687865856, Generator: nil},
{Name: "STP", OpcodeMask: 4290772992, Opcode: 2835349504, Fields: []InsnField{
{"imm7", 21, 7},
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2835349504, Generator: nil},
{Name: "STR (immediate)", OpcodeMask: 4292873216, Opcode: 3087008768, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 3087008768, Generator: nil},
{Name: "STR (immediate)", OpcodeMask: 4292873216, Opcode: 4160750592, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 4160750592, Generator: nil},
{Name: "STR (immediate)", OpcodeMask: 4292873216, Opcode: 3087010816, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 3087010816, Generator: nil},
{Name: "STR (immediate)", OpcodeMask: 4292873216, Opcode: 4160752640, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 4160752640, Generator: nil},
{Name: "STR (immediate)", OpcodeMask: 4290772992, Opcode: 3103784960, Fields: []InsnField{
{"imm12", 21, 12},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 3103784960, Generator: nil},
{Name: "STR (immediate)", OpcodeMask: 4290772992, Opcode: 4177526784, Fields: []InsnField{
{"imm12", 21, 12},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 4177526784, Generator: nil},
{Name: "STR (register)", OpcodeMask: 4292873216, Opcode: 3089106944, Fields: []InsnField{
{"Rm", 20, 5},
{"option", 15, 3},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 3089106944, Generator: nil},
{Name: "STR (register)", OpcodeMask: 4292873216, Opcode: 4162848768, Fields: []InsnField{
{"Rm", 20, 5},
{"option", 15, 3},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 4162848768, Generator: nil},
{Name: "STRB (immediate)", OpcodeMask: 4292873216, Opcode: 939525120, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 939525120, Generator: nil},
{Name: "STRB (immediate)", OpcodeMask: 4292873216, Opcode: 939527168, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 939527168, Generator: nil},
{Name: "STRB (immediate)", OpcodeMask: 4290772992, Opcode: 956301312, Fields: []InsnField{
{"imm12", 21, 12},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 956301312, Generator: nil},
{Name: "STRB (register)", OpcodeMask: 4292873216, Opcode: 941623296, Fields: []InsnField{
{"Rm", 20, 5},
{"option", 15, 3},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 941623296, Generator: nil},
{Name: "STRB (register)", OpcodeMask: 4292930560, Opcode: 941647872, Fields: []InsnField{
{"Rm", 20, 5},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 941647872, Generator: nil},
{Name: "STRH (immediate)", OpcodeMask: 4292873216, Opcode: 2013266944, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2013266944, Generator: nil},
{Name: "STRH (immediate)", OpcodeMask: 4292873216, Opcode: 2013268992, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2013268992, Generator: nil},
{Name: "STRH (immediate)", OpcodeMask: 4290772992, Opcode: 2030043136, Fields: []InsnField{
{"imm12", 21, 12},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2030043136, Generator: nil},
{Name: "STRH (register)", OpcodeMask: 4292873216, Opcode: 2015365120, Fields: []InsnField{
{"Rm", 20, 5},
{"option", 15, 3},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2015365120, Generator: nil},
{Name: "STTR", OpcodeMask: 4292873216, Opcode: 3087009792, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 3087009792, Generator: nil},
{Name: "STTR", OpcodeMask: 4292873216, Opcode: 4160751616, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 4160751616, Generator: nil},
{Name: "STTRB", OpcodeMask: 4292873216, Opcode: 939526144, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 939526144, Generator: nil},
{Name: "STTRH", OpcodeMask: 4292873216, Opcode: 2013267968, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2013267968, Generator: nil},
{Name: "STUR", OpcodeMask: 4292873216, Opcode: 3087007744, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 3087007744, Generator: nil},
{Name: "STUR", OpcodeMask: 4292873216, Opcode: 4160749568, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 4160749568, Generator: nil},
{Name: "STURB", OpcodeMask: 4292873216, Opcode: 939524096, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 939524096, Generator: nil},
{Name: "STURH", OpcodeMask: 4292873216, Opcode: 2013265920, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2013265920, Generator: nil},
{Name: "STXP", OpcodeMask: 4292902912, Opcode: 2283798528, Fields: []InsnField{
{"Rs", 20, 5},
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2283798528, Generator: nil},
{Name: "STXP", OpcodeMask: 4292902912, Opcode: 3357540352, Fields: []InsnField{
{"Rs", 20, 5},
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 3357540352, Generator: nil},
{Name: "STXR", OpcodeMask: 4292902912, Opcode: 2281701376, Fields: []InsnField{
{"Rs", 20, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2281701376, Generator: nil},
{Name: "STXR", OpcodeMask: 4292902912, Opcode: 3355443200, Fields: []InsnField{
{"Rs", 20, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 3355443200, Generator: nil},
{Name: "STXRB", OpcodeMask: 4292902912, Opcode: 134217728, Fields: []InsnField{
{"Rs", 20, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 134217728, Generator: nil},
{Name: "STXRH", OpcodeMask: 4292902912, Opcode: 1207959552, Fields: []InsnField{
{"Rs", 20, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 1207959552, Generator: nil},
{Name: "SUB (extended register)", OpcodeMask: 4292870144, Opcode: 1260388352, Fields: []InsnField{
{"Rm", 20, 5},
{"option", 15, 3},
{"imm3", 12, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1260388352, Generator: nil},
{Name: "SUB (extended register)", OpcodeMask: 4292870144, Opcode: 3407872000, Fields: []InsnField{
{"Rm", 20, 5},
{"option", 15, 3},
{"imm3", 12, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 3407872000, Generator: nil},
{Name: "SUB (immediate)", OpcodeMask: 4278190080, Opcode: 1358954496, Fields: []InsnField{
{"shift", 23, 2},
{"imm12", 21, 12},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1358954496, Generator: nil},
{Name: "SUB (immediate)", OpcodeMask: 4278190080, Opcode: 3506438144, Fields: []InsnField{
{"shift", 23, 2},
{"imm12", 21, 12},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 3506438144, Generator: nil},
{Name: "SUB (shifted register)", OpcodeMask: 4280287232, Opcode: 1258291200, Fields: []InsnField{
{"shift", 23, 2},
{"Rm", 20, 5},
{"imm6", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1258291200, Generator: nil},
{Name: "SUB (shifted register)", OpcodeMask: 4280287232, Opcode: 3405774848, Fields: []InsnField{
{"shift", 23, 2},
{"Rm", 20, 5},
{"imm6", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 3405774848, Generator: nil},
{Name: "SUBS (extended register)", OpcodeMask: 4292870144, Opcode: 1797259264, Fields: []InsnField{
{"Rm", 20, 5},
{"option", 15, 3},
{"imm3", 12, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1797259264, Generator: nil},
{Name: "SUBS (extended register)", OpcodeMask: 4292870144, Opcode: 3944742912, Fields: []InsnField{
{"Rm", 20, 5},
{"option", 15, 3},
{"imm3", 12, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 3944742912, Generator: nil},
{Name: "SUBS (immediate)", OpcodeMask: 4278190080, Opcode: 1895825408, Fields: []InsnField{
{"shift", 23, 2},
{"imm12", 21, 12},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1895825408, Generator: nil},
{Name: "SUBS (immediate)", OpcodeMask: 4278190080, Opcode: 4043309056, Fields: []InsnField{
{"shift", 23, 2},
{"imm12", 21, 12},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 4043309056, Generator: nil},
{Name: "SUBS (shifted register)", OpcodeMask: 4280287232, Opcode: 1795162112, Fields: []InsnField{
{"shift", 23, 2},
{"Rm", 20, 5},
{"imm6", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1795162112, Generator: nil},
{Name: "SUBS (shifted register)", OpcodeMask: 4280287232, Opcode: 3942645760, Fields: []InsnField{
{"shift", 23, 2},
{"Rm", 20, 5},
{"imm6", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 3942645760, Generator: nil},
{Name: "SVC", OpcodeMask: 4292870175, Opcode: 3556769793, Fields: []InsnField{
{"imm16", 20, 16},
}, AsUInt32: 3556769793, Generator: nil},
{Name: "SXTB", OpcodeMask: 4294966272, Opcode: 318774272, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 318774272, Generator: nil},
{Name: "SXTB", OpcodeMask: 4294966272, Opcode: 2470452224, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2470452224, Generator: nil},
{Name: "SXTH", OpcodeMask: 4294966272, Opcode: 318782464, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 318782464, Generator: nil},
{Name: "SXTH", OpcodeMask: 4294966272, Opcode: 2470460416, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2470460416, Generator: nil},
{Name: "SXTW", OpcodeMask: 4294966272, Opcode: 2470476800, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2470476800, Generator: nil},
{Name: "SYS", OpcodeMask: 4294443008, Opcode: 3574071296, Fields: []InsnField{
{"op1", 18, 3},
{"CRn", 15, 4},
{"CRm", 11, 4},
{"op2", 7, 3},
{"Rt", 4, 5},
}, AsUInt32: 3574071296, Priv: true, Generator: nil},
{Name: "SYSL", OpcodeMask: 4294443008, Opcode: 3576168448, Fields: []InsnField{
{"op1", 18, 3},
{"CRn", 15, 4},
{"CRm", 11, 4},
{"op2", 7, 3},
{"Rt", 4, 5},
}, AsUInt32: 3576168448, Priv: true, Generator: nil},
{Name: "TBNZ", OpcodeMask: 2130706432, Opcode: 922746880, Fields: []InsnField{
{"b5", 31, 1},
{"b40", 23, 5},
{"imm14", 18, 14},
{"Rt", 4, 5},
}, AsUInt32: 922746880, Generator: nil},
{Name: "TBZ", OpcodeMask: 2130706432, Opcode: 905969664, Fields: []InsnField{
{"b5", 31, 1},
{"b40", 23, 5},
{"imm14", 18, 14},
{"Rt", 4, 5},
}, AsUInt32: 905969664, Generator: nil},
{Name: "TLBI", OpcodeMask: 4294504448, Opcode: 3574104064, Fields: []InsnField{
{"op1", 18, 3},
{"CRm", 11, 4},
{"op2", 7, 3},
{"Rt", 4, 5},
}, AsUInt32: 3574104064, Priv: true, Generator: nil},
{Name: "TST (immediate)", OpcodeMask: 4290773023, Opcode: 1912602655, Fields: []InsnField{
{"immr", 21, 6},
{"imms", 15, 6},
{"Rn", 9, 5},
}, AsUInt32: 1912602655, Generator: nil},
{Name: "TST (immediate)", OpcodeMask: 4286578719, Opcode: 4060086303, Fields: []InsnField{
{"N", 22, 1},
{"immr", 21, 6},
{"imms", 15, 6},
{"Rn", 9, 5},
}, AsUInt32: 4060086303, Generator: nil},
{Name: "TST (shifted register)", OpcodeMask: 4280287263, Opcode: 1778384927, Fields: []InsnField{
{"shift", 23, 2},
{"Rm", 20, 5},
{"imm6", 15, 6},
{"Rn", 9, 5},
}, AsUInt32: 1778384927, Generator: nil},
{Name: "TST (shifted register)", OpcodeMask: 4280287263, Opcode: 3925868575, Fields: []InsnField{
{"shift", 23, 2},
{"Rm", 20, 5},
{"imm6", 15, 6},
{"Rn", 9, 5},
}, AsUInt32: 3925868575, Generator: nil},
{Name: "UBFIZ", OpcodeMask: 4290772992, Opcode: 1392508928, Fields: []InsnField{
{"immr", 21, 6},
{"imms", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1392508928, Generator: nil},
{Name: "UBFIZ", OpcodeMask: 4290772992, Opcode: 3544186880, Fields: []InsnField{
{"immr", 21, 6},
{"imms", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 3544186880, Generator: nil},
{Name: "UBFM", OpcodeMask: 4290772992, Opcode: 1392508928, Fields: []InsnField{
{"immr", 21, 6},
{"imms", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1392508928, Generator: nil},
{Name: "UBFM", OpcodeMask: 4290772992, Opcode: 3544186880, Fields: []InsnField{
{"immr", 21, 6},
{"imms", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 3544186880, Generator: nil},
{Name: "UBFX", OpcodeMask: 4290772992, Opcode: 1392508928, Fields: []InsnField{
{"immr", 21, 6},
{"imms", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1392508928, Generator: nil},
{Name: "UBFX", OpcodeMask: 4290772992, Opcode: 3544186880, Fields: []InsnField{
{"immr", 21, 6},
{"imms", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 3544186880, Generator: nil},
{Name: "UDIV", OpcodeMask: 4292934656, Opcode: 448792576, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 448792576, Generator: nil},
{Name: "UDIV", OpcodeMask: 4292934656, Opcode: 2596276224, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2596276224, Generator: nil},
{Name: "UMADDL", OpcodeMask: 4292902912, Opcode: 2610954240, Fields: []InsnField{
{"Rm", 20, 5},
{"Ra", 14, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2610954240, Generator: nil},
{Name: "UMNEGL", OpcodeMask: 4292934656, Opcode: 2611018752, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2611018752, Generator: nil},
{Name: "UMSUBL", OpcodeMask: 4292902912, Opcode: 2610987008, Fields: []InsnField{
{"Rm", 20, 5},
{"Ra", 14, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2610987008, Generator: nil},
{Name: "UMULH", OpcodeMask: 4292902912, Opcode: 2613051392, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2613051392, Generator: nil},
{Name: "UMULL", OpcodeMask: 4292934656, Opcode: 2610985984, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2610985984, Generator: nil},
{Name: "UXTB", OpcodeMask: 4294966272, Opcode: 1392516096, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1392516096, Generator: nil},
{Name: "UXTH", OpcodeMask: 4294966272, Opcode: 1392524288, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1392524288, Generator: nil},
{Name: "WFE", OpcodeMask: 4294967295, Opcode: 3573751903, AsUInt32: 3573751903, Generator: nil},
{Name: "WFI", OpcodeMask: 4294967295, Opcode: 3573751935, AsUInt32: 3573751935, Generator: nil},
{Name: "YIELD", OpcodeMask: 4294967295, Opcode: 3573751871, AsUInt32: 3573751871, Generator: nil},
{Name: "ABS", OpcodeMask: 4282383360, Opcode: 1579202560, Fields: []InsnField{
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1579202560, Generator: nil},
{Name: "ABS", OpcodeMask: 3208641536, Opcode: 237025280, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 237025280, Generator: nil},
{Name: "ADD (vector)", OpcodeMask: 4280351744, Opcode: 1579189248, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1579189248, Generator: nil},
{Name: "ADD (vector)", OpcodeMask: 3206609920, Opcode: 237011968, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 237011968, Generator: nil},
{Name: "ADDHN, ADDHN2", OpcodeMask: 4280351744, Opcode: 236994560, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 236994560, Generator: nil},
{Name: "ADDHN, ADDHN2", OpcodeMask: 4280351744, Opcode: 1310736384, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1310736384, Generator: nil},
{Name: "ADDP (scalar)", OpcodeMask: 4282383360, Opcode: 1580316672, Fields: []InsnField{
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1580316672, Generator: nil},
{Name: "ADDP (vector)", OpcodeMask: 3206609920, Opcode: 237026304, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 237026304, Generator: nil},
{Name: "ADDV", OpcodeMask: 3208641536, Opcode: 238139392, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 238139392, Generator: nil},
{Name: "AESD", OpcodeMask: 4294966272, Opcode: 1311266816, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1311266816, Generator: nil},
{Name: "AESE", OpcodeMask: 4294966272, Opcode: 1311262720, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1311262720, Generator: nil},
{Name: "AESIMC", OpcodeMask: 4294966272, Opcode: 1311275008, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1311275008, Generator: nil},
{Name: "AESMC", OpcodeMask: 4294966272, Opcode: 1311270912, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1311270912, Generator: nil},
{Name: "AND (vector)", OpcodeMask: 3219192832, Opcode: 236985344, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 236985344, Generator: nil},
{Name: "BIC (vector, immediate)", OpcodeMask: 3220704256, Opcode: 788530176, Fields: []InsnField{
{"Q", 30, 1},
{"a", 18, 1},
{"b", 17, 1},
{"c", 16, 1},
{"cmode", 15, 4},
{"d", 9, 1},
{"e", 8, 1},
{"f", 7, 1},
{"g", 6, 1},
{"h", 5, 1},
{"Rd", 4, 5},
}, AsUInt32: 788530176, Generator: nil},
{Name: "BIC (vector, immediate)", OpcodeMask: 3220704256, Opcode: 788530176, Fields: []InsnField{
{"Q", 30, 1},
{"a", 18, 1},
{"b", 17, 1},
{"c", 16, 1},
{"cmode", 15, 4},
{"d", 9, 1},
{"e", 8, 1},
{"f", 7, 1},
{"g", 6, 1},
{"h", 5, 1},
{"Rd", 4, 5},
}, AsUInt32: 788530176, Generator: nil},
{Name: "BIC (vector, register)", OpcodeMask: 3219192832, Opcode: 241179648, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 241179648, Generator: nil},
{Name: "BIF", OpcodeMask: 3219192832, Opcode: 786439168, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 786439168, Generator: nil},
{Name: "BIT", OpcodeMask: 3219192832, Opcode: 782244864, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 782244864, Generator: nil},
{Name: "BSL", OpcodeMask: 3219192832, Opcode: 778050560, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 778050560, Generator: nil},
{Name: "CLS (vector)", OpcodeMask: 3208641536, Opcode: 236996608, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 236996608, Generator: nil},
{Name: "CLZ (vector)", OpcodeMask: 3208641536, Opcode: 773867520, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773867520, Generator: nil},
{Name: "CMEQ (register)", OpcodeMask: 4280351744, Opcode: 2116062208, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2116062208, Generator: nil},
{Name: "CMEQ (register)", OpcodeMask: 3206609920, Opcode: 773884928, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773884928, Generator: nil},
{Name: "CMEQ (zero)", OpcodeMask: 4282383360, Opcode: 1579194368, Fields: []InsnField{
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1579194368, Generator: nil},
{Name: "CMEQ (zero)", OpcodeMask: 3208641536, Opcode: 237017088, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 237017088, Generator: nil},
{Name: "CMGE (register)", OpcodeMask: 4280351744, Opcode: 1579170816, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1579170816, Generator: nil},
{Name: "CMGE (register)", OpcodeMask: 3206609920, Opcode: 236993536, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 236993536, Generator: nil},
{Name: "CMGE (zero)", OpcodeMask: 4282383360, Opcode: 2116061184, Fields: []InsnField{
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2116061184, Generator: nil},
{Name: "CMGE (zero)", OpcodeMask: 3208641536, Opcode: 773883904, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773883904, Generator: nil},
{Name: "CMGT (register)", OpcodeMask: 4280351744, Opcode: 1579168768, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1579168768, Generator: nil},
{Name: "CMGT (register)", OpcodeMask: 3206609920, Opcode: 236991488, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 236991488, Generator: nil},
{Name: "CMGT (zero)", OpcodeMask: 4282383360, Opcode: 1579190272, Fields: []InsnField{
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1579190272, Generator: nil},
{Name: "CMGT (zero)", OpcodeMask: 3208641536, Opcode: 237012992, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 237012992, Generator: nil},
{Name: "CMHI (register)", OpcodeMask: 4280351744, Opcode: 2116039680, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2116039680, Generator: nil},
{Name: "CMHI (register)", OpcodeMask: 3206609920, Opcode: 773862400, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773862400, Generator: nil},
{Name: "CMHS (register)", OpcodeMask: 4280351744, Opcode: 2116041728, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2116041728, Generator: nil},
{Name: "CMHS (register)", OpcodeMask: 3206609920, Opcode: 773864448, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773864448, Generator: nil},
{Name: "CMLE (zero)", OpcodeMask: 4282383360, Opcode: 2116065280, Fields: []InsnField{
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2116065280, Generator: nil},
{Name: "CMLE (zero)", OpcodeMask: 3208641536, Opcode: 773888000, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773888000, Generator: nil},
{Name: "CMLT (zero)", OpcodeMask: 4282383360, Opcode: 1579198464, Fields: []InsnField{
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1579198464, Generator: nil},
{Name: "CMLT (zero)", OpcodeMask: 3208641536, Opcode: 237021184, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 237021184, Generator: nil},
{Name: "CMTST", OpcodeMask: 4280351744, Opcode: 1579191296, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1579191296, Generator: nil},
{Name: "CMTST", OpcodeMask: 3206609920, Opcode: 237014016, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 237014016, Generator: nil},
{Name: "CNT", OpcodeMask: 3208641536, Opcode: 237000704, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 237000704, Generator: nil},
{Name: "DUP (element)", OpcodeMask: 4292934656, Opcode: 1577059328, Fields: []InsnField{
{"imm5", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1577059328, Generator: nil},
{Name: "DUP (element)", OpcodeMask: 3219192832, Opcode: 234882048, Fields: []InsnField{
{"Q", 30, 1},
{"imm5", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 234882048, Generator: nil},
{Name: "DUP (general)", OpcodeMask: 3219192832, Opcode: 234884096, Fields: []InsnField{
{"Q", 30, 1},
{"imm5", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 234884096, Generator: nil},
{Name: "EOR (vector)", OpcodeMask: 3219192832, Opcode: 773856256, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773856256, Generator: nil},
{Name: "EXT", OpcodeMask: 3219162112, Opcode: 771751936, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"imm4", 14, 4},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 771751936, Generator: nil},
{Name: "FABD", OpcodeMask: 4288740352, Opcode: 2124469248, Fields: []InsnField{
{"sz", 22, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2124469248, Generator: nil},
{Name: "FABD", OpcodeMask: 3214998528, Opcode: 782291968, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 782291968, Generator: nil},
{Name: "FABS (vector)", OpcodeMask: 3217030144, Opcode: 245430272, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 245430272, Generator: nil},
{Name: "FABS (scalar)", OpcodeMask: 4294966272, Opcode: 505462784, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 505462784, Generator: nil},
{Name: "FABS (scalar)", OpcodeMask: 4294966272, Opcode: 509657088, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 509657088, Generator: nil},
{Name: "FACGE", OpcodeMask: 4288740352, Opcode: 2116086784, Fields: []InsnField{
{"sz", 22, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2116086784, Generator: nil},
{Name: "FACGE", OpcodeMask: 3214998528, Opcode: 773909504, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773909504, Generator: nil},
{Name: "FACGT", OpcodeMask: 4288740352, Opcode: 2124475392, Fields: []InsnField{
{"sz", 22, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2124475392, Generator: nil},
{Name: "FACGT", OpcodeMask: 3214998528, Opcode: 782298112, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 782298112, Generator: nil},
{Name: "FADD (vector)", OpcodeMask: 3214998528, Opcode: 237032448, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 237032448, Generator: nil},
{Name: "FADD (scalar)", OpcodeMask: 4292934656, Opcode: 505423872, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 505423872, Generator: nil},
{Name: "FADD (scalar)", OpcodeMask: 4292934656, Opcode: 509618176, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 509618176, Generator: nil},
{Name: "FADDP (scalar)", OpcodeMask: 4290771968, Opcode: 2117130240, Fields: []InsnField{
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2117130240, Generator: nil},
{Name: "FADDP (vector)", OpcodeMask: 3214998528, Opcode: 773903360, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773903360, Generator: nil},
{Name: "FCCMP", OpcodeMask: 4292873232, Opcode: 505414656, Fields: []InsnField{
{"Rm", 20, 5},
{"cond", 15, 4},
{"Rn", 9, 5},
{"nzcv", 3, 4},
}, AsUInt32: 505414656, Generator: nil},
{Name: "FCCMP", OpcodeMask: 4292873232, Opcode: 509608960, Fields: []InsnField{
{"Rm", 20, 5},
{"cond", 15, 4},
{"Rn", 9, 5},
{"nzcv", 3, 4},
}, AsUInt32: 509608960, Generator: nil},
{Name: "FCCMPE", OpcodeMask: 4292873232, Opcode: 505414672, Fields: []InsnField{
{"Rm", 20, 5},
{"cond", 15, 4},
{"Rn", 9, 5},
{"nzcv", 3, 4},
}, AsUInt32: 505414672, Generator: nil},
{Name: "FCCMPE", OpcodeMask: 4292873232, Opcode: 509608976, Fields: []InsnField{
{"Rm", 20, 5},
{"cond", 15, 4},
{"Rn", 9, 5},
{"nzcv", 3, 4},
}, AsUInt32: 509608976, Generator: nil},
{Name: "FCMEQ (register)", OpcodeMask: 4288740352, Opcode: 1579213824, Fields: []InsnField{
{"sz", 22, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1579213824, Generator: nil},
{Name: "FCMEQ (register)", OpcodeMask: 3214998528, Opcode: 237036544, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 237036544, Generator: nil},
{Name: "FCMEQ (zero)", OpcodeMask: 4290771968, Opcode: 1587599360, Fields: []InsnField{
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1587599360, Generator: nil},
{Name: "FCMEQ (zero)", OpcodeMask: 3217030144, Opcode: 245422080, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 245422080, Generator: nil},
{Name: "FCMGE (register)", OpcodeMask: 4288740352, Opcode: 2116084736, Fields: []InsnField{
{"sz", 22, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2116084736, Generator: nil},
{Name: "FCMGE (register)", OpcodeMask: 3214998528, Opcode: 773907456, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773907456, Generator: nil},
{Name: "FCMGE (zero)", OpcodeMask: 4290771968, Opcode: 2124466176, Fields: []InsnField{
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2124466176, Generator: nil},
{Name: "FCMGE (zero)", OpcodeMask: 3217030144, Opcode: 782288896, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 782288896, Generator: nil},
{Name: "FCMGT (register)", OpcodeMask: 4288740352, Opcode: 2124473344, Fields: []InsnField{
{"sz", 22, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2124473344, Generator: nil},
{Name: "FCMGT (register)", OpcodeMask: 3214998528, Opcode: 782296064, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 782296064, Generator: nil},
{Name: "FCMGT (zero)", OpcodeMask: 4290771968, Opcode: 1587595264, Fields: []InsnField{
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1587595264, Generator: nil},
{Name: "FCMGT (zero)", OpcodeMask: 3217030144, Opcode: 245417984, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 245417984, Generator: nil},
{Name: "FCMLE (zero)", OpcodeMask: 4290771968, Opcode: 2124470272, Fields: []InsnField{
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2124470272, Generator: nil},
{Name: "FCMLE (zero)", OpcodeMask: 3217030144, Opcode: 782292992, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 782292992, Generator: nil},
{Name: "FCMLT (zero)", OpcodeMask: 4290771968, Opcode: 1587603456, Fields: []InsnField{
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1587603456, Generator: nil},
{Name: "FCMLT (zero)", OpcodeMask: 3217030144, Opcode: 245426176, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 245426176, Generator: nil},
{Name: "FCMP", OpcodeMask: 4292934687, Opcode: 505421824, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
}, AsUInt32: 505421824, Generator: nil},
{Name: "FCMP", OpcodeMask: 4292934687, Opcode: 505421832, Fields: []InsnField{
{"Rn", 9, 5},
}, AsUInt32: 505421832, Generator: nil},
{Name: "FCMP", OpcodeMask: 4292934687, Opcode: 509616128, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
}, AsUInt32: 509616128, Generator: nil},
{Name: "FCMP", OpcodeMask: 4292934687, Opcode: 509616136, Fields: []InsnField{
{"Rn", 9, 5},
}, AsUInt32: 509616136, Generator: nil},
{Name: "FCMPE", OpcodeMask: 4292934687, Opcode: 505421840, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
}, AsUInt32: 505421840, Generator: nil},
{Name: "FCMPE", OpcodeMask: 4292934687, Opcode: 505421848, Fields: []InsnField{
{"Rn", 9, 5},
}, AsUInt32: 505421848, Generator: nil},
{Name: "FCMPE", OpcodeMask: 4292934687, Opcode: 509616144, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
}, AsUInt32: 509616144, Generator: nil},
{Name: "FCMPE", OpcodeMask: 4292934687, Opcode: 509616152, Fields: []InsnField{
{"Rn", 9, 5},
}, AsUInt32: 509616152, Generator: nil},
{Name: "FCSEL", OpcodeMask: 4292873216, Opcode: 505416704, Fields: []InsnField{
{"Rm", 20, 5},
{"cond", 15, 4},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 505416704, Generator: nil},
{Name: "FCSEL", OpcodeMask: 4292873216, Opcode: 509611008, Fields: []InsnField{
{"Rm", 20, 5},
{"cond", 15, 4},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 509611008, Generator: nil},
{Name: "FCVT", OpcodeMask: 4294966272, Opcode: 518144000, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 518144000, Generator: nil},
{Name: "FCVT", OpcodeMask: 4294966272, Opcode: 518176768, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 518176768, Generator: nil},
{Name: "FCVT", OpcodeMask: 4294966272, Opcode: 505659392, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 505659392, Generator: nil},
{Name: "FCVT", OpcodeMask: 4294966272, Opcode: 505593856, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 505593856, Generator: nil},
{Name: "FCVT", OpcodeMask: 4294966272, Opcode: 509853696, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 509853696, Generator: nil},
{Name: "FCVT", OpcodeMask: 4294966272, Opcode: 509755392, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 509755392, Generator: nil},
{Name: "FCVTAS (vector)", OpcodeMask: 4290771968, Opcode: 1579272192, Fields: []InsnField{
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1579272192, Generator: nil},
{Name: "FCVTAS (vector)", OpcodeMask: 3217030144, Opcode: 237094912, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 237094912, Generator: nil},
{Name: "FCVTAS (scalar)", OpcodeMask: 4294966272, Opcode: 505675776, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 505675776, Generator: nil},
{Name: "FCVTAS (scalar)", OpcodeMask: 4294966272, Opcode: 2653159424, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2653159424, Generator: nil},
{Name: "FCVTAS (scalar)", OpcodeMask: 4294966272, Opcode: 509870080, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 509870080, Generator: nil},
{Name: "FCVTAS (scalar)", OpcodeMask: 4294966272, Opcode: 2657353728, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2657353728, Generator: nil},
{Name: "FCVTAU (vector)", OpcodeMask: 4290771968, Opcode: 2116143104, Fields: []InsnField{
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2116143104, Generator: nil},
{Name: "FCVTAU (vector)", OpcodeMask: 3217030144, Opcode: 773965824, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773965824, Generator: nil},
{Name: "FCVTAU (scalar)", OpcodeMask: 4294966272, Opcode: 505741312, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 505741312, Generator: nil},
{Name: "FCVTAU (scalar)", OpcodeMask: 4294966272, Opcode: 2653224960, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2653224960, Generator: nil},
{Name: "FCVTAU (scalar)", OpcodeMask: 4294966272, Opcode: 509935616, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 509935616, Generator: nil},
{Name: "FCVTAU (scalar)", OpcodeMask: 4294966272, Opcode: 2657419264, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2657419264, Generator: nil},
{Name: "FCVTL, FCVTL2", OpcodeMask: 4290771968, Opcode: 237074432, Fields: []InsnField{
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 237074432, Generator: nil},
{Name: "FCVTL, FCVTL2", OpcodeMask: 4290771968, Opcode: 1310816256, Fields: []InsnField{
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1310816256, Generator: nil},
{Name: "FCVTMS (vector)", OpcodeMask: 4290771968, Opcode: 1579268096, Fields: []InsnField{
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1579268096, Generator: nil},
{Name: "FCVTMS (vector)", OpcodeMask: 3217030144, Opcode: 237090816, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 237090816, Generator: nil},
{Name: "FCVTMS (scalar)", OpcodeMask: 4294966272, Opcode: 506462208, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 506462208, Generator: nil},
{Name: "FCVTMS (scalar)", OpcodeMask: 4294966272, Opcode: 2653945856, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2653945856, Generator: nil},
{Name: "FCVTMS (scalar)", OpcodeMask: 4294966272, Opcode: 510656512, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 510656512, Generator: nil},
{Name: "FCVTMS (scalar)", OpcodeMask: 4294966272, Opcode: 2658140160, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2658140160, Generator: nil},
{Name: "FCVTMU (vector)", OpcodeMask: 4290771968, Opcode: 2116139008, Fields: []InsnField{
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2116139008, Generator: nil},
{Name: "FCVTMU (vector)", OpcodeMask: 3217030144, Opcode: 773961728, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773961728, Generator: nil},
{Name: "FCVTMU (scalar)", OpcodeMask: 4294966272, Opcode: 506527744, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 506527744, Generator: nil},
{Name: "FCVTMU (scalar)", OpcodeMask: 4294966272, Opcode: 2654011392, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2654011392, Generator: nil},
{Name: "FCVTMU (scalar)", OpcodeMask: 4294966272, Opcode: 510722048, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 510722048, Generator: nil},
{Name: "FCVTMU (scalar)", OpcodeMask: 4294966272, Opcode: 2658205696, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2658205696, Generator: nil},
{Name: "FCVTN, FCVTN2", OpcodeMask: 4290771968, Opcode: 237070336, Fields: []InsnField{
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 237070336, Generator: nil},
{Name: "FCVTN, FCVTN2", OpcodeMask: 4290771968, Opcode: 1310812160, Fields: []InsnField{
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1310812160, Generator: nil},
{Name: "FCVTNS (vector)", OpcodeMask: 4290771968, Opcode: 1579264000, Fields: []InsnField{
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1579264000, Generator: nil},
{Name: "FCVTNS (vector)", OpcodeMask: 3217030144, Opcode: 237086720, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 237086720, Generator: nil},
{Name: "FCVTNS (scalar)", OpcodeMask: 4294966272, Opcode: 505413632, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 505413632, Generator: nil},
{Name: "FCVTNS (scalar)", OpcodeMask: 4294966272, Opcode: 2652897280, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2652897280, Generator: nil},
{Name: "FCVTNS (scalar)", OpcodeMask: 4294966272, Opcode: 509607936, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 509607936, Generator: nil},
{Name: "FCVTNS (scalar)", OpcodeMask: 4294966272, Opcode: 2657091584, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2657091584, Generator: nil},
{Name: "FCVTNU (vector)", OpcodeMask: 4290771968, Opcode: 2116134912, Fields: []InsnField{
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2116134912, Generator: nil},
{Name: "FCVTNU (vector)", OpcodeMask: 3217030144, Opcode: 773957632, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773957632, Generator: nil},
{Name: "FCVTNU (scalar)", OpcodeMask: 4294966272, Opcode: 505479168, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 505479168, Generator: nil},
{Name: "FCVTNU (scalar)", OpcodeMask: 4294966272, Opcode: 2652962816, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2652962816, Generator: nil},
{Name: "FCVTNU (scalar)", OpcodeMask: 4294966272, Opcode: 509673472, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 509673472, Generator: nil},
{Name: "FCVTNU (scalar)", OpcodeMask: 4294966272, Opcode: 2657157120, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2657157120, Generator: nil},
{Name: "FCVTPS (vector)", OpcodeMask: 4290771968, Opcode: 1587652608, Fields: []InsnField{
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1587652608, Generator: nil},
{Name: "FCVTPS (vector)", OpcodeMask: 3217030144, Opcode: 245475328, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 245475328, Generator: nil},
{Name: "FCVTPS (scalar)", OpcodeMask: 4294966272, Opcode: 505937920, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 505937920, Generator: nil},
{Name: "FCVTPS (scalar)", OpcodeMask: 4294966272, Opcode: 2653421568, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2653421568, Generator: nil},
{Name: "FCVTPS (scalar)", OpcodeMask: 4294966272, Opcode: 510132224, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 510132224, Generator: nil},
{Name: "FCVTPS (scalar)", OpcodeMask: 4294966272, Opcode: 2657615872, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2657615872, Generator: nil},
{Name: "FCVTPU (vector)", OpcodeMask: 4290771968, Opcode: 2124523520, Fields: []InsnField{
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2124523520, Generator: nil},
{Name: "FCVTPU (vector)", OpcodeMask: 3217030144, Opcode: 782346240, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 782346240, Generator: nil},
{Name: "FCVTPU (scalar)", OpcodeMask: 4294966272, Opcode: 506003456, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 506003456, Generator: nil},
{Name: "FCVTPU (scalar)", OpcodeMask: 4294966272, Opcode: 2653487104, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2653487104, Generator: nil},
{Name: "FCVTPU (scalar)", OpcodeMask: 4294966272, Opcode: 510197760, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 510197760, Generator: nil},
{Name: "FCVTPU (scalar)", OpcodeMask: 4294966272, Opcode: 2657681408, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2657681408, Generator: nil},
{Name: "FCVTXN, FCVTXN2", OpcodeMask: 4290771968, Opcode: 2116118528, Fields: []InsnField{
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2116118528, Generator: nil},
{Name: "FCVTXN, FCVTXN2", OpcodeMask: 4290771968, Opcode: 773941248, Fields: []InsnField{
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773941248, Generator: nil},
{Name: "FCVTXN, FCVTXN2", OpcodeMask: 4290771968, Opcode: 1847683072, Fields: []InsnField{
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1847683072, Generator: nil},
{Name: "FCVTZS (vector, fixed-point)", OpcodeMask: 4286643200, Opcode: 1593900032, Fields: []InsnField{
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1593900032, Generator: nil},
{Name: "FCVTZS (vector, fixed-point)", OpcodeMask: 3212901376, Opcode: 251722752, Fields: []InsnField{
{"Q", 30, 1},
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 251722752, Generator: nil},
{Name: "FCVTZS (vector, integer)", OpcodeMask: 4290771968, Opcode: 1587656704, Fields: []InsnField{
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1587656704, Generator: nil},
{Name: "FCVTZS (vector, integer)", OpcodeMask: 3217030144, Opcode: 245479424, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 245479424, Generator: nil},
{Name: "FCVTZS (scalar, fixed-point)", OpcodeMask: 4294901760, Opcode: 504889344, Fields: []InsnField{
{"scale", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 504889344, Generator: nil},
{Name: "FCVTZS (scalar, fixed-point)", OpcodeMask: 4294901760, Opcode: 2652372992, Fields: []InsnField{
{"scale", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2652372992, Generator: nil},
{Name: "FCVTZS (scalar, fixed-point)", OpcodeMask: 4294901760, Opcode: 509083648, Fields: []InsnField{
{"scale", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 509083648, Generator: nil},
{Name: "FCVTZS (scalar, fixed-point)", OpcodeMask: 4294901760, Opcode: 2656567296, Fields: []InsnField{
{"scale", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2656567296, Generator: nil},
{Name: "FCVTZS (scalar, integer)", OpcodeMask: 4294966272, Opcode: 506986496, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 506986496, Generator: nil},
{Name: "FCVTZS (scalar, integer)", OpcodeMask: 4294966272, Opcode: 2654470144, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2654470144, Generator: nil},
{Name: "FCVTZS (scalar, integer)", OpcodeMask: 4294966272, Opcode: 511180800, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 511180800, Generator: nil},
{Name: "FCVTZS (scalar, integer)", OpcodeMask: 4294966272, Opcode: 2658664448, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2658664448, Generator: nil},
{Name: "FCVTZU (vector, fixed-point)", OpcodeMask: 4286643200, Opcode: 2130770944, Fields: []InsnField{
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2130770944, Generator: nil},
{Name: "FCVTZU (vector, fixed-point)", OpcodeMask: 3212901376, Opcode: 788593664, Fields: []InsnField{
{"Q", 30, 1},
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 788593664, Generator: nil},
{Name: "FCVTZU (vector, integer)", OpcodeMask: 4290771968, Opcode: 2124527616, Fields: []InsnField{
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2124527616, Generator: nil},
{Name: "FCVTZU (vector, integer)", OpcodeMask: 3217030144, Opcode: 782350336, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 782350336, Generator: nil},
{Name: "FCVTZU (scalar, fixed-point)", OpcodeMask: 4294901760, Opcode: 504954880, Fields: []InsnField{
{"scale", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 504954880, Generator: nil},
{Name: "FCVTZU (scalar, fixed-point)", OpcodeMask: 4294901760, Opcode: 2652438528, Fields: []InsnField{
{"scale", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2652438528, Generator: nil},
{Name: "FCVTZU (scalar, fixed-point)", OpcodeMask: 4294901760, Opcode: 509149184, Fields: []InsnField{
{"scale", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 509149184, Generator: nil},
{Name: "FCVTZU (scalar, fixed-point)", OpcodeMask: 4294901760, Opcode: 2656632832, Fields: []InsnField{
{"scale", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2656632832, Generator: nil},
{Name: "FCVTZU (scalar, integer)", OpcodeMask: 4294966272, Opcode: 507052032, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 507052032, Generator: nil},
{Name: "FCVTZU (scalar, integer)", OpcodeMask: 4294966272, Opcode: 2654535680, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2654535680, Generator: nil},
{Name: "FCVTZU (scalar, integer)", OpcodeMask: 4294966272, Opcode: 511246336, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 511246336, Generator: nil},
{Name: "FCVTZU (scalar, integer)", OpcodeMask: 4294966272, Opcode: 2658729984, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2658729984, Generator: nil},
{Name: "FDIV (vector)", OpcodeMask: 3214998528, Opcode: 773913600, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773913600, Generator: nil},
{Name: "FDIV (scalar)", OpcodeMask: 4292934656, Opcode: 505419776, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 505419776, Generator: nil},
{Name: "FDIV (scalar)", OpcodeMask: 4292934656, Opcode: 509614080, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 509614080, Generator: nil},
{Name: "FMADD", OpcodeMask: 4292902912, Opcode: 520093696, Fields: []InsnField{
{"Rm", 20, 5},
{"Ra", 14, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 520093696, Generator: nil},
{Name: "FMADD", OpcodeMask: 4292902912, Opcode: 524288000, Fields: []InsnField{
{"Rm", 20, 5},
{"Ra", 14, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 524288000, Generator: nil},
{Name: "FMAX (vector)", OpcodeMask: 3214998528, Opcode: 237040640, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 237040640, Generator: nil},
{Name: "FMAX (scalar)", OpcodeMask: 4292934656, Opcode: 505432064, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 505432064, Generator: nil},
{Name: "FMAX (scalar)", OpcodeMask: 4292934656, Opcode: 509626368, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 509626368, Generator: nil},
{Name: "FMAXNM (vector)", OpcodeMask: 3214998528, Opcode: 237028352, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 237028352, Generator: nil},
{Name: "FMAXNM (scalar)", OpcodeMask: 4292934656, Opcode: 505440256, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 505440256, Generator: nil},
{Name: "FMAXNM (scalar)", OpcodeMask: 4292934656, Opcode: 509634560, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 509634560, Generator: nil},
{Name: "FMAXNMP (scalar)", OpcodeMask: 4290771968, Opcode: 2117126144, Fields: []InsnField{
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2117126144, Generator: nil},
{Name: "FMAXNMP (vector)", OpcodeMask: 3214998528, Opcode: 773899264, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773899264, Generator: nil},
{Name: "FMAXNMV", OpcodeMask: 3217030144, Opcode: 774948864, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 774948864, Generator: nil},
{Name: "FMAXP (scalar)", OpcodeMask: 4290771968, Opcode: 2117138432, Fields: []InsnField{
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2117138432, Generator: nil},
{Name: "FMAXP (vector)", OpcodeMask: 3214998528, Opcode: 773911552, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773911552, Generator: nil},
{Name: "FMAXV", OpcodeMask: 3217030144, Opcode: 774961152, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 774961152, Generator: nil},
{Name: "FMIN (vector)", OpcodeMask: 3214998528, Opcode: 245429248, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 245429248, Generator: nil},
{Name: "FMIN (scalar)", OpcodeMask: 4292934656, Opcode: 505436160, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 505436160, Generator: nil},
{Name: "FMIN (scalar)", OpcodeMask: 4292934656, Opcode: 509630464, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 509630464, Generator: nil},
{Name: "FMINNM (vector)", OpcodeMask: 3214998528, Opcode: 245416960, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 245416960, Generator: nil},
{Name: "FMINNM (scalar)", OpcodeMask: 4292934656, Opcode: 505444352, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 505444352, Generator: nil},
{Name: "FMINNM (scalar)", OpcodeMask: 4292934656, Opcode: 509638656, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 509638656, Generator: nil},
{Name: "FMINNMP (scalar)", OpcodeMask: 4290771968, Opcode: 2125514752, Fields: []InsnField{
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2125514752, Generator: nil},
{Name: "FMINNMP (vector)", OpcodeMask: 3214998528, Opcode: 782287872, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 782287872, Generator: nil},
{Name: "FMINNMV", OpcodeMask: 3217030144, Opcode: 783337472, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 783337472, Generator: nil},
{Name: "FMINP (scalar)", OpcodeMask: 4290771968, Opcode: 2125527040, Fields: []InsnField{
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2125527040, Generator: nil},
{Name: "FMINP (vector)", OpcodeMask: 3214998528, Opcode: 782300160, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 782300160, Generator: nil},
{Name: "FMINV", OpcodeMask: 3217030144, Opcode: 783349760, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 783349760, Generator: nil},
{Name: "FMLA (by element)", OpcodeMask: 4286641152, Opcode: 1602228224, Fields: []InsnField{
{"sz", 22, 1},
{"L", 21, 1},
{"M", 20, 1},
{"Rm", 19, 4},
{"H", 11, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1602228224, Generator: nil},
{Name: "FMLA (by element)", OpcodeMask: 3212899328, Opcode: 260050944, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"L", 21, 1},
{"M", 20, 1},
{"Rm", 19, 4},
{"H", 11, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 260050944, Generator: nil},
{Name: "FMLA (vector)", OpcodeMask: 3214998528, Opcode: 237030400, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 237030400, Generator: nil},
{Name: "FMLS (by element)", OpcodeMask: 4286641152, Opcode: 1602244608, Fields: []InsnField{
{"sz", 22, 1},
{"L", 21, 1},
{"M", 20, 1},
{"Rm", 19, 4},
{"H", 11, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1602244608, Generator: nil},
{Name: "FMLS (by element)", OpcodeMask: 3212899328, Opcode: 260067328, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"L", 21, 1},
{"M", 20, 1},
{"Rm", 19, 4},
{"H", 11, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 260067328, Generator: nil},
{Name: "FMLS (vector)", OpcodeMask: 3214998528, Opcode: 245419008, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 245419008, Generator: nil},
{Name: "FMOV (vector, immediate)", OpcodeMask: 3220765696, Opcode: 251720704, Fields: []InsnField{
{"Q", 30, 1},
{"a", 18, 1},
{"b", 17, 1},
{"c", 16, 1},
{"d", 9, 1},
{"e", 8, 1},
{"f", 7, 1},
{"g", 6, 1},
{"h", 5, 1},
{"Rd", 4, 5},
}, AsUInt32: 251720704, Generator: nil},
{Name: "FMOV (vector, immediate)", OpcodeMask: 4294507520, Opcode: 1862333440, Fields: []InsnField{
{"a", 18, 1},
{"b", 17, 1},
{"c", 16, 1},
{"d", 9, 1},
{"e", 8, 1},
{"f", 7, 1},
{"g", 6, 1},
{"h", 5, 1},
{"Rd", 4, 5},
}, AsUInt32: 1862333440, Generator: nil},
{Name: "FMOV (register)", OpcodeMask: 4294966272, Opcode: 505430016, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 505430016, Generator: nil},
{Name: "FMOV (register)", OpcodeMask: 4294966272, Opcode: 509624320, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 509624320, Generator: nil},
{Name: "FMOV (general)", OpcodeMask: 4294966272, Opcode: 505872384, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 505872384, Generator: nil},
{Name: "FMOV (general)", OpcodeMask: 4294966272, Opcode: 505806848, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 505806848, Generator: nil},
{Name: "FMOV (general)", OpcodeMask: 4294966272, Opcode: 2657550336, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2657550336, Generator: nil},
{Name: "FMOV (general)", OpcodeMask: 4294966272, Opcode: 2662268928, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2662268928, Generator: nil},
{Name: "FMOV (general)", OpcodeMask: 4294966272, Opcode: 2657484800, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2657484800, Generator: nil},
{Name: "FMOV (general)", OpcodeMask: 4294966272, Opcode: 2662203392, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2662203392, Generator: nil},
{Name: "FMOV (scalar, immediate)", OpcodeMask: 4292878304, Opcode: 505417728, Fields: []InsnField{
{"imm8", 20, 8},
{"Rd", 4, 5},
}, AsUInt32: 505417728, Generator: nil},
{Name: "FMOV (scalar, immediate)", OpcodeMask: 4292878304, Opcode: 509612032, Fields: []InsnField{
{"imm8", 20, 8},
{"Rd", 4, 5},
}, AsUInt32: 509612032, Generator: nil},
{Name: "FMSUB", OpcodeMask: 4292902912, Opcode: 520126464, Fields: []InsnField{
{"Rm", 20, 5},
{"Ra", 14, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 520126464, Generator: nil},
{Name: "FMSUB", OpcodeMask: 4292902912, Opcode: 524320768, Fields: []InsnField{
{"Rm", 20, 5},
{"Ra", 14, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 524320768, Generator: nil},
{Name: "FMUL (by element)", OpcodeMask: 4286641152, Opcode: 1602260992, Fields: []InsnField{
{"sz", 22, 1},
{"L", 21, 1},
{"M", 20, 1},
{"Rm", 19, 4},
{"H", 11, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1602260992, Generator: nil},
{Name: "FMUL (by element)", OpcodeMask: 3212899328, Opcode: 260083712, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"L", 21, 1},
{"M", 20, 1},
{"Rm", 19, 4},
{"H", 11, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 260083712, Generator: nil},
{Name: "FMUL (vector)", OpcodeMask: 3214998528, Opcode: 773905408, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773905408, Generator: nil},
{Name: "FMUL (scalar)", OpcodeMask: 4292934656, Opcode: 505415680, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 505415680, Generator: nil},
{Name: "FMUL (scalar)", OpcodeMask: 4292934656, Opcode: 509609984, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 509609984, Generator: nil},
{Name: "FMULX (by element)", OpcodeMask: 4286641152, Opcode: 2139131904, Fields: []InsnField{
{"sz", 22, 1},
{"L", 21, 1},
{"M", 20, 1},
{"Rm", 19, 4},
{"H", 11, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2139131904, Generator: nil},
{Name: "FMULX (by element)", OpcodeMask: 3212899328, Opcode: 796954624, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"L", 21, 1},
{"M", 20, 1},
{"Rm", 19, 4},
{"H", 11, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 796954624, Generator: nil},
{Name: "FMULX", OpcodeMask: 4288740352, Opcode: 1579211776, Fields: []InsnField{
{"sz", 22, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1579211776, Generator: nil},
{Name: "FMULX", OpcodeMask: 3214998528, Opcode: 237034496, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 237034496, Generator: nil},
{Name: "FNEG (vector)", OpcodeMask: 3217030144, Opcode: 782301184, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 782301184, Generator: nil},
{Name: "FNEG (scalar)", OpcodeMask: 4294966272, Opcode: 505495552, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 505495552, Generator: nil},
{Name: "FNEG (scalar)", OpcodeMask: 4294966272, Opcode: 509689856, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 509689856, Generator: nil},
{Name: "FNMADD", OpcodeMask: 4292902912, Opcode: 522190848, Fields: []InsnField{
{"Rm", 20, 5},
{"Ra", 14, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 522190848, Generator: nil},
{Name: "FNMADD", OpcodeMask: 4292902912, Opcode: 526385152, Fields: []InsnField{
{"Rm", 20, 5},
{"Ra", 14, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 526385152, Generator: nil},
{Name: "FNMSUB", OpcodeMask: 4292902912, Opcode: 522223616, Fields: []InsnField{
{"Rm", 20, 5},
{"Ra", 14, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 522223616, Generator: nil},
{Name: "FNMSUB", OpcodeMask: 4292902912, Opcode: 526417920, Fields: []InsnField{
{"Rm", 20, 5},
{"Ra", 14, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 526417920, Generator: nil},
{Name: "FNMUL (scalar)", OpcodeMask: 4292934656, Opcode: 505448448, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 505448448, Generator: nil},
{Name: "FNMUL (scalar)", OpcodeMask: 4292934656, Opcode: 509642752, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 509642752, Generator: nil},
{Name: "FRECPE", OpcodeMask: 4290771968, Opcode: 1587664896, Fields: []InsnField{
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1587664896, Generator: nil},
{Name: "FRECPE", OpcodeMask: 3217030144, Opcode: 245487616, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 245487616, Generator: nil},
{Name: "FRECPS", OpcodeMask: 4288740352, Opcode: 1579219968, Fields: []InsnField{
{"sz", 22, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1579219968, Generator: nil},
{Name: "FRECPS", OpcodeMask: 3214998528, Opcode: 237042688, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 237042688, Generator: nil},
{Name: "FRECPX", OpcodeMask: 4290771968, Opcode: 1587673088, Fields: []InsnField{
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1587673088, Generator: nil},
{Name: "FRINTA (vector)", OpcodeMask: 3217030144, Opcode: 773949440, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773949440, Generator: nil},
{Name: "FRINTA (scalar)", OpcodeMask: 4294966272, Opcode: 505823232, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 505823232, Generator: nil},
{Name: "FRINTA (scalar)", OpcodeMask: 4294966272, Opcode: 510017536, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 510017536, Generator: nil},
{Name: "FRINTI (vector)", OpcodeMask: 3217030144, Opcode: 782342144, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 782342144, Generator: nil},
{Name: "FRINTI (scalar)", OpcodeMask: 4294966272, Opcode: 505921536, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 505921536, Generator: nil},
{Name: "FRINTI (scalar)", OpcodeMask: 4294966272, Opcode: 510115840, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 510115840, Generator: nil},
{Name: "FRINTM (vector)", OpcodeMask: 3217030144, Opcode: 237082624, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 237082624, Generator: nil},
{Name: "FRINTM (scalar)", OpcodeMask: 4294966272, Opcode: 505757696, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 505757696, Generator: nil},
{Name: "FRINTM (scalar)", OpcodeMask: 4294966272, Opcode: 509952000, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 509952000, Generator: nil},
{Name: "FRINTN (vector)", OpcodeMask: 3217030144, Opcode: 237078528, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 237078528, Generator: nil},
{Name: "FRINTN (scalar)", OpcodeMask: 4294966272, Opcode: 505692160, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 505692160, Generator: nil},
{Name: "FRINTN (scalar)", OpcodeMask: 4294966272, Opcode: 509886464, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 509886464, Generator: nil},
{Name: "FRINTP (vector)", OpcodeMask: 3217030144, Opcode: 245467136, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 245467136, Generator: nil},
{Name: "FRINTP (scalar)", OpcodeMask: 4294966272, Opcode: 505724928, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 505724928, Generator: nil},
{Name: "FRINTP (scalar)", OpcodeMask: 4294966272, Opcode: 509919232, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 509919232, Generator: nil},
{Name: "FRINTX (vector)", OpcodeMask: 3217030144, Opcode: 773953536, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773953536, Generator: nil},
{Name: "FRINTX (scalar)", OpcodeMask: 4294966272, Opcode: 505888768, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 505888768, Generator: nil},
{Name: "FRINTX (scalar)", OpcodeMask: 4294966272, Opcode: 510083072, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 510083072, Generator: nil},
{Name: "FRINTZ (vector)", OpcodeMask: 3217030144, Opcode: 245471232, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 245471232, Generator: nil},
{Name: "FRINTZ (scalar)", OpcodeMask: 4294966272, Opcode: 505790464, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 505790464, Generator: nil},
{Name: "FRINTZ (scalar)", OpcodeMask: 4294966272, Opcode: 509984768, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 509984768, Generator: nil},
{Name: "FRSQRTE", OpcodeMask: 4290771968, Opcode: 2124535808, Fields: []InsnField{
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2124535808, Generator: nil},
{Name: "FRSQRTE", OpcodeMask: 3217030144, Opcode: 782358528, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 782358528, Generator: nil},
{Name: "FRSQRTS", OpcodeMask: 4288740352, Opcode: 1587608576, Fields: []InsnField{
{"sz", 22, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1587608576, Generator: nil},
{Name: "FRSQRTS", OpcodeMask: 3214998528, Opcode: 245431296, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 245431296, Generator: nil},
{Name: "FSQRT (vector)", OpcodeMask: 3217030144, Opcode: 782366720, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 782366720, Generator: nil},
{Name: "FSQRT (scalar)", OpcodeMask: 4294966272, Opcode: 505528320, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 505528320, Generator: nil},
{Name: "FSQRT (scalar)", OpcodeMask: 4294966272, Opcode: 509722624, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 509722624, Generator: nil},
{Name: "FSUB (vector)", OpcodeMask: 3214998528, Opcode: 245421056, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 245421056, Generator: nil},
{Name: "FSUB (scalar)", OpcodeMask: 4292934656, Opcode: 505427968, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 505427968, Generator: nil},
{Name: "FSUB (scalar)", OpcodeMask: 4292934656, Opcode: 509622272, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 509622272, Generator: nil},
{Name: "INS (element)", OpcodeMask: 4292903936, Opcode: 1845494784, Fields: []InsnField{
{"imm5", 20, 5},
{"imm4", 14, 4},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1845494784, Generator: nil},
{Name: "INS (general)", OpcodeMask: 4292934656, Opcode: 1308630016, Fields: []InsnField{
{"imm5", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1308630016, Generator: nil},
{Name: "LD1 (multiple structures)", OpcodeMask: 3221221376, Opcode: 205549568, Fields: []InsnField{
{"Q", 30, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 205549568, Generator: nil},
{Name: "LD1 (multiple structures)", OpcodeMask: 3221221376, Opcode: 205561856, Fields: []InsnField{
{"Q", 30, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 205561856, Generator: nil},
{Name: "LD1 (multiple structures)", OpcodeMask: 3221221376, Opcode: 205545472, Fields: []InsnField{
{"Q", 30, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 205545472, Generator: nil},
{Name: "LD1 (multiple structures)", OpcodeMask: 3221221376, Opcode: 205529088, Fields: []InsnField{
{"Q", 30, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 205529088, Generator: nil},
{Name: "LD1 (multiple structures)", OpcodeMask: 3221221376, Opcode: 215969792, Fields: []InsnField{
{"Q", 30, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 215969792, Generator: nil},
{Name: "LD1 (multiple structures)", OpcodeMask: 3219189760, Opcode: 213938176, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 213938176, Generator: nil},
{Name: "LD1 (multiple structures)", OpcodeMask: 3221221376, Opcode: 215982080, Fields: []InsnField{
{"Q", 30, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 215982080, Generator: nil},
{Name: "LD1 (multiple structures)", OpcodeMask: 3219189760, Opcode: 213950464, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 213950464, Generator: nil},
{Name: "LD1 (multiple structures)", OpcodeMask: 3221221376, Opcode: 215965696, Fields: []InsnField{
{"Q", 30, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 215965696, Generator: nil},
{Name: "LD1 (multiple structures)", OpcodeMask: 3219189760, Opcode: 213934080, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 213934080, Generator: nil},
{Name: "LD1 (multiple structures)", OpcodeMask: 3221221376, Opcode: 215949312, Fields: []InsnField{
{"Q", 30, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 215949312, Generator: nil},
{Name: "LD1 (multiple structures)", OpcodeMask: 3219189760, Opcode: 213917696, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 213917696, Generator: nil},
{Name: "LD1 (single structure)", OpcodeMask: 3221217280, Opcode: 222298112, Fields: []InsnField{
{"Q", 30, 1},
{"S", 12, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 222298112, Generator: nil},
{Name: "LD1 (single structure)", OpcodeMask: 3221217280, Opcode: 222314496, Fields: []InsnField{
{"Q", 30, 1},
{"S", 12, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 222314496, Generator: nil},
{Name: "LD1 (single structure)", OpcodeMask: 3221220352, Opcode: 222330880, Fields: []InsnField{
{"Q", 30, 1},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 222330880, Generator: nil},
{Name: "LD1 (single structure)", OpcodeMask: 3221224448, Opcode: 222331904, Fields: []InsnField{
{"Q", 30, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 222331904, Generator: nil},
{Name: "LD1 (single structure)", OpcodeMask: 3221217280, Opcode: 232718336, Fields: []InsnField{
{"Q", 30, 1},
{"S", 12, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 232718336, Generator: nil},
{Name: "LD1 (single structure)", OpcodeMask: 3219185664, Opcode: 230686720, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"S", 12, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 230686720, Generator: nil},
{Name: "LD1 (single structure)", OpcodeMask: 3221217280, Opcode: 232734720, Fields: []InsnField{
{"Q", 30, 1},
{"S", 12, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 232734720, Generator: nil},
{Name: "LD1 (single structure)", OpcodeMask: 3219185664, Opcode: 230703104, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"S", 12, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 230703104, Generator: nil},
{Name: "LD1 (single structure)", OpcodeMask: 3221220352, Opcode: 232751104, Fields: []InsnField{
{"Q", 30, 1},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 232751104, Generator: nil},
{Name: "LD1 (single structure)", OpcodeMask: 3219188736, Opcode: 230719488, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 230719488, Generator: nil},
{Name: "LD1 (single structure)", OpcodeMask: 3221224448, Opcode: 232752128, Fields: []InsnField{
{"Q", 30, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 232752128, Generator: nil},
{Name: "LD1 (single structure)", OpcodeMask: 3219192832, Opcode: 230720512, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 230720512, Generator: nil},
{Name: "LD1R", OpcodeMask: 3221221376, Opcode: 222347264, Fields: []InsnField{
{"Q", 30, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 222347264, Generator: nil},
{Name: "LD1R", OpcodeMask: 3221221376, Opcode: 232767488, Fields: []InsnField{
{"Q", 30, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 232767488, Generator: nil},
{Name: "LD1R", OpcodeMask: 3219189760, Opcode: 230735872, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 230735872, Generator: nil},
{Name: "LD2 (multiple structures)", OpcodeMask: 3221221376, Opcode: 205553664, Fields: []InsnField{
{"Q", 30, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 205553664, Generator: nil},
{Name: "LD2 (multiple structures)", OpcodeMask: 3221221376, Opcode: 215973888, Fields: []InsnField{
{"Q", 30, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 215973888, Generator: nil},
{Name: "LD2 (multiple structures)", OpcodeMask: 3219189760, Opcode: 213942272, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 213942272, Generator: nil},
{Name: "LD2 (single structure)", OpcodeMask: 3221217280, Opcode: 224395264, Fields: []InsnField{
{"Q", 30, 1},
{"S", 12, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 224395264, Generator: nil},
{Name: "LD2 (single structure)", OpcodeMask: 3221217280, Opcode: 224411648, Fields: []InsnField{
{"Q", 30, 1},
{"S", 12, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 224411648, Generator: nil},
{Name: "LD2 (single structure)", OpcodeMask: 3221220352, Opcode: 224428032, Fields: []InsnField{
{"Q", 30, 1},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 224428032, Generator: nil},
{Name: "LD2 (single structure)", OpcodeMask: 3221224448, Opcode: 224429056, Fields: []InsnField{
{"Q", 30, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 224429056, Generator: nil},
{Name: "LD2 (single structure)", OpcodeMask: 3221217280, Opcode: 234815488, Fields: []InsnField{
{"Q", 30, 1},
{"S", 12, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 234815488, Generator: nil},
{Name: "LD2 (single structure)", OpcodeMask: 3219185664, Opcode: 232783872, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"S", 12, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 232783872, Generator: nil},
{Name: "LD2 (single structure)", OpcodeMask: 3221217280, Opcode: 234831872, Fields: []InsnField{
{"Q", 30, 1},
{"S", 12, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 234831872, Generator: nil},
{Name: "LD2 (single structure)", OpcodeMask: 3219185664, Opcode: 232800256, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"S", 12, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 232800256, Generator: nil},
{Name: "LD2 (single structure)", OpcodeMask: 3221220352, Opcode: 234848256, Fields: []InsnField{
{"Q", 30, 1},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 234848256, Generator: nil},
{Name: "LD2 (single structure)", OpcodeMask: 3219188736, Opcode: 232816640, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 232816640, Generator: nil},
{Name: "LD2 (single structure)", OpcodeMask: 3221224448, Opcode: 234849280, Fields: []InsnField{
{"Q", 30, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 234849280, Generator: nil},
{Name: "LD2 (single structure)", OpcodeMask: 3219192832, Opcode: 232817664, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 232817664, Generator: nil},
{Name: "LD2R", OpcodeMask: 3221221376, Opcode: 224444416, Fields: []InsnField{
{"Q", 30, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 224444416, Generator: nil},
{Name: "LD2R", OpcodeMask: 3221221376, Opcode: 234864640, Fields: []InsnField{
{"Q", 30, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 234864640, Generator: nil},
{Name: "LD2R", OpcodeMask: 3219189760, Opcode: 232833024, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 232833024, Generator: nil},
{Name: "LD3 (multiple structures)", OpcodeMask: 3221221376, Opcode: 205537280, Fields: []InsnField{
{"Q", 30, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 205537280, Generator: nil},
{Name: "LD3 (multiple structures)", OpcodeMask: 3221221376, Opcode: 215957504, Fields: []InsnField{
{"Q", 30, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 215957504, Generator: nil},
{Name: "LD3 (multiple structures)", OpcodeMask: 3219189760, Opcode: 213925888, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 213925888, Generator: nil},
{Name: "LD3 (single structure)", OpcodeMask: 3221217280, Opcode: 222306304, Fields: []InsnField{
{"Q", 30, 1},
{"S", 12, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 222306304, Generator: nil},
{Name: "LD3 (single structure)", OpcodeMask: 3221217280, Opcode: 222322688, Fields: []InsnField{
{"Q", 30, 1},
{"S", 12, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 222322688, Generator: nil},
{Name: "LD3 (single structure)", OpcodeMask: 3221220352, Opcode: 222339072, Fields: []InsnField{
{"Q", 30, 1},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 222339072, Generator: nil},
{Name: "LD3 (single structure)", OpcodeMask: 3221224448, Opcode: 222340096, Fields: []InsnField{
{"Q", 30, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 222340096, Generator: nil},
{Name: "LD3 (single structure)", OpcodeMask: 3221217280, Opcode: 232726528, Fields: []InsnField{
{"Q", 30, 1},
{"S", 12, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 232726528, Generator: nil},
{Name: "LD3 (single structure)", OpcodeMask: 3219185664, Opcode: 230694912, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"S", 12, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 230694912, Generator: nil},
{Name: "LD3 (single structure)", OpcodeMask: 3221217280, Opcode: 232742912, Fields: []InsnField{
{"Q", 30, 1},
{"S", 12, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 232742912, Generator: nil},
{Name: "LD3 (single structure)", OpcodeMask: 3219185664, Opcode: 230711296, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"S", 12, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 230711296, Generator: nil},
{Name: "LD3 (single structure)", OpcodeMask: 3221220352, Opcode: 232759296, Fields: []InsnField{
{"Q", 30, 1},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 232759296, Generator: nil},
{Name: "LD3 (single structure)", OpcodeMask: 3219188736, Opcode: 230727680, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 230727680, Generator: nil},
{Name: "LD3 (single structure)", OpcodeMask: 3221224448, Opcode: 232760320, Fields: []InsnField{
{"Q", 30, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 232760320, Generator: nil},
{Name: "LD3 (single structure)", OpcodeMask: 3219192832, Opcode: 230728704, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 230728704, Generator: nil},
{Name: "LD3R", OpcodeMask: 3221221376, Opcode: 222355456, Fields: []InsnField{
{"Q", 30, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 222355456, Generator: nil},
{Name: "LD3R", OpcodeMask: 3221221376, Opcode: 232775680, Fields: []InsnField{
{"Q", 30, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 232775680, Generator: nil},
{Name: "LD3R", OpcodeMask: 3219189760, Opcode: 230744064, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 230744064, Generator: nil},
{Name: "LD4 (multiple structures)", OpcodeMask: 3221221376, Opcode: 205520896, Fields: []InsnField{
{"Q", 30, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 205520896, Generator: nil},
{Name: "LD4 (multiple structures)", OpcodeMask: 3221221376, Opcode: 215941120, Fields: []InsnField{
{"Q", 30, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 215941120, Generator: nil},
{Name: "LD4 (multiple structures)", OpcodeMask: 3219189760, Opcode: 213909504, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 213909504, Generator: nil},
{Name: "LD4 (single structure)", OpcodeMask: 3221217280, Opcode: 224403456, Fields: []InsnField{
{"Q", 30, 1},
{"S", 12, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 224403456, Generator: nil},
{Name: "LD4 (single structure)", OpcodeMask: 3221217280, Opcode: 224419840, Fields: []InsnField{
{"Q", 30, 1},
{"S", 12, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 224419840, Generator: nil},
{Name: "LD4 (single structure)", OpcodeMask: 3221220352, Opcode: 224436224, Fields: []InsnField{
{"Q", 30, 1},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 224436224, Generator: nil},
{Name: "LD4 (single structure)", OpcodeMask: 3221224448, Opcode: 224437248, Fields: []InsnField{
{"Q", 30, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 224437248, Generator: nil},
{Name: "LD4 (single structure)", OpcodeMask: 3221217280, Opcode: 234823680, Fields: []InsnField{
{"Q", 30, 1},
{"S", 12, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 234823680, Generator: nil},
{Name: "LD4 (single structure)", OpcodeMask: 3219185664, Opcode: 232792064, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"S", 12, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 232792064, Generator: nil},
{Name: "LD4 (single structure)", OpcodeMask: 3221217280, Opcode: 234840064, Fields: []InsnField{
{"Q", 30, 1},
{"S", 12, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 234840064, Generator: nil},
{Name: "LD4 (single structure)", OpcodeMask: 3219185664, Opcode: 232808448, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"S", 12, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 232808448, Generator: nil},
{Name: "LD4 (single structure)", OpcodeMask: 3221220352, Opcode: 234856448, Fields: []InsnField{
{"Q", 30, 1},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 234856448, Generator: nil},
{Name: "LD4 (single structure)", OpcodeMask: 3219188736, Opcode: 232824832, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 232824832, Generator: nil},
{Name: "LD4 (single structure)", OpcodeMask: 3221224448, Opcode: 234857472, Fields: []InsnField{
{"Q", 30, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 234857472, Generator: nil},
{Name: "LD4 (single structure)", OpcodeMask: 3219192832, Opcode: 232825856, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 232825856, Generator: nil},
{Name: "LD4R", OpcodeMask: 3221221376, Opcode: 224452608, Fields: []InsnField{
{"Q", 30, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 224452608, Generator: nil},
{Name: "LD4R", OpcodeMask: 3221221376, Opcode: 234872832, Fields: []InsnField{
{"Q", 30, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 234872832, Generator: nil},
{Name: "LD4R", OpcodeMask: 3219189760, Opcode: 232841216, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 232841216, Generator: nil},
{Name: "LDNP (SIMD&FP)", OpcodeMask: 4290772992, Opcode: 742391808, Fields: []InsnField{
{"imm7", 21, 7},
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 742391808, Generator: nil},
{Name: "LDNP (SIMD&FP)", OpcodeMask: 4290772992, Opcode: 1816133632, Fields: []InsnField{
{"imm7", 21, 7},
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 1816133632, Generator: nil},
{Name: "LDNP (SIMD&FP)", OpcodeMask: 4290772992, Opcode: 2889875456, Fields: []InsnField{
{"imm7", 21, 7},
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2889875456, Generator: nil},
{Name: "LDP (SIMD&FP)", OpcodeMask: 4290772992, Opcode: 750780416, Fields: []InsnField{
{"imm7", 21, 7},
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 750780416, Generator: nil},
{Name: "LDP (SIMD&FP)", OpcodeMask: 4290772992, Opcode: 1824522240, Fields: []InsnField{
{"imm7", 21, 7},
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 1824522240, Generator: nil},
{Name: "LDP (SIMD&FP)", OpcodeMask: 4290772992, Opcode: 2898264064, Fields: []InsnField{
{"imm7", 21, 7},
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2898264064, Generator: nil},
{Name: "LDP (SIMD&FP)", OpcodeMask: 4290772992, Opcode: 767557632, Fields: []InsnField{
{"imm7", 21, 7},
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 767557632, Generator: nil},
{Name: "LDP (SIMD&FP)", OpcodeMask: 4290772992, Opcode: 1841299456, Fields: []InsnField{
{"imm7", 21, 7},
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 1841299456, Generator: nil},
{Name: "LDP (SIMD&FP)", OpcodeMask: 4290772992, Opcode: 2915041280, Fields: []InsnField{
{"imm7", 21, 7},
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2915041280, Generator: nil},
{Name: "LDP (SIMD&FP)", OpcodeMask: 4290772992, Opcode: 759169024, Fields: []InsnField{
{"imm7", 21, 7},
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 759169024, Generator: nil},
{Name: "LDP (SIMD&FP)", OpcodeMask: 4290772992, Opcode: 1832910848, Fields: []InsnField{
{"imm7", 21, 7},
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 1832910848, Generator: nil},
{Name: "LDP (SIMD&FP)", OpcodeMask: 4290772992, Opcode: 2906652672, Fields: []InsnField{
{"imm7", 21, 7},
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2906652672, Generator: nil},
{Name: "LDR (immediate, SIMD&FP)", OpcodeMask: 4292873216, Opcode: 1010828288, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 1010828288, Generator: nil},
{Name: "LDR (immediate, SIMD&FP)", OpcodeMask: 4292873216, Opcode: 2084570112, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2084570112, Generator: nil},
{Name: "LDR (immediate, SIMD&FP)", OpcodeMask: 4292873216, Opcode: 3158311936, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 3158311936, Generator: nil},
{Name: "LDR (immediate, SIMD&FP)", OpcodeMask: 4292873216, Opcode: 4232053760, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 4232053760, Generator: nil},
{Name: "LDR (immediate, SIMD&FP)", OpcodeMask: 4292873216, Opcode: 1019216896, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 1019216896, Generator: nil},
{Name: "LDR (immediate, SIMD&FP)", OpcodeMask: 4292873216, Opcode: 1010830336, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 1010830336, Generator: nil},
{Name: "LDR (immediate, SIMD&FP)", OpcodeMask: 4292873216, Opcode: 2084572160, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2084572160, Generator: nil},
{Name: "LDR (immediate, SIMD&FP)", OpcodeMask: 4292873216, Opcode: 3158313984, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 3158313984, Generator: nil},
{Name: "LDR (immediate, SIMD&FP)", OpcodeMask: 4292873216, Opcode: 4232055808, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 4232055808, Generator: nil},
{Name: "LDR (immediate, SIMD&FP)", OpcodeMask: 4292873216, Opcode: 1019218944, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 1019218944, Generator: nil},
{Name: "LDR (immediate, SIMD&FP)", OpcodeMask: 4290772992, Opcode: 1027604480, Fields: []InsnField{
{"imm12", 21, 12},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 1027604480, Generator: nil},
{Name: "LDR (immediate, SIMD&FP)", OpcodeMask: 4290772992, Opcode: 2101346304, Fields: []InsnField{
{"imm12", 21, 12},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2101346304, Generator: nil},
{Name: "LDR (immediate, SIMD&FP)", OpcodeMask: 4290772992, Opcode: 3175088128, Fields: []InsnField{
{"imm12", 21, 12},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 3175088128, Generator: nil},
{Name: "LDR (immediate, SIMD&FP)", OpcodeMask: 4290772992, Opcode: 4248829952, Fields: []InsnField{
{"imm12", 21, 12},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 4248829952, Generator: nil},
{Name: "LDR (immediate, SIMD&FP)", OpcodeMask: 4290772992, Opcode: 1035993088, Fields: []InsnField{
{"imm12", 21, 12},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 1035993088, Generator: nil},
{Name: "LDR (literal, SIMD&FP)", OpcodeMask: 4278190080, Opcode: 469762048, Fields: []InsnField{
{"imm19", 23, 19},
{"Rt", 4, 5},
}, AsUInt32: 469762048, Generator: nil},
{Name: "LDR (literal, SIMD&FP)", OpcodeMask: 4278190080, Opcode: 1543503872, Fields: []InsnField{
{"imm19", 23, 19},
{"Rt", 4, 5},
}, AsUInt32: 1543503872, Generator: nil},
{Name: "LDR (literal, SIMD&FP)", OpcodeMask: 4278190080, Opcode: 2617245696, Fields: []InsnField{
{"imm19", 23, 19},
{"Rt", 4, 5},
}, AsUInt32: 2617245696, Generator: nil},
{Name: "LDR (register, SIMD&FP)", OpcodeMask: 4292873216, Opcode: 1012926464, Fields: []InsnField{
{"Rm", 20, 5},
{"option", 15, 3},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 1012926464, Generator: nil},
{Name: "LDR (register, SIMD&FP)", OpcodeMask: 4292930560, Opcode: 1012951040, Fields: []InsnField{
{"Rm", 20, 5},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 1012951040, Generator: nil},
{Name: "LDR (register, SIMD&FP)", OpcodeMask: 4292873216, Opcode: 2086668288, Fields: []InsnField{
{"Rm", 20, 5},
{"option", 15, 3},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2086668288, Generator: nil},
{Name: "LDR (register, SIMD&FP)", OpcodeMask: 4292873216, Opcode: 3160410112, Fields: []InsnField{
{"Rm", 20, 5},
{"option", 15, 3},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 3160410112, Generator: nil},
{Name: "LDR (register, SIMD&FP)", OpcodeMask: 4292873216, Opcode: 4234151936, Fields: []InsnField{
{"Rm", 20, 5},
{"option", 15, 3},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 4234151936, Generator: nil},
{Name: "LDR (register, SIMD&FP)", OpcodeMask: 4292873216, Opcode: 1021315072, Fields: []InsnField{
{"Rm", 20, 5},
{"option", 15, 3},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 1021315072, Generator: nil},
{Name: "LDUR (SIMD&FP)", OpcodeMask: 4292873216, Opcode: 1010827264, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 1010827264, Generator: nil},
{Name: "LDUR (SIMD&FP)", OpcodeMask: 4292873216, Opcode: 2084569088, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2084569088, Generator: nil},
{Name: "LDUR (SIMD&FP)", OpcodeMask: 4292873216, Opcode: 3158310912, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 3158310912, Generator: nil},
{Name: "LDUR (SIMD&FP)", OpcodeMask: 4292873216, Opcode: 4232052736, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 4232052736, Generator: nil},
{Name: "LDUR (SIMD&FP)", OpcodeMask: 4292873216, Opcode: 1019215872, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 1019215872, Generator: nil},
{Name: "MLA (by element)", OpcodeMask: 3204510720, Opcode: 788529152, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"L", 21, 1},
{"M", 20, 1},
{"Rm", 19, 4},
{"H", 11, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 788529152, Generator: nil},
{Name: "MLA (vector)", OpcodeMask: 3206609920, Opcode: 237016064, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 237016064, Generator: nil},
{Name: "MLS (by element)", OpcodeMask: 3204510720, Opcode: 788545536, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"L", 21, 1},
{"M", 20, 1},
{"Rm", 19, 4},
{"H", 11, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 788545536, Generator: nil},
{Name: "MLS (vector)", OpcodeMask: 3206609920, Opcode: 773886976, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773886976, Generator: nil},
{Name: "MOV (scalar)", OpcodeMask: 4292934656, Opcode: 1577059328, Fields: []InsnField{
{"imm5", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1577059328, Generator: nil},
{Name: "MOV (element)", OpcodeMask: 4292903936, Opcode: 1845494784, Fields: []InsnField{
{"imm5", 20, 5},
{"imm4", 14, 4},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1845494784, Generator: nil},
{Name: "MOV (from general)", OpcodeMask: 4292934656, Opcode: 1308630016, Fields: []InsnField{
{"imm5", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1308630016, Generator: nil},
{Name: "MOV (vector)", OpcodeMask: 3219192832, Opcode: 245373952, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 245373952, Generator: nil},
{Name: "MOV (to general)", OpcodeMask: 4292934656, Opcode: 234896384, Fields: []InsnField{
{"imm5", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 234896384, Generator: nil},
{Name: "MOV (to general)", OpcodeMask: 4292934656, Opcode: 1308638208, Fields: []InsnField{
{"imm5", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1308638208, Generator: nil},
{Name: "MOVI", OpcodeMask: 3220765696, Opcode: 251716608, Fields: []InsnField{
{"Q", 30, 1},
{"a", 18, 1},
{"b", 17, 1},
{"c", 16, 1},
{"d", 9, 1},
{"e", 8, 1},
{"f", 7, 1},
{"g", 6, 1},
{"h", 5, 1},
{"Rd", 4, 5},
}, AsUInt32: 251716608, Generator: nil},
{Name: "MOVI", OpcodeMask: 3220704256, Opcode: 251659264, Fields: []InsnField{
{"Q", 30, 1},
{"a", 18, 1},
{"b", 17, 1},
{"c", 16, 1},
{"cmode", 15, 4},
{"d", 9, 1},
{"e", 8, 1},
{"f", 7, 1},
{"g", 6, 1},
{"h", 5, 1},
{"Rd", 4, 5},
}, AsUInt32: 251659264, Generator: nil},
{Name: "MOVI", OpcodeMask: 3220704256, Opcode: 251659264, Fields: []InsnField{
{"Q", 30, 1},
{"a", 18, 1},
{"b", 17, 1},
{"c", 16, 1},
{"cmode", 15, 4},
{"d", 9, 1},
{"e", 8, 1},
{"f", 7, 1},
{"g", 6, 1},
{"h", 5, 1},
{"Rd", 4, 5},
}, AsUInt32: 251659264, Generator: nil},
{Name: "MOVI", OpcodeMask: 3220704256, Opcode: 251659264, Fields: []InsnField{
{"Q", 30, 1},
{"a", 18, 1},
{"b", 17, 1},
{"c", 16, 1},
{"cmode", 15, 4},
{"d", 9, 1},
{"e", 8, 1},
{"f", 7, 1},
{"g", 6, 1},
{"h", 5, 1},
{"Rd", 4, 5},
}, AsUInt32: 251659264, Generator: nil},
{Name: "MOVI", OpcodeMask: 4294507520, Opcode: 788587520, Fields: []InsnField{
{"a", 18, 1},
{"b", 17, 1},
{"c", 16, 1},
{"d", 9, 1},
{"e", 8, 1},
{"f", 7, 1},
{"g", 6, 1},
{"h", 5, 1},
{"Rd", 4, 5},
}, AsUInt32: 788587520, Generator: nil},
{Name: "MOVI", OpcodeMask: 4294507520, Opcode: 1862329344, Fields: []InsnField{
{"a", 18, 1},
{"b", 17, 1},
{"c", 16, 1},
{"d", 9, 1},
{"e", 8, 1},
{"f", 7, 1},
{"g", 6, 1},
{"h", 5, 1},
{"Rd", 4, 5},
}, AsUInt32: 1862329344, Generator: nil},
{Name: "MUL (by element)", OpcodeMask: 3204510720, Opcode: 251691008, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"L", 21, 1},
{"M", 20, 1},
{"Rm", 19, 4},
{"H", 11, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 251691008, Generator: nil},
{Name: "MUL (vector)", OpcodeMask: 3206609920, Opcode: 237018112, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 237018112, Generator: nil},
{Name: "MVN", OpcodeMask: 3221224448, Opcode: 773871616, Fields: []InsnField{
{"Q", 30, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773871616, Generator: nil},
{Name: "MVNI", OpcodeMask: 3220704256, Opcode: 788530176, Fields: []InsnField{
{"Q", 30, 1},
{"a", 18, 1},
{"b", 17, 1},
{"c", 16, 1},
{"cmode", 15, 4},
{"d", 9, 1},
{"e", 8, 1},
{"f", 7, 1},
{"g", 6, 1},
{"h", 5, 1},
{"Rd", 4, 5},
}, AsUInt32: 788530176, Generator: nil},
{Name: "MVNI", OpcodeMask: 3220704256, Opcode: 788530176, Fields: []InsnField{
{"Q", 30, 1},
{"a", 18, 1},
{"b", 17, 1},
{"c", 16, 1},
{"cmode", 15, 4},
{"d", 9, 1},
{"e", 8, 1},
{"f", 7, 1},
{"g", 6, 1},
{"h", 5, 1},
{"Rd", 4, 5},
}, AsUInt32: 788530176, Generator: nil},
{Name: "MVNI", OpcodeMask: 3220704256, Opcode: 788530176, Fields: []InsnField{
{"Q", 30, 1},
{"a", 18, 1},
{"b", 17, 1},
{"c", 16, 1},
{"cmode", 15, 4},
{"d", 9, 1},
{"e", 8, 1},
{"f", 7, 1},
{"g", 6, 1},
{"h", 5, 1},
{"Rd", 4, 5},
}, AsUInt32: 788530176, Generator: nil},
{Name: "NEG (vector)", OpcodeMask: 4282383360, Opcode: 2116073472, Fields: []InsnField{
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2116073472, Generator: nil},
{Name: "NEG (vector)", OpcodeMask: 3208641536, Opcode: 773896192, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773896192, Generator: nil},
{Name: "NOT", OpcodeMask: 3221224448, Opcode: 773871616, Fields: []InsnField{
{"Q", 30, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773871616, Generator: nil},
{Name: "ORN (vector)", OpcodeMask: 3219192832, Opcode: 249568256, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 249568256, Generator: nil},
{Name: "ORR (vector, immediate)", OpcodeMask: 3220704256, Opcode: 251659264, Fields: []InsnField{
{"Q", 30, 1},
{"a", 18, 1},
{"b", 17, 1},
{"c", 16, 1},
{"cmode", 15, 4},
{"d", 9, 1},
{"e", 8, 1},
{"f", 7, 1},
{"g", 6, 1},
{"h", 5, 1},
{"Rd", 4, 5},
}, AsUInt32: 251659264, Generator: nil},
{Name: "ORR (vector, immediate)", OpcodeMask: 3220704256, Opcode: 251659264, Fields: []InsnField{
{"Q", 30, 1},
{"a", 18, 1},
{"b", 17, 1},
{"c", 16, 1},
{"cmode", 15, 4},
{"d", 9, 1},
{"e", 8, 1},
{"f", 7, 1},
{"g", 6, 1},
{"h", 5, 1},
{"Rd", 4, 5},
}, AsUInt32: 251659264, Generator: nil},
{Name: "ORR (vector, register)", OpcodeMask: 3219192832, Opcode: 245373952, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 245373952, Generator: nil},
{Name: "PMUL", OpcodeMask: 3206609920, Opcode: 773889024, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773889024, Generator: nil},
{Name: "PMULL, PMULL2", OpcodeMask: 4280351744, Opcode: 237035520, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 237035520, Generator: nil},
{Name: "PMULL, PMULL2", OpcodeMask: 4280351744, Opcode: 1310777344, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1310777344, Generator: nil},
{Name: "RADDHN, RADDHN2", OpcodeMask: 4280351744, Opcode: 773865472, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773865472, Generator: nil},
{Name: "RADDHN, RADDHN2", OpcodeMask: 4280351744, Opcode: 1847607296, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1847607296, Generator: nil},
{Name: "RBIT (vector)", OpcodeMask: 3221224448, Opcode: 778065920, Fields: []InsnField{
{"Q", 30, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 778065920, Generator: nil},
{Name: "REV16 (vector)", OpcodeMask: 3208641536, Opcode: 236984320, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 236984320, Generator: nil},
{Name: "REV32 (vector)", OpcodeMask: 3208641536, Opcode: 773851136, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773851136, Generator: nil},
{Name: "REV64", OpcodeMask: 3208641536, Opcode: 236980224, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 236980224, Generator: nil},
{Name: "RSHRN, RSHRN2", OpcodeMask: 4286643200, Opcode: 251694080, Fields: []InsnField{
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 251694080, Generator: nil},
{Name: "RSHRN, RSHRN2", OpcodeMask: 4286643200, Opcode: 1325435904, Fields: []InsnField{
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1325435904, Generator: nil},
{Name: "RSUBHN, RSUBHN2", OpcodeMask: 4280351744, Opcode: 773873664, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773873664, Generator: nil},
{Name: "RSUBHN, RSUBHN2", OpcodeMask: 4280351744, Opcode: 1847615488, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1847615488, Generator: nil},
{Name: "SABA", OpcodeMask: 3206609920, Opcode: 237009920, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 237009920, Generator: nil},
{Name: "SABAL, SABAL2", OpcodeMask: 4280351744, Opcode: 236998656, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 236998656, Generator: nil},
{Name: "SABAL, SABAL2", OpcodeMask: 4280351744, Opcode: 1310740480, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1310740480, Generator: nil},
{Name: "SABD", OpcodeMask: 3206609920, Opcode: 237007872, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 237007872, Generator: nil},
{Name: "SABDL, SABDL2", OpcodeMask: 4280351744, Opcode: 237006848, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 237006848, Generator: nil},
{Name: "SABDL, SABDL2", OpcodeMask: 4280351744, Opcode: 1310748672, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1310748672, Generator: nil},
{Name: "SADALP", OpcodeMask: 3208641536, Opcode: 237004800, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 237004800, Generator: nil},
{Name: "SADDL, SADDL2", OpcodeMask: 4280351744, Opcode: 236978176, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 236978176, Generator: nil},
{Name: "SADDL, SADDL2", OpcodeMask: 4280351744, Opcode: 1310720000, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1310720000, Generator: nil},
{Name: "SADDLP", OpcodeMask: 3208641536, Opcode: 236988416, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 236988416, Generator: nil},
{Name: "SADDLV", OpcodeMask: 3208641536, Opcode: 238041088, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 238041088, Generator: nil},
{Name: "SADDW, SADDW2", OpcodeMask: 4280351744, Opcode: 236982272, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 236982272, Generator: nil},
{Name: "SADDW, SADDW2", OpcodeMask: 4280351744, Opcode: 1310724096, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1310724096, Generator: nil},
{Name: "SCVTF (vector, fixed-point)", OpcodeMask: 4286643200, Opcode: 1593893888, Fields: []InsnField{
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1593893888, Generator: nil},
{Name: "SCVTF (vector, fixed-point)", OpcodeMask: 3212901376, Opcode: 251716608, Fields: []InsnField{
{"Q", 30, 1},
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 251716608, Generator: nil},
{Name: "SCVTF (vector, integer)", OpcodeMask: 4290771968, Opcode: 1579276288, Fields: []InsnField{
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1579276288, Generator: nil},
{Name: "SCVTF (vector, integer)", OpcodeMask: 3217030144, Opcode: 237099008, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 237099008, Generator: nil},
{Name: "SCVTF (scalar, fixed-point)", OpcodeMask: 4294901760, Opcode: 503447552, Fields: []InsnField{
{"scale", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 503447552, Generator: nil},
{Name: "SCVTF (scalar, fixed-point)", OpcodeMask: 4294901760, Opcode: 507641856, Fields: []InsnField{
{"scale", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 507641856, Generator: nil},
{Name: "SCVTF (scalar, fixed-point)", OpcodeMask: 4294901760, Opcode: 2650931200, Fields: []InsnField{
{"scale", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2650931200, Generator: nil},
{Name: "SCVTF (scalar, fixed-point)", OpcodeMask: 4294901760, Opcode: 2655125504, Fields: []InsnField{
{"scale", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2655125504, Generator: nil},
{Name: "SCVTF (scalar, integer)", OpcodeMask: 4294966272, Opcode: 505544704, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 505544704, Generator: nil},
{Name: "SCVTF (scalar, integer)", OpcodeMask: 4294966272, Opcode: 509739008, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 509739008, Generator: nil},
{Name: "SCVTF (scalar, integer)", OpcodeMask: 4294966272, Opcode: 2653028352, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2653028352, Generator: nil},
{Name: "SCVTF (scalar, integer)", OpcodeMask: 4294966272, Opcode: 2657222656, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2657222656, Generator: nil},
{Name: "SHA1C", OpcodeMask: 4292934656, Opcode: 1577058304, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1577058304, Generator: nil},
{Name: "SHA1H", OpcodeMask: 4294966272, Opcode: 1579681792, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1579681792, Generator: nil},
{Name: "SHA1M", OpcodeMask: 4292934656, Opcode: 1577066496, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1577066496, Generator: nil},
{Name: "SHA1P", OpcodeMask: 4292934656, Opcode: 1577062400, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1577062400, Generator: nil},
{Name: "SHA1SU0", OpcodeMask: 4292934656, Opcode: 1577070592, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1577070592, Generator: nil},
{Name: "SHA1SU1", OpcodeMask: 4294966272, Opcode: 1579685888, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1579685888, Generator: nil},
{Name: "SHA256H2", OpcodeMask: 4292934656, Opcode: 1577078784, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1577078784, Generator: nil},
{Name: "SHA256H", OpcodeMask: 4292934656, Opcode: 1577074688, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1577074688, Generator: nil},
{Name: "SHA256SU0", OpcodeMask: 4294966272, Opcode: 1579689984, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1579689984, Generator: nil},
{Name: "SHA256SU1", OpcodeMask: 4292934656, Opcode: 1577082880, Fields: []InsnField{
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1577082880, Generator: nil},
{Name: "SHADD", OpcodeMask: 3206609920, Opcode: 236979200, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 236979200, Generator: nil},
{Name: "SHL", OpcodeMask: 4286643200, Opcode: 1593857024, Fields: []InsnField{
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1593857024, Generator: nil},
{Name: "SHL", OpcodeMask: 3212901376, Opcode: 251679744, Fields: []InsnField{
{"Q", 30, 1},
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 251679744, Generator: nil},
{Name: "SHLL, SHLL2", OpcodeMask: 4282383360, Opcode: 773928960, Fields: []InsnField{
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773928960, Generator: nil},
{Name: "SHLL, SHLL2", OpcodeMask: 4282383360, Opcode: 1847670784, Fields: []InsnField{
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1847670784, Generator: nil},
{Name: "SHRN, SHRN2", OpcodeMask: 4286643200, Opcode: 251692032, Fields: []InsnField{
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 251692032, Generator: nil},
{Name: "SHRN, SHRN2", OpcodeMask: 4286643200, Opcode: 1325433856, Fields: []InsnField{
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1325433856, Generator: nil},
{Name: "SHSUB", OpcodeMask: 3206609920, Opcode: 236987392, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 236987392, Generator: nil},
{Name: "SLI", OpcodeMask: 4286643200, Opcode: 2130727936, Fields: []InsnField{
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2130727936, Generator: nil},
{Name: "SLI", OpcodeMask: 3212901376, Opcode: 788550656, Fields: []InsnField{
{"Q", 30, 1},
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 788550656, Generator: nil},
{Name: "SMAX", OpcodeMask: 3206609920, Opcode: 237003776, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 237003776, Generator: nil},
{Name: "SMAXP", OpcodeMask: 3206609920, Opcode: 237020160, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 237020160, Generator: nil},
{Name: "SMAXV", OpcodeMask: 3208641536, Opcode: 238069760, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 238069760, Generator: nil},
{Name: "SMIN", OpcodeMask: 3206609920, Opcode: 237005824, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 237005824, Generator: nil},
{Name: "SMINP", OpcodeMask: 3206609920, Opcode: 237022208, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 237022208, Generator: nil},
{Name: "SMINV", OpcodeMask: 3208641536, Opcode: 238135296, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 238135296, Generator: nil},
{Name: "SMLAL, SMLAL2 (by element)", OpcodeMask: 4278252544, Opcode: 251666432, Fields: []InsnField{
{"size", 23, 2},
{"L", 21, 1},
{"M", 20, 1},
{"Rm", 19, 4},
{"H", 11, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 251666432, Generator: nil},
{Name: "SMLAL, SMLAL2 (by element)", OpcodeMask: 4278252544, Opcode: 1325408256, Fields: []InsnField{
{"size", 23, 2},
{"L", 21, 1},
{"M", 20, 1},
{"Rm", 19, 4},
{"H", 11, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1325408256, Generator: nil},
{Name: "SMLAL, SMLAL2 (vector)", OpcodeMask: 4280351744, Opcode: 237010944, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 237010944, Generator: nil},
{Name: "SMLAL, SMLAL2 (vector)", OpcodeMask: 4280351744, Opcode: 1310752768, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1310752768, Generator: nil},
{Name: "SMLSL, SMLSL2 (by element)", OpcodeMask: 4278252544, Opcode: 251682816, Fields: []InsnField{
{"size", 23, 2},
{"L", 21, 1},
{"M", 20, 1},
{"Rm", 19, 4},
{"H", 11, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 251682816, Generator: nil},
{Name: "SMLSL, SMLSL2 (by element)", OpcodeMask: 4278252544, Opcode: 1325424640, Fields: []InsnField{
{"size", 23, 2},
{"L", 21, 1},
{"M", 20, 1},
{"Rm", 19, 4},
{"H", 11, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1325424640, Generator: nil},
{Name: "SMLSL, SMLSL2 (vector)", OpcodeMask: 4280351744, Opcode: 237019136, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 237019136, Generator: nil},
{Name: "SMLSL, SMLSL2 (vector)", OpcodeMask: 4280351744, Opcode: 1310760960, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1310760960, Generator: nil},
{Name: "SMOV", OpcodeMask: 4292934656, Opcode: 234892288, Fields: []InsnField{
{"imm5", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 234892288, Generator: nil},
{Name: "SMOV", OpcodeMask: 4292934656, Opcode: 1308634112, Fields: []InsnField{
{"imm5", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1308634112, Generator: nil},
{Name: "SMULL, SMULL2 (by element)", OpcodeMask: 4278252544, Opcode: 251699200, Fields: []InsnField{
{"size", 23, 2},
{"L", 21, 1},
{"M", 20, 1},
{"Rm", 19, 4},
{"H", 11, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 251699200, Generator: nil},
{Name: "SMULL, SMULL2 (by element)", OpcodeMask: 4278252544, Opcode: 1325441024, Fields: []InsnField{
{"size", 23, 2},
{"L", 21, 1},
{"M", 20, 1},
{"Rm", 19, 4},
{"H", 11, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1325441024, Generator: nil},
{Name: "SMULL, SMULL2 (vector)", OpcodeMask: 4280351744, Opcode: 237027328, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 237027328, Generator: nil},
{Name: "SMULL, SMULL2 (vector)", OpcodeMask: 4280351744, Opcode: 1310769152, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1310769152, Generator: nil},
{Name: "SQABS", OpcodeMask: 4282383360, Opcode: 1579186176, Fields: []InsnField{
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1579186176, Generator: nil},
{Name: "SQABS", OpcodeMask: 3208641536, Opcode: 237008896, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 237008896, Generator: nil},
{Name: "SQADD", OpcodeMask: 4280351744, Opcode: 1579158528, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1579158528, Generator: nil},
{Name: "SQADD", OpcodeMask: 3206609920, Opcode: 236981248, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 236981248, Generator: nil},
{Name: "SQDMLAL, SQDMLAL2 (by element)", OpcodeMask: 4278252544, Opcode: 1593847808, Fields: []InsnField{
{"size", 23, 2},
{"L", 21, 1},
{"M", 20, 1},
{"Rm", 19, 4},
{"H", 11, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1593847808, Generator: nil},
{Name: "SQDMLAL, SQDMLAL2 (by element)", OpcodeMask: 4278252544, Opcode: 251670528, Fields: []InsnField{
{"size", 23, 2},
{"L", 21, 1},
{"M", 20, 1},
{"Rm", 19, 4},
{"H", 11, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 251670528, Generator: nil},
{Name: "SQDMLAL, SQDMLAL2 (by element)", OpcodeMask: 4278252544, Opcode: 1325412352, Fields: []InsnField{
{"size", 23, 2},
{"L", 21, 1},
{"M", 20, 1},
{"Rm", 19, 4},
{"H", 11, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1325412352, Generator: nil},
{Name: "SQDMLAL, SQDMLAL2 (vector)", OpcodeMask: 4280351744, Opcode: 1579192320, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1579192320, Generator: nil},
{Name: "SQDMLAL, SQDMLAL2 (vector)", OpcodeMask: 4280351744, Opcode: 237015040, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 237015040, Generator: nil},
{Name: "SQDMLAL, SQDMLAL2 (vector)", OpcodeMask: 4280351744, Opcode: 1310756864, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1310756864, Generator: nil},
{Name: "SQDMLSL, SQDMLSL2 (by element)", OpcodeMask: 4278252544, Opcode: 1593864192, Fields: []InsnField{
{"size", 23, 2},
{"L", 21, 1},
{"M", 20, 1},
{"Rm", 19, 4},
{"H", 11, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1593864192, Generator: nil},
{Name: "SQDMLSL, SQDMLSL2 (by element)", OpcodeMask: 4278252544, Opcode: 251686912, Fields: []InsnField{
{"size", 23, 2},
{"L", 21, 1},
{"M", 20, 1},
{"Rm", 19, 4},
{"H", 11, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 251686912, Generator: nil},
{Name: "SQDMLSL, SQDMLSL2 (by element)", OpcodeMask: 4278252544, Opcode: 1325428736, Fields: []InsnField{
{"size", 23, 2},
{"L", 21, 1},
{"M", 20, 1},
{"Rm", 19, 4},
{"H", 11, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1325428736, Generator: nil},
{Name: "SQDMLSL, SQDMLSL2 (vector)", OpcodeMask: 4280351744, Opcode: 1579200512, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1579200512, Generator: nil},
{Name: "SQDMLSL, SQDMLSL2 (vector)", OpcodeMask: 4280351744, Opcode: 237023232, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 237023232, Generator: nil},
{Name: "SQDMLSL, SQDMLSL2 (vector)", OpcodeMask: 4280351744, Opcode: 1310765056, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1310765056, Generator: nil},
{Name: "SQDMULH (by element)", OpcodeMask: 4278252544, Opcode: 1593884672, Fields: []InsnField{
{"size", 23, 2},
{"L", 21, 1},
{"M", 20, 1},
{"Rm", 19, 4},
{"H", 11, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1593884672, Generator: nil},
{Name: "SQDMULH (by element)", OpcodeMask: 3204510720, Opcode: 251707392, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"L", 21, 1},
{"M", 20, 1},
{"Rm", 19, 4},
{"H", 11, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 251707392, Generator: nil},
{Name: "SQDMULH (vector)", OpcodeMask: 4280351744, Opcode: 1579201536, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1579201536, Generator: nil},
{Name: "SQDMULH (vector)", OpcodeMask: 3206609920, Opcode: 237024256, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 237024256, Generator: nil},
{Name: "SQDMULL, SQDMULL2 (by element)", OpcodeMask: 4278252544, Opcode: 1593880576, Fields: []InsnField{
{"size", 23, 2},
{"L", 21, 1},
{"M", 20, 1},
{"Rm", 19, 4},
{"H", 11, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1593880576, Generator: nil},
{Name: "SQDMULL, SQDMULL2 (by element)", OpcodeMask: 4278252544, Opcode: 251703296, Fields: []InsnField{
{"size", 23, 2},
{"L", 21, 1},
{"M", 20, 1},
{"Rm", 19, 4},
{"H", 11, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 251703296, Generator: nil},
{Name: "SQDMULL, SQDMULL2 (by element)", OpcodeMask: 4278252544, Opcode: 1325445120, Fields: []InsnField{
{"size", 23, 2},
{"L", 21, 1},
{"M", 20, 1},
{"Rm", 19, 4},
{"H", 11, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1325445120, Generator: nil},
{Name: "SQDMULL, SQDMULL2 (vector)", OpcodeMask: 4280351744, Opcode: 1579208704, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1579208704, Generator: nil},
{Name: "SQDMULL, SQDMULL2 (vector)", OpcodeMask: 4280351744, Opcode: 237031424, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 237031424, Generator: nil},
{Name: "SQDMULL, SQDMULL2 (vector)", OpcodeMask: 4280351744, Opcode: 1310773248, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1310773248, Generator: nil},
{Name: "SQNEG", OpcodeMask: 4282383360, Opcode: 2116057088, Fields: []InsnField{
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2116057088, Generator: nil},
{Name: "SQNEG", OpcodeMask: 3208641536, Opcode: 773879808, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773879808, Generator: nil},
{Name: "SQRDMULH (by element)", OpcodeMask: 4278252544, Opcode: 1593888768, Fields: []InsnField{
{"size", 23, 2},
{"L", 21, 1},
{"M", 20, 1},
{"Rm", 19, 4},
{"H", 11, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1593888768, Generator: nil},
{Name: "SQRDMULH (by element)", OpcodeMask: 3204510720, Opcode: 251711488, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"L", 21, 1},
{"M", 20, 1},
{"Rm", 19, 4},
{"H", 11, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 251711488, Generator: nil},
{Name: "SQRDMULH (vector)", OpcodeMask: 4280351744, Opcode: 2116072448, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2116072448, Generator: nil},
{Name: "SQRDMULH (vector)", OpcodeMask: 3206609920, Opcode: 773895168, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773895168, Generator: nil},
{Name: "SQRSHL", OpcodeMask: 4280351744, Opcode: 1579179008, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1579179008, Generator: nil},
{Name: "SQRSHL", OpcodeMask: 3206609920, Opcode: 237001728, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 237001728, Generator: nil},
{Name: "SQRSHRN, SQRSHRN2", OpcodeMask: 4286643200, Opcode: 1593875456, Fields: []InsnField{
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1593875456, Generator: nil},
{Name: "SQRSHRN, SQRSHRN2", OpcodeMask: 4286643200, Opcode: 251698176, Fields: []InsnField{
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 251698176, Generator: nil},
{Name: "SQRSHRN, SQRSHRN2", OpcodeMask: 4286643200, Opcode: 1325440000, Fields: []InsnField{
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1325440000, Generator: nil},
{Name: "SQRSHRUN, SQRSHRUN2", OpcodeMask: 4286643200, Opcode: 2130742272, Fields: []InsnField{
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2130742272, Generator: nil},
{Name: "SQRSHRUN, SQRSHRUN2", OpcodeMask: 4286643200, Opcode: 788564992, Fields: []InsnField{
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 788564992, Generator: nil},
{Name: "SQRSHRUN, SQRSHRUN2", OpcodeMask: 4286643200, Opcode: 1862306816, Fields: []InsnField{
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1862306816, Generator: nil},
{Name: "SQSHL (immediate)", OpcodeMask: 4286643200, Opcode: 1593865216, Fields: []InsnField{
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1593865216, Generator: nil},
{Name: "SQSHL (immediate)", OpcodeMask: 3212901376, Opcode: 251687936, Fields: []InsnField{
{"Q", 30, 1},
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 251687936, Generator: nil},
{Name: "SQSHL (register)", OpcodeMask: 4280351744, Opcode: 1579174912, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1579174912, Generator: nil},
{Name: "SQSHL (register)", OpcodeMask: 3206609920, Opcode: 236997632, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 236997632, Generator: nil},
{Name: "SQSHLU", OpcodeMask: 4286643200, Opcode: 2130732032, Fields: []InsnField{
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2130732032, Generator: nil},
{Name: "SQSHLU", OpcodeMask: 3212901376, Opcode: 788554752, Fields: []InsnField{
{"Q", 30, 1},
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 788554752, Generator: nil},
{Name: "SQSHRN, SQSHRN2", OpcodeMask: 4286643200, Opcode: 1593873408, Fields: []InsnField{
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1593873408, Generator: nil},
{Name: "SQSHRN, SQSHRN2", OpcodeMask: 4286643200, Opcode: 251696128, Fields: []InsnField{
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 251696128, Generator: nil},
{Name: "SQSHRN, SQSHRN2", OpcodeMask: 4286643200, Opcode: 1325437952, Fields: []InsnField{
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1325437952, Generator: nil},
{Name: "SQSHRUN, SQSHRUN2", OpcodeMask: 4286643200, Opcode: 2130740224, Fields: []InsnField{
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2130740224, Generator: nil},
{Name: "SQSHRUN, SQSHRUN2", OpcodeMask: 4286643200, Opcode: 788562944, Fields: []InsnField{
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 788562944, Generator: nil},
{Name: "SQSHRUN, SQSHRUN2", OpcodeMask: 4286643200, Opcode: 1862304768, Fields: []InsnField{
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1862304768, Generator: nil},
{Name: "SQSUB", OpcodeMask: 4280351744, Opcode: 1579166720, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1579166720, Generator: nil},
{Name: "SQSUB", OpcodeMask: 3206609920, Opcode: 236989440, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 236989440, Generator: nil},
{Name: "SQXTN, SQXTN2", OpcodeMask: 4282383360, Opcode: 1579239424, Fields: []InsnField{
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1579239424, Generator: nil},
{Name: "SQXTN, SQXTN2", OpcodeMask: 4282383360, Opcode: 237062144, Fields: []InsnField{
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 237062144, Generator: nil},
{Name: "SQXTN, SQXTN2", OpcodeMask: 4282383360, Opcode: 1310803968, Fields: []InsnField{
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1310803968, Generator: nil},
{Name: "SQXTUN, SQXTUN2", OpcodeMask: 4282383360, Opcode: 2116102144, Fields: []InsnField{
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2116102144, Generator: nil},
{Name: "SQXTUN, SQXTUN2", OpcodeMask: 4282383360, Opcode: 773924864, Fields: []InsnField{
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773924864, Generator: nil},
{Name: "SQXTUN, SQXTUN2", OpcodeMask: 4282383360, Opcode: 1847666688, Fields: []InsnField{
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1847666688, Generator: nil},
{Name: "SRHADD", OpcodeMask: 3206609920, Opcode: 236983296, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 236983296, Generator: nil},
{Name: "SRI", OpcodeMask: 4286643200, Opcode: 2130723840, Fields: []InsnField{
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2130723840, Generator: nil},
{Name: "SRI", OpcodeMask: 3212901376, Opcode: 788546560, Fields: []InsnField{
{"Q", 30, 1},
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 788546560, Generator: nil},
{Name: "SRSHL", OpcodeMask: 4280351744, Opcode: 1579176960, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1579176960, Generator: nil},
{Name: "SRSHL", OpcodeMask: 3206609920, Opcode: 236999680, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 236999680, Generator: nil},
{Name: "SRSHR", OpcodeMask: 4286643200, Opcode: 1593844736, Fields: []InsnField{
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1593844736, Generator: nil},
{Name: "SRSHR", OpcodeMask: 3212901376, Opcode: 251667456, Fields: []InsnField{
{"Q", 30, 1},
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 251667456, Generator: nil},
{Name: "SRSRA", OpcodeMask: 4286643200, Opcode: 1593848832, Fields: []InsnField{
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1593848832, Generator: nil},
{Name: "SRSRA", OpcodeMask: 3212901376, Opcode: 251671552, Fields: []InsnField{
{"Q", 30, 1},
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 251671552, Generator: nil},
{Name: "SSHL", OpcodeMask: 4280351744, Opcode: 1579172864, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1579172864, Generator: nil},
{Name: "SSHL", OpcodeMask: 3206609920, Opcode: 236995584, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 236995584, Generator: nil},
{Name: "SSHLL, SSHLL2", OpcodeMask: 4286643200, Opcode: 251700224, Fields: []InsnField{
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 251700224, Generator: nil},
{Name: "SSHLL, SSHLL2", OpcodeMask: 4286643200, Opcode: 1325442048, Fields: []InsnField{
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1325442048, Generator: nil},
{Name: "SSHR", OpcodeMask: 4286643200, Opcode: 1593836544, Fields: []InsnField{
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1593836544, Generator: nil},
{Name: "SSHR", OpcodeMask: 3212901376, Opcode: 251659264, Fields: []InsnField{
{"Q", 30, 1},
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 251659264, Generator: nil},
{Name: "SSRA", OpcodeMask: 4286643200, Opcode: 1593840640, Fields: []InsnField{
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1593840640, Generator: nil},
{Name: "SSRA", OpcodeMask: 3212901376, Opcode: 251663360, Fields: []InsnField{
{"Q", 30, 1},
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 251663360, Generator: nil},
{Name: "SSUBL, SSUBL2", OpcodeMask: 4280351744, Opcode: 236986368, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 236986368, Generator: nil},
{Name: "SSUBL, SSUBL2", OpcodeMask: 4280351744, Opcode: 1310728192, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1310728192, Generator: nil},
{Name: "SSUBW, SSUBW2", OpcodeMask: 4280351744, Opcode: 236990464, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 236990464, Generator: nil},
{Name: "SSUBW, SSUBW2", OpcodeMask: 4280351744, Opcode: 1310732288, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1310732288, Generator: nil},
{Name: "ST1 (multiple structures)", OpcodeMask: 3221221376, Opcode: 201355264, Fields: []InsnField{
{"Q", 30, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 201355264, Generator: nil},
{Name: "ST1 (multiple structures)", OpcodeMask: 3221221376, Opcode: 201367552, Fields: []InsnField{
{"Q", 30, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 201367552, Generator: nil},
{Name: "ST1 (multiple structures)", OpcodeMask: 3221221376, Opcode: 201351168, Fields: []InsnField{
{"Q", 30, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 201351168, Generator: nil},
{Name: "ST1 (multiple structures)", OpcodeMask: 3221221376, Opcode: 201334784, Fields: []InsnField{
{"Q", 30, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 201334784, Generator: nil},
{Name: "ST1 (multiple structures)", OpcodeMask: 3221221376, Opcode: 211775488, Fields: []InsnField{
{"Q", 30, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 211775488, Generator: nil},
{Name: "ST1 (multiple structures)", OpcodeMask: 3219189760, Opcode: 209743872, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 209743872, Generator: nil},
{Name: "ST1 (multiple structures)", OpcodeMask: 3221221376, Opcode: 211787776, Fields: []InsnField{
{"Q", 30, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 211787776, Generator: nil},
{Name: "ST1 (multiple structures)", OpcodeMask: 3219189760, Opcode: 209756160, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 209756160, Generator: nil},
{Name: "ST1 (multiple structures)", OpcodeMask: 3221221376, Opcode: 211771392, Fields: []InsnField{
{"Q", 30, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 211771392, Generator: nil},
{Name: "ST1 (multiple structures)", OpcodeMask: 3219189760, Opcode: 209739776, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 209739776, Generator: nil},
{Name: "ST1 (multiple structures)", OpcodeMask: 3221221376, Opcode: 211755008, Fields: []InsnField{
{"Q", 30, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 211755008, Generator: nil},
{Name: "ST1 (multiple structures)", OpcodeMask: 3219189760, Opcode: 209723392, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 209723392, Generator: nil},
{Name: "ST1 (single structure)", OpcodeMask: 3221217280, Opcode: 218103808, Fields: []InsnField{
{"Q", 30, 1},
{"S", 12, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 218103808, Generator: nil},
{Name: "ST1 (single structure)", OpcodeMask: 3221217280, Opcode: 218120192, Fields: []InsnField{
{"Q", 30, 1},
{"S", 12, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 218120192, Generator: nil},
{Name: "ST1 (single structure)", OpcodeMask: 3221220352, Opcode: 218136576, Fields: []InsnField{
{"Q", 30, 1},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 218136576, Generator: nil},
{Name: "ST1 (single structure)", OpcodeMask: 3221224448, Opcode: 218137600, Fields: []InsnField{
{"Q", 30, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 218137600, Generator: nil},
{Name: "ST1 (single structure)", OpcodeMask: 3221217280, Opcode: 228524032, Fields: []InsnField{
{"Q", 30, 1},
{"S", 12, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 228524032, Generator: nil},
{Name: "ST1 (single structure)", OpcodeMask: 3219185664, Opcode: 226492416, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"S", 12, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 226492416, Generator: nil},
{Name: "ST1 (single structure)", OpcodeMask: 3221217280, Opcode: 228540416, Fields: []InsnField{
{"Q", 30, 1},
{"S", 12, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 228540416, Generator: nil},
{Name: "ST1 (single structure)", OpcodeMask: 3219185664, Opcode: 226508800, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"S", 12, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 226508800, Generator: nil},
{Name: "ST1 (single structure)", OpcodeMask: 3221220352, Opcode: 228556800, Fields: []InsnField{
{"Q", 30, 1},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 228556800, Generator: nil},
{Name: "ST1 (single structure)", OpcodeMask: 3219188736, Opcode: 226525184, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 226525184, Generator: nil},
{Name: "ST1 (single structure)", OpcodeMask: 3221224448, Opcode: 228557824, Fields: []InsnField{
{"Q", 30, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 228557824, Generator: nil},
{Name: "ST1 (single structure)", OpcodeMask: 3219192832, Opcode: 226526208, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 226526208, Generator: nil},
{Name: "ST2 (multiple structures)", OpcodeMask: 3221221376, Opcode: 201359360, Fields: []InsnField{
{"Q", 30, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 201359360, Generator: nil},
{Name: "ST2 (multiple structures)", OpcodeMask: 3221221376, Opcode: 211779584, Fields: []InsnField{
{"Q", 30, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 211779584, Generator: nil},
{Name: "ST2 (multiple structures)", OpcodeMask: 3219189760, Opcode: 209747968, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 209747968, Generator: nil},
{Name: "ST2 (single structure)", OpcodeMask: 3221217280, Opcode: 220200960, Fields: []InsnField{
{"Q", 30, 1},
{"S", 12, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 220200960, Generator: nil},
{Name: "ST2 (single structure)", OpcodeMask: 3221217280, Opcode: 220217344, Fields: []InsnField{
{"Q", 30, 1},
{"S", 12, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 220217344, Generator: nil},
{Name: "ST2 (single structure)", OpcodeMask: 3221220352, Opcode: 220233728, Fields: []InsnField{
{"Q", 30, 1},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 220233728, Generator: nil},
{Name: "ST2 (single structure)", OpcodeMask: 3221224448, Opcode: 220234752, Fields: []InsnField{
{"Q", 30, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 220234752, Generator: nil},
{Name: "ST2 (single structure)", OpcodeMask: 3221217280, Opcode: 230621184, Fields: []InsnField{
{"Q", 30, 1},
{"S", 12, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 230621184, Generator: nil},
{Name: "ST2 (single structure)", OpcodeMask: 3219185664, Opcode: 228589568, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"S", 12, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 228589568, Generator: nil},
{Name: "ST2 (single structure)", OpcodeMask: 3221217280, Opcode: 230637568, Fields: []InsnField{
{"Q", 30, 1},
{"S", 12, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 230637568, Generator: nil},
{Name: "ST2 (single structure)", OpcodeMask: 3219185664, Opcode: 228605952, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"S", 12, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 228605952, Generator: nil},
{Name: "ST2 (single structure)", OpcodeMask: 3221220352, Opcode: 230653952, Fields: []InsnField{
{"Q", 30, 1},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 230653952, Generator: nil},
{Name: "ST2 (single structure)", OpcodeMask: 3219188736, Opcode: 228622336, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 228622336, Generator: nil},
{Name: "ST2 (single structure)", OpcodeMask: 3221224448, Opcode: 230654976, Fields: []InsnField{
{"Q", 30, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 230654976, Generator: nil},
{Name: "ST2 (single structure)", OpcodeMask: 3219192832, Opcode: 228623360, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 228623360, Generator: nil},
{Name: "ST3 (multiple structures)", OpcodeMask: 3221221376, Opcode: 201342976, Fields: []InsnField{
{"Q", 30, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 201342976, Generator: nil},
{Name: "ST3 (multiple structures)", OpcodeMask: 3221221376, Opcode: 211763200, Fields: []InsnField{
{"Q", 30, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 211763200, Generator: nil},
{Name: "ST3 (multiple structures)", OpcodeMask: 3219189760, Opcode: 209731584, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 209731584, Generator: nil},
{Name: "ST3 (single structure)", OpcodeMask: 3221217280, Opcode: 218112000, Fields: []InsnField{
{"Q", 30, 1},
{"S", 12, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 218112000, Generator: nil},
{Name: "ST3 (single structure)", OpcodeMask: 3221217280, Opcode: 218128384, Fields: []InsnField{
{"Q", 30, 1},
{"S", 12, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 218128384, Generator: nil},
{Name: "ST3 (single structure)", OpcodeMask: 3221220352, Opcode: 218144768, Fields: []InsnField{
{"Q", 30, 1},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 218144768, Generator: nil},
{Name: "ST3 (single structure)", OpcodeMask: 3221224448, Opcode: 218145792, Fields: []InsnField{
{"Q", 30, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 218145792, Generator: nil},
{Name: "ST3 (single structure)", OpcodeMask: 3221217280, Opcode: 228532224, Fields: []InsnField{
{"Q", 30, 1},
{"S", 12, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 228532224, Generator: nil},
{Name: "ST3 (single structure)", OpcodeMask: 3219185664, Opcode: 226500608, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"S", 12, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 226500608, Generator: nil},
{Name: "ST3 (single structure)", OpcodeMask: 3221217280, Opcode: 228548608, Fields: []InsnField{
{"Q", 30, 1},
{"S", 12, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 228548608, Generator: nil},
{Name: "ST3 (single structure)", OpcodeMask: 3219185664, Opcode: 226516992, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"S", 12, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 226516992, Generator: nil},
{Name: "ST3 (single structure)", OpcodeMask: 3221220352, Opcode: 228564992, Fields: []InsnField{
{"Q", 30, 1},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 228564992, Generator: nil},
{Name: "ST3 (single structure)", OpcodeMask: 3219188736, Opcode: 226533376, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 226533376, Generator: nil},
{Name: "ST3 (single structure)", OpcodeMask: 3221224448, Opcode: 228566016, Fields: []InsnField{
{"Q", 30, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 228566016, Generator: nil},
{Name: "ST3 (single structure)", OpcodeMask: 3219192832, Opcode: 226534400, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 226534400, Generator: nil},
{Name: "ST4 (multiple structures)", OpcodeMask: 3221221376, Opcode: 201326592, Fields: []InsnField{
{"Q", 30, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 201326592, Generator: nil},
{Name: "ST4 (multiple structures)", OpcodeMask: 3221221376, Opcode: 211746816, Fields: []InsnField{
{"Q", 30, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 211746816, Generator: nil},
{Name: "ST4 (multiple structures)", OpcodeMask: 3219189760, Opcode: 209715200, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 209715200, Generator: nil},
{Name: "ST4 (single structure)", OpcodeMask: 3221217280, Opcode: 220209152, Fields: []InsnField{
{"Q", 30, 1},
{"S", 12, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 220209152, Generator: nil},
{Name: "ST4 (single structure)", OpcodeMask: 3221217280, Opcode: 220225536, Fields: []InsnField{
{"Q", 30, 1},
{"S", 12, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 220225536, Generator: nil},
{Name: "ST4 (single structure)", OpcodeMask: 3221220352, Opcode: 220241920, Fields: []InsnField{
{"Q", 30, 1},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 220241920, Generator: nil},
{Name: "ST4 (single structure)", OpcodeMask: 3221224448, Opcode: 220242944, Fields: []InsnField{
{"Q", 30, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 220242944, Generator: nil},
{Name: "ST4 (single structure)", OpcodeMask: 3221217280, Opcode: 230629376, Fields: []InsnField{
{"Q", 30, 1},
{"S", 12, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 230629376, Generator: nil},
{Name: "ST4 (single structure)", OpcodeMask: 3219185664, Opcode: 228597760, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"S", 12, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 228597760, Generator: nil},
{Name: "ST4 (single structure)", OpcodeMask: 3221217280, Opcode: 230645760, Fields: []InsnField{
{"Q", 30, 1},
{"S", 12, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 230645760, Generator: nil},
{Name: "ST4 (single structure)", OpcodeMask: 3219185664, Opcode: 228614144, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"S", 12, 1},
{"size", 11, 2},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 228614144, Generator: nil},
{Name: "ST4 (single structure)", OpcodeMask: 3221220352, Opcode: 230662144, Fields: []InsnField{
{"Q", 30, 1},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 230662144, Generator: nil},
{Name: "ST4 (single structure)", OpcodeMask: 3219188736, Opcode: 228630528, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 228630528, Generator: nil},
{Name: "ST4 (single structure)", OpcodeMask: 3221224448, Opcode: 230663168, Fields: []InsnField{
{"Q", 30, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 230663168, Generator: nil},
{Name: "ST4 (single structure)", OpcodeMask: 3219192832, Opcode: 228631552, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 228631552, Generator: nil},
{Name: "STNP (SIMD&FP)", OpcodeMask: 4290772992, Opcode: 738197504, Fields: []InsnField{
{"imm7", 21, 7},
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 738197504, Generator: nil},
{Name: "STNP (SIMD&FP)", OpcodeMask: 4290772992, Opcode: 1811939328, Fields: []InsnField{
{"imm7", 21, 7},
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 1811939328, Generator: nil},
{Name: "STNP (SIMD&FP)", OpcodeMask: 4290772992, Opcode: 2885681152, Fields: []InsnField{
{"imm7", 21, 7},
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2885681152, Generator: nil},
{Name: "STP (SIMD&FP)", OpcodeMask: 4290772992, Opcode: 746586112, Fields: []InsnField{
{"imm7", 21, 7},
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 746586112, Generator: nil},
{Name: "STP (SIMD&FP)", OpcodeMask: 4290772992, Opcode: 1820327936, Fields: []InsnField{
{"imm7", 21, 7},
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 1820327936, Generator: nil},
{Name: "STP (SIMD&FP)", OpcodeMask: 4290772992, Opcode: 2894069760, Fields: []InsnField{
{"imm7", 21, 7},
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2894069760, Generator: nil},
{Name: "STP (SIMD&FP)", OpcodeMask: 4290772992, Opcode: 763363328, Fields: []InsnField{
{"imm7", 21, 7},
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 763363328, Generator: nil},
{Name: "STP (SIMD&FP)", OpcodeMask: 4290772992, Opcode: 1837105152, Fields: []InsnField{
{"imm7", 21, 7},
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 1837105152, Generator: nil},
{Name: "STP (SIMD&FP)", OpcodeMask: 4290772992, Opcode: 2910846976, Fields: []InsnField{
{"imm7", 21, 7},
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2910846976, Generator: nil},
{Name: "STP (SIMD&FP)", OpcodeMask: 4290772992, Opcode: 754974720, Fields: []InsnField{
{"imm7", 21, 7},
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 754974720, Generator: nil},
{Name: "STP (SIMD&FP)", OpcodeMask: 4290772992, Opcode: 1828716544, Fields: []InsnField{
{"imm7", 21, 7},
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 1828716544, Generator: nil},
{Name: "STP (SIMD&FP)", OpcodeMask: 4290772992, Opcode: 2902458368, Fields: []InsnField{
{"imm7", 21, 7},
{"Rt2", 14, 5},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2902458368, Generator: nil},
{Name: "STR (immediate, SIMD&FP)", OpcodeMask: 4292873216, Opcode: 1006633984, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 1006633984, Generator: nil},
{Name: "STR (immediate, SIMD&FP)", OpcodeMask: 4292873216, Opcode: 2080375808, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2080375808, Generator: nil},
{Name: "STR (immediate, SIMD&FP)", OpcodeMask: 4292873216, Opcode: 3154117632, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 3154117632, Generator: nil},
{Name: "STR (immediate, SIMD&FP)", OpcodeMask: 4292873216, Opcode: 4227859456, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 4227859456, Generator: nil},
{Name: "STR (immediate, SIMD&FP)", OpcodeMask: 4292873216, Opcode: 1015022592, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 1015022592, Generator: nil},
{Name: "STR (immediate, SIMD&FP)", OpcodeMask: 4292873216, Opcode: 1006636032, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 1006636032, Generator: nil},
{Name: "STR (immediate, SIMD&FP)", OpcodeMask: 4292873216, Opcode: 2080377856, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2080377856, Generator: nil},
{Name: "STR (immediate, SIMD&FP)", OpcodeMask: 4292873216, Opcode: 3154119680, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 3154119680, Generator: nil},
{Name: "STR (immediate, SIMD&FP)", OpcodeMask: 4292873216, Opcode: 4227861504, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 4227861504, Generator: nil},
{Name: "STR (immediate, SIMD&FP)", OpcodeMask: 4292873216, Opcode: 1015024640, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 1015024640, Generator: nil},
{Name: "STR (immediate, SIMD&FP)", OpcodeMask: 4290772992, Opcode: 1023410176, Fields: []InsnField{
{"imm12", 21, 12},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 1023410176, Generator: nil},
{Name: "STR (immediate, SIMD&FP)", OpcodeMask: 4290772992, Opcode: 2097152000, Fields: []InsnField{
{"imm12", 21, 12},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2097152000, Generator: nil},
{Name: "STR (immediate, SIMD&FP)", OpcodeMask: 4290772992, Opcode: 3170893824, Fields: []InsnField{
{"imm12", 21, 12},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 3170893824, Generator: nil},
{Name: "STR (immediate, SIMD&FP)", OpcodeMask: 4290772992, Opcode: 4244635648, Fields: []InsnField{
{"imm12", 21, 12},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 4244635648, Generator: nil},
{Name: "STR (immediate, SIMD&FP)", OpcodeMask: 4290772992, Opcode: 1031798784, Fields: []InsnField{
{"imm12", 21, 12},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 1031798784, Generator: nil},
{Name: "STR (register, SIMD&FP)", OpcodeMask: 4292873216, Opcode: 1008732160, Fields: []InsnField{
{"Rm", 20, 5},
{"option", 15, 3},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 1008732160, Generator: nil},
{Name: "STR (register, SIMD&FP)", OpcodeMask: 4292930560, Opcode: 1008756736, Fields: []InsnField{
{"Rm", 20, 5},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 1008756736, Generator: nil},
{Name: "STR (register, SIMD&FP)", OpcodeMask: 4292873216, Opcode: 2082473984, Fields: []InsnField{
{"Rm", 20, 5},
{"option", 15, 3},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2082473984, Generator: nil},
{Name: "STR (register, SIMD&FP)", OpcodeMask: 4292873216, Opcode: 3156215808, Fields: []InsnField{
{"Rm", 20, 5},
{"option", 15, 3},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 3156215808, Generator: nil},
{Name: "STR (register, SIMD&FP)", OpcodeMask: 4292873216, Opcode: 4229957632, Fields: []InsnField{
{"Rm", 20, 5},
{"option", 15, 3},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 4229957632, Generator: nil},
{Name: "STR (register, SIMD&FP)", OpcodeMask: 4292873216, Opcode: 1017120768, Fields: []InsnField{
{"Rm", 20, 5},
{"option", 15, 3},
{"S", 12, 1},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 1017120768, Generator: nil},
{Name: "STUR (SIMD&FP)", OpcodeMask: 4292873216, Opcode: 1006632960, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 1006632960, Generator: nil},
{Name: "STUR (SIMD&FP)", OpcodeMask: 4292873216, Opcode: 2080374784, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 2080374784, Generator: nil},
{Name: "STUR (SIMD&FP)", OpcodeMask: 4292873216, Opcode: 3154116608, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 3154116608, Generator: nil},
{Name: "STUR (SIMD&FP)", OpcodeMask: 4292873216, Opcode: 4227858432, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 4227858432, Generator: nil},
{Name: "STUR (SIMD&FP)", OpcodeMask: 4292873216, Opcode: 1015021568, Fields: []InsnField{
{"imm9", 20, 9},
{"Rn", 9, 5},
{"Rt", 4, 5},
}, AsUInt32: 1015021568, Generator: nil},
{Name: "SUB (vector)", OpcodeMask: 4280351744, Opcode: 2116060160, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2116060160, Generator: nil},
{Name: "SUB (vector)", OpcodeMask: 3206609920, Opcode: 773882880, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773882880, Generator: nil},
{Name: "SUBHN, SUBHN2", OpcodeMask: 4280351744, Opcode: 237002752, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 237002752, Generator: nil},
{Name: "SUBHN, SUBHN2", OpcodeMask: 4280351744, Opcode: 1310744576, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1310744576, Generator: nil},
{Name: "SUQADD", OpcodeMask: 4282383360, Opcode: 1579169792, Fields: []InsnField{
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1579169792, Generator: nil},
{Name: "SUQADD", OpcodeMask: 3208641536, Opcode: 236992512, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 236992512, Generator: nil},
{Name: "SXTL, SXTL2", OpcodeMask: 4287101952, Opcode: 251700224, Fields: []InsnField{
{"immh", 22, 4},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 251700224, Generator: nil},
{Name: "SXTL, SXTL2", OpcodeMask: 4287101952, Opcode: 1325442048, Fields: []InsnField{
{"immh", 22, 4},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1325442048, Generator: nil},
{Name: "TBL", OpcodeMask: 3219192832, Opcode: 234889216, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 234889216, Generator: nil},
{Name: "TBL", OpcodeMask: 3219192832, Opcode: 234897408, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 234897408, Generator: nil},
{Name: "TBL", OpcodeMask: 3219192832, Opcode: 234905600, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 234905600, Generator: nil},
{Name: "TBL", OpcodeMask: 3219192832, Opcode: 234881024, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 234881024, Generator: nil},
{Name: "TBX", OpcodeMask: 3219192832, Opcode: 234893312, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 234893312, Generator: nil},
{Name: "TBX", OpcodeMask: 3219192832, Opcode: 234901504, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 234901504, Generator: nil},
{Name: "TBX", OpcodeMask: 3219192832, Opcode: 234909696, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 234909696, Generator: nil},
{Name: "TBX", OpcodeMask: 3219192832, Opcode: 234885120, Fields: []InsnField{
{"Q", 30, 1},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 234885120, Generator: nil},
{Name: "TRN1", OpcodeMask: 3206609920, Opcode: 234891264, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 234891264, Generator: nil},
{Name: "TRN2", OpcodeMask: 3206609920, Opcode: 234907648, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 234907648, Generator: nil},
{Name: "UABA", OpcodeMask: 3206609920, Opcode: 773880832, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773880832, Generator: nil},
{Name: "UABAL, UABAL2", OpcodeMask: 4280351744, Opcode: 773869568, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773869568, Generator: nil},
{Name: "UABAL, UABAL2", OpcodeMask: 4280351744, Opcode: 1847611392, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1847611392, Generator: nil},
{Name: "UABD", OpcodeMask: 3206609920, Opcode: 773878784, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773878784, Generator: nil},
{Name: "UABDL, UABDL2", OpcodeMask: 4280351744, Opcode: 773877760, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773877760, Generator: nil},
{Name: "UABDL, UABDL2", OpcodeMask: 4280351744, Opcode: 1847619584, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1847619584, Generator: nil},
{Name: "UADALP", OpcodeMask: 3208641536, Opcode: 773875712, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773875712, Generator: nil},
{Name: "UADDL, UADDL2", OpcodeMask: 4280351744, Opcode: 773849088, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773849088, Generator: nil},
{Name: "UADDL, UADDL2", OpcodeMask: 4280351744, Opcode: 1847590912, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1847590912, Generator: nil},
{Name: "UADDLP", OpcodeMask: 3208641536, Opcode: 773859328, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773859328, Generator: nil},
{Name: "UADDLV", OpcodeMask: 3208641536, Opcode: 774912000, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 774912000, Generator: nil},
{Name: "UADDW, UADDW2", OpcodeMask: 4280351744, Opcode: 773853184, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773853184, Generator: nil},
{Name: "UADDW, UADDW2", OpcodeMask: 4280351744, Opcode: 1847595008, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1847595008, Generator: nil},
{Name: "UCVTF (vector, fixed-point)", OpcodeMask: 4286643200, Opcode: 2130764800, Fields: []InsnField{
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2130764800, Generator: nil},
{Name: "UCVTF (vector, fixed-point)", OpcodeMask: 3212901376, Opcode: 788587520, Fields: []InsnField{
{"Q", 30, 1},
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 788587520, Generator: nil},
{Name: "UCVTF (vector, integer)", OpcodeMask: 4290771968, Opcode: 2116147200, Fields: []InsnField{
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2116147200, Generator: nil},
{Name: "UCVTF (vector, integer)", OpcodeMask: 3217030144, Opcode: 773969920, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773969920, Generator: nil},
{Name: "UCVTF (scalar, fixed-point)", OpcodeMask: 4294901760, Opcode: 503513088, Fields: []InsnField{
{"scale", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 503513088, Generator: nil},
{Name: "UCVTF (scalar, fixed-point)", OpcodeMask: 4294901760, Opcode: 507707392, Fields: []InsnField{
{"scale", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 507707392, Generator: nil},
{Name: "UCVTF (scalar, fixed-point)", OpcodeMask: 4294901760, Opcode: 2650996736, Fields: []InsnField{
{"scale", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2650996736, Generator: nil},
{Name: "UCVTF (scalar, fixed-point)", OpcodeMask: 4294901760, Opcode: 2655191040, Fields: []InsnField{
{"scale", 15, 6},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2655191040, Generator: nil},
{Name: "UCVTF (scalar, integer)", OpcodeMask: 4294966272, Opcode: 505610240, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 505610240, Generator: nil},
{Name: "UCVTF (scalar, integer)", OpcodeMask: 4294966272, Opcode: 509804544, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 509804544, Generator: nil},
{Name: "UCVTF (scalar, integer)", OpcodeMask: 4294966272, Opcode: 2653093888, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2653093888, Generator: nil},
{Name: "UCVTF (scalar, integer)", OpcodeMask: 4294966272, Opcode: 2657288192, Fields: []InsnField{
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2657288192, Generator: nil},
{Name: "UHADD", OpcodeMask: 3206609920, Opcode: 773850112, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773850112, Generator: nil},
{Name: "UHSUB", OpcodeMask: 3206609920, Opcode: 773858304, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773858304, Generator: nil},
{Name: "UMAX", OpcodeMask: 3206609920, Opcode: 773874688, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773874688, Generator: nil},
{Name: "UMAXP", OpcodeMask: 3206609920, Opcode: 773891072, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773891072, Generator: nil},
{Name: "UMAXV", OpcodeMask: 3208641536, Opcode: 774940672, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 774940672, Generator: nil},
{Name: "UMIN", OpcodeMask: 3206609920, Opcode: 773876736, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773876736, Generator: nil},
{Name: "UMINP", OpcodeMask: 3206609920, Opcode: 773893120, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773893120, Generator: nil},
{Name: "UMINV", OpcodeMask: 3208641536, Opcode: 775006208, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 775006208, Generator: nil},
{Name: "UMLAL, UMLAL2 (by element)", OpcodeMask: 4278252544, Opcode: 788537344, Fields: []InsnField{
{"size", 23, 2},
{"L", 21, 1},
{"M", 20, 1},
{"Rm", 19, 4},
{"H", 11, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 788537344, Generator: nil},
{Name: "UMLAL, UMLAL2 (by element)", OpcodeMask: 4278252544, Opcode: 1862279168, Fields: []InsnField{
{"size", 23, 2},
{"L", 21, 1},
{"M", 20, 1},
{"Rm", 19, 4},
{"H", 11, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1862279168, Generator: nil},
{Name: "UMLAL, UMLAL2 (vector)", OpcodeMask: 4280351744, Opcode: 773881856, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773881856, Generator: nil},
{Name: "UMLAL, UMLAL2 (vector)", OpcodeMask: 4280351744, Opcode: 1847623680, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1847623680, Generator: nil},
{Name: "UMLSL, UMLSL2 (by element)", OpcodeMask: 4278252544, Opcode: 788553728, Fields: []InsnField{
{"size", 23, 2},
{"L", 21, 1},
{"M", 20, 1},
{"Rm", 19, 4},
{"H", 11, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 788553728, Generator: nil},
{Name: "UMLSL, UMLSL2 (by element)", OpcodeMask: 4278252544, Opcode: 1862295552, Fields: []InsnField{
{"size", 23, 2},
{"L", 21, 1},
{"M", 20, 1},
{"Rm", 19, 4},
{"H", 11, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1862295552, Generator: nil},
{Name: "UMLSL, UMLSL2 (vector)", OpcodeMask: 4280351744, Opcode: 773890048, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773890048, Generator: nil},
{Name: "UMLSL, UMLSL2 (vector)", OpcodeMask: 4280351744, Opcode: 1847631872, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1847631872, Generator: nil},
{Name: "UMOV", OpcodeMask: 4292934656, Opcode: 234896384, Fields: []InsnField{
{"imm5", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 234896384, Generator: nil},
{Name: "UMOV", OpcodeMask: 4292934656, Opcode: 1308638208, Fields: []InsnField{
{"imm5", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1308638208, Generator: nil},
{Name: "UMULL, UMULL2 (by element)", OpcodeMask: 4278252544, Opcode: 788570112, Fields: []InsnField{
{"size", 23, 2},
{"L", 21, 1},
{"M", 20, 1},
{"Rm", 19, 4},
{"H", 11, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 788570112, Generator: nil},
{Name: "UMULL, UMULL2 (by element)", OpcodeMask: 4278252544, Opcode: 1862311936, Fields: []InsnField{
{"size", 23, 2},
{"L", 21, 1},
{"M", 20, 1},
{"Rm", 19, 4},
{"H", 11, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1862311936, Generator: nil},
{Name: "UMULL, UMULL2 (vector)", OpcodeMask: 4280351744, Opcode: 773898240, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773898240, Generator: nil},
{Name: "UMULL, UMULL2 (vector)", OpcodeMask: 4280351744, Opcode: 1847640064, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1847640064, Generator: nil},
{Name: "UQADD", OpcodeMask: 4280351744, Opcode: 2116029440, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2116029440, Generator: nil},
{Name: "UQADD", OpcodeMask: 3206609920, Opcode: 773852160, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773852160, Generator: nil},
{Name: "UQRSHL", OpcodeMask: 4280351744, Opcode: 2116049920, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2116049920, Generator: nil},
{Name: "UQRSHL", OpcodeMask: 3206609920, Opcode: 773872640, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773872640, Generator: nil},
{Name: "UQRSHRN, UQRSHRN2", OpcodeMask: 4286643200, Opcode: 2130746368, Fields: []InsnField{
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2130746368, Generator: nil},
{Name: "UQRSHRN, UQRSHRN2", OpcodeMask: 4286643200, Opcode: 788569088, Fields: []InsnField{
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 788569088, Generator: nil},
{Name: "UQRSHRN, UQRSHRN2", OpcodeMask: 4286643200, Opcode: 1862310912, Fields: []InsnField{
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1862310912, Generator: nil},
{Name: "UQSHL (immediate)", OpcodeMask: 4286643200, Opcode: 2130736128, Fields: []InsnField{
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2130736128, Generator: nil},
{Name: "UQSHL (immediate)", OpcodeMask: 3212901376, Opcode: 788558848, Fields: []InsnField{
{"Q", 30, 1},
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 788558848, Generator: nil},
{Name: "UQSHL (register)", OpcodeMask: 4280351744, Opcode: 2116045824, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2116045824, Generator: nil},
{Name: "UQSHL (register)", OpcodeMask: 3206609920, Opcode: 773868544, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773868544, Generator: nil},
{Name: "UQSHRN, UQSHRN2", OpcodeMask: 4286643200, Opcode: 2130744320, Fields: []InsnField{
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2130744320, Generator: nil},
{Name: "UQSHRN, UQSHRN2", OpcodeMask: 4286643200, Opcode: 788567040, Fields: []InsnField{
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 788567040, Generator: nil},
{Name: "UQSHRN, UQSHRN2", OpcodeMask: 4286643200, Opcode: 1862308864, Fields: []InsnField{
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1862308864, Generator: nil},
{Name: "UQSUB", OpcodeMask: 4280351744, Opcode: 2116037632, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2116037632, Generator: nil},
{Name: "UQSUB", OpcodeMask: 3206609920, Opcode: 773860352, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773860352, Generator: nil},
{Name: "UQXTN, UQXTN2", OpcodeMask: 4282383360, Opcode: 2116110336, Fields: []InsnField{
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2116110336, Generator: nil},
{Name: "UQXTN, UQXTN2", OpcodeMask: 4282383360, Opcode: 773933056, Fields: []InsnField{
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773933056, Generator: nil},
{Name: "UQXTN, UQXTN2", OpcodeMask: 4282383360, Opcode: 1847674880, Fields: []InsnField{
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1847674880, Generator: nil},
{Name: "URECPE", OpcodeMask: 3217030144, Opcode: 245483520, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 245483520, Generator: nil},
{Name: "URHADD", OpcodeMask: 3206609920, Opcode: 773854208, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773854208, Generator: nil},
{Name: "URSHL", OpcodeMask: 4280351744, Opcode: 2116047872, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2116047872, Generator: nil},
{Name: "URSHL", OpcodeMask: 3206609920, Opcode: 773870592, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773870592, Generator: nil},
{Name: "URSHR", OpcodeMask: 4286643200, Opcode: 2130715648, Fields: []InsnField{
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2130715648, Generator: nil},
{Name: "URSHR", OpcodeMask: 3212901376, Opcode: 788538368, Fields: []InsnField{
{"Q", 30, 1},
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 788538368, Generator: nil},
{Name: "URSQRTE", OpcodeMask: 3217030144, Opcode: 782354432, Fields: []InsnField{
{"Q", 30, 1},
{"sz", 22, 1},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 782354432, Generator: nil},
{Name: "URSRA", OpcodeMask: 4286643200, Opcode: 2130719744, Fields: []InsnField{
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2130719744, Generator: nil},
{Name: "URSRA", OpcodeMask: 3212901376, Opcode: 788542464, Fields: []InsnField{
{"Q", 30, 1},
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 788542464, Generator: nil},
{Name: "USHL", OpcodeMask: 4280351744, Opcode: 2116043776, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2116043776, Generator: nil},
{Name: "USHL", OpcodeMask: 3206609920, Opcode: 773866496, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773866496, Generator: nil},
{Name: "USHLL, USHLL2", OpcodeMask: 4286643200, Opcode: 788571136, Fields: []InsnField{
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 788571136, Generator: nil},
{Name: "USHLL, USHLL2", OpcodeMask: 4286643200, Opcode: 1862312960, Fields: []InsnField{
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1862312960, Generator: nil},
{Name: "USHR", OpcodeMask: 4286643200, Opcode: 2130707456, Fields: []InsnField{
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2130707456, Generator: nil},
{Name: "USHR", OpcodeMask: 3212901376, Opcode: 788530176, Fields: []InsnField{
{"Q", 30, 1},
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 788530176, Generator: nil},
{Name: "USQADD", OpcodeMask: 4282383360, Opcode: 2116040704, Fields: []InsnField{
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2116040704, Generator: nil},
{Name: "USQADD", OpcodeMask: 3208641536, Opcode: 773863424, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773863424, Generator: nil},
{Name: "USRA", OpcodeMask: 4286643200, Opcode: 2130711552, Fields: []InsnField{
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 2130711552, Generator: nil},
{Name: "USRA", OpcodeMask: 3212901376, Opcode: 788534272, Fields: []InsnField{
{"Q", 30, 1},
{"immh", 22, 4},
{"immb", 18, 3},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 788534272, Generator: nil},
{Name: "USUBL, USUBL2", OpcodeMask: 4280351744, Opcode: 773857280, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773857280, Generator: nil},
{Name: "USUBL, USUBL2", OpcodeMask: 4280351744, Opcode: 1847599104, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1847599104, Generator: nil},
{Name: "USUBW, USUBW2", OpcodeMask: 4280351744, Opcode: 773861376, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 773861376, Generator: nil},
{Name: "USUBW, USUBW2", OpcodeMask: 4280351744, Opcode: 1847603200, Fields: []InsnField{
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1847603200, Generator: nil},
{Name: "UXTL, UXTL2", OpcodeMask: 4287101952, Opcode: 788571136, Fields: []InsnField{
{"immh", 22, 4},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 788571136, Generator: nil},
{Name: "UXTL, UXTL2", OpcodeMask: 4287101952, Opcode: 1862312960, Fields: []InsnField{
{"immh", 22, 4},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1862312960, Generator: nil},
{Name: "UZP1", OpcodeMask: 3206609920, Opcode: 234887168, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 234887168, Generator: nil},
{Name: "UZP2", OpcodeMask: 3206609920, Opcode: 234903552, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 234903552, Generator: nil},
{Name: "XTN, XTN2", OpcodeMask: 4282383360, Opcode: 237053952, Fields: []InsnField{
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 237053952, Generator: nil},
{Name: "XTN, XTN2", OpcodeMask: 4282383360, Opcode: 1310795776, Fields: []InsnField{
{"size", 23, 2},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 1310795776, Generator: nil},
{Name: "ZIP1", OpcodeMask: 3206609920, Opcode: 234895360, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 234895360, Generator: nil},
{Name: "ZIP2", OpcodeMask: 3206609920, Opcode: 234911744, Fields: []InsnField{
{"Q", 30, 1},
{"size", 23, 2},
{"Rm", 20, 5},
{"Rn", 9, 5},
{"Rd", 4, 5},
}, AsUInt32: 234911744, Generator: nil},
}
// Copyright 2024 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
// Pseudo instructions for arm64 architecture.
package arm64
import (
"math/rand"
"github.com/google/syzkaller/pkg/ifuzz/iset"
)
var pseudo = []*Insn{
{
Name: "PSEUDO_HCALL",
Pseudo: true,
Priv: true,
Generator: func(cfg *iset.Config, r *rand.Rand) []byte {
gen := makeGen(cfg, r)
gen.smcccHvc()
return gen.text
},
},
}
type generator struct {
r *rand.Rand
text []byte
}
func makeGen(cfg *iset.Config, r *rand.Rand) *generator {
return &generator{
r: r,
}
}
func (gen *generator) smcccHvc() {
cmd := (uint32(1) << 31) | (uint32(gen.r.Intn(2)) << 30) |
(uint32(gen.r.Intn(8)&0x3F) << 24) | (uint32(gen.r.Intn(0x10000)) & 0xFFFF)
gen.movRegImm32(0, cmd)
gen.movRegImm16(1, uint32(gen.r.Intn(16)))
gen.movRegImm16(2, uint32(gen.r.Intn(16)))
gen.movRegImm16(3, uint32(gen.r.Intn(16)))
gen.movRegImm16(4, uint32(gen.r.Intn(16)))
gen.byte(0x02, 0x00, 0x00, 0xd4)
}
func (gen *generator) movRegImm32(reg, imm uint32) {
gen.movRegImm16(reg, imm)
// Encoding `movk reg, imm16, LSL #16`.
upper := (imm >> 16) & 0xffff
opcode := uint32(0xf2a00000)
opcode |= upper << 5
opcode |= reg & 0xf
gen.imm32(opcode)
}
func (gen *generator) movRegImm16(reg, imm uint32) {
// Encoding `mov reg, imm16`.
imm = imm & 0xffff
opcode := uint32(0xd2800000)
opcode |= imm << 5
opcode |= reg & 0xf
gen.imm32(opcode)
}
func (gen *generator) imm32(v uint32) {
gen.byte(byte(v>>0), byte(v>>8), byte(v>>16), byte(v>>24))
}
func (gen *generator) byte(v ...uint8) {
gen.text = append(gen.text, v...)
}
// Copyright 2024 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package arm64
func extractBits(from uint32, start, size uint) uint32 {
mask := uint32((1 << size) - 1)
return (from >> (start - size + 1)) & mask
}
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package ifuzz
import (
"math/rand"
_ "github.com/google/syzkaller/pkg/ifuzz/arm64/generated" // pull in generated instruction descriptions
"github.com/google/syzkaller/pkg/ifuzz/iset"
_ "github.com/google/syzkaller/pkg/ifuzz/powerpc/generated" // pull in generated instruction descriptions
_ "github.com/google/syzkaller/pkg/ifuzz/x86/generated" // pull in generated instruction descriptions
)
type (
Config = iset.Config
MemRegion = iset.MemRegion
Mode = iset.Mode
)
const (
ArchX86 = iset.ArchX86
ArchPowerPC = iset.ArchPowerPC
ArchArm64 = iset.ArchArm64
ModeLong64 = iset.ModeLong64
ModeProt32 = iset.ModeProt32
ModeProt16 = iset.ModeProt16
ModeReal16 = iset.ModeReal16
)
func Generate(cfg *Config, r *rand.Rand) []byte {
var text []byte
for i := 0; i < cfg.Len; i++ {
insn := randInsn(cfg, r)
text = append(text, insn.Encode(cfg, r)...)
}
return text
}
func Mutate(cfg *Config, r *rand.Rand, text []byte) []byte {
insns := split(cfg, text)
retry := false
for stop := false; !stop || retry || len(insns) == 0; stop = r.Intn(2) == 0 {
retry = false
switch x := r.Intn(100); {
case x < 10 && len(insns) != 0:
// Delete instruction.
i := r.Intn(len(insns))
copy(insns[i:], insns[i+1:])
insns = insns[:len(insns)-1]
case x < 40 && len(insns) != 0:
// Replace instruction with another.
insn := randInsn(cfg, r)
text1 := insn.Encode(cfg, r)
i := r.Intn(len(insns))
insns[i] = text1
case x < 70 && len(insns) != 0:
// Mutate instruction.
i := r.Intn(len(insns))
text1 := insns[i]
for stop := false; !stop || len(text1) == 0; stop = r.Intn(2) == 0 {
switch x := r.Intn(100); {
case x < 5 && len(text1) != 0:
// Delete byte.
pos := r.Intn(len(text1))
copy(text1[pos:], text1[pos+1:])
text1 = text1[:len(text1)-1]
case x < 40 && len(text1) != 0:
// Replace a byte.
pos := r.Intn(len(text1))
text1[pos] = byte(r.Intn(256))
case x < 70 && len(text1) != 0:
// Flip a bit.
pos := r.Intn(len(text1))
text1[pos] ^= 1 << byte(r.Intn(8))
default:
// Insert a byte.
pos := r.Intn(len(text1) + 1)
text1 = append(text1, 0)
copy(text1[pos+1:], text1[pos:])
text1[pos] = byte(r.Intn(256))
}
}
insns[i] = text1
case len(insns) < cfg.Len:
// Insert a new instruction.
insn := randInsn(cfg, r)
text1 := insn.Encode(cfg, r)
i := r.Intn(len(insns) + 1)
insns = append(insns, nil)
copy(insns[i+1:], insns[i:])
insns[i] = text1
default:
retry = true
}
}
text = nil
for _, insn := range insns {
text = append(text, insn...)
}
return text
}
func randInsn(cfg *Config, r *rand.Rand) iset.Insn {
insnset := iset.Arches[cfg.Arch]
var insns []iset.Insn
if cfg.Priv && cfg.Exec {
insns = insnset.GetInsns(cfg.Mode, iset.Type(r.Intn(3)))
} else if cfg.Priv {
insns = insnset.GetInsns(cfg.Mode, iset.Type(r.Intn(2)))
} else {
insns = insnset.GetInsns(cfg.Mode, iset.TypeUser)
}
return insns[r.Intn(len(insns))]
}
func split(cfg *Config, text []byte) [][]byte {
insnset := iset.Arches[cfg.Arch]
text = append([]byte{}, text...)
var insns [][]byte
var bad []byte
for len(text) != 0 {
n, err := insnset.Decode(cfg.Mode, text)
if err != nil || n == 0 {
bad = append(bad, text[0])
text = text[1:]
continue
}
if bad != nil {
insns = append(insns, bad)
bad = nil
}
insns = append(insns, text[:n])
text = text[n:]
}
if bad != nil {
insns = append(insns, bad)
}
return insns
}
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
// Package iset ("instruction set") provides base and helper types for ifuzz arch implementations.
package iset
import (
"math/rand"
)
const (
ArchX86 = "x86"
ArchPowerPC = "powerpc"
ArchArm64 = "arm64"
)
var Arches = make(map[string]InsnSet)
type (
Mode uint
Type uint
)
type Insn interface {
Info() (name string, mode Mode, pseudo, priv bool)
Encode(cfg *Config, r *rand.Rand) []byte
}
type InsnSet interface {
GetInsns(mode Mode, typ Type) []Insn
Decode(mode Mode, text []byte) (int, error)
DecodeExt(mode Mode, text []byte) (int, error) // XED, to keep ifuzz_test happy
}
type Config struct {
Arch string
Len int // number of instructions to generate
Mode Mode // one of ModeXXX
Priv bool // generate CPL=0 instructions (x86), HV/!PR mode (PPC)
Exec bool // generate instructions sequences interesting for execution
MemRegions []MemRegion // generated instructions will reference these regions
}
type MemRegion struct {
Start uint64
Size uint64
}
const (
ModeLong64 Mode = iota
ModeProt32
ModeProt16
ModeReal16
ModeLast
)
const (
TypeExec Type = iota
TypePriv
TypeUser
TypeAll
TypeLast
)
var SpecialNumbers = [...]uint64{0, 1 << 15, 1 << 16, 1 << 31, 1 << 32, 1 << 47, 1 << 47, 1 << 63}
type ModeInsns [ModeLast][TypeLast][]Insn
func (modeInsns *ModeInsns) Add(insn Insn) {
_, mode, pseudo, priv := insn.Info()
for m := Mode(0); m < ModeLast; m++ {
if mode&(1<<uint(m)) == 0 {
continue
}
set := &modeInsns[m]
if pseudo {
set[TypeExec] = append(set[TypeExec], insn)
} else if priv {
set[TypePriv] = append(set[TypePriv], insn)
set[TypeAll] = append(set[TypeAll], insn)
} else {
set[TypeUser] = append(set[TypeUser], insn)
set[TypeAll] = append(set[TypeAll], insn)
}
}
}
func (cfg *Config) IsCompatible(insn Insn) bool {
_, mode, pseudo, priv := insn.Info()
if cfg.Mode >= ModeLast {
panic("bad mode")
}
if priv && !cfg.Priv {
return false
}
if pseudo && !cfg.Exec {
return false
}
if mode&(1<<uint(cfg.Mode)) == 0 {
return false
}
return true
}
func GenerateInt(cfg *Config, r *rand.Rand, size int) uint64 {
if size != 1 && size != 2 && size != 4 && size != 8 {
panic("bad arg size")
}
var v uint64
switch x := r.Intn(60); {
case x < 10:
v = uint64(r.Intn(1 << 4))
case x < 20:
v = uint64(r.Intn(1 << 16))
case x < 25:
v = uint64(r.Int63()) % (1 << 32)
case x < 30:
v = uint64(r.Int63())
case x < 40:
v = SpecialNumbers[r.Intn(len(SpecialNumbers))]
if r.Intn(5) == 0 {
v += uint64(r.Intn(33)) - 16
}
case x < 50 && len(cfg.MemRegions) != 0:
mem := cfg.MemRegions[r.Intn(len(cfg.MemRegions))]
switch x := r.Intn(100); {
case x < 25:
v = mem.Start
case x < 50:
v = mem.Start + mem.Size
case x < 75:
v = mem.Start + mem.Size/2
default:
v = mem.Start + uint64(r.Int63())%mem.Size
}
if r.Intn(10) == 0 {
v += uint64(r.Intn(33)) - 16
}
default:
v = uint64(r.Intn(1 << 8))
}
if r.Intn(50) == 0 {
v = uint64(-int64(v))
}
if r.Intn(50) == 0 && size != 1 {
v &^= 1<<12 - 1
}
return v
}
// Code generated by ./pkg/ifuzz/powerpc/gen/powerisa31_tex_to_syz. DO NOT EDIT.
//go:build !codeanalysis
package generated
import "github.com/google/syzkaller/pkg/ifuzz/powerpc"
func init() {
powerpc.Register(insns)
}
var insns = []*powerpc.Insn{
{Name: "add", Opcode: 0x7c000214, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "add.", Opcode: 0x7c000215, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "addc", Opcode: 0x7c000014, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "addc.", Opcode: 0x7c000015, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "addco", Opcode: 0x7c000414, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "addco.", Opcode: 0x7c000415, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "adde", Opcode: 0x7c000114, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "adde.", Opcode: 0x7c000115, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "addeo", Opcode: 0x7c000514, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "addeo.", Opcode: 0x7c000515, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "addex", Opcode: 0x7c000154, Mask: 0xfc0001ff, Fields: []powerpc.InsnField{{Name: "CY", Bits: []powerpc.InsnBits{{21, 2}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "addg6s", Opcode: 0x7c000094, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "addi", Opcode: 0x38000000, Mask: 0xfc000000, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "SI", Bits: []powerpc.InsnBits{{16, 16}}}}},
{Name: "addic", Opcode: 0x30000000, Mask: 0xfc000000, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "SI", Bits: []powerpc.InsnBits{{16, 16}}}}},
{Name: "addic.", Opcode: 0x34000000, Mask: 0xfc000000, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "SI", Bits: []powerpc.InsnBits{{16, 16}}}}},
{Name: "addis", Opcode: 0x3c000000, Mask: 0xfc000000, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "SI", Bits: []powerpc.InsnBits{{16, 16}}}}},
{Name: "addme", Opcode: 0x7c0001d4, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "addme.", Opcode: 0x7c0001d5, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "addmeo", Opcode: 0x7c0005d4, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "addmeo.", Opcode: 0x7c0005d5, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "addo", Opcode: 0x7c000614, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "addo.", Opcode: 0x7c000615, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "addpcis", Opcode: 0x4c000004, Mask: 0xfc00003e, Fields: []powerpc.InsnField{{Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "d0", Bits: []powerpc.InsnBits{{16, 10}}}, {Name: "d1", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "d2", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "addze", Opcode: 0x7c000194, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "addze.", Opcode: 0x7c000195, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "addzeo", Opcode: 0x7c000594, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "addzeo.", Opcode: 0x7c000595, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "and", Opcode: 0x7c000038, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "and.", Opcode: 0x7c000039, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "andc", Opcode: 0x7c000078, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "andc.", Opcode: 0x7c000079, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "andi.", Opcode: 0x70000000, Mask: 0xfc000000, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "UI", Bits: []powerpc.InsnBits{{16, 16}}}}},
{Name: "andis.", Opcode: 0x74000000, Mask: 0xfc000000, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "UI", Bits: []powerpc.InsnBits{{16, 16}}}}},
{Name: "b", Opcode: 0x48000000, Mask: 0xfc000003, Fields: []powerpc.InsnField{{Name: "LI", Bits: []powerpc.InsnBits{{6, 24}}}}},
{Name: "ba", Opcode: 0x48000002, Mask: 0xfc000003, Fields: []powerpc.InsnField{{Name: "LI", Bits: []powerpc.InsnBits{{6, 24}}}}},
{Name: "bc", Opcode: 0x40000000, Mask: 0xfc000003, Fields: []powerpc.InsnField{{Name: "BD", Bits: []powerpc.InsnBits{{16, 14}}}, {Name: "BI", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "BO", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "bca", Opcode: 0x40000002, Mask: 0xfc000003, Fields: []powerpc.InsnField{{Name: "BD", Bits: []powerpc.InsnBits{{16, 14}}}, {Name: "BI", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "BO", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "bcctr", Opcode: 0x4c000420, Mask: 0xfc00e7ff, Fields: []powerpc.InsnField{{Name: "BH", Bits: []powerpc.InsnBits{{19, 2}}}, {Name: "BI", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "BO", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "bcctrl", Opcode: 0x4c000421, Mask: 0xfc00e7ff, Fields: []powerpc.InsnField{{Name: "BH", Bits: []powerpc.InsnBits{{19, 2}}}, {Name: "BI", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "BO", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "bcdadd.", Opcode: 0x10000401, Mask: 0xfc0005ff, Fields: []powerpc.InsnField{{Name: "PS", Bits: []powerpc.InsnBits{{22, 1}}}, {Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "bcdcfn.", Opcode: 0x10070581, Mask: 0xfc1f05ff, Fields: []powerpc.InsnField{{Name: "PS", Bits: []powerpc.InsnBits{{22, 1}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "bcdcfsq.", Opcode: 0x10020581, Mask: 0xfc1f05ff, Fields: []powerpc.InsnField{{Name: "PS", Bits: []powerpc.InsnBits{{22, 1}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "bcdcfz.", Opcode: 0x10060581, Mask: 0xfc1f05ff, Fields: []powerpc.InsnField{{Name: "PS", Bits: []powerpc.InsnBits{{22, 1}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "bcdcpsgn.", Opcode: 0x10000341, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "bcdctn.", Opcode: 0x10050581, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "bcdctsq.", Opcode: 0x10000581, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "bcdctz.", Opcode: 0x10040581, Mask: 0xfc1f05ff, Fields: []powerpc.InsnField{{Name: "PS", Bits: []powerpc.InsnBits{{22, 1}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "bcds.", Opcode: 0x100004c1, Mask: 0xfc0005ff, Fields: []powerpc.InsnField{{Name: "PS", Bits: []powerpc.InsnBits{{22, 1}}}, {Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "bcdsetsgn.", Opcode: 0x101f0581, Mask: 0xfc1f05ff, Fields: []powerpc.InsnField{{Name: "PS", Bits: []powerpc.InsnBits{{22, 1}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "bcdsr.", Opcode: 0x100005c1, Mask: 0xfc0005ff, Fields: []powerpc.InsnField{{Name: "PS", Bits: []powerpc.InsnBits{{22, 1}}}, {Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "bcdsub.", Opcode: 0x10000441, Mask: 0xfc0005ff, Fields: []powerpc.InsnField{{Name: "PS", Bits: []powerpc.InsnBits{{22, 1}}}, {Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "bcdtrunc.", Opcode: 0x10000501, Mask: 0xfc0005ff, Fields: []powerpc.InsnField{{Name: "PS", Bits: []powerpc.InsnBits{{22, 1}}}, {Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "bcdus.", Opcode: 0x10000481, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "bcdutrunc.", Opcode: 0x10000541, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "bcl", Opcode: 0x40000001, Mask: 0xfc000003, Fields: []powerpc.InsnField{{Name: "BD", Bits: []powerpc.InsnBits{{16, 14}}}, {Name: "BI", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "BO", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "bcla", Opcode: 0x40000003, Mask: 0xfc000003, Fields: []powerpc.InsnField{{Name: "BD", Bits: []powerpc.InsnBits{{16, 14}}}, {Name: "BI", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "BO", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "bclr", Opcode: 0x4c000020, Mask: 0xfc00e7ff, Fields: []powerpc.InsnField{{Name: "BH", Bits: []powerpc.InsnBits{{19, 2}}}, {Name: "BI", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "BO", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "bclrl", Opcode: 0x4c000021, Mask: 0xfc00e7ff, Fields: []powerpc.InsnField{{Name: "BH", Bits: []powerpc.InsnBits{{19, 2}}}, {Name: "BI", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "BO", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "bctar", Opcode: 0x4c000460, Mask: 0xfc00e7ff, Fields: []powerpc.InsnField{{Name: "BH", Bits: []powerpc.InsnBits{{19, 2}}}, {Name: "BI", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "BO", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "bctarl", Opcode: 0x4c000461, Mask: 0xfc00e7ff, Fields: []powerpc.InsnField{{Name: "BH", Bits: []powerpc.InsnBits{{19, 2}}}, {Name: "BI", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "BO", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "bl", Opcode: 0x48000001, Mask: 0xfc000003, Fields: []powerpc.InsnField{{Name: "LI", Bits: []powerpc.InsnBits{{6, 24}}}}},
{Name: "bla", Opcode: 0x48000003, Mask: 0xfc000003, Fields: []powerpc.InsnField{{Name: "LI", Bits: []powerpc.InsnBits{{6, 24}}}}},
{Name: "bpermd", Opcode: 0x7c0001f8, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "brd", Opcode: 0x7c000176, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "brh", Opcode: 0x7c0001b6, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "brw", Opcode: 0x7c000136, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "cbcdtd", Opcode: 0x7c000274, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "cdtbcd", Opcode: 0x7c000234, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "cfuged", Opcode: 0x7c0001b8, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "clrbhrb", Opcode: 0x7c00035c, Mask: 0xffffffff, Fields: []powerpc.InsnField{}},
{Name: "cmp", Opcode: 0x7c000000, Mask: 0xfc4007ff, Fields: []powerpc.InsnField{{Name: "BF", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "L", Bits: []powerpc.InsnBits{{10, 1}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "cmpb", Opcode: 0x7c0003f8, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "Rc", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "cmpeqb", Opcode: 0x7c0001c0, Mask: 0xfc6007ff, Fields: []powerpc.InsnField{{Name: "BF", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "cmpi", Opcode: 0x2c000000, Mask: 0xfc400000, Fields: []powerpc.InsnField{{Name: "BF", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "L", Bits: []powerpc.InsnBits{{10, 1}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "SI", Bits: []powerpc.InsnBits{{16, 16}}}}},
{Name: "cmpl", Opcode: 0x7c000040, Mask: 0xfc4007ff, Fields: []powerpc.InsnField{{Name: "BF", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "L", Bits: []powerpc.InsnBits{{10, 1}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "cmpli", Opcode: 0x28000000, Mask: 0xfc400000, Fields: []powerpc.InsnField{{Name: "BF", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "L", Bits: []powerpc.InsnBits{{10, 1}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "UI", Bits: []powerpc.InsnBits{{16, 16}}}}},
{Name: "cmprb", Opcode: 0x7c000180, Mask: 0xfc4007ff, Fields: []powerpc.InsnField{{Name: "BF", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "L", Bits: []powerpc.InsnBits{{10, 1}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "cntlzd", Opcode: 0x7c000074, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "cntlzd.", Opcode: 0x7c000075, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "cntlzdm", Opcode: 0x7c000076, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "cntlzw", Opcode: 0x7c000034, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "cntlzw.", Opcode: 0x7c000035, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "cnttzd", Opcode: 0x7c000474, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "cnttzd.", Opcode: 0x7c000475, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "cnttzdm", Opcode: 0x7c000476, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "cnttzw", Opcode: 0x7c000434, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "cnttzw.", Opcode: 0x7c000435, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "copy", Opcode: 0x7c20060c, Mask: 0xffe007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "cpabort", Opcode: 0x7c00068c, Mask: 0xffffffff, Fields: []powerpc.InsnField{}},
{Name: "crand", Opcode: 0x4c000202, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "BA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "BB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "crandc", Opcode: 0x4c000102, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "BA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "BB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "creqv", Opcode: 0x4c000242, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "BA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "BB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "crnand", Opcode: 0x4c0001c2, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "BA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "BB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "crnor", Opcode: 0x4c000042, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "BA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "BB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "cror", Opcode: 0x4c000382, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "BA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "BB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "crorc", Opcode: 0x4c000342, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "BA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "BB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "crxor", Opcode: 0x4c000182, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "BA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "BB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "dadd", Opcode: 0xec000004, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "dadd.", Opcode: 0xec000005, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "daddq", Opcode: 0xfc000004, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FRAp", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRBp", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRTp", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "daddq.", Opcode: 0xfc000005, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FRAp", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRBp", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRTp", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "darn", Opcode: 0x7c0005e6, Mask: 0xfc1cffff, Fields: []powerpc.InsnField{{Name: "L", Bits: []powerpc.InsnBits{{14, 2}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "dcbf", Opcode: 0x7c0000ac, Mask: 0xff0007ff, Fields: []powerpc.InsnField{{Name: "L", Bits: []powerpc.InsnBits{{8, 3}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "dcbst", Opcode: 0x7c00006c, Mask: 0xffe007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "dcbt", Opcode: 0x7c00022c, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "TH", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "dcbtst", Opcode: 0x7c0001ec, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "TH", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "dcbz", Opcode: 0x7c0007ec, Mask: 0xffe007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "dcffix", Opcode: 0xec000644, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "dcffix.", Opcode: 0xec000645, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "dcffixq", Opcode: 0xfc000644, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRTp", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "dcffixq.", Opcode: 0xfc000645, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRTp", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "dcffixqq", Opcode: 0xfc0007c4, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRTp", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "dcmpo", Opcode: 0xec000104, Mask: 0xfc6007ff, Fields: []powerpc.InsnField{{Name: "BF", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "dcmpoq", Opcode: 0xfc000104, Mask: 0xfc6007ff, Fields: []powerpc.InsnField{{Name: "BF", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "FRAp", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRBp", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "dcmpu", Opcode: 0xec000504, Mask: 0xfc6007ff, Fields: []powerpc.InsnField{{Name: "BF", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "dcmpuq", Opcode: 0xfc000504, Mask: 0xfc6007ff, Fields: []powerpc.InsnField{{Name: "BF", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "FRAp", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRBp", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "dctdp", Opcode: 0xec000204, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "dctdp.", Opcode: 0xec000205, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "dctfix", Opcode: 0xec000244, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "dctfix.", Opcode: 0xec000245, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "dctfixq", Opcode: 0xfc000244, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRBp", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "dctfixq.", Opcode: 0xfc000245, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRBp", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "dctfixqq", Opcode: 0xfc0107c4, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRBp", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "dctqpq", Opcode: 0xfc000204, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRTp", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "dctqpq.", Opcode: 0xfc000205, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRTp", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "ddedpd", Opcode: 0xec000284, Mask: 0xfc0707ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "SP", Bits: []powerpc.InsnBits{{11, 2}}}}},
{Name: "ddedpd.", Opcode: 0xec000285, Mask: 0xfc0707ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "SP", Bits: []powerpc.InsnBits{{11, 2}}}}},
{Name: "ddedpdq", Opcode: 0xfc000284, Mask: 0xfc0707ff, Fields: []powerpc.InsnField{{Name: "FRBp", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRTp", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "SP", Bits: []powerpc.InsnBits{{11, 2}}}}},
{Name: "ddedpdq.", Opcode: 0xfc000285, Mask: 0xfc0707ff, Fields: []powerpc.InsnField{{Name: "FRBp", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRTp", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "SP", Bits: []powerpc.InsnBits{{11, 2}}}}},
{Name: "ddiv", Opcode: 0xec000444, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "ddiv.", Opcode: 0xec000445, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "ddivq", Opcode: 0xfc000444, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FRAp", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRBp", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRTp", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "ddivq.", Opcode: 0xfc000445, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FRAp", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRBp", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRTp", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "denbcd", Opcode: 0xec000684, Mask: 0xfc0f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "S", Bits: []powerpc.InsnBits{{11, 1}}}}},
{Name: "denbcd.", Opcode: 0xec000685, Mask: 0xfc0f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "S", Bits: []powerpc.InsnBits{{11, 1}}}}},
{Name: "denbcdq", Opcode: 0xfc000684, Mask: 0xfc0f07ff, Fields: []powerpc.InsnField{{Name: "FRBp", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRTp", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "S", Bits: []powerpc.InsnBits{{11, 1}}}}},
{Name: "denbcdq.", Opcode: 0xfc000685, Mask: 0xfc0f07ff, Fields: []powerpc.InsnField{{Name: "FRBp", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRTp", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "S", Bits: []powerpc.InsnBits{{11, 1}}}}},
{Name: "diex", Opcode: 0xec0006c4, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "diex.", Opcode: 0xec0006c5, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "diexq", Opcode: 0xfc0006c4, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRBp", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRTp", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "Rc", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "diexq.", Opcode: 0xfc0006c5, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRBp", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRTp", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "divd", Opcode: 0x7c0003d2, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "divd.", Opcode: 0x7c0003d3, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "divde", Opcode: 0x7c000352, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "divde.", Opcode: 0x7c000353, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "divdeo", Opcode: 0x7c000752, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "divdeo.", Opcode: 0x7c000753, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "divdeu", Opcode: 0x7c000312, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "divdeu.", Opcode: 0x7c000313, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "divdeuo", Opcode: 0x7c000712, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "divdeuo.", Opcode: 0x7c000713, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "divdo", Opcode: 0x7c0007d2, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "divdo.", Opcode: 0x7c0007d3, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "divdu", Opcode: 0x7c000392, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "divdu.", Opcode: 0x7c000393, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "divduo", Opcode: 0x7c000792, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "divduo.", Opcode: 0x7c000793, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "divw", Opcode: 0x7c0003d6, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "divw.", Opcode: 0x7c0003d7, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "divwe", Opcode: 0x7c000356, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "divwe.", Opcode: 0x7c000357, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "divweo", Opcode: 0x7c000756, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "divweo.", Opcode: 0x7c000757, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "divweu", Opcode: 0x7c000316, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "divweu.", Opcode: 0x7c000317, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "divweuo", Opcode: 0x7c000716, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "divweuo.", Opcode: 0x7c000717, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "divwo", Opcode: 0x7c0007d6, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "divwo.", Opcode: 0x7c0007d7, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "divwu", Opcode: 0x7c000396, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "divwu.", Opcode: 0x7c000397, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "divwuo", Opcode: 0x7c000796, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "divwuo.", Opcode: 0x7c000797, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "dmul", Opcode: 0xec000044, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "dmul.", Opcode: 0xec000045, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "dmulq", Opcode: 0xfc000044, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FRAp", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRBp", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRTp", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "dmulq.", Opcode: 0xfc000045, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FRAp", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRBp", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRTp", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "dqua", Opcode: 0xec000006, Mask: 0xfc0001ff, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "RMC", Bits: []powerpc.InsnBits{{21, 2}}}}},
{Name: "dqua.", Opcode: 0xec000007, Mask: 0xfc0001ff, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "RMC", Bits: []powerpc.InsnBits{{21, 2}}}}},
{Name: "dquai", Opcode: 0xec000086, Mask: 0xfc0001ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "RMC", Bits: []powerpc.InsnBits{{21, 2}}}, {Name: "TE", Bits: []powerpc.InsnBits{{11, 5}}}}},
{Name: "dquai.", Opcode: 0xec000087, Mask: 0xfc0001ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "RMC", Bits: []powerpc.InsnBits{{21, 2}}}, {Name: "TE", Bits: []powerpc.InsnBits{{11, 5}}}}},
{Name: "dquaiq", Opcode: 0xfc000086, Mask: 0xfc0001ff, Fields: []powerpc.InsnField{{Name: "FRBp", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRTp", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "RMC", Bits: []powerpc.InsnBits{{21, 2}}}, {Name: "TE", Bits: []powerpc.InsnBits{{11, 5}}}}},
{Name: "dquaiq.", Opcode: 0xfc000087, Mask: 0xfc0001ff, Fields: []powerpc.InsnField{{Name: "FRBp", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRTp", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "RMC", Bits: []powerpc.InsnBits{{21, 2}}}, {Name: "TE", Bits: []powerpc.InsnBits{{11, 5}}}}},
{Name: "dquaq", Opcode: 0xfc000006, Mask: 0xfc0001ff, Fields: []powerpc.InsnField{{Name: "FRAp", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRBp", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRTp", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "RMC", Bits: []powerpc.InsnBits{{21, 2}}}}},
{Name: "dquaq.", Opcode: 0xfc000007, Mask: 0xfc0001ff, Fields: []powerpc.InsnField{{Name: "FRAp", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRBp", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRTp", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "RMC", Bits: []powerpc.InsnBits{{21, 2}}}}},
{Name: "drdpq", Opcode: 0xfc000604, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRBp", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRTp", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "drdpq.", Opcode: 0xfc000605, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRBp", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRTp", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "drintn", Opcode: 0xec0001c6, Mask: 0xfc1e01ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "R", Bits: []powerpc.InsnBits{{15, 1}}}, {Name: "RMC", Bits: []powerpc.InsnBits{{21, 2}}}}},
{Name: "drintn.", Opcode: 0xec0001c7, Mask: 0xfc1e01ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "R", Bits: []powerpc.InsnBits{{15, 1}}}, {Name: "RMC", Bits: []powerpc.InsnBits{{21, 2}}}}},
{Name: "drintnq", Opcode: 0xfc0001c6, Mask: 0xfc1e01ff, Fields: []powerpc.InsnField{{Name: "FRBp", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRTp", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "R", Bits: []powerpc.InsnBits{{15, 1}}}, {Name: "RMC", Bits: []powerpc.InsnBits{{21, 2}}}}},
{Name: "drintnq.", Opcode: 0xfc0001c7, Mask: 0xfc1e01ff, Fields: []powerpc.InsnField{{Name: "FRBp", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRTp", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "R", Bits: []powerpc.InsnBits{{15, 1}}}, {Name: "RMC", Bits: []powerpc.InsnBits{{21, 2}}}}},
{Name: "drintx", Opcode: 0xec0000c6, Mask: 0xfc1e01ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "R", Bits: []powerpc.InsnBits{{15, 1}}}, {Name: "RMC", Bits: []powerpc.InsnBits{{21, 2}}}}},
{Name: "drintx.", Opcode: 0xec0000c7, Mask: 0xfc1e01ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "R", Bits: []powerpc.InsnBits{{15, 1}}}, {Name: "RMC", Bits: []powerpc.InsnBits{{21, 2}}}}},
{Name: "drintxq", Opcode: 0xfc0000c6, Mask: 0xfc1e01ff, Fields: []powerpc.InsnField{{Name: "FRBp", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRTp", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "R", Bits: []powerpc.InsnBits{{15, 1}}}, {Name: "RMC", Bits: []powerpc.InsnBits{{21, 2}}}}},
{Name: "drintxq.", Opcode: 0xfc0000c7, Mask: 0xfc1e01ff, Fields: []powerpc.InsnField{{Name: "FRBp", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRTp", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "R", Bits: []powerpc.InsnBits{{15, 1}}}, {Name: "RMC", Bits: []powerpc.InsnBits{{21, 2}}}}},
{Name: "drrnd", Opcode: 0xec000046, Mask: 0xfc0001ff, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "RMC", Bits: []powerpc.InsnBits{{21, 2}}}}},
{Name: "drrnd.", Opcode: 0xec000047, Mask: 0xfc0001ff, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "RMC", Bits: []powerpc.InsnBits{{21, 2}}}}},
{Name: "drrndq", Opcode: 0xfc000046, Mask: 0xfc0001ff, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRBp", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRTp", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "RMC", Bits: []powerpc.InsnBits{{21, 2}}}}},
{Name: "drrndq.", Opcode: 0xfc000047, Mask: 0xfc0001ff, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRBp", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRTp", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "RMC", Bits: []powerpc.InsnBits{{21, 2}}}}},
{Name: "drsp", Opcode: 0xec000604, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "drsp.", Opcode: 0xec000605, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "dscli", Opcode: 0xec000084, Mask: 0xfc0003ff, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "SH", Bits: []powerpc.InsnBits{{16, 6}}}}},
{Name: "dscli.", Opcode: 0xec000085, Mask: 0xfc0003ff, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "SH", Bits: []powerpc.InsnBits{{16, 6}}}}},
{Name: "dscliq", Opcode: 0xfc000084, Mask: 0xfc0003ff, Fields: []powerpc.InsnField{{Name: "FRAp", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRTp", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "SH", Bits: []powerpc.InsnBits{{16, 6}}}}},
{Name: "dscliq.", Opcode: 0xfc000085, Mask: 0xfc0003ff, Fields: []powerpc.InsnField{{Name: "FRAp", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRTp", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "SH", Bits: []powerpc.InsnBits{{16, 6}}}}},
{Name: "dscri", Opcode: 0xec0000c4, Mask: 0xfc0003ff, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "SH", Bits: []powerpc.InsnBits{{16, 6}}}}},
{Name: "dscri.", Opcode: 0xec0000c5, Mask: 0xfc0003ff, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "SH", Bits: []powerpc.InsnBits{{16, 6}}}}},
{Name: "dscriq", Opcode: 0xfc0000c4, Mask: 0xfc0003ff, Fields: []powerpc.InsnField{{Name: "FRAp", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRTp", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "SH", Bits: []powerpc.InsnBits{{16, 6}}}}},
{Name: "dscriq.", Opcode: 0xfc0000c5, Mask: 0xfc0003ff, Fields: []powerpc.InsnField{{Name: "FRAp", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRTp", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "SH", Bits: []powerpc.InsnBits{{16, 6}}}}},
{Name: "dsub", Opcode: 0xec000404, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "dsub.", Opcode: 0xec000405, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "dsubq", Opcode: 0xfc000404, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FRAp", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRBp", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRTp", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "dsubq.", Opcode: 0xfc000405, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FRAp", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRBp", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRTp", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "dtstdc", Opcode: 0xec000184, Mask: 0xfc6003ff, Fields: []powerpc.InsnField{{Name: "BF", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "DCM", Bits: []powerpc.InsnBits{{16, 6}}}, {Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}}},
{Name: "dtstdcq", Opcode: 0xfc000184, Mask: 0xfc6003ff, Fields: []powerpc.InsnField{{Name: "BF", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "DCM", Bits: []powerpc.InsnBits{{16, 6}}}, {Name: "FRAp", Bits: []powerpc.InsnBits{{11, 5}}}}},
{Name: "dtstdg", Opcode: 0xec0001c4, Mask: 0xfc6003ff, Fields: []powerpc.InsnField{{Name: "BF", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "DGM", Bits: []powerpc.InsnBits{{16, 6}}}, {Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}}},
{Name: "dtstdgq", Opcode: 0xfc0001c4, Mask: 0xfc6003ff, Fields: []powerpc.InsnField{{Name: "BF", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "DGM", Bits: []powerpc.InsnBits{{16, 6}}}, {Name: "FRAp", Bits: []powerpc.InsnBits{{11, 5}}}}},
{Name: "dtstex", Opcode: 0xec000144, Mask: 0xfc6007ff, Fields: []powerpc.InsnField{{Name: "BF", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "dtstexq", Opcode: 0xfc000144, Mask: 0xfc6007ff, Fields: []powerpc.InsnField{{Name: "BF", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "FRAp", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRBp", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "dtstsf", Opcode: 0xec000544, Mask: 0xfc6007ff, Fields: []powerpc.InsnField{{Name: "BF", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "dtstsfi", Opcode: 0xec000546, Mask: 0xfc4007ff, Fields: []powerpc.InsnField{{Name: "BF", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "UIM", Bits: []powerpc.InsnBits{{10, 6}}}}},
{Name: "dtstsfiq", Opcode: 0xfc000546, Mask: 0xfc4007ff, Fields: []powerpc.InsnField{{Name: "BF", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "FRBp", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "UIM", Bits: []powerpc.InsnBits{{10, 6}}}}},
{Name: "dtstsfq", Opcode: 0xfc000544, Mask: 0xfc6007ff, Fields: []powerpc.InsnField{{Name: "BF", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRBp", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "dxex", Opcode: 0xec0002c4, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "dxex.", Opcode: 0xec0002c5, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "dxexq", Opcode: 0xfc0002c4, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRBp", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "dxexq.", Opcode: 0xfc0002c5, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRBp", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "eieio", Opcode: 0x7c0006ac, Mask: 0xffffffff, Fields: []powerpc.InsnField{}},
{Name: "eqv", Opcode: 0x7c000238, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "eqv.", Opcode: 0x7c000239, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "extsb", Opcode: 0x7c000774, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "extsb.", Opcode: 0x7c000775, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "extsh", Opcode: 0x7c000734, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "extsh.", Opcode: 0x7c000735, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "extsw", Opcode: 0x7c0007b4, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "extsw.", Opcode: 0x7c0007b5, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "extswsli", Opcode: 0x7c0006f4, Mask: 0xfc0007fd, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "sh", Bits: []powerpc.InsnBits{{16, 5}, {30, 1}}}}},
{Name: "extswsli.", Opcode: 0x7c0006f5, Mask: 0xfc0007fd, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "sh", Bits: []powerpc.InsnBits{{16, 5}, {30, 1}}}}},
{Name: "fabs", Opcode: 0xfc000210, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fabs.", Opcode: 0xfc000211, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fadd", Opcode: 0xfc00002a, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fadd.", Opcode: 0xfc00002b, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fadds", Opcode: 0xec00002a, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fadds.", Opcode: 0xec00002b, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fcfid", Opcode: 0xfc00069c, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fcfid.", Opcode: 0xfc00069d, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fcfids", Opcode: 0xec00069c, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fcfids.", Opcode: 0xec00069d, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fcfidu", Opcode: 0xfc00079c, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fcfidu.", Opcode: 0xfc00079d, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fcfidus", Opcode: 0xec00079c, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fcfidus.", Opcode: 0xec00079d, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fcmpo", Opcode: 0xfc000040, Mask: 0xfc6007ff, Fields: []powerpc.InsnField{{Name: "BF", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "fcmpu", Opcode: 0xfc000000, Mask: 0xfc6007ff, Fields: []powerpc.InsnField{{Name: "BF", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "fcpsgn", Opcode: 0xfc000010, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fcpsgn.", Opcode: 0xfc000011, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fctid", Opcode: 0xfc00065c, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fctid.", Opcode: 0xfc00065d, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fctidu", Opcode: 0xfc00075c, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fctidu.", Opcode: 0xfc00075d, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fctiduz", Opcode: 0xfc00075e, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fctiduz.", Opcode: 0xfc00075f, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fctidz", Opcode: 0xfc00065e, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fctidz.", Opcode: 0xfc00065f, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fctiw", Opcode: 0xfc00001c, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fctiw.", Opcode: 0xfc00001d, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fctiwu", Opcode: 0xfc00011c, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fctiwu.", Opcode: 0xfc00011d, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fctiwuz", Opcode: 0xfc00011e, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fctiwuz.", Opcode: 0xfc00011f, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fctiwz", Opcode: 0xfc00001e, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fctiwz.", Opcode: 0xfc00001f, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fdiv", Opcode: 0xfc000024, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fdiv.", Opcode: 0xfc000025, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fdivs", Opcode: 0xec000024, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fdivs.", Opcode: 0xec000025, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fmadd", Opcode: 0xfc00003a, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fmadd.", Opcode: 0xfc00003b, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fmadds", Opcode: 0xec00003a, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fmadds.", Opcode: 0xec00003b, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fmr", Opcode: 0xfc000090, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fmr.", Opcode: 0xfc000091, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fmrgew", Opcode: 0xfc00078c, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fmrgow", Opcode: 0xfc00068c, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fmsub", Opcode: 0xfc000038, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fmsub.", Opcode: 0xfc000039, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fmsubs", Opcode: 0xec000038, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fmsubs.", Opcode: 0xec000039, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fmul", Opcode: 0xfc000032, Mask: 0xfc00f83f, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fmul.", Opcode: 0xfc000033, Mask: 0xfc00f83f, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fmuls", Opcode: 0xec000032, Mask: 0xfc00f83f, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fmuls.", Opcode: 0xec000033, Mask: 0xfc00f83f, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fnabs", Opcode: 0xfc000110, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fnabs.", Opcode: 0xfc000111, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fneg", Opcode: 0xfc000050, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fneg.", Opcode: 0xfc000051, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fnmadd", Opcode: 0xfc00003e, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fnmadd.", Opcode: 0xfc00003f, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fnmadds", Opcode: 0xec00003e, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fnmadds.", Opcode: 0xec00003f, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fnmsub", Opcode: 0xfc00003c, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fnmsub.", Opcode: 0xfc00003d, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fnmsubs", Opcode: 0xec00003c, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fnmsubs.", Opcode: 0xec00003d, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fre", Opcode: 0xfc000030, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fre.", Opcode: 0xfc000031, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fres", Opcode: 0xec000030, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fres.", Opcode: 0xec000031, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "frim", Opcode: 0xfc0003d0, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "frim.", Opcode: 0xfc0003d1, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "frin", Opcode: 0xfc000310, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "frin.", Opcode: 0xfc000311, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "frip", Opcode: 0xfc000390, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "frip.", Opcode: 0xfc000391, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "friz", Opcode: 0xfc000350, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "friz.", Opcode: 0xfc000351, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "frsp", Opcode: 0xfc000018, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "frsp.", Opcode: 0xfc000019, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "frsqrte", Opcode: 0xfc000034, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "frsqrte.", Opcode: 0xfc000035, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "frsqrtes", Opcode: 0xec000034, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "frsqrtes.", Opcode: 0xec000035, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fsel", Opcode: 0xfc00002e, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fsel.", Opcode: 0xfc00002f, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fsqrt", Opcode: 0xfc00002c, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fsqrt.", Opcode: 0xfc00002d, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fsqrts", Opcode: 0xec00002c, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fsqrts.", Opcode: 0xec00002d, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fsub", Opcode: 0xfc000028, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fsub.", Opcode: 0xfc000029, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fsubs", Opcode: 0xec000028, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "fsubs.", Opcode: 0xec000029, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "ftdiv", Opcode: 0xfc000100, Mask: 0xfc6007ff, Fields: []powerpc.InsnField{{Name: "BF", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "FRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "ftsqrt", Opcode: 0xfc000140, Mask: 0xfc7f07ff, Fields: []powerpc.InsnField{{Name: "BF", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "hashchk", Opcode: 0x7c0005e4, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "D", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "DX", Bits: []powerpc.InsnBits{{31, 1}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "hashchkp", Opcode: 0x7c000564, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "D", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "DX", Bits: []powerpc.InsnBits{{31, 1}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}}, Priv: true},
{Name: "hashst", Opcode: 0x7c0005a4, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "D", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "DX", Bits: []powerpc.InsnBits{{31, 1}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "hashstp", Opcode: 0x7c000524, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "D", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "DX", Bits: []powerpc.InsnBits{{31, 1}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}}, Priv: true},
{Name: "hrfid", Opcode: 0x4c000224, Mask: 0xffffffff, Fields: []powerpc.InsnField{}, Priv: true},
{Name: "icbi", Opcode: 0x7c0007ac, Mask: 0xffe007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "icbt", Opcode: 0x7c00002c, Mask: 0xfe0007ff, Fields: []powerpc.InsnField{{Name: "CT", Bits: []powerpc.InsnBits{{7, 4}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "isel", Opcode: 0x7c00001e, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "BC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "isync", Opcode: 0x4c00012c, Mask: 0xffffffff, Fields: []powerpc.InsnField{}},
{Name: "lbarx", Opcode: 0x7c000068, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "EH", Bits: []powerpc.InsnBits{{31, 1}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "lbz", Opcode: 0x88000000, Mask: 0xfc000000, Fields: []powerpc.InsnField{{Name: "D", Bits: []powerpc.InsnBits{{16, 16}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "lbzcix", Opcode: 0x7c0006aa, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}, Priv: true},
{Name: "lbzu", Opcode: 0x8c000000, Mask: 0xfc000000, Fields: []powerpc.InsnField{{Name: "D", Bits: []powerpc.InsnBits{{16, 16}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "lbzux", Opcode: 0x7c0000ee, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "lbzx", Opcode: 0x7c0000ae, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "ld", Opcode: 0xe8000000, Mask: 0xfc000003, Fields: []powerpc.InsnField{{Name: "DS", Bits: []powerpc.InsnBits{{16, 14}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "ldarx", Opcode: 0x7c0000a8, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "EH", Bits: []powerpc.InsnBits{{31, 1}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "ldat", Opcode: 0x7c0004cc, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FC", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "ldbrx", Opcode: 0x7c000428, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "ldcix", Opcode: 0x7c0006ea, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}, Priv: true},
{Name: "ldu", Opcode: 0xe8000001, Mask: 0xfc000003, Fields: []powerpc.InsnField{{Name: "DS", Bits: []powerpc.InsnBits{{16, 14}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "ldux", Opcode: 0x7c00006a, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "ldx", Opcode: 0x7c00002a, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "lfd", Opcode: 0xc8000000, Mask: 0xfc000000, Fields: []powerpc.InsnField{{Name: "D", Bits: []powerpc.InsnBits{{16, 16}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}}},
{Name: "lfdp", Opcode: 0xe4000000, Mask: 0xfc000003, Fields: []powerpc.InsnField{{Name: "DS", Bits: []powerpc.InsnBits{{16, 14}}}, {Name: "FRTp", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}}},
{Name: "lfdpx", Opcode: 0x7c00062e, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FRTp", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "lfdu", Opcode: 0xcc000000, Mask: 0xfc000000, Fields: []powerpc.InsnField{{Name: "D", Bits: []powerpc.InsnBits{{16, 16}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}}},
{Name: "lfdux", Opcode: 0x7c0004ee, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "lfdx", Opcode: 0x7c0004ae, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "lfiwax", Opcode: 0x7c0006ae, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "lfiwzx", Opcode: 0x7c0006ee, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "lfs", Opcode: 0xc0000000, Mask: 0xfc000000, Fields: []powerpc.InsnField{{Name: "D", Bits: []powerpc.InsnBits{{16, 16}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}}},
{Name: "lfsu", Opcode: 0xc4000000, Mask: 0xfc000000, Fields: []powerpc.InsnField{{Name: "D", Bits: []powerpc.InsnBits{{16, 16}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}}},
{Name: "lfsux", Opcode: 0x7c00046e, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "lfsx", Opcode: 0x7c00042e, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "lha", Opcode: 0xa8000000, Mask: 0xfc000000, Fields: []powerpc.InsnField{{Name: "D", Bits: []powerpc.InsnBits{{16, 16}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "lharx", Opcode: 0x7c0000e8, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "EH", Bits: []powerpc.InsnBits{{31, 1}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "lhau", Opcode: 0xac000000, Mask: 0xfc000000, Fields: []powerpc.InsnField{{Name: "D", Bits: []powerpc.InsnBits{{16, 16}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "lhaux", Opcode: 0x7c0002ee, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "lhax", Opcode: 0x7c0002ae, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "lhbrx", Opcode: 0x7c00062c, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "lhz", Opcode: 0xa0000000, Mask: 0xfc000000, Fields: []powerpc.InsnField{{Name: "D", Bits: []powerpc.InsnBits{{16, 16}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "lhzcix", Opcode: 0x7c00066a, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}, Priv: true},
{Name: "lhzu", Opcode: 0xa4000000, Mask: 0xfc000000, Fields: []powerpc.InsnField{{Name: "D", Bits: []powerpc.InsnBits{{16, 16}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "lhzux", Opcode: 0x7c00026e, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "lhzx", Opcode: 0x7c00022e, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "lmw", Opcode: 0xb8000000, Mask: 0xfc000000, Fields: []powerpc.InsnField{{Name: "D", Bits: []powerpc.InsnBits{{16, 16}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "lq", Opcode: 0xe0000000, Mask: 0xfc00000f, Fields: []powerpc.InsnField{{Name: "DQ", Bits: []powerpc.InsnBits{{16, 12}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RTp", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "lqarx", Opcode: 0x7c000228, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "EH", Bits: []powerpc.InsnBits{{31, 1}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RTp", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "lswi", Opcode: 0x7c0004aa, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "NB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "lswx", Opcode: 0x7c00042a, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "lvebx", Opcode: 0x7c00000e, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "lvehx", Opcode: 0x7c00004e, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "lvewx", Opcode: 0x7c00008e, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "lvsl", Opcode: 0x7c00000c, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "lvsr", Opcode: 0x7c00004c, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "lvx", Opcode: 0x7c0000ce, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "lvxl", Opcode: 0x7c0002ce, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "lwa", Opcode: 0xe8000002, Mask: 0xfc000003, Fields: []powerpc.InsnField{{Name: "DS", Bits: []powerpc.InsnBits{{16, 14}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "lwarx", Opcode: 0x7c000028, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "EH", Bits: []powerpc.InsnBits{{31, 1}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "lwat", Opcode: 0x7c00048c, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FC", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "lwaux", Opcode: 0x7c0002ea, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "lwax", Opcode: 0x7c0002aa, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "lwbrx", Opcode: 0x7c00042c, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "lwz", Opcode: 0x80000000, Mask: 0xfc000000, Fields: []powerpc.InsnField{{Name: "D", Bits: []powerpc.InsnBits{{16, 16}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "lwzcix", Opcode: 0x7c00062a, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}, Priv: true},
{Name: "lwzu", Opcode: 0x84000000, Mask: 0xfc000000, Fields: []powerpc.InsnField{{Name: "D", Bits: []powerpc.InsnBits{{16, 16}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "lwzux", Opcode: 0x7c00006e, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "lwzx", Opcode: 0x7c00002e, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "lxsd", Opcode: 0xe4000002, Mask: 0xfc000003, Fields: []powerpc.InsnField{{Name: "DS", Bits: []powerpc.InsnBits{{16, 14}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "lxsdx", Opcode: 0x7c000498, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "lxsibzx", Opcode: 0x7c00061a, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "lxsihzx", Opcode: 0x7c00065a, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "lxsiwax", Opcode: 0x7c000098, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "lxsiwzx", Opcode: 0x7c000018, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "lxssp", Opcode: 0xe4000003, Mask: 0xfc000003, Fields: []powerpc.InsnField{{Name: "DS", Bits: []powerpc.InsnBits{{16, 14}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "lxsspx", Opcode: 0x7c000418, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "lxv", Opcode: 0xf4000001, Mask: 0xfc000007, Fields: []powerpc.InsnField{{Name: "DQ", Bits: []powerpc.InsnBits{{16, 12}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{28, 1}}}}},
{Name: "lxvb16x", Opcode: 0x7c0006d8, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "lxvd2x", Opcode: 0x7c000698, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "lxvdsx", Opcode: 0x7c000298, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "lxvh8x", Opcode: 0x7c000658, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "lxvkq", Opcode: 0xf01f02d0, Mask: 0xfc1f07fe, Fields: []powerpc.InsnField{{Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}, {Name: "UIM", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "lxvl", Opcode: 0x7c00021a, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "lxvll", Opcode: 0x7c00025a, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "lxvp", Opcode: 0x18000000, Mask: 0xfc00000f, Fields: []powerpc.InsnField{{Name: "DQ", Bits: []powerpc.InsnBits{{16, 12}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{10, 1}}}, {Name: "Tp", Bits: []powerpc.InsnBits{{6, 4}}}}},
{Name: "lxvpx", Opcode: 0x7c00029a, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{10, 1}}}, {Name: "Tp", Bits: []powerpc.InsnBits{{6, 4}}}}},
{Name: "lxvrbx", Opcode: 0x7c00001a, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "lxvrdx", Opcode: 0x7c0000da, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "lxvrhx", Opcode: 0x7c00005a, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "lxvrwx", Opcode: 0x7c00009a, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "lxvw4x", Opcode: 0x7c000618, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "lxvwsx", Opcode: 0x7c0002d8, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "lxvx", Opcode: 0x7c000218, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "maddhd", Opcode: 0x10000030, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "maddhdu", Opcode: 0x10000031, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "maddld", Opcode: 0x10000033, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "mcrf", Opcode: 0x4c000000, Mask: 0xfc63ffff, Fields: []powerpc.InsnField{{Name: "BF", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "BFA", Bits: []powerpc.InsnBits{{11, 3}}}}},
{Name: "mcrfs", Opcode: 0xfc000080, Mask: 0xfc63ffff, Fields: []powerpc.InsnField{{Name: "BF", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "BFA", Bits: []powerpc.InsnBits{{11, 3}}}}},
{Name: "mcrxrx", Opcode: 0x7c000480, Mask: 0xfc7fffff, Fields: []powerpc.InsnField{{Name: "BF", Bits: []powerpc.InsnBits{{6, 3}}}}},
{Name: "mfbhrbe", Opcode: 0x7c00025c, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "BHRBE", Bits: []powerpc.InsnBits{{11, 10}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "mfcr", Opcode: 0x7c000026, Mask: 0xfc1fffff, Fields: []powerpc.InsnField{{Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "mffs", Opcode: 0xfc00048e, Mask: 0xfc1fffff, Fields: []powerpc.InsnField{{Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "mffs.", Opcode: 0xfc00048f, Mask: 0xfc1fffff, Fields: []powerpc.InsnField{{Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "mffscdrn", Opcode: 0xfc14048e, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "mffscdrni", Opcode: 0xfc15048e, Mask: 0xfc1fc7ff, Fields: []powerpc.InsnField{{Name: "DRM", Bits: []powerpc.InsnBits{{18, 3}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "mffsce", Opcode: 0xfc01048e, Mask: 0xfc1fffff, Fields: []powerpc.InsnField{{Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "mffscrn", Opcode: 0xfc16048e, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "mffscrni", Opcode: 0xfc17048e, Mask: 0xfc1fe7ff, Fields: []powerpc.InsnField{{Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "RM", Bits: []powerpc.InsnBits{{19, 2}}}}},
{Name: "mffsl", Opcode: 0xfc18048e, Mask: 0xfc1fffff, Fields: []powerpc.InsnField{{Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "mfmsr", Opcode: 0x7c0000a6, Mask: 0xfc1fffff, Fields: []powerpc.InsnField{{Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}, Priv: true},
{Name: "mfocrf", Opcode: 0x7c100026, Mask: 0xfc100fff, Fields: []powerpc.InsnField{{Name: "FXM", Bits: []powerpc.InsnBits{{12, 8}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "mfspr", Opcode: 0x7c0002a6, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "spr", Bits: []powerpc.InsnBits{{16, 5}, {11, 5}}}}},
{Name: "mftb", Opcode: 0x7c0002e6, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "tbr", Bits: []powerpc.InsnBits{{11, 10}}}}},
{Name: "mfvscr", Opcode: 0x10000604, Mask: 0xfc1fffff, Fields: []powerpc.InsnField{{Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "mfvsrd", Opcode: 0x7c000066, Mask: 0xfc00fffe, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "S", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "SX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "mfvsrld", Opcode: 0x7c000266, Mask: 0xfc00fffe, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "S", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "SX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "mfvsrwz", Opcode: 0x7c0000e6, Mask: 0xfc00fffe, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "S", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "SX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "modsd", Opcode: 0x7c000612, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "modsw", Opcode: 0x7c000616, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "modud", Opcode: 0x7c000212, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "moduw", Opcode: 0x7c000216, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "msgclr", Opcode: 0x7c0001dc, Mask: 0xffff07ff, Fields: []powerpc.InsnField{{Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}}, Priv: true},
{Name: "msgclrp", Opcode: 0x7c00015c, Mask: 0xffff07ff, Fields: []powerpc.InsnField{{Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}}, Priv: true},
{Name: "msgclru", Opcode: 0x7c0000dc, Mask: 0xffff07ff, Fields: []powerpc.InsnField{{Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}}, Priv: true},
{Name: "msgsnd", Opcode: 0x7c00019c, Mask: 0xffff07ff, Fields: []powerpc.InsnField{{Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}}, Priv: true},
{Name: "msgsndp", Opcode: 0x7c00011c, Mask: 0xffff07ff, Fields: []powerpc.InsnField{{Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}}, Priv: true},
{Name: "msgsndu", Opcode: 0x7c00009c, Mask: 0xffff07ff, Fields: []powerpc.InsnField{{Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}}, Priv: true},
{Name: "msgsync", Opcode: 0x7c0006ec, Mask: 0xffffffff, Fields: []powerpc.InsnField{}, Priv: true},
{Name: "mtcrf", Opcode: 0x7c000120, Mask: 0xfc100fff, Fields: []powerpc.InsnField{{Name: "FXM", Bits: []powerpc.InsnBits{{12, 8}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "mtfsb0", Opcode: 0xfc00008c, Mask: 0xfc1fffff, Fields: []powerpc.InsnField{{Name: "BT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "mtfsb0.", Opcode: 0xfc00008d, Mask: 0xfc1fffff, Fields: []powerpc.InsnField{{Name: "BT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "mtfsb1", Opcode: 0xfc00004c, Mask: 0xfc1fffff, Fields: []powerpc.InsnField{{Name: "BT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "mtfsb1.", Opcode: 0xfc00004d, Mask: 0xfc1fffff, Fields: []powerpc.InsnField{{Name: "BT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "mtfsf", Opcode: 0xfc00058e, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FLM", Bits: []powerpc.InsnBits{{7, 8}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "L", Bits: []powerpc.InsnBits{{6, 1}}}, {Name: "W", Bits: []powerpc.InsnBits{{15, 1}}}}},
{Name: "mtfsf.", Opcode: 0xfc00058f, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FLM", Bits: []powerpc.InsnBits{{7, 8}}}, {Name: "FRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "L", Bits: []powerpc.InsnBits{{6, 1}}}, {Name: "W", Bits: []powerpc.InsnBits{{15, 1}}}}},
{Name: "mtfsfi", Opcode: 0xfc00010c, Mask: 0xfc7e0fff, Fields: []powerpc.InsnField{{Name: "BF", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "U", Bits: []powerpc.InsnBits{{16, 4}}}, {Name: "W", Bits: []powerpc.InsnBits{{15, 1}}}}},
{Name: "mtfsfi.", Opcode: 0xfc00010d, Mask: 0xfc7e0fff, Fields: []powerpc.InsnField{{Name: "BF", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "U", Bits: []powerpc.InsnBits{{16, 4}}}, {Name: "W", Bits: []powerpc.InsnBits{{15, 1}}}}},
{Name: "mtmsr", Opcode: 0x7c000124, Mask: 0xfc1effff, Fields: []powerpc.InsnField{{Name: "L", Bits: []powerpc.InsnBits{{15, 1}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}, Priv: true},
{Name: "mtmsrd", Opcode: 0x7c000164, Mask: 0xfc1effff, Fields: []powerpc.InsnField{{Name: "L", Bits: []powerpc.InsnBits{{15, 1}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}, Priv: true},
{Name: "mtocrf", Opcode: 0x7c100120, Mask: 0xfc100fff, Fields: []powerpc.InsnField{{Name: "FXM", Bits: []powerpc.InsnBits{{12, 8}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "mtspr", Opcode: 0x7c0003a6, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "spr", Bits: []powerpc.InsnBits{{16, 5}, {11, 5}}}}},
{Name: "mtvscr", Opcode: 0x10000644, Mask: 0xffff07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "mtvsrbm", Opcode: 0x10100642, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "mtvsrbmi", Opcode: 0x10000014, Mask: 0xfc00003e, Fields: []powerpc.InsnField{{Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "b0", Bits: []powerpc.InsnBits{{16, 10}}}, {Name: "b1", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "b2", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "mtvsrd", Opcode: 0x7c000166, Mask: 0xfc00fffe, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "mtvsrdd", Opcode: 0x7c000366, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "mtvsrdm", Opcode: 0x10130642, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "mtvsrhm", Opcode: 0x10110642, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "mtvsrqm", Opcode: 0x10140642, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "mtvsrwa", Opcode: 0x7c0001a6, Mask: 0xfc00fffe, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "mtvsrwm", Opcode: 0x10120642, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "mtvsrws", Opcode: 0x7c000326, Mask: 0xfc00fffe, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "mtvsrwz", Opcode: 0x7c0001e6, Mask: 0xfc00fffe, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "mulhd", Opcode: 0x7c000092, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "mulhd.", Opcode: 0x7c000093, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "mulhdu", Opcode: 0x7c000012, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "mulhdu.", Opcode: 0x7c000013, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "mulhw", Opcode: 0x7c000096, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "mulhw.", Opcode: 0x7c000097, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "mulhwu", Opcode: 0x7c000016, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "mulhwu.", Opcode: 0x7c000017, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "mulld", Opcode: 0x7c0001d2, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "mulld.", Opcode: 0x7c0001d3, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "mulldo", Opcode: 0x7c0005d2, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "mulldo.", Opcode: 0x7c0005d3, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "mulli", Opcode: 0x1c000000, Mask: 0xfc000000, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "SI", Bits: []powerpc.InsnBits{{16, 16}}}}},
{Name: "mullw", Opcode: 0x7c0001d6, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "mullw.", Opcode: 0x7c0001d7, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "mullwo", Opcode: 0x7c0005d6, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "mullwo.", Opcode: 0x7c0005d7, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "nand", Opcode: 0x7c0003b8, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "nand.", Opcode: 0x7c0003b9, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "neg", Opcode: 0x7c0000d0, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "neg.", Opcode: 0x7c0000d1, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "nego", Opcode: 0x7c0004d0, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "nego.", Opcode: 0x7c0004d1, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "nor", Opcode: 0x7c0000f8, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "nor.", Opcode: 0x7c0000f9, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "or", Opcode: 0x7c000378, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "or.", Opcode: 0x7c000379, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "orc", Opcode: 0x7c000338, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "orc.", Opcode: 0x7c000339, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "ori", Opcode: 0x60000000, Mask: 0xfc000000, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "UI", Bits: []powerpc.InsnBits{{16, 16}}}}},
{Name: "oris", Opcode: 0x64000000, Mask: 0xfc000000, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "UI", Bits: []powerpc.InsnBits{{16, 16}}}}},
{Name: "paddi", Opcode: 0x06000000, Mask: 0xffec0000, Fields: []powerpc.InsnField{{Name: "R", Bits: []powerpc.InsnBits{{11, 1}}}, {Name: "si0", Bits: []powerpc.InsnBits{{14, 18}}}},
OpcodeSuffix: 0x38000000, MaskSuffix: 0xfc000000, FieldsSuffix: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "si1", Bits: []powerpc.InsnBits{{16, 16}}}}},
{Name: "paste.", Opcode: 0x7c00070d, Mask: 0xffc007ff, Fields: []powerpc.InsnField{{Name: "L", Bits: []powerpc.InsnBits{{10, 1}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "pdepd", Opcode: 0x7c000138, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "pextd", Opcode: 0x7c000178, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "plbz", Opcode: 0x06000000, Mask: 0xffec0000, Fields: []powerpc.InsnField{{Name: "R", Bits: []powerpc.InsnBits{{11, 1}}}, {Name: "d0", Bits: []powerpc.InsnBits{{14, 18}}}},
OpcodeSuffix: 0x88000000, MaskSuffix: 0xfc000000, FieldsSuffix: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "d1", Bits: []powerpc.InsnBits{{16, 16}}}}},
{Name: "pld", Opcode: 0x04000000, Mask: 0xffec0000, Fields: []powerpc.InsnField{{Name: "R", Bits: []powerpc.InsnBits{{11, 1}}}, {Name: "d0", Bits: []powerpc.InsnBits{{14, 18}}}},
OpcodeSuffix: 0xe4000000, MaskSuffix: 0xfc000000, FieldsSuffix: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "d1", Bits: []powerpc.InsnBits{{16, 16}}}}},
{Name: "plfd", Opcode: 0x06000000, Mask: 0xffec0000, Fields: []powerpc.InsnField{{Name: "R", Bits: []powerpc.InsnBits{{11, 1}}}, {Name: "d0", Bits: []powerpc.InsnBits{{14, 18}}}},
OpcodeSuffix: 0xc8000000, MaskSuffix: 0xfc000000, FieldsSuffix: []powerpc.InsnField{{Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "d1", Bits: []powerpc.InsnBits{{16, 16}}}}},
{Name: "plfs", Opcode: 0x06000000, Mask: 0xffec0000, Fields: []powerpc.InsnField{{Name: "R", Bits: []powerpc.InsnBits{{11, 1}}}, {Name: "d0", Bits: []powerpc.InsnBits{{14, 18}}}},
OpcodeSuffix: 0xc0000000, MaskSuffix: 0xfc000000, FieldsSuffix: []powerpc.InsnField{{Name: "FRT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "d1", Bits: []powerpc.InsnBits{{16, 16}}}}},
{Name: "plha", Opcode: 0x06000000, Mask: 0xffec0000, Fields: []powerpc.InsnField{{Name: "R", Bits: []powerpc.InsnBits{{11, 1}}}, {Name: "d0", Bits: []powerpc.InsnBits{{14, 18}}}},
OpcodeSuffix: 0xa8000000, MaskSuffix: 0xfc000000, FieldsSuffix: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "d1", Bits: []powerpc.InsnBits{{16, 16}}}}},
{Name: "plhz", Opcode: 0x06000000, Mask: 0xffec0000, Fields: []powerpc.InsnField{{Name: "R", Bits: []powerpc.InsnBits{{11, 1}}}, {Name: "d0", Bits: []powerpc.InsnBits{{14, 18}}}},
OpcodeSuffix: 0xa0000000, MaskSuffix: 0xfc000000, FieldsSuffix: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "d1", Bits: []powerpc.InsnBits{{16, 16}}}}},
{Name: "plq", Opcode: 0x04000000, Mask: 0xffec0000, Fields: []powerpc.InsnField{{Name: "R", Bits: []powerpc.InsnBits{{11, 1}}}, {Name: "d0", Bits: []powerpc.InsnBits{{14, 18}}}},
OpcodeSuffix: 0xe0000000, MaskSuffix: 0xfc000000, FieldsSuffix: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RTp", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "d1", Bits: []powerpc.InsnBits{{16, 16}}}}},
{Name: "plwa", Opcode: 0x04000000, Mask: 0xffec0000, Fields: []powerpc.InsnField{{Name: "R", Bits: []powerpc.InsnBits{{11, 1}}}, {Name: "d0", Bits: []powerpc.InsnBits{{14, 18}}}},
OpcodeSuffix: 0xa4000000, MaskSuffix: 0xfc000000, FieldsSuffix: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "d1", Bits: []powerpc.InsnBits{{16, 16}}}}},
{Name: "plwz", Opcode: 0x06000000, Mask: 0xffec0000, Fields: []powerpc.InsnField{{Name: "R", Bits: []powerpc.InsnBits{{11, 1}}}, {Name: "d0", Bits: []powerpc.InsnBits{{14, 18}}}},
OpcodeSuffix: 0x80000000, MaskSuffix: 0xfc000000, FieldsSuffix: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "d1", Bits: []powerpc.InsnBits{{16, 16}}}}},
{Name: "plxsd", Opcode: 0x04000000, Mask: 0xffec0000, Fields: []powerpc.InsnField{{Name: "R", Bits: []powerpc.InsnBits{{11, 1}}}, {Name: "d0", Bits: []powerpc.InsnBits{{14, 18}}}},
OpcodeSuffix: 0xa8000000, MaskSuffix: 0xfc000000, FieldsSuffix: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "d1", Bits: []powerpc.InsnBits{{16, 16}}}}},
{Name: "plxssp", Opcode: 0x04000000, Mask: 0xffec0000, Fields: []powerpc.InsnField{{Name: "R", Bits: []powerpc.InsnBits{{11, 1}}}, {Name: "d0", Bits: []powerpc.InsnBits{{14, 18}}}},
OpcodeSuffix: 0xac000000, MaskSuffix: 0xfc000000, FieldsSuffix: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "d1", Bits: []powerpc.InsnBits{{16, 16}}}}},
{Name: "plxv", Opcode: 0x04000000, Mask: 0xffec0000, Fields: []powerpc.InsnField{{Name: "R", Bits: []powerpc.InsnBits{{11, 1}}}, {Name: "d0", Bits: []powerpc.InsnBits{{14, 18}}}},
OpcodeSuffix: 0xc8000000, MaskSuffix: 0xf8000000, FieldsSuffix: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{5, 1}}}, {Name: "d1", Bits: []powerpc.InsnBits{{16, 16}}}}},
{Name: "plxvp", Opcode: 0x04000000, Mask: 0xffec0000, Fields: []powerpc.InsnField{{Name: "R", Bits: []powerpc.InsnBits{{11, 1}}}, {Name: "d0", Bits: []powerpc.InsnBits{{14, 18}}}},
OpcodeSuffix: 0xe8000000, MaskSuffix: 0xfc000000, FieldsSuffix: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{10, 1}}}, {Name: "Tp", Bits: []powerpc.InsnBits{{6, 4}}}, {Name: "d1", Bits: []powerpc.InsnBits{{16, 16}}}}},
{Name: "pmxvbf16ger2", Opcode: 0x07900000, Mask: 0xffff3f00, Fields: []powerpc.InsnField{{Name: "PMSK", Bits: []powerpc.InsnBits{{16, 2}}}, {Name: "XMSK", Bits: []powerpc.InsnBits{{24, 4}}}, {Name: "YMSK", Bits: []powerpc.InsnBits{{28, 4}}}},
OpcodeSuffix: 0xec000198, MaskSuffix: 0xfc6007f9, FieldsSuffix: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "pmxvbf16ger2nn", Opcode: 0x07900000, Mask: 0xffff3f00, Fields: []powerpc.InsnField{{Name: "PMSK", Bits: []powerpc.InsnBits{{16, 2}}}, {Name: "XMSK", Bits: []powerpc.InsnBits{{24, 4}}}, {Name: "YMSK", Bits: []powerpc.InsnBits{{28, 4}}}},
OpcodeSuffix: 0xec000790, MaskSuffix: 0xfc6007f9, FieldsSuffix: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "pmxvbf16ger2np", Opcode: 0x07900000, Mask: 0xffff3f00, Fields: []powerpc.InsnField{{Name: "PMSK", Bits: []powerpc.InsnBits{{16, 2}}}, {Name: "XMSK", Bits: []powerpc.InsnBits{{24, 4}}}, {Name: "YMSK", Bits: []powerpc.InsnBits{{28, 4}}}},
OpcodeSuffix: 0xec000390, MaskSuffix: 0xfc6007f9, FieldsSuffix: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "pmxvbf16ger2pn", Opcode: 0x07900000, Mask: 0xffff3f00, Fields: []powerpc.InsnField{{Name: "PMSK", Bits: []powerpc.InsnBits{{16, 2}}}, {Name: "XMSK", Bits: []powerpc.InsnBits{{24, 4}}}, {Name: "YMSK", Bits: []powerpc.InsnBits{{28, 4}}}},
OpcodeSuffix: 0xec000590, MaskSuffix: 0xfc6007f9, FieldsSuffix: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "pmxvbf16ger2pp", Opcode: 0x07900000, Mask: 0xffff3f00, Fields: []powerpc.InsnField{{Name: "PMSK", Bits: []powerpc.InsnBits{{16, 2}}}, {Name: "XMSK", Bits: []powerpc.InsnBits{{24, 4}}}, {Name: "YMSK", Bits: []powerpc.InsnBits{{28, 4}}}},
OpcodeSuffix: 0xec000190, MaskSuffix: 0xfc6007f9, FieldsSuffix: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "pmxvf16ger2", Opcode: 0x07900000, Mask: 0xffff3f00, Fields: []powerpc.InsnField{{Name: "PMSK", Bits: []powerpc.InsnBits{{16, 2}}}, {Name: "XMSK", Bits: []powerpc.InsnBits{{24, 4}}}, {Name: "YMSK", Bits: []powerpc.InsnBits{{28, 4}}}},
OpcodeSuffix: 0xec000098, MaskSuffix: 0xfc6007f9, FieldsSuffix: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "pmxvf16ger2nn", Opcode: 0x07900000, Mask: 0xffff3f00, Fields: []powerpc.InsnField{{Name: "PMSK", Bits: []powerpc.InsnBits{{16, 2}}}, {Name: "XMSK", Bits: []powerpc.InsnBits{{24, 4}}}, {Name: "YMSK", Bits: []powerpc.InsnBits{{28, 4}}}},
OpcodeSuffix: 0xec000690, MaskSuffix: 0xfc6007f9, FieldsSuffix: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "pmxvf16ger2np", Opcode: 0x07900000, Mask: 0xffff3f00, Fields: []powerpc.InsnField{{Name: "PMSK", Bits: []powerpc.InsnBits{{16, 2}}}, {Name: "XMSK", Bits: []powerpc.InsnBits{{24, 4}}}, {Name: "YMSK", Bits: []powerpc.InsnBits{{28, 4}}}},
OpcodeSuffix: 0xec000290, MaskSuffix: 0xfc6007f9, FieldsSuffix: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "pmxvf16ger2pn", Opcode: 0x07900000, Mask: 0xffff3f00, Fields: []powerpc.InsnField{{Name: "PMSK", Bits: []powerpc.InsnBits{{16, 2}}}, {Name: "XMSK", Bits: []powerpc.InsnBits{{24, 4}}}, {Name: "YMSK", Bits: []powerpc.InsnBits{{28, 4}}}},
OpcodeSuffix: 0xec000490, MaskSuffix: 0xfc6007f9, FieldsSuffix: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "pmxvf16ger2pp", Opcode: 0x07900000, Mask: 0xffff3f00, Fields: []powerpc.InsnField{{Name: "PMSK", Bits: []powerpc.InsnBits{{16, 2}}}, {Name: "XMSK", Bits: []powerpc.InsnBits{{24, 4}}}, {Name: "YMSK", Bits: []powerpc.InsnBits{{28, 4}}}},
OpcodeSuffix: 0xec000090, MaskSuffix: 0xfc6007f9, FieldsSuffix: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "pmxvf32ger", Opcode: 0x07900000, Mask: 0xffffff00, Fields: []powerpc.InsnField{{Name: "XMSK", Bits: []powerpc.InsnBits{{24, 4}}}, {Name: "YMSK", Bits: []powerpc.InsnBits{{28, 4}}}},
OpcodeSuffix: 0xec0000d8, MaskSuffix: 0xfc6007f9, FieldsSuffix: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "pmxvf32gernn", Opcode: 0x07900000, Mask: 0xffffff00, Fields: []powerpc.InsnField{{Name: "XMSK", Bits: []powerpc.InsnBits{{24, 4}}}, {Name: "YMSK", Bits: []powerpc.InsnBits{{28, 4}}}},
OpcodeSuffix: 0xec0006d0, MaskSuffix: 0xfc6007f9, FieldsSuffix: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "pmxvf32gernp", Opcode: 0x07900000, Mask: 0xffffff00, Fields: []powerpc.InsnField{{Name: "XMSK", Bits: []powerpc.InsnBits{{24, 4}}}, {Name: "YMSK", Bits: []powerpc.InsnBits{{28, 4}}}},
OpcodeSuffix: 0xec0002d0, MaskSuffix: 0xfc6007f9, FieldsSuffix: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "pmxvf32gerpn", Opcode: 0x07900000, Mask: 0xffffff00, Fields: []powerpc.InsnField{{Name: "XMSK", Bits: []powerpc.InsnBits{{24, 4}}}, {Name: "YMSK", Bits: []powerpc.InsnBits{{28, 4}}}},
OpcodeSuffix: 0xec0004d0, MaskSuffix: 0xfc6007f9, FieldsSuffix: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "pmxvf32gerpp", Opcode: 0x07900000, Mask: 0xffffff00, Fields: []powerpc.InsnField{{Name: "XMSK", Bits: []powerpc.InsnBits{{24, 4}}}, {Name: "YMSK", Bits: []powerpc.InsnBits{{28, 4}}}},
OpcodeSuffix: 0xec0000d0, MaskSuffix: 0xfc6007f9, FieldsSuffix: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "pmxvf64ger", Opcode: 0x07900000, Mask: 0xffffff00, Fields: []powerpc.InsnField{{Name: "XMSK", Bits: []powerpc.InsnBits{{24, 4}}}, {Name: "YMSK", Bits: []powerpc.InsnBits{{28, 2}}}},
OpcodeSuffix: 0xec0001d8, MaskSuffix: 0xfc6007f9, FieldsSuffix: []powerpc.InsnField{{Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "Ap", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "pmxvf64gernn", Opcode: 0x07900000, Mask: 0xffffff00, Fields: []powerpc.InsnField{{Name: "XMSK", Bits: []powerpc.InsnBits{{24, 4}}}, {Name: "YMSK", Bits: []powerpc.InsnBits{{28, 2}}}},
OpcodeSuffix: 0xec0007d0, MaskSuffix: 0xfc6007f9, FieldsSuffix: []powerpc.InsnField{{Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "Ap", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "pmxvf64gernp", Opcode: 0x07900000, Mask: 0xffffff00, Fields: []powerpc.InsnField{{Name: "XMSK", Bits: []powerpc.InsnBits{{24, 4}}}, {Name: "YMSK", Bits: []powerpc.InsnBits{{28, 2}}}},
OpcodeSuffix: 0xec0003d0, MaskSuffix: 0xfc6007f9, FieldsSuffix: []powerpc.InsnField{{Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "Ap", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "pmxvf64gerpn", Opcode: 0x07900000, Mask: 0xffffff00, Fields: []powerpc.InsnField{{Name: "XMSK", Bits: []powerpc.InsnBits{{24, 4}}}, {Name: "YMSK", Bits: []powerpc.InsnBits{{28, 2}}}},
OpcodeSuffix: 0xec0005d0, MaskSuffix: 0xfc6007f9, FieldsSuffix: []powerpc.InsnField{{Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "Ap", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "pmxvf64gerpp", Opcode: 0x07900000, Mask: 0xffffff00, Fields: []powerpc.InsnField{{Name: "XMSK", Bits: []powerpc.InsnBits{{24, 4}}}, {Name: "YMSK", Bits: []powerpc.InsnBits{{28, 2}}}},
OpcodeSuffix: 0xec0001d0, MaskSuffix: 0xfc6007f9, FieldsSuffix: []powerpc.InsnField{{Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "Ap", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "pmxvi16ger2", Opcode: 0x07900000, Mask: 0xffff3f00, Fields: []powerpc.InsnField{{Name: "PMSK", Bits: []powerpc.InsnBits{{16, 2}}}, {Name: "XMSK", Bits: []powerpc.InsnBits{{24, 4}}}, {Name: "YMSK", Bits: []powerpc.InsnBits{{28, 4}}}},
OpcodeSuffix: 0xec000258, MaskSuffix: 0xfc6007f9, FieldsSuffix: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "pmxvi16ger2pp", Opcode: 0x07900000, Mask: 0xffff3f00, Fields: []powerpc.InsnField{{Name: "PMSK", Bits: []powerpc.InsnBits{{16, 2}}}, {Name: "XMSK", Bits: []powerpc.InsnBits{{24, 4}}}, {Name: "YMSK", Bits: []powerpc.InsnBits{{28, 4}}}},
OpcodeSuffix: 0xec000358, MaskSuffix: 0xfc6007f9, FieldsSuffix: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "pmxvi16ger2s", Opcode: 0x07900000, Mask: 0xffff3f00, Fields: []powerpc.InsnField{{Name: "PMSK", Bits: []powerpc.InsnBits{{16, 2}}}, {Name: "XMSK", Bits: []powerpc.InsnBits{{24, 4}}}, {Name: "YMSK", Bits: []powerpc.InsnBits{{28, 4}}}},
OpcodeSuffix: 0xec000158, MaskSuffix: 0xfc6007f9, FieldsSuffix: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "pmxvi16ger2spp", Opcode: 0x07900000, Mask: 0xffff3f00, Fields: []powerpc.InsnField{{Name: "PMSK", Bits: []powerpc.InsnBits{{16, 2}}}, {Name: "XMSK", Bits: []powerpc.InsnBits{{24, 4}}}, {Name: "YMSK", Bits: []powerpc.InsnBits{{28, 4}}}},
OpcodeSuffix: 0xec000150, MaskSuffix: 0xfc6007f9, FieldsSuffix: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "pmxvi4ger8", Opcode: 0x07900000, Mask: 0xffff0000, Fields: []powerpc.InsnField{{Name: "PMSK", Bits: []powerpc.InsnBits{{16, 8}}}, {Name: "XMSK", Bits: []powerpc.InsnBits{{24, 4}}}, {Name: "YMSK", Bits: []powerpc.InsnBits{{28, 4}}}},
OpcodeSuffix: 0xec000118, MaskSuffix: 0xfc6007f9, FieldsSuffix: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "pmxvi4ger8pp", Opcode: 0x07900000, Mask: 0xffff0000, Fields: []powerpc.InsnField{{Name: "PMSK", Bits: []powerpc.InsnBits{{16, 8}}}, {Name: "XMSK", Bits: []powerpc.InsnBits{{24, 4}}}, {Name: "YMSK", Bits: []powerpc.InsnBits{{28, 4}}}},
OpcodeSuffix: 0xec000110, MaskSuffix: 0xfc6007f9, FieldsSuffix: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "pmxvi8ger4", Opcode: 0x07900000, Mask: 0xffff0f00, Fields: []powerpc.InsnField{{Name: "PMSK", Bits: []powerpc.InsnBits{{16, 4}}}, {Name: "XMSK", Bits: []powerpc.InsnBits{{24, 4}}}, {Name: "YMSK", Bits: []powerpc.InsnBits{{28, 4}}}},
OpcodeSuffix: 0xec000018, MaskSuffix: 0xfc6007f9, FieldsSuffix: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "pmxvi8ger4pp", Opcode: 0x07900000, Mask: 0xffff0f00, Fields: []powerpc.InsnField{{Name: "PMSK", Bits: []powerpc.InsnBits{{16, 4}}}, {Name: "XMSK", Bits: []powerpc.InsnBits{{24, 4}}}, {Name: "YMSK", Bits: []powerpc.InsnBits{{28, 4}}}},
OpcodeSuffix: 0xec000010, MaskSuffix: 0xfc6007f9, FieldsSuffix: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "pmxvi8ger4spp", Opcode: 0x07900000, Mask: 0xffff0f00, Fields: []powerpc.InsnField{{Name: "PMSK", Bits: []powerpc.InsnBits{{16, 4}}}, {Name: "XMSK", Bits: []powerpc.InsnBits{{24, 4}}}, {Name: "YMSK", Bits: []powerpc.InsnBits{{28, 4}}}},
OpcodeSuffix: 0xec000318, MaskSuffix: 0xfc6007f9, FieldsSuffix: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "pnop", Opcode: 0x07000000, Mask: 0xffffffff, Fields: []powerpc.InsnField{},
OpcodeSuffix: 0x00000000, MaskSuffix: 0x00000000, FieldsSuffix: []powerpc.InsnField{}},
{Name: "popcntb", Opcode: 0x7c0000f4, Mask: 0xfc00fffe, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "Rc", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "popcntd", Opcode: 0x7c0003f4, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "popcntw", Opcode: 0x7c0002f4, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "prtyd", Opcode: 0x7c000174, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "prtyw", Opcode: 0x7c000134, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "pstb", Opcode: 0x06000000, Mask: 0xffec0000, Fields: []powerpc.InsnField{{Name: "R", Bits: []powerpc.InsnBits{{11, 1}}}, {Name: "d0", Bits: []powerpc.InsnBits{{14, 18}}}},
OpcodeSuffix: 0x98000000, MaskSuffix: 0xfc000000, FieldsSuffix: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "d1", Bits: []powerpc.InsnBits{{16, 16}}}}},
{Name: "pstd", Opcode: 0x04000000, Mask: 0xffec0000, Fields: []powerpc.InsnField{{Name: "R", Bits: []powerpc.InsnBits{{11, 1}}}, {Name: "d0", Bits: []powerpc.InsnBits{{14, 18}}}},
OpcodeSuffix: 0xf4000000, MaskSuffix: 0xfc000000, FieldsSuffix: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "d1", Bits: []powerpc.InsnBits{{16, 16}}}}},
{Name: "pstfd", Opcode: 0x06000000, Mask: 0xffec0000, Fields: []powerpc.InsnField{{Name: "R", Bits: []powerpc.InsnBits{{11, 1}}}, {Name: "d0", Bits: []powerpc.InsnBits{{14, 18}}}},
OpcodeSuffix: 0xd8000000, MaskSuffix: 0xfc000000, FieldsSuffix: []powerpc.InsnField{{Name: "FRS", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "d1", Bits: []powerpc.InsnBits{{16, 16}}}}},
{Name: "pstfs", Opcode: 0x06000000, Mask: 0xffec0000, Fields: []powerpc.InsnField{{Name: "R", Bits: []powerpc.InsnBits{{11, 1}}}, {Name: "d0", Bits: []powerpc.InsnBits{{14, 18}}}},
OpcodeSuffix: 0xd0000000, MaskSuffix: 0xfc000000, FieldsSuffix: []powerpc.InsnField{{Name: "FRS", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "d1", Bits: []powerpc.InsnBits{{16, 16}}}}},
{Name: "psth", Opcode: 0x06000000, Mask: 0xffec0000, Fields: []powerpc.InsnField{{Name: "R", Bits: []powerpc.InsnBits{{11, 1}}}, {Name: "d0", Bits: []powerpc.InsnBits{{14, 18}}}},
OpcodeSuffix: 0xb0000000, MaskSuffix: 0xfc000000, FieldsSuffix: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "d1", Bits: []powerpc.InsnBits{{16, 16}}}}},
{Name: "pstq", Opcode: 0x04000000, Mask: 0xffec0000, Fields: []powerpc.InsnField{{Name: "R", Bits: []powerpc.InsnBits{{11, 1}}}, {Name: "d0", Bits: []powerpc.InsnBits{{14, 18}}}},
OpcodeSuffix: 0xf0000000, MaskSuffix: 0xfc000000, FieldsSuffix: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RSp", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "d1", Bits: []powerpc.InsnBits{{16, 16}}}}},
{Name: "pstw", Opcode: 0x06000000, Mask: 0xffec0000, Fields: []powerpc.InsnField{{Name: "R", Bits: []powerpc.InsnBits{{11, 1}}}, {Name: "d0", Bits: []powerpc.InsnBits{{14, 18}}}},
OpcodeSuffix: 0x90000000, MaskSuffix: 0xfc000000, FieldsSuffix: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "d1", Bits: []powerpc.InsnBits{{16, 16}}}}},
{Name: "pstxsd", Opcode: 0x04000000, Mask: 0xffec0000, Fields: []powerpc.InsnField{{Name: "R", Bits: []powerpc.InsnBits{{11, 1}}}, {Name: "d0", Bits: []powerpc.InsnBits{{14, 18}}}},
OpcodeSuffix: 0xb8000000, MaskSuffix: 0xfc000000, FieldsSuffix: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRS", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "d1", Bits: []powerpc.InsnBits{{16, 16}}}}},
{Name: "pstxssp", Opcode: 0x04000000, Mask: 0xffec0000, Fields: []powerpc.InsnField{{Name: "R", Bits: []powerpc.InsnBits{{11, 1}}}, {Name: "d0", Bits: []powerpc.InsnBits{{14, 18}}}},
OpcodeSuffix: 0xbc000000, MaskSuffix: 0xfc000000, FieldsSuffix: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRS", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "d1", Bits: []powerpc.InsnBits{{16, 16}}}}},
{Name: "pstxv", Opcode: 0x04000000, Mask: 0xffec0000, Fields: []powerpc.InsnField{{Name: "R", Bits: []powerpc.InsnBits{{11, 1}}}, {Name: "d0", Bits: []powerpc.InsnBits{{14, 18}}}},
OpcodeSuffix: 0xd8000000, MaskSuffix: 0xf8000000, FieldsSuffix: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "S", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "SX", Bits: []powerpc.InsnBits{{5, 1}}}, {Name: "d1", Bits: []powerpc.InsnBits{{16, 16}}}}},
{Name: "pstxvp", Opcode: 0x04000000, Mask: 0xffec0000, Fields: []powerpc.InsnField{{Name: "R", Bits: []powerpc.InsnBits{{11, 1}}}, {Name: "d0", Bits: []powerpc.InsnBits{{14, 18}}}},
OpcodeSuffix: 0xf8000000, MaskSuffix: 0xfc000000, FieldsSuffix: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "SX", Bits: []powerpc.InsnBits{{10, 1}}}, {Name: "Sp", Bits: []powerpc.InsnBits{{6, 4}}}, {Name: "d1", Bits: []powerpc.InsnBits{{16, 16}}}}},
{Name: "rfebb", Opcode: 0x4c000124, Mask: 0xfffff7ff, Fields: []powerpc.InsnField{{Name: "S", Bits: []powerpc.InsnBits{{20, 1}}}}},
{Name: "rfid", Opcode: 0x4c000024, Mask: 0xffffffff, Fields: []powerpc.InsnField{}, Priv: true},
{Name: "rfscv", Opcode: 0x4c0000a4, Mask: 0xffffffff, Fields: []powerpc.InsnField{}, Priv: true},
{Name: "rldcl", Opcode: 0x78000010, Mask: 0xfc00001f, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "mb", Bits: []powerpc.InsnBits{{21, 5}, {26, 1}}}}},
{Name: "rldcl.", Opcode: 0x78000011, Mask: 0xfc00001f, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "mb", Bits: []powerpc.InsnBits{{21, 5}, {26, 1}}}}},
{Name: "rldcr", Opcode: 0x78000012, Mask: 0xfc00001f, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "me", Bits: []powerpc.InsnBits{{21, 5}, {26, 1}}}}},
{Name: "rldcr.", Opcode: 0x78000013, Mask: 0xfc00001f, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "me", Bits: []powerpc.InsnBits{{21, 5}, {26, 1}}}}},
{Name: "rldic", Opcode: 0x78000008, Mask: 0xfc00001d, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "mb", Bits: []powerpc.InsnBits{{21, 5}, {26, 1}}}, {Name: "sh", Bits: []powerpc.InsnBits{{16, 5}, {30, 1}}}}},
{Name: "rldic.", Opcode: 0x78000009, Mask: 0xfc00001d, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "mb", Bits: []powerpc.InsnBits{{21, 5}, {26, 1}}}, {Name: "sh", Bits: []powerpc.InsnBits{{16, 5}, {30, 1}}}}},
{Name: "rldicl", Opcode: 0x78000000, Mask: 0xfc00001d, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "mb", Bits: []powerpc.InsnBits{{21, 5}, {26, 1}}}, {Name: "sh", Bits: []powerpc.InsnBits{{16, 5}, {30, 1}}}}},
{Name: "rldicl.", Opcode: 0x78000001, Mask: 0xfc00001d, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "mb", Bits: []powerpc.InsnBits{{21, 5}, {26, 1}}}, {Name: "sh", Bits: []powerpc.InsnBits{{16, 5}, {30, 1}}}}},
{Name: "rldicr", Opcode: 0x78000004, Mask: 0xfc00001d, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "me", Bits: []powerpc.InsnBits{{21, 5}, {26, 1}}}, {Name: "sh", Bits: []powerpc.InsnBits{{16, 5}, {30, 1}}}}},
{Name: "rldicr.", Opcode: 0x78000005, Mask: 0xfc00001d, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "me", Bits: []powerpc.InsnBits{{21, 5}, {26, 1}}}, {Name: "sh", Bits: []powerpc.InsnBits{{16, 5}, {30, 1}}}}},
{Name: "rldimi", Opcode: 0x7800000c, Mask: 0xfc00001d, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "mb", Bits: []powerpc.InsnBits{{21, 5}, {26, 1}}}, {Name: "sh", Bits: []powerpc.InsnBits{{16, 5}, {30, 1}}}}},
{Name: "rldimi.", Opcode: 0x7800000d, Mask: 0xfc00001d, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "mb", Bits: []powerpc.InsnBits{{21, 5}, {26, 1}}}, {Name: "sh", Bits: []powerpc.InsnBits{{16, 5}, {30, 1}}}}},
{Name: "rlwimi", Opcode: 0x50000000, Mask: 0xfc000001, Fields: []powerpc.InsnField{{Name: "MB", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "ME", Bits: []powerpc.InsnBits{{26, 5}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "SH", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "rlwimi.", Opcode: 0x50000001, Mask: 0xfc000001, Fields: []powerpc.InsnField{{Name: "MB", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "ME", Bits: []powerpc.InsnBits{{26, 5}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "SH", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "rlwinm", Opcode: 0x54000000, Mask: 0xfc000001, Fields: []powerpc.InsnField{{Name: "MB", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "ME", Bits: []powerpc.InsnBits{{26, 5}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "SH", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "rlwinm.", Opcode: 0x54000001, Mask: 0xfc000001, Fields: []powerpc.InsnField{{Name: "MB", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "ME", Bits: []powerpc.InsnBits{{26, 5}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "SH", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "rlwnm", Opcode: 0x5c000000, Mask: 0xfc000001, Fields: []powerpc.InsnField{{Name: "MB", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "ME", Bits: []powerpc.InsnBits{{26, 5}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "rlwnm.", Opcode: 0x5c000001, Mask: 0xfc000001, Fields: []powerpc.InsnField{{Name: "MB", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "ME", Bits: []powerpc.InsnBits{{26, 5}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "sc", Opcode: 0x44000002, Mask: 0xfffff01f, Fields: []powerpc.InsnField{{Name: "LEV", Bits: []powerpc.InsnBits{{20, 7}}}}},
{Name: "scv", Opcode: 0x44000001, Mask: 0xfffff01f, Fields: []powerpc.InsnField{{Name: "LEV", Bits: []powerpc.InsnBits{{20, 7}}}}},
{Name: "setb", Opcode: 0x7c000100, Mask: 0xfc03ffff, Fields: []powerpc.InsnField{{Name: "BFA", Bits: []powerpc.InsnBits{{11, 3}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "setbc", Opcode: 0x7c000300, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "BI", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "setbcr", Opcode: 0x7c000340, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "BI", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "setnbc", Opcode: 0x7c000380, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "BI", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "setnbcr", Opcode: 0x7c0003c0, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "BI", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "slbfee.", Opcode: 0x7c0007a7, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}, Priv: true},
{Name: "slbia", Opcode: 0x7c0003e4, Mask: 0xff1fffff, Fields: []powerpc.InsnField{{Name: "IH", Bits: []powerpc.InsnBits{{8, 3}}}}, Priv: true},
{Name: "slbiag", Opcode: 0x7c0006a4, Mask: 0xfc1effff, Fields: []powerpc.InsnField{{Name: "L", Bits: []powerpc.InsnBits{{15, 1}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}, Priv: true},
{Name: "slbie", Opcode: 0x7c000364, Mask: 0xffff07ff, Fields: []powerpc.InsnField{{Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}}, Priv: true},
{Name: "slbieg", Opcode: 0x7c0003a4, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}, Priv: true},
{Name: "slbmfee", Opcode: 0x7c000726, Mask: 0xfc1e07ff, Fields: []powerpc.InsnField{{Name: "L", Bits: []powerpc.InsnBits{{15, 1}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}, Priv: true},
{Name: "slbmfev", Opcode: 0x7c0006a6, Mask: 0xfc1e07ff, Fields: []powerpc.InsnField{{Name: "L", Bits: []powerpc.InsnBits{{15, 1}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}, Priv: true},
{Name: "slbmte", Opcode: 0x7c000324, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}, Priv: true},
{Name: "slbsync", Opcode: 0x7c0002a4, Mask: 0xffffffff, Fields: []powerpc.InsnField{}, Priv: true},
{Name: "sld", Opcode: 0x7c000036, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "sld.", Opcode: 0x7c000037, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "slw", Opcode: 0x7c000030, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "slw.", Opcode: 0x7c000031, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "srad", Opcode: 0x7c000634, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "srad.", Opcode: 0x7c000635, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "sradi", Opcode: 0x7c000674, Mask: 0xfc0007fd, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "sh", Bits: []powerpc.InsnBits{{16, 5}, {30, 1}}}}},
{Name: "sradi.", Opcode: 0x7c000675, Mask: 0xfc0007fd, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "sh", Bits: []powerpc.InsnBits{{16, 5}, {30, 1}}}}},
{Name: "sraw", Opcode: 0x7c000630, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "sraw.", Opcode: 0x7c000631, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "srawi", Opcode: 0x7c000670, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "SH", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "srawi.", Opcode: 0x7c000671, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "SH", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "srd", Opcode: 0x7c000436, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "srd.", Opcode: 0x7c000437, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "srw", Opcode: 0x7c000430, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "srw.", Opcode: 0x7c000431, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "stb", Opcode: 0x98000000, Mask: 0xfc000000, Fields: []powerpc.InsnField{{Name: "D", Bits: []powerpc.InsnBits{{16, 16}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "stbcix", Opcode: 0x7c0007aa, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}, Priv: true},
{Name: "stbcx.", Opcode: 0x7c00056d, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "stbu", Opcode: 0x9c000000, Mask: 0xfc000000, Fields: []powerpc.InsnField{{Name: "D", Bits: []powerpc.InsnBits{{16, 16}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "stbux", Opcode: 0x7c0001ee, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "stbx", Opcode: 0x7c0001ae, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "std", Opcode: 0xf8000000, Mask: 0xfc000003, Fields: []powerpc.InsnField{{Name: "DS", Bits: []powerpc.InsnBits{{16, 14}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "stdat", Opcode: 0x7c0005cc, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FC", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "stdbrx", Opcode: 0x7c000528, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "stdcix", Opcode: 0x7c0007ea, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}, Priv: true},
{Name: "stdcx.", Opcode: 0x7c0001ad, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "stdu", Opcode: 0xf8000001, Mask: 0xfc000003, Fields: []powerpc.InsnField{{Name: "DS", Bits: []powerpc.InsnBits{{16, 14}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "stdux", Opcode: 0x7c00016a, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "stdx", Opcode: 0x7c00012a, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "stfd", Opcode: 0xd8000000, Mask: 0xfc000000, Fields: []powerpc.InsnField{{Name: "D", Bits: []powerpc.InsnBits{{16, 16}}}, {Name: "FRS", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}}},
{Name: "stfdp", Opcode: 0xf4000000, Mask: 0xfc000003, Fields: []powerpc.InsnField{{Name: "DS", Bits: []powerpc.InsnBits{{16, 14}}}, {Name: "FRSp", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}}},
{Name: "stfdpx", Opcode: 0x7c00072e, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FRSp", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "stfdu", Opcode: 0xdc000000, Mask: 0xfc000000, Fields: []powerpc.InsnField{{Name: "D", Bits: []powerpc.InsnBits{{16, 16}}}, {Name: "FRS", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}}},
{Name: "stfdux", Opcode: 0x7c0005ee, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FRS", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "stfdx", Opcode: 0x7c0005ae, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FRS", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "stfiwx", Opcode: 0x7c0007ae, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FRS", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "stfs", Opcode: 0xd0000000, Mask: 0xfc000000, Fields: []powerpc.InsnField{{Name: "D", Bits: []powerpc.InsnBits{{16, 16}}}, {Name: "FRS", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}}},
{Name: "stfsu", Opcode: 0xd4000000, Mask: 0xfc000000, Fields: []powerpc.InsnField{{Name: "D", Bits: []powerpc.InsnBits{{16, 16}}}, {Name: "FRS", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}}},
{Name: "stfsux", Opcode: 0x7c00056e, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FRS", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "stfsx", Opcode: 0x7c00052e, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FRS", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "sth", Opcode: 0xb0000000, Mask: 0xfc000000, Fields: []powerpc.InsnField{{Name: "D", Bits: []powerpc.InsnBits{{16, 16}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "sthbrx", Opcode: 0x7c00072c, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "sthcix", Opcode: 0x7c00076a, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}, Priv: true},
{Name: "sthcx.", Opcode: 0x7c0005ad, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "sthu", Opcode: 0xb4000000, Mask: 0xfc000000, Fields: []powerpc.InsnField{{Name: "D", Bits: []powerpc.InsnBits{{16, 16}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "sthux", Opcode: 0x7c00036e, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "sthx", Opcode: 0x7c00032e, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "stmw", Opcode: 0xbc000000, Mask: 0xfc000000, Fields: []powerpc.InsnField{{Name: "D", Bits: []powerpc.InsnBits{{16, 16}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "stop", Opcode: 0x4c0002e4, Mask: 0xffffffff, Fields: []powerpc.InsnField{}, Priv: true},
{Name: "stq", Opcode: 0xf8000002, Mask: 0xfc000003, Fields: []powerpc.InsnField{{Name: "DS", Bits: []powerpc.InsnBits{{16, 14}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RSp", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "stqcx.", Opcode: 0x7c00016d, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RSp", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "stswi", Opcode: 0x7c0005aa, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "NB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "stswx", Opcode: 0x7c00052a, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "stvebx", Opcode: 0x7c00010e, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "stvehx", Opcode: 0x7c00014e, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "stvewx", Opcode: 0x7c00018e, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "stvx", Opcode: 0x7c0001ce, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "stvxl", Opcode: 0x7c0003ce, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "stw", Opcode: 0x90000000, Mask: 0xfc000000, Fields: []powerpc.InsnField{{Name: "D", Bits: []powerpc.InsnBits{{16, 16}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "stwat", Opcode: 0x7c00058c, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "FC", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "stwbrx", Opcode: 0x7c00052c, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "stwcix", Opcode: 0x7c00072a, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}, Priv: true},
{Name: "stwcx.", Opcode: 0x7c00012d, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "stwu", Opcode: 0x94000000, Mask: 0xfc000000, Fields: []powerpc.InsnField{{Name: "D", Bits: []powerpc.InsnBits{{16, 16}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "stwux", Opcode: 0x7c00016e, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "stwx", Opcode: 0x7c00012e, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "stxsd", Opcode: 0xf4000002, Mask: 0xfc000003, Fields: []powerpc.InsnField{{Name: "DS", Bits: []powerpc.InsnBits{{16, 14}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "stxsdx", Opcode: 0x7c000598, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "S", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "SX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "stxsibx", Opcode: 0x7c00071a, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "S", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "SX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "stxsihx", Opcode: 0x7c00075a, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "S", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "SX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "stxsiwx", Opcode: 0x7c000118, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "S", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "SX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "stxssp", Opcode: 0xf4000003, Mask: 0xfc000003, Fields: []powerpc.InsnField{{Name: "DS", Bits: []powerpc.InsnBits{{16, 14}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "stxsspx", Opcode: 0x7c000518, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "S", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "SX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "stxv", Opcode: 0xf4000005, Mask: 0xfc000007, Fields: []powerpc.InsnField{{Name: "DQ", Bits: []powerpc.InsnBits{{16, 12}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "S", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "SX", Bits: []powerpc.InsnBits{{28, 1}}}}},
{Name: "stxvb16x", Opcode: 0x7c0007d8, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "S", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "SX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "stxvd2x", Opcode: 0x7c000798, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "S", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "SX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "stxvh8x", Opcode: 0x7c000758, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "S", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "SX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "stxvl", Opcode: 0x7c00031a, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "S", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "SX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "stxvll", Opcode: 0x7c00035a, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "S", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "SX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "stxvp", Opcode: 0x18000001, Mask: 0xfc00000f, Fields: []powerpc.InsnField{{Name: "DQ", Bits: []powerpc.InsnBits{{16, 12}}}, {Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "SX", Bits: []powerpc.InsnBits{{10, 1}}}, {Name: "Sp", Bits: []powerpc.InsnBits{{6, 4}}}}},
{Name: "stxvpx", Opcode: 0x7c00039a, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "SX", Bits: []powerpc.InsnBits{{10, 1}}}, {Name: "Sp", Bits: []powerpc.InsnBits{{6, 4}}}}},
{Name: "stxvrbx", Opcode: 0x7c00011a, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "S", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "SX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "stxvrdx", Opcode: 0x7c0001da, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "S", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "SX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "stxvrhx", Opcode: 0x7c00015a, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "S", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "SX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "stxvrwx", Opcode: 0x7c00019a, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "S", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "SX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "stxvw4x", Opcode: 0x7c000718, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "S", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "SX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "stxvx", Opcode: 0x7c000318, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "S", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "SX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "subf", Opcode: 0x7c000050, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "subf.", Opcode: 0x7c000051, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "subfc", Opcode: 0x7c000010, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "subfc.", Opcode: 0x7c000011, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "subfco", Opcode: 0x7c000410, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "subfco.", Opcode: 0x7c000411, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "subfe", Opcode: 0x7c000110, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "subfe.", Opcode: 0x7c000111, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "subfeo", Opcode: 0x7c000510, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "subfeo.", Opcode: 0x7c000511, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "subfic", Opcode: 0x20000000, Mask: 0xfc000000, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "SI", Bits: []powerpc.InsnBits{{16, 16}}}}},
{Name: "subfme", Opcode: 0x7c0001d0, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "subfme.", Opcode: 0x7c0001d1, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "subfmeo", Opcode: 0x7c0005d0, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "subfmeo.", Opcode: 0x7c0005d1, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "subfo", Opcode: 0x7c000450, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "subfo.", Opcode: 0x7c000451, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "subfze", Opcode: 0x7c000190, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "subfze.", Opcode: 0x7c000191, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "subfzeo", Opcode: 0x7c000590, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "subfzeo.", Opcode: 0x7c000591, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "sync", Opcode: 0x7c0004ac, Mask: 0xff1cffff, Fields: []powerpc.InsnField{{Name: "L", Bits: []powerpc.InsnBits{{8, 3}}}, {Name: "SC", Bits: []powerpc.InsnBits{{14, 2}}}}},
{Name: "td", Opcode: 0x7c000088, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "TO", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "tdi", Opcode: 0x08000000, Mask: 0xfc000000, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "SI", Bits: []powerpc.InsnBits{{16, 16}}}, {Name: "TO", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "tlbie", Opcode: 0x7c000264, Mask: 0xfc1007ff, Fields: []powerpc.InsnField{{Name: "PRS", Bits: []powerpc.InsnBits{{14, 1}}}, {Name: "R", Bits: []powerpc.InsnBits{{15, 1}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RIC", Bits: []powerpc.InsnBits{{12, 2}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}, Priv: true},
{Name: "tlbiel", Opcode: 0x7c000224, Mask: 0xfc1007ff, Fields: []powerpc.InsnField{{Name: "PRS", Bits: []powerpc.InsnBits{{14, 1}}}, {Name: "R", Bits: []powerpc.InsnBits{{15, 1}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RIC", Bits: []powerpc.InsnBits{{12, 2}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}, Priv: true},
{Name: "tlbsync", Opcode: 0x7c00046c, Mask: 0xffffffff, Fields: []powerpc.InsnField{}, Priv: true},
{Name: "tw", Opcode: 0x7c000008, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "TO", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "twi", Opcode: 0x0c000000, Mask: 0xfc000000, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "SI", Bits: []powerpc.InsnBits{{16, 16}}}, {Name: "TO", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "urfid", Opcode: 0x4c000264, Mask: 0xffffffff, Fields: []powerpc.InsnField{}, Priv: true},
{Name: "vabsdub", Opcode: 0x10000403, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vabsduh", Opcode: 0x10000443, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vabsduw", Opcode: 0x10000483, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vaddcuq", Opcode: 0x10000140, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vaddcuw", Opcode: 0x10000180, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vaddecuq", Opcode: 0x1000003d, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vaddeuqm", Opcode: 0x1000003c, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vaddfp", Opcode: 0x1000000a, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vaddsbs", Opcode: 0x10000300, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vaddshs", Opcode: 0x10000340, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vaddsws", Opcode: 0x10000380, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vaddubm", Opcode: 0x10000000, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vaddubs", Opcode: 0x10000200, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vaddudm", Opcode: 0x100000c0, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vadduhm", Opcode: 0x10000040, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vadduhs", Opcode: 0x10000240, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vadduqm", Opcode: 0x10000100, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vadduwm", Opcode: 0x10000080, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vadduws", Opcode: 0x10000280, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vand", Opcode: 0x10000404, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vandc", Opcode: 0x10000444, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vavgsb", Opcode: 0x10000502, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vavgsh", Opcode: 0x10000542, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vavgsw", Opcode: 0x10000582, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vavgub", Opcode: 0x10000402, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vavguh", Opcode: 0x10000442, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vavguw", Opcode: 0x10000482, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vbpermd", Opcode: 0x100005cc, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vbpermq", Opcode: 0x1000054c, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcfsx", Opcode: 0x1000034a, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "UIM", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcfuged", Opcode: 0x1000054d, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcfux", Opcode: 0x1000030a, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "UIM", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcipher", Opcode: 0x10000508, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcipherlast", Opcode: 0x10000509, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vclrlb", Opcode: 0x1000018d, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vclrrb", Opcode: 0x100001cd, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vclzb", Opcode: 0x10000702, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vclzd", Opcode: 0x100007c2, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vclzdm", Opcode: 0x10000784, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vclzh", Opcode: 0x10000742, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vclzlsbb", Opcode: 0x10000602, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "vclzw", Opcode: 0x10000782, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpbfp", Opcode: 0x100003c6, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpbfp.", Opcode: 0x100007c6, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpeqfp", Opcode: 0x100000c6, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpeqfp.", Opcode: 0x100004c6, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpequb", Opcode: 0x10000006, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpequb.", Opcode: 0x10000406, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpequd", Opcode: 0x100000c7, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpequd.", Opcode: 0x100004c7, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpequh", Opcode: 0x10000046, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpequh.", Opcode: 0x10000446, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpequq", Opcode: 0x100001c7, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpequq.", Opcode: 0x100005c7, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpequw", Opcode: 0x10000086, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpequw.", Opcode: 0x10000486, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpgefp", Opcode: 0x100001c6, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpgefp.", Opcode: 0x100005c6, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpgtfp", Opcode: 0x100002c6, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpgtfp.", Opcode: 0x100006c6, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpgtsb", Opcode: 0x10000306, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpgtsb.", Opcode: 0x10000706, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpgtsd", Opcode: 0x100003c7, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpgtsd.", Opcode: 0x100007c7, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpgtsh", Opcode: 0x10000346, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpgtsh.", Opcode: 0x10000746, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpgtsq", Opcode: 0x10000387, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpgtsq.", Opcode: 0x10000787, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpgtsw", Opcode: 0x10000386, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpgtsw.", Opcode: 0x10000786, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpgtub", Opcode: 0x10000206, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpgtub.", Opcode: 0x10000606, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpgtud", Opcode: 0x100002c7, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpgtud.", Opcode: 0x100006c7, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpgtuh", Opcode: 0x10000246, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpgtuh.", Opcode: 0x10000646, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpgtuq", Opcode: 0x10000287, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpgtuq.", Opcode: 0x10000687, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpgtuw", Opcode: 0x10000286, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpgtuw.", Opcode: 0x10000686, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpneb", Opcode: 0x10000007, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpneb.", Opcode: 0x10000407, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpneh", Opcode: 0x10000047, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpneh.", Opcode: 0x10000447, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpnew", Opcode: 0x10000087, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpnew.", Opcode: 0x10000487, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpnezb", Opcode: 0x10000107, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpnezb.", Opcode: 0x10000507, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpnezh", Opcode: 0x10000147, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpnezh.", Opcode: 0x10000547, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpnezw", Opcode: 0x10000187, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpnezw.", Opcode: 0x10000587, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vcmpsq", Opcode: 0x10000141, Mask: 0xfc6007ff, Fields: []powerpc.InsnField{{Name: "BF", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "vcmpuq", Opcode: 0x10000101, Mask: 0xfc6007ff, Fields: []powerpc.InsnField{{Name: "BF", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "vcntmbb", Opcode: 0x10180642, Mask: 0xfc1e07ff, Fields: []powerpc.InsnField{{Name: "MP", Bits: []powerpc.InsnBits{{15, 1}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "vcntmbd", Opcode: 0x101e0642, Mask: 0xfc1e07ff, Fields: []powerpc.InsnField{{Name: "MP", Bits: []powerpc.InsnBits{{15, 1}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "vcntmbh", Opcode: 0x101a0642, Mask: 0xfc1e07ff, Fields: []powerpc.InsnField{{Name: "MP", Bits: []powerpc.InsnBits{{15, 1}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "vcntmbw", Opcode: 0x101c0642, Mask: 0xfc1e07ff, Fields: []powerpc.InsnField{{Name: "MP", Bits: []powerpc.InsnBits{{15, 1}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "vctsxs", Opcode: 0x100003ca, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "UIM", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vctuxs", Opcode: 0x1000038a, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "UIM", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vctzb", Opcode: 0x101c0602, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vctzd", Opcode: 0x101f0602, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vctzdm", Opcode: 0x100007c4, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vctzh", Opcode: 0x101d0602, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vctzlsbb", Opcode: 0x10010602, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "vctzw", Opcode: 0x101e0602, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vdivesd", Opcode: 0x100003cb, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vdivesq", Opcode: 0x1000030b, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vdivesw", Opcode: 0x1000038b, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vdiveud", Opcode: 0x100002cb, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vdiveuq", Opcode: 0x1000020b, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vdiveuw", Opcode: 0x1000028b, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vdivsd", Opcode: 0x100001cb, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vdivsq", Opcode: 0x1000010b, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vdivsw", Opcode: 0x1000018b, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vdivud", Opcode: 0x100000cb, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vdivuq", Opcode: 0x1000000b, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vdivuw", Opcode: 0x1000008b, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "veqv", Opcode: 0x10000684, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vexpandbm", Opcode: 0x10000642, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vexpanddm", Opcode: 0x10030642, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vexpandhm", Opcode: 0x10010642, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vexpandqm", Opcode: 0x10040642, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vexpandwm", Opcode: 0x10020642, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vexptefp", Opcode: 0x1000018a, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vextddvlx", Opcode: 0x1000001e, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "RC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vextddvrx", Opcode: 0x1000001f, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "RC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vextdubvlx", Opcode: 0x10000018, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "RC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vextdubvrx", Opcode: 0x10000019, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "RC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vextduhvlx", Opcode: 0x1000001a, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "RC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vextduhvrx", Opcode: 0x1000001b, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "RC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vextduwvlx", Opcode: 0x1000001c, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "RC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vextduwvrx", Opcode: 0x1000001d, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "RC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vextractbm", Opcode: 0x10080642, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "vextractd", Opcode: 0x100002cd, Mask: 0xfc1007ff, Fields: []powerpc.InsnField{{Name: "UIM", Bits: []powerpc.InsnBits{{12, 4}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vextractdm", Opcode: 0x100b0642, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "vextracthm", Opcode: 0x10090642, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "vextractqm", Opcode: 0x100c0642, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "vextractub", Opcode: 0x1000020d, Mask: 0xfc1007ff, Fields: []powerpc.InsnField{{Name: "UIM", Bits: []powerpc.InsnBits{{12, 4}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vextractuh", Opcode: 0x1000024d, Mask: 0xfc1007ff, Fields: []powerpc.InsnField{{Name: "UIM", Bits: []powerpc.InsnBits{{12, 4}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vextractuw", Opcode: 0x1000028d, Mask: 0xfc1007ff, Fields: []powerpc.InsnField{{Name: "UIM", Bits: []powerpc.InsnBits{{12, 4}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vextractwm", Opcode: 0x100a0642, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "vextsb2d", Opcode: 0x10180602, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vextsb2w", Opcode: 0x10100602, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vextsd2q", Opcode: 0x101b0602, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vextsh2d", Opcode: 0x10190602, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vextsh2w", Opcode: 0x10110602, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vextsw2d", Opcode: 0x101a0602, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vextublx", Opcode: 0x1000060d, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "vextubrx", Opcode: 0x1000070d, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "vextuhlx", Opcode: 0x1000064d, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "vextuhrx", Opcode: 0x1000074d, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "vextuwlx", Opcode: 0x1000068d, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "vextuwrx", Opcode: 0x1000078d, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "vgbbd", Opcode: 0x1000050c, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vgnb", Opcode: 0x100004cc, Mask: 0xfc1807ff, Fields: []powerpc.InsnField{{Name: "N", Bits: []powerpc.InsnBits{{13, 3}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "vinsblx", Opcode: 0x1000020f, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vinsbrx", Opcode: 0x1000030f, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vinsbvlx", Opcode: 0x1000000f, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vinsbvrx", Opcode: 0x1000010f, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vinsd", Opcode: 0x100001cf, Mask: 0xfc1007ff, Fields: []powerpc.InsnField{{Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "UIM", Bits: []powerpc.InsnBits{{12, 4}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vinsdlx", Opcode: 0x100002cf, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vinsdrx", Opcode: 0x100003cf, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vinsertb", Opcode: 0x1000030d, Mask: 0xfc1007ff, Fields: []powerpc.InsnField{{Name: "UIM", Bits: []powerpc.InsnBits{{12, 4}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vinsertd", Opcode: 0x100003cd, Mask: 0xfc1007ff, Fields: []powerpc.InsnField{{Name: "UIM", Bits: []powerpc.InsnBits{{12, 4}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vinserth", Opcode: 0x1000034d, Mask: 0xfc1007ff, Fields: []powerpc.InsnField{{Name: "UIM", Bits: []powerpc.InsnBits{{12, 4}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vinsertw", Opcode: 0x1000038d, Mask: 0xfc1007ff, Fields: []powerpc.InsnField{{Name: "UIM", Bits: []powerpc.InsnBits{{12, 4}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vinshlx", Opcode: 0x1000024f, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vinshrx", Opcode: 0x1000034f, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vinshvlx", Opcode: 0x1000004f, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vinshvrx", Opcode: 0x1000014f, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vinsw", Opcode: 0x100000cf, Mask: 0xfc1007ff, Fields: []powerpc.InsnField{{Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "UIM", Bits: []powerpc.InsnBits{{12, 4}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vinswlx", Opcode: 0x1000028f, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vinswrx", Opcode: 0x1000038f, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vinswvlx", Opcode: 0x1000008f, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vinswvrx", Opcode: 0x1000018f, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vlogefp", Opcode: 0x100001ca, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmaddfp", Opcode: 0x1000002e, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmaxfp", Opcode: 0x1000040a, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmaxsb", Opcode: 0x10000102, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmaxsd", Opcode: 0x100001c2, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmaxsh", Opcode: 0x10000142, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmaxsw", Opcode: 0x10000182, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmaxub", Opcode: 0x10000002, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmaxud", Opcode: 0x100000c2, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmaxuh", Opcode: 0x10000042, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmaxuw", Opcode: 0x10000082, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmhaddshs", Opcode: 0x10000020, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmhraddshs", Opcode: 0x10000021, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vminfp", Opcode: 0x1000044a, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vminsb", Opcode: 0x10000302, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vminsd", Opcode: 0x100003c2, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vminsh", Opcode: 0x10000342, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vminsw", Opcode: 0x10000382, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vminub", Opcode: 0x10000202, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vminud", Opcode: 0x100002c2, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vminuh", Opcode: 0x10000242, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vminuw", Opcode: 0x10000282, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmladduhm", Opcode: 0x10000022, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmodsd", Opcode: 0x100007cb, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmodsq", Opcode: 0x1000070b, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmodsw", Opcode: 0x1000078b, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmodud", Opcode: 0x100006cb, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmoduq", Opcode: 0x1000060b, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmoduw", Opcode: 0x1000068b, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmrgew", Opcode: 0x1000078c, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmrghb", Opcode: 0x1000000c, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmrghh", Opcode: 0x1000004c, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmrghw", Opcode: 0x1000008c, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmrglb", Opcode: 0x1000010c, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmrglh", Opcode: 0x1000014c, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmrglw", Opcode: 0x1000018c, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmrgow", Opcode: 0x1000068c, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmsumcud", Opcode: 0x10000017, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmsummbm", Opcode: 0x10000025, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmsumshm", Opcode: 0x10000028, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmsumshs", Opcode: 0x10000029, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmsumubm", Opcode: 0x10000024, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmsumudm", Opcode: 0x10000023, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmsumuhm", Opcode: 0x10000026, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmsumuhs", Opcode: 0x10000027, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmul10cuq", Opcode: 0x10000001, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmul10ecuq", Opcode: 0x10000041, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmul10euq", Opcode: 0x10000241, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmul10uq", Opcode: 0x10000201, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmulesb", Opcode: 0x10000308, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmulesd", Opcode: 0x100003c8, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmulesh", Opcode: 0x10000348, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmulesw", Opcode: 0x10000388, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmuleub", Opcode: 0x10000208, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmuleud", Opcode: 0x100002c8, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmuleuh", Opcode: 0x10000248, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmuleuw", Opcode: 0x10000288, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmulhsd", Opcode: 0x100003c9, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmulhsw", Opcode: 0x10000389, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmulhud", Opcode: 0x100002c9, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmulhuw", Opcode: 0x10000289, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmulld", Opcode: 0x100001c9, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmulosb", Opcode: 0x10000108, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmulosd", Opcode: 0x100001c8, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmulosh", Opcode: 0x10000148, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmulosw", Opcode: 0x10000188, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmuloub", Opcode: 0x10000008, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmuloud", Opcode: 0x100000c8, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmulouh", Opcode: 0x10000048, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmulouw", Opcode: 0x10000088, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vmuluwm", Opcode: 0x10000089, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vnand", Opcode: 0x10000584, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vncipher", Opcode: 0x10000548, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vncipherlast", Opcode: 0x10000549, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vnegd", Opcode: 0x10070602, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vnegw", Opcode: 0x10060602, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vnmsubfp", Opcode: 0x1000002f, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vnor", Opcode: 0x10000504, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vor", Opcode: 0x10000484, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vorc", Opcode: 0x10000544, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vpdepd", Opcode: 0x100005cd, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vperm", Opcode: 0x1000002b, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vpermr", Opcode: 0x1000003b, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vpermxor", Opcode: 0x1000002d, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vpextd", Opcode: 0x1000058d, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vpkpx", Opcode: 0x1000030e, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vpksdss", Opcode: 0x100005ce, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vpksdus", Opcode: 0x1000054e, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vpkshss", Opcode: 0x1000018e, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vpkshus", Opcode: 0x1000010e, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vpkswss", Opcode: 0x100001ce, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vpkswus", Opcode: 0x1000014e, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vpkudum", Opcode: 0x1000044e, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vpkudus", Opcode: 0x100004ce, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vpkuhum", Opcode: 0x1000000e, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vpkuhus", Opcode: 0x1000008e, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vpkuwum", Opcode: 0x1000004e, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vpkuwus", Opcode: 0x100000ce, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vpmsumb", Opcode: 0x10000408, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vpmsumd", Opcode: 0x100004c8, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vpmsumh", Opcode: 0x10000448, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vpmsumw", Opcode: 0x10000488, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vpopcntb", Opcode: 0x10000703, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vpopcntd", Opcode: 0x100007c3, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vpopcnth", Opcode: 0x10000743, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vpopcntw", Opcode: 0x10000783, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vprtybd", Opcode: 0x10090602, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vprtybq", Opcode: 0x100a0602, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vprtybw", Opcode: 0x10080602, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vrefp", Opcode: 0x1000010a, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vrfim", Opcode: 0x100002ca, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vrfin", Opcode: 0x1000020a, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vrfip", Opcode: 0x1000028a, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vrfiz", Opcode: 0x1000024a, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vrlb", Opcode: 0x10000004, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vrld", Opcode: 0x100000c4, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vrldmi", Opcode: 0x100000c5, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vrldnm", Opcode: 0x100001c5, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vrlh", Opcode: 0x10000044, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vrlq", Opcode: 0x10000005, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vrlqmi", Opcode: 0x10000045, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vrlqnm", Opcode: 0x10000145, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vrlw", Opcode: 0x10000084, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vrlwmi", Opcode: 0x10000085, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vrlwnm", Opcode: 0x10000185, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vrsqrtefp", Opcode: 0x1000014a, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vsbox", Opcode: 0x100005c8, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vsel", Opcode: 0x1000002a, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vshasigmad", Opcode: 0x100006c2, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "SIX", Bits: []powerpc.InsnBits{{17, 4}}}, {Name: "ST", Bits: []powerpc.InsnBits{{16, 1}}}, {Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vshasigmaw", Opcode: 0x10000682, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "SIX", Bits: []powerpc.InsnBits{{17, 4}}}, {Name: "ST", Bits: []powerpc.InsnBits{{16, 1}}}, {Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vsl", Opcode: 0x100001c4, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vslb", Opcode: 0x10000104, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vsld", Opcode: 0x100005c4, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vsldbi", Opcode: 0x10000016, Mask: 0xfc00063f, Fields: []powerpc.InsnField{{Name: "SH", Bits: []powerpc.InsnBits{{23, 3}}}, {Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vsldoi", Opcode: 0x1000002c, Mask: 0xfc00043f, Fields: []powerpc.InsnField{{Name: "SHB", Bits: []powerpc.InsnBits{{22, 4}}}, {Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vslh", Opcode: 0x10000144, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vslo", Opcode: 0x1000040c, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vslq", Opcode: 0x10000105, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vslv", Opcode: 0x10000744, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vslw", Opcode: 0x10000184, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vspltb", Opcode: 0x1000020c, Mask: 0xfc1007ff, Fields: []powerpc.InsnField{{Name: "UIM", Bits: []powerpc.InsnBits{{12, 4}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vsplth", Opcode: 0x1000024c, Mask: 0xfc1807ff, Fields: []powerpc.InsnField{{Name: "UIM", Bits: []powerpc.InsnBits{{13, 3}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vspltisb", Opcode: 0x1000030c, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "SIM", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vspltish", Opcode: 0x1000034c, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "SIM", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vspltisw", Opcode: 0x1000038c, Mask: 0xfc00ffff, Fields: []powerpc.InsnField{{Name: "SIM", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vspltw", Opcode: 0x1000028c, Mask: 0xfc1c07ff, Fields: []powerpc.InsnField{{Name: "UIM", Bits: []powerpc.InsnBits{{14, 2}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vsr", Opcode: 0x100002c4, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vsrab", Opcode: 0x10000304, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vsrad", Opcode: 0x100003c4, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vsrah", Opcode: 0x10000344, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vsraq", Opcode: 0x10000305, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vsraw", Opcode: 0x10000384, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vsrb", Opcode: 0x10000204, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vsrd", Opcode: 0x100006c4, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vsrdbi", Opcode: 0x10000216, Mask: 0xfc00063f, Fields: []powerpc.InsnField{{Name: "SH", Bits: []powerpc.InsnBits{{23, 3}}}, {Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vsrh", Opcode: 0x10000244, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vsro", Opcode: 0x1000044c, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vsrq", Opcode: 0x10000205, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vsrv", Opcode: 0x10000704, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vsrw", Opcode: 0x10000284, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vstribl", Opcode: 0x1000000d, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vstribl.", Opcode: 0x1000040d, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vstribr", Opcode: 0x1001000d, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vstribr.", Opcode: 0x1001040d, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vstrihl", Opcode: 0x1002000d, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vstrihl.", Opcode: 0x1002040d, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vstrihr", Opcode: 0x1003000d, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vstrihr.", Opcode: 0x1003040d, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vsubcuq", Opcode: 0x10000540, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vsubcuw", Opcode: 0x10000580, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vsubecuq", Opcode: 0x1000003f, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vsubeuqm", Opcode: 0x1000003e, Mask: 0xfc00003f, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRC", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vsubfp", Opcode: 0x1000004a, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vsubsbs", Opcode: 0x10000700, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vsubshs", Opcode: 0x10000740, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vsubsws", Opcode: 0x10000780, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vsububm", Opcode: 0x10000400, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vsububs", Opcode: 0x10000600, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vsubudm", Opcode: 0x100004c0, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vsubuhm", Opcode: 0x10000440, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vsubuhs", Opcode: 0x10000640, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vsubuqm", Opcode: 0x10000500, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vsubuwm", Opcode: 0x10000480, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vsubuws", Opcode: 0x10000680, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vsum2sws", Opcode: 0x10000688, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vsum4sbs", Opcode: 0x10000708, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vsum4shs", Opcode: 0x10000648, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vsum4ubs", Opcode: 0x10000608, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vsumsws", Opcode: 0x10000788, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vupkhpx", Opcode: 0x1000034e, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vupkhsb", Opcode: 0x1000020e, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vupkhsh", Opcode: 0x1000024e, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vupkhsw", Opcode: 0x1000064e, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vupklpx", Opcode: 0x100003ce, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vupklsb", Opcode: 0x1000028e, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vupklsh", Opcode: 0x100002ce, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vupklsw", Opcode: 0x100006ce, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "vxor", Opcode: 0x100004c4, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "wait", Opcode: 0x7c00003c, Mask: 0xfc9cffff, Fields: []powerpc.InsnField{{Name: "PL", Bits: []powerpc.InsnBits{{14, 2}}}, {Name: "WC", Bits: []powerpc.InsnBits{{9, 2}}}}},
{Name: "xor", Opcode: 0x7c000278, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "xor.", Opcode: 0x7c000279, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "xori", Opcode: 0x68000000, Mask: 0xfc000000, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "UI", Bits: []powerpc.InsnBits{{16, 16}}}}},
{Name: "xoris", Opcode: 0x6c000000, Mask: 0xfc000000, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RS", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "UI", Bits: []powerpc.InsnBits{{16, 16}}}}},
{Name: "xsabsdp", Opcode: 0xf0000564, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xsabsqp", Opcode: 0xfc000648, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "xsadddp", Opcode: 0xf0000100, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xsaddqp", Opcode: 0xfc000008, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "xsaddqpo", Opcode: 0xfc000009, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "xsaddsp", Opcode: 0xf0000000, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xscmpeqdp", Opcode: 0xf0000018, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xscmpeqqp", Opcode: 0xfc000088, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "xscmpexpdp", Opcode: 0xf00001d8, Mask: 0xfc6007f9, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BF", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "xscmpexpqp", Opcode: 0xfc000148, Mask: 0xfc6007ff, Fields: []powerpc.InsnField{{Name: "BF", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "xscmpgedp", Opcode: 0xf0000098, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xscmpgeqp", Opcode: 0xfc000188, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "xscmpgtdp", Opcode: 0xf0000058, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xscmpgtqp", Opcode: 0xfc0001c8, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "xscmpodp", Opcode: 0xf0000158, Mask: 0xfc6007f9, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BF", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "xscmpoqp", Opcode: 0xfc000108, Mask: 0xfc6007ff, Fields: []powerpc.InsnField{{Name: "BF", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "xscmpudp", Opcode: 0xf0000118, Mask: 0xfc6007f9, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BF", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "xscmpuqp", Opcode: 0xfc000508, Mask: 0xfc6007ff, Fields: []powerpc.InsnField{{Name: "BF", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "xscpsgndp", Opcode: 0xf0000580, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xscpsgnqp", Opcode: 0xfc0000c8, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "xscvdphp", Opcode: 0xf011056c, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xscvdpqp", Opcode: 0xfc160688, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "xscvdpsp", Opcode: 0xf0000424, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xscvdpspn", Opcode: 0xf000042c, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xscvdpsxds", Opcode: 0xf0000560, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xscvdpsxws", Opcode: 0xf0000160, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xscvdpuxds", Opcode: 0xf0000520, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xscvdpuxws", Opcode: 0xf0000120, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xscvhpdp", Opcode: 0xf010056c, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xscvqpdp", Opcode: 0xfc140688, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "xscvqpdpo", Opcode: 0xfc140689, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "xscvqpsdz", Opcode: 0xfc190688, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "xscvqpsqz", Opcode: 0xfc080688, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "xscvqpswz", Opcode: 0xfc090688, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "xscvqpudz", Opcode: 0xfc110688, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "xscvqpuqz", Opcode: 0xfc000688, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "xscvqpuwz", Opcode: 0xfc010688, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "xscvsdqp", Opcode: 0xfc0a0688, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "xscvspdp", Opcode: 0xf0000524, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xscvspdpn", Opcode: 0xf000052c, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xscvsqqp", Opcode: 0xfc0b0688, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "xscvsxddp", Opcode: 0xf00005e0, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xscvsxdsp", Opcode: 0xf00004e0, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xscvudqp", Opcode: 0xfc020688, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "xscvuqqp", Opcode: 0xfc030688, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "xscvuxddp", Opcode: 0xf00005a0, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xscvuxdsp", Opcode: 0xf00004a0, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xsdivdp", Opcode: 0xf00001c0, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xsdivqp", Opcode: 0xfc000448, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "xsdivqpo", Opcode: 0xfc000449, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "xsdivsp", Opcode: 0xf00000c0, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xsiexpdp", Opcode: 0xf000072c, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "RA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "RB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xsiexpqp", Opcode: 0xfc0006c8, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "xsmaddadp", Opcode: 0xf0000108, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xsmaddasp", Opcode: 0xf0000008, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xsmaddmdp", Opcode: 0xf0000148, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xsmaddmsp", Opcode: 0xf0000048, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xsmaddqp", Opcode: 0xfc000308, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "xsmaddqpo", Opcode: 0xfc000309, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "xsmaxcdp", Opcode: 0xf0000400, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xsmaxcqp", Opcode: 0xfc000548, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "xsmaxdp", Opcode: 0xf0000500, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xsmaxjdp", Opcode: 0xf0000480, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xsmincdp", Opcode: 0xf0000440, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xsmincqp", Opcode: 0xfc0005c8, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "xsmindp", Opcode: 0xf0000540, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xsminjdp", Opcode: 0xf00004c0, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xsmsubadp", Opcode: 0xf0000188, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xsmsubasp", Opcode: 0xf0000088, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xsmsubmdp", Opcode: 0xf00001c8, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xsmsubmsp", Opcode: 0xf00000c8, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xsmsubqp", Opcode: 0xfc000348, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "xsmsubqpo", Opcode: 0xfc000349, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "xsmuldp", Opcode: 0xf0000180, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xsmulqp", Opcode: 0xfc000048, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "xsmulqpo", Opcode: 0xfc000049, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "xsmulsp", Opcode: 0xf0000080, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xsnabsdp", Opcode: 0xf00005a4, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xsnabsqp", Opcode: 0xfc080648, Mask: 0xfc1f07fe, Fields: []powerpc.InsnField{{Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "xsnegdp", Opcode: 0xf00005e4, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xsnegqp", Opcode: 0xfc100648, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "xsnmaddadp", Opcode: 0xf0000508, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xsnmaddasp", Opcode: 0xf0000408, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xsnmaddmdp", Opcode: 0xf0000548, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xsnmaddmsp", Opcode: 0xf0000448, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xsnmaddqp", Opcode: 0xfc000388, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "xsnmaddqpo", Opcode: 0xfc000389, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "xsnmsubadp", Opcode: 0xf0000588, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xsnmsubasp", Opcode: 0xf0000488, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xsnmsubmdp", Opcode: 0xf00005c8, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xsnmsubmsp", Opcode: 0xf00004c8, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xsnmsubqp", Opcode: 0xfc0003c8, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "xsnmsubqpo", Opcode: 0xfc0003c9, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "xsrdpi", Opcode: 0xf0000124, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xsrdpic", Opcode: 0xf00001ac, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xsrdpim", Opcode: 0xf00001e4, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xsrdpip", Opcode: 0xf00001a4, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xsrdpiz", Opcode: 0xf0000164, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xsredp", Opcode: 0xf0000168, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xsresp", Opcode: 0xf0000068, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xsrqpi", Opcode: 0xfc00000a, Mask: 0xfc1e01ff, Fields: []powerpc.InsnField{{Name: "R", Bits: []powerpc.InsnBits{{15, 1}}}, {Name: "RMC", Bits: []powerpc.InsnBits{{21, 2}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "xsrqpix", Opcode: 0xfc00000b, Mask: 0xfc1e01ff, Fields: []powerpc.InsnField{{Name: "R", Bits: []powerpc.InsnBits{{15, 1}}}, {Name: "RMC", Bits: []powerpc.InsnBits{{21, 2}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "xsrqpxp", Opcode: 0xfc00004a, Mask: 0xfc1e01ff, Fields: []powerpc.InsnField{{Name: "R", Bits: []powerpc.InsnBits{{15, 1}}}, {Name: "RMC", Bits: []powerpc.InsnBits{{21, 2}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "xsrsp", Opcode: 0xf0000464, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xsrsqrtedp", Opcode: 0xf0000128, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xsrsqrtesp", Opcode: 0xf0000028, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xssqrtdp", Opcode: 0xf000012c, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xssqrtqp", Opcode: 0xfc1b0648, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "xssqrtqpo", Opcode: 0xfc1b0649, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "xssqrtsp", Opcode: 0xf000002c, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xssubdp", Opcode: 0xf0000140, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xssubqp", Opcode: 0xfc000408, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "xssubqpo", Opcode: 0xfc000409, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "VRA", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "xssubsp", Opcode: 0xf0000040, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xstdivdp", Opcode: 0xf00001e8, Mask: 0xfc6007f9, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BF", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "xstsqrtdp", Opcode: 0xf00001a8, Mask: 0xfc7f07fd, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BF", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "xststdcdp", Opcode: 0xf00005a8, Mask: 0xfc0007fd, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BF", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "DCMX", Bits: []powerpc.InsnBits{{9, 7}}}}},
{Name: "xststdcqp", Opcode: 0xfc000588, Mask: 0xfc0007ff, Fields: []powerpc.InsnField{{Name: "BF", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "DCMX", Bits: []powerpc.InsnBits{{9, 7}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "xststdcsp", Opcode: 0xf00004a8, Mask: 0xfc0007fd, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BF", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "DCMX", Bits: []powerpc.InsnBits{{9, 7}}}}},
{Name: "xsxexpdp", Opcode: 0xf000056c, Mask: 0xfc1f07fd, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "xsxexpqp", Opcode: 0xfc020648, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "xsxsigdp", Opcode: 0xf001056c, Mask: 0xfc1f07fd, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "RT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "xsxsigqp", Opcode: 0xfc120648, Mask: 0xfc1f07ff, Fields: []powerpc.InsnField{{Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "VRT", Bits: []powerpc.InsnBits{{6, 5}}}}},
{Name: "xvabsdp", Opcode: 0xf0000764, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvabssp", Opcode: 0xf0000664, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvadddp", Opcode: 0xf0000300, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvaddsp", Opcode: 0xf0000200, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvbf16ger2", Opcode: 0xec000198, Mask: 0xfc6007f9, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "xvbf16ger2nn", Opcode: 0xec000790, Mask: 0xfc6007f9, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "xvbf16ger2np", Opcode: 0xec000390, Mask: 0xfc6007f9, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "xvbf16ger2pn", Opcode: 0xec000590, Mask: 0xfc6007f9, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "xvbf16ger2pp", Opcode: 0xec000190, Mask: 0xfc6007f9, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "xvcmpeqdp", Opcode: 0xf0000318, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvcmpeqdp.", Opcode: 0xf0000718, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvcmpeqsp", Opcode: 0xf0000218, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvcmpeqsp.", Opcode: 0xf0000618, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvcmpgedp", Opcode: 0xf0000398, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvcmpgedp.", Opcode: 0xf0000798, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvcmpgesp", Opcode: 0xf0000298, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvcmpgesp.", Opcode: 0xf0000698, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvcmpgtdp", Opcode: 0xf0000358, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvcmpgtdp.", Opcode: 0xf0000758, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvcmpgtsp", Opcode: 0xf0000258, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvcmpgtsp.", Opcode: 0xf0000658, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvcpsgndp", Opcode: 0xf0000780, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvcpsgnsp", Opcode: 0xf0000680, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvcvbf16spn", Opcode: 0xf010076c, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvcvdpsp", Opcode: 0xf0000624, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvcvdpsxds", Opcode: 0xf0000760, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvcvdpsxws", Opcode: 0xf0000360, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvcvdpuxds", Opcode: 0xf0000720, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvcvdpuxws", Opcode: 0xf0000320, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvcvhpsp", Opcode: 0xf018076c, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvcvspbf16", Opcode: 0xf011076c, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvcvspdp", Opcode: 0xf0000724, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvcvsphp", Opcode: 0xf019076c, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvcvspsxds", Opcode: 0xf0000660, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvcvspsxws", Opcode: 0xf0000260, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvcvspuxds", Opcode: 0xf0000620, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvcvspuxws", Opcode: 0xf0000220, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvcvsxddp", Opcode: 0xf00007e0, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvcvsxdsp", Opcode: 0xf00006e0, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvcvsxwdp", Opcode: 0xf00003e0, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvcvsxwsp", Opcode: 0xf00002e0, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvcvuxddp", Opcode: 0xf00007a0, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvcvuxdsp", Opcode: 0xf00006a0, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvcvuxwdp", Opcode: 0xf00003a0, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvcvuxwsp", Opcode: 0xf00002a0, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvdivdp", Opcode: 0xf00003c0, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvdivsp", Opcode: 0xf00002c0, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvf16ger2", Opcode: 0xec000098, Mask: 0xfc6007f9, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "xvf16ger2nn", Opcode: 0xec000690, Mask: 0xfc6007f9, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "xvf16ger2np", Opcode: 0xec000290, Mask: 0xfc6007f9, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "xvf16ger2pn", Opcode: 0xec000490, Mask: 0xfc6007f9, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "xvf16ger2pp", Opcode: 0xec000090, Mask: 0xfc6007f9, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "xvf32ger", Opcode: 0xec0000d8, Mask: 0xfc6007f9, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "xvf32gernn", Opcode: 0xec0006d0, Mask: 0xfc6007f9, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "xvf32gernp", Opcode: 0xec0002d0, Mask: 0xfc6007f9, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "xvf32gerpn", Opcode: 0xec0004d0, Mask: 0xfc6007f9, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "xvf32gerpp", Opcode: 0xec0000d0, Mask: 0xfc6007f9, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "xvf64ger", Opcode: 0xec0001d8, Mask: 0xfc6007f9, Fields: []powerpc.InsnField{{Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "Ap", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "xvf64gernn", Opcode: 0xec0007d0, Mask: 0xfc6007f9, Fields: []powerpc.InsnField{{Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "Ap", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "xvf64gernp", Opcode: 0xec0003d0, Mask: 0xfc6007f9, Fields: []powerpc.InsnField{{Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "Ap", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "xvf64gerpn", Opcode: 0xec0005d0, Mask: 0xfc6007f9, Fields: []powerpc.InsnField{{Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "Ap", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "xvf64gerpp", Opcode: 0xec0001d0, Mask: 0xfc6007f9, Fields: []powerpc.InsnField{{Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "Ap", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "xvi16ger2", Opcode: 0xec000258, Mask: 0xfc6007f9, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "xvi16ger2pp", Opcode: 0xec000358, Mask: 0xfc6007f9, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "xvi16ger2s", Opcode: 0xec000158, Mask: 0xfc6007f9, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "xvi16ger2spp", Opcode: 0xec000150, Mask: 0xfc6007f9, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "xvi4ger8", Opcode: 0xec000118, Mask: 0xfc6007f9, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "xvi4ger8pp", Opcode: 0xec000110, Mask: 0xfc6007f9, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "xvi8ger4", Opcode: 0xec000018, Mask: 0xfc6007f9, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "xvi8ger4pp", Opcode: 0xec000010, Mask: 0xfc6007f9, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "xvi8ger4spp", Opcode: 0xec000318, Mask: 0xfc6007f9, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "xviexpdp", Opcode: 0xf00007c0, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xviexpsp", Opcode: 0xf00006c0, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvmaddadp", Opcode: 0xf0000308, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvmaddasp", Opcode: 0xf0000208, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvmaddmdp", Opcode: 0xf0000348, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvmaddmsp", Opcode: 0xf0000248, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvmaxdp", Opcode: 0xf0000700, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvmaxsp", Opcode: 0xf0000600, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvmindp", Opcode: 0xf0000740, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvminsp", Opcode: 0xf0000640, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvmsubadp", Opcode: 0xf0000388, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvmsubasp", Opcode: 0xf0000288, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvmsubmdp", Opcode: 0xf00003c8, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvmsubmsp", Opcode: 0xf00002c8, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvmuldp", Opcode: 0xf0000380, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvmulsp", Opcode: 0xf0000280, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvnabsdp", Opcode: 0xf00007a4, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvnabssp", Opcode: 0xf00006a4, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvnegdp", Opcode: 0xf00007e4, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvnegsp", Opcode: 0xf00006e4, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvnmaddadp", Opcode: 0xf0000708, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvnmaddasp", Opcode: 0xf0000608, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvnmaddmdp", Opcode: 0xf0000748, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvnmaddmsp", Opcode: 0xf0000648, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvnmsubadp", Opcode: 0xf0000788, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvnmsubasp", Opcode: 0xf0000688, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvnmsubmdp", Opcode: 0xf00007c8, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvnmsubmsp", Opcode: 0xf00006c8, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvrdpi", Opcode: 0xf0000324, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvrdpic", Opcode: 0xf00003ac, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvrdpim", Opcode: 0xf00003e4, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvrdpip", Opcode: 0xf00003a4, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvrdpiz", Opcode: 0xf0000364, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvredp", Opcode: 0xf0000368, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvresp", Opcode: 0xf0000268, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvrspi", Opcode: 0xf0000224, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvrspic", Opcode: 0xf00002ac, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvrspim", Opcode: 0xf00002e4, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvrspip", Opcode: 0xf00002a4, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvrspiz", Opcode: 0xf0000264, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvrsqrtedp", Opcode: 0xf0000328, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvrsqrtesp", Opcode: 0xf0000228, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvsqrtdp", Opcode: 0xf000032c, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvsqrtsp", Opcode: 0xf000022c, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvsubdp", Opcode: 0xf0000340, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvsubsp", Opcode: 0xf0000240, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvtdivdp", Opcode: 0xf00003e8, Mask: 0xfc6007f9, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BF", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "xvtdivsp", Opcode: 0xf00002e8, Mask: 0xfc6007f9, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BF", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "xvtlsbb", Opcode: 0xf002076c, Mask: 0xfc7f07fd, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BF", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "xvtsqrtdp", Opcode: 0xf00003a8, Mask: 0xfc7f07fd, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BF", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "xvtsqrtsp", Opcode: 0xf00002a8, Mask: 0xfc7f07fd, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BF", Bits: []powerpc.InsnBits{{6, 3}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}}},
{Name: "xvtstdcdp", Opcode: 0xf00007a8, Mask: 0xfc0007b8, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}, {Name: "dc", Bits: []powerpc.InsnBits{{25, 1}}}, {Name: "dm", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "dx", Bits: []powerpc.InsnBits{{11, 5}}}}},
{Name: "xvtstdcsp", Opcode: 0xf00006a8, Mask: 0xfc0007b8, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}, {Name: "dc", Bits: []powerpc.InsnBits{{25, 1}}}, {Name: "dm", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "dx", Bits: []powerpc.InsnBits{{11, 5}}}}},
{Name: "xvxexpdp", Opcode: 0xf000076c, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvxexpsp", Opcode: 0xf008076c, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvxsigdp", Opcode: 0xf001076c, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xvxsigsp", Opcode: 0xf009076c, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xxblendvb", Opcode: 0x05000000, Mask: 0xffffffff, Fields: []powerpc.InsnField{},
OpcodeSuffix: 0x84000000, MaskSuffix: 0xfc000030, FieldsSuffix: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "C", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "CX", Bits: []powerpc.InsnBits{{28, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xxblendvd", Opcode: 0x05000000, Mask: 0xffffffff, Fields: []powerpc.InsnField{},
OpcodeSuffix: 0x84000030, MaskSuffix: 0xfc000030, FieldsSuffix: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "C", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "CX", Bits: []powerpc.InsnBits{{28, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xxblendvh", Opcode: 0x05000000, Mask: 0xffffffff, Fields: []powerpc.InsnField{},
OpcodeSuffix: 0x84000010, MaskSuffix: 0xfc000030, FieldsSuffix: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "C", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "CX", Bits: []powerpc.InsnBits{{28, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xxblendvw", Opcode: 0x05000000, Mask: 0xffffffff, Fields: []powerpc.InsnField{},
OpcodeSuffix: 0x84000020, MaskSuffix: 0xfc000030, FieldsSuffix: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "C", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "CX", Bits: []powerpc.InsnBits{{28, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xxbrd", Opcode: 0xf017076c, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xxbrh", Opcode: 0xf007076c, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xxbrq", Opcode: 0xf01f076c, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xxbrw", Opcode: 0xf00f076c, Mask: 0xfc1f07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xxeval", Opcode: 0x05000000, Mask: 0xffffff00, Fields: []powerpc.InsnField{{Name: "IMM", Bits: []powerpc.InsnBits{{24, 8}}}},
OpcodeSuffix: 0x88000010, MaskSuffix: 0xfc000030, FieldsSuffix: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "C", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "CX", Bits: []powerpc.InsnBits{{28, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xxextractuw", Opcode: 0xf0000294, Mask: 0xfc1007fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}, {Name: "UIM", Bits: []powerpc.InsnBits{{12, 4}}}}},
{Name: "xxgenpcvbm", Opcode: 0xf0000728, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "IMM", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "xxgenpcvdm", Opcode: 0xf000076a, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "IMM", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "xxgenpcvhm", Opcode: 0xf000072a, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "IMM", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "xxgenpcvwm", Opcode: 0xf0000768, Mask: 0xfc0007fe, Fields: []powerpc.InsnField{{Name: "IMM", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}, {Name: "VRB", Bits: []powerpc.InsnBits{{16, 5}}}}},
{Name: "xxinsertw", Opcode: 0xf00002d4, Mask: 0xfc1007fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}, {Name: "UIM", Bits: []powerpc.InsnBits{{12, 4}}}}},
{Name: "xxland", Opcode: 0xf0000410, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xxlandc", Opcode: 0xf0000450, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xxleqv", Opcode: 0xf00005d0, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xxlnand", Opcode: 0xf0000590, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xxlnor", Opcode: 0xf0000510, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xxlor", Opcode: 0xf0000490, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xxlorc", Opcode: 0xf0000550, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xxlxor", Opcode: 0xf00004d0, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xxmfacc", Opcode: 0x7c000162, Mask: 0xfc7fffff, Fields: []powerpc.InsnField{{Name: "AS", Bits: []powerpc.InsnBits{{6, 3}}}}},
{Name: "xxmrghw", Opcode: 0xf0000090, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xxmrglw", Opcode: 0xf0000190, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xxmtacc", Opcode: 0x7c010162, Mask: 0xfc7fffff, Fields: []powerpc.InsnField{{Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}}},
{Name: "xxperm", Opcode: 0xf00000d0, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xxpermdi", Opcode: 0xf0000050, Mask: 0xfc0004f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "DM", Bits: []powerpc.InsnBits{{22, 2}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xxpermr", Opcode: 0xf00001d0, Mask: 0xfc0007f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xxpermx", Opcode: 0x05000000, Mask: 0xfffffff8, Fields: []powerpc.InsnField{{Name: "UIM", Bits: []powerpc.InsnBits{{29, 3}}}},
OpcodeSuffix: 0x88000000, MaskSuffix: 0xfc000030, FieldsSuffix: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "C", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "CX", Bits: []powerpc.InsnBits{{28, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xxsel", Opcode: 0xf0000030, Mask: 0xfc000030, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "C", Bits: []powerpc.InsnBits{{21, 5}}}, {Name: "CX", Bits: []powerpc.InsnBits{{28, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xxsetaccz", Opcode: 0x7c030162, Mask: 0xfc7fffff, Fields: []powerpc.InsnField{{Name: "AT", Bits: []powerpc.InsnBits{{6, 3}}}}},
{Name: "xxsldwi", Opcode: 0xf0000010, Mask: 0xfc0004f8, Fields: []powerpc.InsnField{{Name: "A", Bits: []powerpc.InsnBits{{11, 5}}}, {Name: "AX", Bits: []powerpc.InsnBits{{29, 1}}}, {Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "SHW", Bits: []powerpc.InsnBits{{22, 2}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xxsplti32dx", Opcode: 0x05000000, Mask: 0xffff0000, Fields: []powerpc.InsnField{{Name: "imm0", Bits: []powerpc.InsnBits{{16, 16}}}},
OpcodeSuffix: 0x80000000, MaskSuffix: 0xfc1c0000, FieldsSuffix: []powerpc.InsnField{{Name: "IX", Bits: []powerpc.InsnBits{{14, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{15, 1}}}, {Name: "imm1", Bits: []powerpc.InsnBits{{16, 16}}}}},
{Name: "xxspltib", Opcode: 0xf00002d0, Mask: 0xfc1807fe, Fields: []powerpc.InsnField{{Name: "IMM8", Bits: []powerpc.InsnBits{{13, 8}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}}},
{Name: "xxspltidp", Opcode: 0x05000000, Mask: 0xffff0000, Fields: []powerpc.InsnField{{Name: "imm0", Bits: []powerpc.InsnBits{{16, 16}}}},
OpcodeSuffix: 0x80040000, MaskSuffix: 0xfc1e0000, FieldsSuffix: []powerpc.InsnField{{Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{15, 1}}}, {Name: "imm1", Bits: []powerpc.InsnBits{{16, 16}}}}},
{Name: "xxspltiw", Opcode: 0x05000000, Mask: 0xffff0000, Fields: []powerpc.InsnField{{Name: "imm0", Bits: []powerpc.InsnBits{{16, 16}}}},
OpcodeSuffix: 0x80060000, MaskSuffix: 0xfc1e0000, FieldsSuffix: []powerpc.InsnField{{Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{15, 1}}}, {Name: "imm1", Bits: []powerpc.InsnBits{{16, 16}}}}},
{Name: "xxspltw", Opcode: 0xf0000290, Mask: 0xfc1c07fc, Fields: []powerpc.InsnField{{Name: "B", Bits: []powerpc.InsnBits{{16, 5}}}, {Name: "BX", Bits: []powerpc.InsnBits{{30, 1}}}, {Name: "T", Bits: []powerpc.InsnBits{{6, 5}}}, {Name: "TX", Bits: []powerpc.InsnBits{{31, 1}}}, {Name: "UIM", Bits: []powerpc.InsnBits{{14, 2}}}}},
}
// Copyright 2020 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
// Package ifuzz allows to generate and mutate PPC64 PowerISA 3.0B machine code.
// The ISA for POWER9 (the latest available at the moment) is at:
// https://openpowerfoundation.org/?resource_lib=power-isa-version-3-0
//
// A script on top of pdftotext was used to produce insns.go:
// ./powerisa30_to_syz /home/aik/Documents/ppc/power9/PowerISA_public.v3.0B.pdf > 1.go
// .
package powerpc
import (
"encoding/binary"
"errors"
"fmt"
"math/rand"
"github.com/google/syzkaller/pkg/ifuzz/iset"
)
type InsnBits struct {
Start uint // Big endian bit order.
Length uint
}
type InsnField struct {
Name string
Bits []InsnBits
}
type Insn struct {
Name string
Priv bool
Pseudo bool
Fields []InsnField // for ra/rb/rt/si/...
Opcode uint32
Mask uint32
FieldsSuffix []InsnField
OpcodeSuffix uint32
MaskSuffix uint32
insnMap *insnSetMap
generator func(cfg *iset.Config, r *rand.Rand) []byte
}
type insnSetMap map[string]*Insn
type InsnSet struct {
Insns []*Insn
modeInsns iset.ModeInsns
insnMap insnSetMap
}
const (
prefixShift = 32 - 6
prefixMask = uint32(0x3f) << prefixShift
prefixOpcode = uint32(1) << prefixShift
)
func (insn *Insn) isPrefixed() bool {
return insn.Opcode&prefixMask == prefixOpcode
}
func (insnset *InsnSet) GetInsns(mode iset.Mode, typ iset.Type) []iset.Insn {
return insnset.modeInsns[mode][typ]
}
func (insnset *InsnSet) Decode(mode iset.Mode, text []byte) (int, error) {
if len(text) < 4 {
return 0, errors.New("must be at least 4 bytes")
}
insn32 := binary.LittleEndian.Uint32(text)
if insn32&prefixMask == prefixOpcode {
insn2 := uint32(0)
for _, ins := range insnset.Insns {
if !ins.isPrefixed() || ins.Mask&insn32 != ins.Opcode {
continue
}
if len(text) < 8 {
return 0, errors.New("prefixed instruction must be at least 8 bytes")
}
insn2 = binary.LittleEndian.Uint32(text[4:])
for _, ins := range insnset.Insns {
if !ins.isPrefixed() {
continue
}
if ins.MaskSuffix&insn2 == ins.OpcodeSuffix {
return 8, nil
}
}
break
}
return 0, fmt.Errorf("unrecognised prefixed instruction %08x %08x", insn32, insn2)
}
for _, ins := range insnset.Insns {
if ins.Mask&insn32 == ins.Opcode {
return 4, nil
}
}
return 0, fmt.Errorf("unrecognised instruction %08x", insn32)
}
func (insnset *InsnSet) DecodeExt(mode iset.Mode, text []byte) (int, error) {
return 0, fmt.Errorf("no external decoder")
}
func encodeBits(n uint, ff []InsnBits) uint32 {
ret := uint32(0)
for _, f := range ff {
mask := uint(1<<f.Length) - 1
field := uint32((n & mask) << (31 - (f.Start + f.Length - 1)))
ret = ret | field
n = n >> f.Length
}
return ret
}
func (insn *Insn) Encode(cfg *iset.Config, r *rand.Rand) []byte {
if insn.Pseudo {
return insn.generator(cfg, r)
}
ret := make([]byte, 0)
ret = append(ret, insn.encodeOpcode(cfg, r, insn.Opcode, insn.Mask, insn.Fields)...)
if insn.isPrefixed() {
ret = append(ret, insn.encodeOpcode(cfg, r, insn.OpcodeSuffix, insn.MaskSuffix, insn.FieldsSuffix)...)
}
return ret
}
func (insn *Insn) encodeOpcode(cfg *iset.Config, r *rand.Rand, opcode, mask uint32, f []InsnField) []byte {
ret := make([]byte, 0)
insn32 := opcode
if len(cfg.MemRegions) != 0 {
// The PowerISA pdf parser could have missed some fields,
// randomize them there.
insn32 |= r.Uint32() & ^mask
}
for _, f := range f {
field := uint(r.Intn(1 << 16))
if f.Name == "Ap" || f.Name == "FRAp" || f.Name == "FRBp" || f.Name == "FRTp" || f.Name == "FRSp" {
// These are pairs and have to be even numbers.
field &^= 1
}
insn32 |= encodeBits(field, f.Bits)
if len(cfg.MemRegions) != 0 && (f.Name == "RA" || f.Name == "RB" || f.Name == "RS") {
val := iset.GenerateInt(cfg, r, 8)
ret = append(ret, insn.insnMap.ld64(field, val)...)
}
}
return append(ret, uint32toBytes(insn32)...)
}
func Register(insns []*Insn) {
if len(insns) == 0 {
panic("no instructions")
}
insnset := &InsnSet{
Insns: insns,
insnMap: make(map[string]*Insn),
}
for _, insn := range insnset.Insns {
insnset.insnMap[insn.Name] = insn
insn.insnMap = &insnset.insnMap
}
insnset.initPseudo()
for _, insn := range insnset.Insns {
insnset.modeInsns.Add(insn)
}
iset.Arches[iset.ArchPowerPC] = insnset
}
func (insn *Insn) Info() (string, iset.Mode, bool, bool) {
return insn.Name, insn.mode(), insn.Pseudo, insn.Priv
}
func (insn *Insn) mode() iset.Mode {
return (1 << iset.ModeLong64) | (1 << iset.ModeProt32)
}
func uint32toBytes(v uint32) []byte {
ret := make([]byte, 4)
binary.LittleEndian.PutUint32(ret, v)
return ret
}
func (insn *Insn) enc(v map[string]uint) []byte {
ret := make([]byte, 0)
ret = append(ret, insn.encOpcode(v, insn.Opcode, insn.Fields)...)
if insn.isPrefixed() {
ret = append(ret, insn.encOpcode(v, insn.OpcodeSuffix, insn.FieldsSuffix)...)
}
return ret
}
func (insn *Insn) encOpcode(v map[string]uint, opcode uint32, f []InsnField) []byte {
insn32 := opcode
for _, f := range insn.Fields {
if val, ok := v[f.Name]; ok {
insn32 |= encodeBits(val, f.Bits)
}
}
return uint32toBytes(insn32)
}
func (imap insnSetMap) ld64(reg uint, v uint64) []byte {
ret := make([]byte, 0)
// This is a widely used macro to load immediate on ppc64
// #define LOAD64(rn,name)
// addis rn,0,name##@highest \ lis rn,name##@highest
// ori rn,rn,name##@higher
// rldicr rn,rn,32,31
// oris rn,rn,name##@h
// ori rn,rn,name##@l
ret = append(ret, imap["addis"].enc(map[string]uint{
"RT": reg,
"RA": 0, // In "addis", '0' means 0, not GPR0 .
"SI": uint((v >> 48) & 0xffff)})...)
ret = append(ret, imap["ori"].enc(map[string]uint{
"RA": reg,
"RS": reg,
"UI": uint((v >> 32) & 0xffff)})...)
ret = append(ret, imap["rldicr"].enc(map[string]uint{
"RA": reg,
"RS": reg,
"SH": 32,
"ME": 31})...)
ret = append(ret, imap["oris"].enc(map[string]uint{
"RA": reg,
"RS": reg,
"UI": uint((v >> 16) & 0xffff)})...)
ret = append(ret, imap["ori"].enc(map[string]uint{
"RA": reg,
"RS": reg,
"UI": uint(v & 0xffff)})...)
return ret
}
func (imap insnSetMap) ld32(reg uint, v uint32) []byte {
ret := make([]byte, 0)
ret = append(ret, imap["addis"].enc(map[string]uint{
"RT": reg,
"RA": 0, // In "addis", '0' means 0, not GPR0
"SI": uint((v >> 16) & 0xffff)})...)
ret = append(ret, imap["ori"].enc(map[string]uint{
"RA": reg,
"RS": reg,
"UI": uint(v & 0xffff)})...)
return ret
}
func (imap insnSetMap) ldgpr32(regaddr, regval uint, addr uint64, v uint32) []byte {
ret := make([]byte, 0)
ret = append(ret, imap.ld64(regaddr, addr)...)
ret = append(ret, imap.ld32(regval, v)...)
ret = append(ret, imap["stw"].enc(map[string]uint{
"RA": regaddr,
"RS": regval})...)
return ret
}
func (imap insnSetMap) sc(lev uint) []byte {
return imap["sc"].enc(map[string]uint{"LEV": lev})
}
// Copyright 2020 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package powerpc
import (
"math/rand"
"github.com/google/syzkaller/pkg/ifuzz/iset"
)
const (
// Valid hcall humbers at the momemt are: 4..0x450.
MaxHcall = 0x450 // MAX_HCALL
SprnSrr0 = 0x01A // pc for rfid (SPRN_SRR0)
SprnSrr1 = 0x01B // msr for rfid (SPRN_SRR1)
)
// nolint:dupl
func (insnset *InsnSet) initPseudo() {
insnset.Insns = append(insnset.Insns, &Insn{
Name: "PSEUDO_hypercall",
Priv: true,
Pseudo: true,
generator: func(cfg *iset.Config, r *rand.Rand) []byte {
gen := makeGen(insnset, cfg, r)
gen.sc(1)
return gen.text
},
})
insnset.Insns = append(insnset.Insns, &Insn{
Name: "PSEUDO_syscall",
Priv: true,
Pseudo: true,
generator: func(cfg *iset.Config, r *rand.Rand) []byte {
gen := makeGen(insnset, cfg, r)
gen.sc(0)
return gen.text
},
})
insnset.Insns = append(insnset.Insns, &Insn{
Name: "PSEUDO_ultracall",
Priv: true,
Pseudo: true,
generator: func(cfg *iset.Config, r *rand.Rand) []byte {
gen := makeGen(insnset, cfg, r)
gen.sc(2)
return gen.text
},
})
insnset.Insns = append(insnset.Insns, &Insn{
Name: "PSEUDO_rtas",
Priv: true,
Pseudo: true,
generator: func(cfg *iset.Config, r *rand.Rand) []byte {
gen := makeGen(insnset, cfg, r)
gen.rtas()
return gen.text
},
})
insnset.Insns = append(insnset.Insns, &Insn{
Name: "PSEUDO_rfid",
Priv: true,
Pseudo: true,
generator: func(cfg *iset.Config, r *rand.Rand) []byte {
gen := makeGen(insnset, cfg, r)
gen.rfid()
return gen.text
},
})
}
type generator struct {
imap insnSetMap
cfg *iset.Config
r *rand.Rand
text []byte
}
func makeGen(insnset *InsnSet, cfg *iset.Config, r *rand.Rand) *generator {
return &generator{
imap: insnset.insnMap,
cfg: cfg,
r: r,
}
}
func (gen *generator) byte(v []byte) {
gen.text = append(gen.text, v...)
}
func (gen *generator) sc(lev uint) {
imap := gen.imap
n := gen.r.Intn(9)
hcrange := gen.r.Intn(3)
offset := 4
maxhc := MaxHcall
switch hcrange {
case 1:
offset = 0xf000
maxhc = 0xf810
case 2:
offset = 0xef00
maxhc = 0xef20
}
hc := gen.r.Intn((maxhc-offset)/4)*4 + offset
gen.byte(imap.ld64(3, uint64(hc)))
for i := 4; i < n+4; i++ {
gen.byte(imap.ld64(uint(i), gen.r.Uint64()))
}
gen.byte(imap.sc(lev))
}
func (gen *generator) rtas() {
imap := gen.imap
addr := iset.GenerateInt(gen.cfg, gen.r, 8)
token := uint32(gen.r.Intn(8) << 24) // There are only 4 tokens handled by KVM and it is BigEndian.
reg := uint(iset.GenerateInt(gen.cfg, gen.r, 4))
gen.byte(imap.ldgpr32(reg, reg+uint(1), addr, token))
for i := 0; i < gen.r.Intn(4)+1; i++ {
gen.byte(imap.ldgpr32(reg, reg+uint(1), addr+uint64(i*4),
uint32(iset.GenerateInt(gen.cfg, gen.r, 4))))
}
gen.byte(imap.ld64(3, 0xF000)) // 0xF000 is a custom H_RTAS hypercall
gen.byte(imap.ld64(4, addr))
gen.byte(imap.sc(1))
}
func (gen *generator) rfid() {
imap := gen.imap
tmpreg := uint(gen.r.Intn(32))
// SRR0 contains a PC
gen.byte(imap.ld64(tmpreg, iset.GenerateInt(gen.cfg, gen.r, 8)))
gen.byte(imap["mtspr"].enc(map[string]uint{"RS": tmpreg, "SPR": SprnSrr0}))
// SRR1 contains an MSR
gen.byte(imap.ld64(tmpreg, gen.r.Uint64()))
gen.byte(imap["mtspr"].enc(map[string]uint{"RS": tmpreg, "SPR": SprnSrr1}))
gen.byte(imap["rfid"].enc(map[string]uint{}))
}
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package x86
import (
"fmt"
"github.com/google/syzkaller/pkg/ifuzz/iset"
)
// Decode decodes instruction length for the given mode.
// It can have falsely decode incorrect instructions,
// but should not fail to decode correct instructions.
// nolint: gocyclo, nestif, gocognit, funlen
func (insnset *InsnSet) Decode(mode iset.Mode, text []byte) (int, error) {
if len(text) == 0 {
return 0, fmt.Errorf("zero-length instruction")
}
prefixes := prefixes32
var operSize, immSize, dispSize, addrSize int
switch mode {
case iset.ModeLong64:
operSize, immSize, dispSize, addrSize = 4, 4, 4, 8
prefixes = prefixes64
case iset.ModeProt32:
operSize, immSize, dispSize, addrSize = 4, 4, 4, 4
case iset.ModeProt16, iset.ModeReal16:
operSize, immSize, dispSize, addrSize = 2, 2, 2, 2
default:
panic("bad mode")
}
prefixLen := 0
var decodedPrefixes []byte
vex := false
if len(text) > 1 {
// There are only 2 32-bit instructions that look like VEX-prefixed but are actually not: LDS, LES.
// They always reference memory (mod!=3), but all VEX instructions have "mod=3" where LDS/LES would have mod.
if (text[0] == 0xc4 || text[0] == 0xc5) && (mode == iset.ModeLong64 || text[1]&0xc0 == 0xc0) {
vex = true
}
// There is only one instruction that looks like XOP-prefixed but is actually not: POP.
// It always has reg=0, but all XOP instructions have "reg!=0" where POP would have reg.
if text[0] == 0x8f && text[1]&0x38 != 0 {
vex = true
}
}
var vexMap byte
if vex {
prefixLen = 3
if text[0] == 0xc5 {
prefixLen = 2
vexMap = 1 // V0F
}
if len(text) < prefixLen {
return 0, fmt.Errorf("bad VEX/XOP prefix")
}
if prefixLen == 3 {
vexMap = text[1] & 0x1f
}
text = text[prefixLen:]
} else {
decodedPrefixes = text
operSize1, immSize1, dispSize1, addrSize1 := operSize, immSize, dispSize, addrSize
for len(text) != 0 && prefixes[text[0]] {
switch text[0] {
case 0x66:
switch immSize {
case 4:
immSize1 = 2
operSize1 = 2
case 2:
immSize1 = 4
operSize1 = 4
}
case 0x67:
switch addrSize {
case 8:
addrSize1 = 4
case 4:
dispSize1 = 2
addrSize1 = 2
case 2:
dispSize1 = 4
addrSize1 = 4
}
}
if text[0] & ^byte(7) == 0x48 {
operSize1 = 8
immSize1 = 4
}
text = text[1:]
prefixLen++
}
operSize, immSize, dispSize, addrSize = operSize1, immSize1, dispSize1, addrSize1
decodedPrefixes = decodedPrefixes[:prefixLen]
if len(text) == 0 {
return 0, fmt.Errorf("no opcode, only prefixes")
}
}
nextInsn:
for _, insn := range insnset.Insns {
if (insn.Mode & (1 << mode)) == 0 {
continue nextInsn
}
if vex != (insn.Vex != 0) {
continue nextInsn
}
if vex && insn.VexMap != vexMap {
continue nextInsn
}
if insn.NoRepPrefix || insn.No66Prefix {
for _, p := range decodedPrefixes {
if len(insn.Prefix) != 0 && insn.Prefix[0] == p {
continue
}
switch p {
case 0xf2, 0xf3:
if insn.NoRepPrefix {
continue nextInsn
}
case 0x66:
if insn.No66Prefix {
continue nextInsn
}
}
}
}
text1 := text
for i, v := range insn.Opcode {
if len(text1) == 0 {
continue nextInsn
}
b := text1[0]
if insn.Srm && i == len(insn.Opcode)-1 {
b &^= 7
}
if b != v {
continue nextInsn
}
text1 = text1[1:]
}
if insn.Modrm {
if len(text1) == 0 {
continue nextInsn
}
modrm := text1[0]
text1 = text1[1:]
mod := modrm >> 6
reg := int8(modrm>>3) & 7
rm := modrm & 7
if insn.Reg >= 0 && reg != insn.Reg {
continue nextInsn
}
if !insn.NoSibDisp {
disp := 0
if addrSize == 2 {
if mod == 1 {
disp = 1
} else if mod == 2 || mod == 0 && rm == 6 {
disp = 2
}
} else {
var sibbase byte
if mod != 3 && rm == 4 {
if len(text1) == 0 {
continue nextInsn
}
sib := text1[0]
text1 = text1[1:]
sibbase = sib & 7
}
if mod == 1 {
disp = 1
} else if mod == 2 || mod == 0 && rm == 5 || mod == 0 && sibbase == 5 {
disp = dispSize
}
}
if disp != 0 {
if len(text1) < disp {
continue nextInsn
}
text1 = text1[disp:]
}
}
}
immLen := 0
for _, imm := range []int8{insn.Imm, insn.Imm2} {
switch imm {
case -1:
immLen += immSize
case -2:
immLen += addrSize
case -3:
immLen += operSize
default:
immLen += int(imm)
}
}
if immLen != 0 {
if len(text1) < immLen {
continue nextInsn
}
text1 = text1[immLen:]
}
for _, v := range insn.Suffix {
if len(text1) == 0 || text1[0] != v {
continue nextInsn
}
text1 = text1[1:]
}
return prefixLen + len(text) - len(text1), nil
}
return 0, fmt.Errorf("unknown instruction")
}
var XedDecode func(mode iset.Mode, text []byte) (int, error)
var (
prefixes32 = map[byte]bool{
0x2E: true, 0x3E: true, 0x26: true, 0x64: true, 0x65: true,
0x36: true, 0x66: true, 0x67: true, 0xF3: true, 0xF2: true,
0xF0: true,
}
prefixes64 = map[byte]bool{
0x2E: true, 0x3E: true, 0x26: true, 0x64: true, 0x65: true,
0x36: true, 0x66: true, 0x67: true, 0xF3: true, 0xF2: true,
0xF0: true, 0x40: true, 0x41: true, 0x42: true, 0x43: true,
0x44: true, 0x45: true, 0x46: true, 0x47: true, 0x48: true,
0x49: true, 0x4a: true, 0x4b: true, 0x4c: true, 0x4d: true,
0x4e: true, 0x4f: true,
}
)
func (insnset *InsnSet) DecodeExt(mode iset.Mode, text []byte) (int, error) {
if XedDecode != nil && text != nil && len(text) > 0 {
return XedDecode(mode, text)
}
if XedDecode == nil {
return 0, fmt.Errorf("no XED")
}
return 0, nil // tells the caller XED is enabled
}
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
// See Intel Software Developer’s Manual Volume 2: Instruction Set Reference
// and AMD64 Architecture Programmer’s Manual Volume 3: General-Purpose and System Instructions
// for details of instruction encoding.
package x86
import (
"math/rand"
"github.com/google/syzkaller/pkg/ifuzz/iset"
)
// nolint: gocyclo, nestif, gocognit, funlen
func (insn *Insn) Encode(cfg *iset.Config, r *rand.Rand) []byte {
if !cfg.IsCompatible(insn) {
panic("instruction is not suitable for this mode")
}
if insn.Pseudo {
return insn.generator(cfg, r)
}
var operSize, immSize, dispSize, addrSize int
switch cfg.Mode {
case iset.ModeLong64:
operSize, immSize, dispSize, addrSize = 4, 4, 4, 8
case iset.ModeProt32:
operSize, immSize, dispSize, addrSize = 4, 4, 4, 4
case iset.ModeProt16, iset.ModeReal16:
operSize, immSize, dispSize, addrSize = 2, 2, 2, 2
default:
panic("bad mode")
}
var code []byte
rexR := false
var vvvv, vexR, vexX, vexB byte
// LEGACY PREFIXES
if insn.Vex == 0 {
for r.Intn(3) == 0 {
// LOCK 0xF0 is always added to insn.Prefix
prefixes := []byte{
0x2E, // CS
0x3E, // DS
0x26, // ES
0x64, // FS
0x65, // GS
0x36, // SS
}
if !insn.No66Prefix {
prefixes = append(prefixes, 0x66) // operand size
}
if cfg.Mode == iset.ModeLong64 || !insn.Mem32 {
prefixes = append(prefixes, 0x67) // address size
}
if !insn.NoRepPrefix {
prefixes = append(prefixes,
0xF3, // REP
0xF2, // REPNE
)
}
pref := prefixes[r.Intn(len(prefixes))]
code = append(code, pref)
}
code = append(code, insn.Prefix...)
// REX
var rex byte
if cfg.Mode == iset.ModeLong64 && r.Intn(2) == 0 {
// bit 0 - B
// bit 1 - X
// bit 2 - R
// bit 3 - W
rex = byte(0x40 | r.Intn(16))
if insn.Rexw == 1 {
rex |= 1 << 3
} else {
rex &^= 1 << 3
}
rexR = rex&0x4 != 0
code = append(code, rex)
}
operSize1, immSize1, dispSize1, addrSize1 := operSize, immSize, dispSize, addrSize
for _, pref := range code {
switch pref {
case 0x66:
switch immSize {
case 4:
immSize1 = 2
operSize1 = 2
case 2:
immSize1 = 4
operSize1 = 4
}
case 0x67:
switch addrSize {
case 8:
addrSize1 = 4
case 4:
dispSize1 = 2
addrSize1 = 2
case 2:
dispSize1 = 4
addrSize1 = 4
}
}
if rex&(1<<3) != 0 {
operSize1 = 8
immSize1 = 4
}
}
operSize, immSize, dispSize, addrSize = operSize1, immSize1, dispSize1, addrSize1
} else {
// VEX/VOP
code = append(code, insn.Vex)
vexR = byte(1)
vexX = byte(1)
if cfg.Mode == iset.ModeLong64 {
vexR = byte(r.Intn(2))
vexX = byte(r.Intn(2))
}
vexB = byte(r.Intn(2))
W := byte(r.Intn(2))
switch insn.Rexw {
case 1:
W = 1
case -1:
W = 0
}
L := byte(r.Intn(2))
switch insn.VexL {
case 1:
L = 1
case -1:
L = 0
}
pp := byte(r.Intn(4))
if insn.VexP != -1 {
pp = byte(insn.VexP)
}
vvvv = 15
if !insn.VexNoR {
vvvv = byte(r.Intn(16))
}
code = append(code, vexR<<7|vexX<<6|vexB<<5|insn.VexMap)
code = append(code, W<<7|vvvv<<3|L<<2|pp)
// TODO: short encoding
if cfg.Mode != iset.ModeLong64 {
vvvv |= 8
}
}
// OPCODE
code = append(code, insn.Opcode...)
if insn.Srm {
rm := byte(insn.Rm)
if insn.Rm == -1 {
rm = byte(r.Intn(8))
}
code[len(code)-1] |= rm
} else if insn.Modrm {
// MODRM
var mod byte
switch insn.Mod {
case 0, 1, 2, 3:
mod = byte(insn.Mod)
case -1:
mod = byte(r.Intn(4))
case -3:
mod = byte(r.Intn(3))
}
reg := byte(insn.Reg)
switch insn.Reg {
case -1:
reg = byte(r.Intn(8))
case -6:
reg = byte(r.Intn(6)) // segment register
case -8:
if rexR {
reg = 0 // CR8
} else {
crs := []byte{0, 2, 3, 4}
reg = crs[r.Intn(len(crs))]
}
}
if insn.Avx2Gather {
if reg|(1-vexR)<<3 == vvvv^0xf {
reg = (reg + 1) & 7
}
}
rm := byte(insn.Rm)
if insn.Rm == -1 {
rm = byte(r.Intn(8))
}
modrm := mod<<6 | reg<<3 | rm
code = append(code, modrm)
if !insn.NoSibDisp {
if addrSize == 2 {
if mod == 1 {
// disp8
code = append(code, generateArg(cfg, r, 1)...)
} else if mod == 2 || mod == 0 && rm == 6 {
// disp16
code = append(code, generateArg(cfg, r, 2)...)
}
} else {
var sibbase byte
if mod != 3 && rm == 4 {
// SIB
scale := byte(r.Intn(4))
index := byte(r.Intn(8))
sibbase = byte(r.Intn(8))
if insn.Avx2Gather {
rrrr := reg | (1-vexR)<<3
for {
iiii := index | (1-vexX)<<3
if iiii != vvvv^0xf && iiii != rrrr {
break
}
index = (index + 1) & 7
}
}
sib := scale<<6 | index<<3 | sibbase
code = append(code, sib)
}
if mod == 1 {
// disp8
code = append(code, generateArg(cfg, r, 1)...)
} else if mod == 2 || mod == 0 && rm == 5 || mod == 0 && sibbase == 5 {
// disp16/32
code = append(code, generateArg(cfg, r, dispSize)...)
}
}
}
}
addImm := func(imm int) {
switch imm {
case -1:
imm = immSize
case -2:
imm = addrSize
case -3:
imm = operSize
}
if imm != 0 {
code = append(code, generateArg(cfg, r, imm)...)
}
}
addImm(int(insn.Imm))
addImm(int(insn.Imm2))
code = append(code, insn.Suffix...)
return code
}
// Code generated by pkg/ifuzz/x86/gen. DO NOT EDIT.
//go:build !codeanalysis
package generated
import . "github.com/google/syzkaller/pkg/ifuzz/x86"
func init() {
Register(insns)
}
var insns = []*Insn{
{Name: "FADD", Extension: "X87", Mode: 15, Opcode: []uint8{216}, Modrm: true, Mod: -3, Rm: -1, Mem32: true, VexP: -1},
{Name: "FMUL", Extension: "X87", Mode: 15, Opcode: []uint8{216}, Modrm: true, Mod: -3, Reg: 1, Rm: -1, Mem32: true, VexP: -1},
{Name: "FCOMP", Extension: "X87", Mode: 15, Opcode: []uint8{216}, Modrm: true, Mod: -3, Reg: 3, Rm: -1, Mem32: true, VexP: -1},
{Name: "FSUB", Extension: "X87", Mode: 15, Opcode: []uint8{216}, Modrm: true, Mod: -3, Reg: 4, Rm: -1, Mem32: true, VexP: -1},
{Name: "FSUBR", Extension: "X87", Mode: 15, Opcode: []uint8{216}, Modrm: true, Mod: -3, Reg: 5, Rm: -1, Mem32: true, VexP: -1},
{Name: "FDIV", Extension: "X87", Mode: 15, Opcode: []uint8{216}, Modrm: true, Mod: -3, Reg: 6, Rm: -1, Mem32: true, VexP: -1},
{Name: "FDIVR", Extension: "X87", Mode: 15, Opcode: []uint8{216}, Modrm: true, Mod: -3, Reg: 7, Rm: -1, Mem32: true, VexP: -1},
{Name: "FADD", Extension: "X87", Mode: 15, Opcode: []uint8{216}, Modrm: true, Mod: 3, Rm: -1, VexP: -1},
{Name: "FMUL", Extension: "X87", Mode: 15, Opcode: []uint8{216}, Modrm: true, Mod: 3, Reg: 1, Rm: -1, VexP: -1},
{Name: "FCOM", Extension: "X87", Mode: 15, Opcode: []uint8{216}, Modrm: true, Mod: -3, Reg: 2, Rm: -1, Mem32: true, VexP: -1},
{Name: "FCOM", Extension: "X87", Mode: 15, Opcode: []uint8{220}, Modrm: true, Mod: -1, Reg: 2, Rm: -1, VexP: -1},
{Name: "FCOM", Extension: "X87", Mode: 15, Opcode: []uint8{216}, Modrm: true, Mod: 3, Reg: 2, Rm: -1, VexP: -1},
{Name: "FCOMP", Extension: "X87", Mode: 15, Opcode: []uint8{216}, Modrm: true, Mod: 3, Reg: 3, Rm: -1, VexP: -1},
{Name: "FCOMP", Extension: "X87", Mode: 15, Opcode: []uint8{220}, Modrm: true, Mod: -1, Reg: 3, Rm: -1, VexP: -1},
{Name: "FCOMP", Extension: "X87", Mode: 15, Opcode: []uint8{222}, Modrm: true, Mod: 3, Reg: 2, Rm: -1, VexP: -1},
{Name: "FSUB", Extension: "X87", Mode: 15, Opcode: []uint8{216}, Modrm: true, Mod: 3, Reg: 4, Rm: -1, VexP: -1},
{Name: "FSUBR", Extension: "X87", Mode: 15, Opcode: []uint8{216}, Modrm: true, Mod: 3, Reg: 5, Rm: -1, VexP: -1},
{Name: "FDIV", Extension: "X87", Mode: 15, Opcode: []uint8{216}, Modrm: true, Mod: 3, Reg: 6, Rm: -1, VexP: -1},
{Name: "FDIVR", Extension: "X87", Mode: 15, Opcode: []uint8{216}, Modrm: true, Mod: 3, Reg: 7, Rm: -1, VexP: -1},
{Name: "FLD", Extension: "X87", Mode: 15, Opcode: []uint8{217}, Modrm: true, Mod: -3, Rm: -1, Mem32: true, VexP: -1},
{Name: "FST", Extension: "X87", Mode: 15, Opcode: []uint8{217}, Modrm: true, Mod: -3, Reg: 2, Rm: -1, Mem32: true, VexP: -1},
{Name: "FSTP", Extension: "X87", Mode: 15, Opcode: []uint8{217}, Modrm: true, Mod: -3, Reg: 3, Rm: -1, Mem32: true, VexP: -1},
{Name: "FSTP", Extension: "X87", Mode: 15, Opcode: []uint8{219}, Modrm: true, Mod: -3, Reg: 7, Rm: -1, VexP: -1},
{Name: "FSTP", Extension: "X87", Mode: 15, Opcode: []uint8{221}, Modrm: true, Mod: -1, Reg: 3, Rm: -1, VexP: -1},
{Name: "FSTP", Extension: "X87", Mode: 15, Opcode: []uint8{223}, Modrm: true, Mod: 3, Reg: 2, Rm: -1, VexP: -1},
{Name: "FSTP", Extension: "X87", Mode: 15, Opcode: []uint8{223}, Modrm: true, Mod: 3, Reg: 3, Rm: -1, VexP: -1},
{Name: "FSTPNCE", Extension: "X87", Mode: 15, Opcode: []uint8{217}, Modrm: true, Mod: 3, Reg: 3, Rm: -1, VexP: -1},
{Name: "FLDENV", Extension: "X87", Mode: 15, Opcode: []uint8{217}, Modrm: true, Mod: -3, Reg: 4, Rm: -1, VexP: -1},
{Name: "FLDCW", Extension: "X87", Mode: 15, Opcode: []uint8{217}, Modrm: true, Mod: -3, Reg: 5, Rm: -1, Mem16: true, VexP: -1},
{Name: "FNSTENV", Extension: "X87", Mode: 15, Opcode: []uint8{217}, Modrm: true, Mod: -3, Reg: 6, Rm: -1, VexP: -1},
{Name: "FNSTCW", Extension: "X87", Mode: 15, Opcode: []uint8{217}, Modrm: true, Mod: -3, Reg: 7, Rm: -1, Mem16: true, VexP: -1},
{Name: "FLD", Extension: "X87", Mode: 15, Opcode: []uint8{217}, Modrm: true, Mod: 3, Rm: -1, VexP: -1},
{Name: "FXCH", Extension: "X87", Mode: 15, Opcode: []uint8{217}, Modrm: true, Mod: 3, Reg: 1, Rm: -1, VexP: -1},
{Name: "FXCH", Extension: "X87", Mode: 15, Opcode: []uint8{223}, Modrm: true, Mod: 3, Reg: 1, Rm: -1, VexP: -1},
{Name: "FXCH", Extension: "X87", Mode: 15, Opcode: []uint8{221}, Modrm: true, Mod: 3, Reg: 1, Rm: -1, VexP: -1},
{Name: "FNOP", Extension: "X87", Mode: 15, Opcode: []uint8{217}, Modrm: true, Mod: 3, Reg: 2, VexP: -1},
{Name: "FCHS", Extension: "X87", Mode: 15, Opcode: []uint8{217}, Modrm: true, Mod: 3, Reg: 4, VexP: -1},
{Name: "FABS", Extension: "X87", Mode: 15, Opcode: []uint8{217}, Modrm: true, Mod: 3, Reg: 4, Rm: 1, VexP: -1},
{Name: "FTST", Extension: "X87", Mode: 15, Opcode: []uint8{217}, Modrm: true, Mod: 3, Reg: 4, Rm: 4, VexP: -1},
{Name: "FXAM", Extension: "X87", Mode: 15, Opcode: []uint8{217}, Modrm: true, Mod: 3, Reg: 4, Rm: 5, VexP: -1},
{Name: "FLD1", Extension: "X87", Mode: 15, Opcode: []uint8{217}, Modrm: true, Mod: 3, Reg: 5, VexP: -1},
{Name: "FLDL2T", Extension: "X87", Mode: 15, Opcode: []uint8{217}, Modrm: true, Mod: 3, Reg: 5, Rm: 1, VexP: -1},
{Name: "FLDL2E", Extension: "X87", Mode: 15, Opcode: []uint8{217}, Modrm: true, Mod: 3, Reg: 5, Rm: 2, VexP: -1},
{Name: "FLDPI", Extension: "X87", Mode: 15, Opcode: []uint8{217}, Modrm: true, Mod: 3, Reg: 5, Rm: 3, VexP: -1},
{Name: "FLDLG2", Extension: "X87", Mode: 15, Opcode: []uint8{217}, Modrm: true, Mod: 3, Reg: 5, Rm: 4, VexP: -1},
{Name: "FLDLN2", Extension: "X87", Mode: 15, Opcode: []uint8{217}, Modrm: true, Mod: 3, Reg: 5, Rm: 5, VexP: -1},
{Name: "FLDZ", Extension: "X87", Mode: 15, Opcode: []uint8{217}, Modrm: true, Mod: 3, Reg: 5, Rm: 6, VexP: -1},
{Name: "F2XM1", Extension: "X87", Mode: 15, Opcode: []uint8{217}, Modrm: true, Mod: 3, Reg: 6, VexP: -1},
{Name: "FYL2X", Extension: "X87", Mode: 15, Opcode: []uint8{217}, Modrm: true, Mod: 3, Reg: 6, Rm: 1, VexP: -1},
{Name: "FPTAN", Extension: "X87", Mode: 15, Opcode: []uint8{217}, Modrm: true, Mod: 3, Reg: 6, Rm: 2, VexP: -1},
{Name: "FPATAN", Extension: "X87", Mode: 15, Opcode: []uint8{217}, Modrm: true, Mod: 3, Reg: 6, Rm: 3, VexP: -1},
{Name: "FXTRACT", Extension: "X87", Mode: 15, Opcode: []uint8{217}, Modrm: true, Mod: 3, Reg: 6, Rm: 4, VexP: -1},
{Name: "FPREM1", Extension: "X87", Mode: 15, Opcode: []uint8{217}, Modrm: true, Mod: 3, Reg: 6, Rm: 5, VexP: -1},
{Name: "FDECSTP", Extension: "X87", Mode: 15, Opcode: []uint8{217}, Modrm: true, Mod: 3, Reg: 6, Rm: 6, VexP: -1},
{Name: "FINCSTP", Extension: "X87", Mode: 15, Opcode: []uint8{217}, Modrm: true, Mod: 3, Reg: 6, Rm: 7, VexP: -1},
{Name: "FPREM", Extension: "X87", Mode: 15, Opcode: []uint8{217}, Modrm: true, Mod: 3, Reg: 7, VexP: -1},
{Name: "FYL2XP1", Extension: "X87", Mode: 15, Opcode: []uint8{217}, Modrm: true, Mod: 3, Reg: 7, Rm: 1, VexP: -1},
{Name: "FSQRT", Extension: "X87", Mode: 15, Opcode: []uint8{217}, Modrm: true, Mod: 3, Reg: 7, Rm: 2, VexP: -1},
{Name: "FSINCOS", Extension: "X87", Mode: 15, Opcode: []uint8{217}, Modrm: true, Mod: 3, Reg: 7, Rm: 3, VexP: -1},
{Name: "FRNDINT", Extension: "X87", Mode: 15, Opcode: []uint8{217}, Modrm: true, Mod: 3, Reg: 7, Rm: 4, VexP: -1},
{Name: "FSCALE", Extension: "X87", Mode: 15, Opcode: []uint8{217}, Modrm: true, Mod: 3, Reg: 7, Rm: 5, VexP: -1},
{Name: "FSIN", Extension: "X87", Mode: 15, Opcode: []uint8{217}, Modrm: true, Mod: 3, Reg: 7, Rm: 6, VexP: -1},
{Name: "FCOS", Extension: "X87", Mode: 15, Opcode: []uint8{217}, Modrm: true, Mod: 3, Reg: 7, Rm: 7, VexP: -1},
{Name: "FIADD", Extension: "X87", Mode: 15, Opcode: []uint8{218}, Modrm: true, Mod: -3, Rm: -1, Mem32: true, VexP: -1},
{Name: "FIMUL", Extension: "X87", Mode: 15, Opcode: []uint8{218}, Modrm: true, Mod: -3, Reg: 1, Rm: -1, Mem32: true, VexP: -1},
{Name: "FICOM", Extension: "X87", Mode: 15, Opcode: []uint8{218}, Modrm: true, Mod: -3, Reg: 2, Rm: -1, Mem32: true, VexP: -1},
{Name: "FICOMP", Extension: "X87", Mode: 15, Opcode: []uint8{218}, Modrm: true, Mod: -3, Reg: 3, Rm: -1, Mem32: true, VexP: -1},
{Name: "FISUB", Extension: "X87", Mode: 15, Opcode: []uint8{218}, Modrm: true, Mod: -3, Reg: 4, Rm: -1, Mem32: true, VexP: -1},
{Name: "FISUBR", Extension: "X87", Mode: 15, Opcode: []uint8{218}, Modrm: true, Mod: -3, Reg: 5, Rm: -1, Mem32: true, VexP: -1},
{Name: "FIDIV", Extension: "X87", Mode: 15, Opcode: []uint8{218}, Modrm: true, Mod: -3, Reg: 6, Rm: -1, Mem32: true, VexP: -1},
{Name: "FIDIVR", Extension: "X87", Mode: 15, Opcode: []uint8{218}, Modrm: true, Mod: -3, Reg: 7, Rm: -1, Mem32: true, VexP: -1},
{Name: "FCMOVB", Extension: "X87", Mode: 15, Opcode: []uint8{218}, Modrm: true, Mod: 3, Rm: -1, VexP: -1},
{Name: "FCMOVE", Extension: "X87", Mode: 15, Opcode: []uint8{218}, Modrm: true, Mod: 3, Reg: 1, Rm: -1, VexP: -1},
{Name: "FCMOVBE", Extension: "X87", Mode: 15, Opcode: []uint8{218}, Modrm: true, Mod: 3, Reg: 2, Rm: -1, VexP: -1},
{Name: "FCMOVU", Extension: "X87", Mode: 15, Opcode: []uint8{218}, Modrm: true, Mod: 3, Reg: 3, Rm: -1, VexP: -1},
{Name: "FUCOMPP", Extension: "X87", Mode: 15, Opcode: []uint8{218}, Modrm: true, Mod: 3, Reg: 5, Rm: 1, VexP: -1},
{Name: "FILD", Extension: "X87", Mode: 15, Opcode: []uint8{219}, Modrm: true, Mod: -3, Rm: -1, Mem32: true, VexP: -1},
{Name: "FISTTP", Extension: "SSE3", Mode: 15, Opcode: []uint8{219}, Modrm: true, Mod: -3, Reg: 1, Rm: -1, Mem32: true, VexP: -1},
{Name: "FIST", Extension: "X87", Mode: 15, Opcode: []uint8{219}, Modrm: true, Mod: -3, Reg: 2, Rm: -1, Mem32: true, VexP: -1},
{Name: "FISTP", Extension: "X87", Mode: 15, Opcode: []uint8{219}, Modrm: true, Mod: -3, Reg: 3, Rm: -1, Mem32: true, VexP: -1},
{Name: "FLD", Extension: "X87", Mode: 15, Opcode: []uint8{219}, Modrm: true, Mod: -3, Reg: 5, Rm: -1, VexP: -1},
{Name: "FCMOVNB", Extension: "X87", Mode: 15, Opcode: []uint8{219}, Modrm: true, Mod: 3, Rm: -1, VexP: -1},
{Name: "FCMOVNE", Extension: "X87", Mode: 15, Opcode: []uint8{219}, Modrm: true, Mod: 3, Reg: 1, Rm: -1, VexP: -1},
{Name: "FCMOVNBE", Extension: "X87", Mode: 15, Opcode: []uint8{219}, Modrm: true, Mod: 3, Reg: 2, Rm: -1, VexP: -1},
{Name: "FCMOVNU", Extension: "X87", Mode: 15, Opcode: []uint8{219}, Modrm: true, Mod: 3, Reg: 3, Rm: -1, VexP: -1},
{Name: "FNCLEX", Extension: "X87", Mode: 15, Opcode: []uint8{219}, Modrm: true, Mod: 3, Reg: 4, Rm: 2, VexP: -1},
{Name: "FNINIT", Extension: "X87", Mode: 15, Opcode: []uint8{219}, Modrm: true, Mod: 3, Reg: 4, Rm: 3, VexP: -1},
{Name: "FSETPM287_NOP", Extension: "X87", Mode: 15, Opcode: []uint8{219}, Modrm: true, Mod: 3, Reg: 4, Rm: 4, VexP: -1},
{Name: "FENI8087_NOP", Extension: "X87", Mode: 15, Opcode: []uint8{219}, Modrm: true, Mod: 3, Reg: 4, VexP: -1},
{Name: "FDISI8087_NOP", Extension: "X87", Mode: 15, Opcode: []uint8{219}, Modrm: true, Mod: 3, Reg: 4, Rm: 1, VexP: -1},
{Name: "FUCOMI", Extension: "X87", Mode: 15, Opcode: []uint8{219}, Modrm: true, Mod: 3, Reg: 5, Rm: -1, VexP: -1},
{Name: "FCOMI", Extension: "X87", Mode: 15, Opcode: []uint8{219}, Modrm: true, Mod: 3, Reg: 6, Rm: -1, VexP: -1},
{Name: "FADD", Extension: "X87", Mode: 15, Opcode: []uint8{220}, Modrm: true, Mod: -1, Rm: -1, VexP: -1},
{Name: "FMUL", Extension: "X87", Mode: 15, Opcode: []uint8{220}, Modrm: true, Mod: -1, Reg: 1, Rm: -1, VexP: -1},
{Name: "FSUB", Extension: "X87", Mode: 15, Opcode: []uint8{220}, Modrm: true, Mod: -3, Reg: 4, Rm: -1, VexP: -1},
{Name: "FSUBR", Extension: "X87", Mode: 15, Opcode: []uint8{220}, Modrm: true, Mod: -3, Reg: 5, Rm: -1, VexP: -1},
{Name: "FDIV", Extension: "X87", Mode: 15, Opcode: []uint8{220}, Modrm: true, Mod: -3, Reg: 6, Rm: -1, VexP: -1},
{Name: "FDIVR", Extension: "X87", Mode: 15, Opcode: []uint8{220}, Modrm: true, Mod: -3, Reg: 7, Rm: -1, VexP: -1},
{Name: "FSUBR", Extension: "X87", Mode: 15, Opcode: []uint8{220}, Modrm: true, Mod: 3, Reg: 4, Rm: -1, VexP: -1},
{Name: "FSUB", Extension: "X87", Mode: 15, Opcode: []uint8{220}, Modrm: true, Mod: 3, Reg: 5, Rm: -1, VexP: -1},
{Name: "FDIVR", Extension: "X87", Mode: 15, Opcode: []uint8{220}, Modrm: true, Mod: 3, Reg: 6, Rm: -1, VexP: -1},
{Name: "FDIV", Extension: "X87", Mode: 15, Opcode: []uint8{220}, Modrm: true, Mod: 3, Reg: 7, Rm: -1, VexP: -1},
{Name: "FLD", Extension: "X87", Mode: 15, Opcode: []uint8{221}, Modrm: true, Mod: -3, Rm: -1, VexP: -1},
{Name: "FISTTP", Extension: "SSE3", Mode: 15, Opcode: []uint8{221}, Modrm: true, Mod: -3, Reg: 1, Rm: -1, VexP: -1},
{Name: "FST", Extension: "X87", Mode: 15, Opcode: []uint8{221}, Modrm: true, Mod: -1, Reg: 2, Rm: -1, VexP: -1},
{Name: "FRSTOR", Extension: "X87", Mode: 15, Opcode: []uint8{221}, Modrm: true, Mod: -3, Reg: 4, Rm: -1, VexP: -1},
{Name: "FNSAVE", Extension: "X87", Mode: 15, Opcode: []uint8{221}, Modrm: true, Mod: -3, Reg: 6, Rm: -1, VexP: -1},
{Name: "FNSTSW", Extension: "X87", Mode: 15, Opcode: []uint8{221}, Modrm: true, Mod: -3, Reg: 7, Rm: -1, Mem16: true, VexP: -1},
{Name: "FFREE", Extension: "X87", Mode: 15, Opcode: []uint8{221}, Modrm: true, Mod: 3, Rm: -1, VexP: -1},
{Name: "FUCOM", Extension: "X87", Mode: 15, Opcode: []uint8{221}, Modrm: true, Mod: 3, Reg: 4, Rm: -1, VexP: -1},
{Name: "FUCOMP", Extension: "X87", Mode: 15, Opcode: []uint8{221}, Modrm: true, Mod: 3, Reg: 5, Rm: -1, VexP: -1},
{Name: "FIADD", Extension: "X87", Mode: 15, Opcode: []uint8{222}, Modrm: true, Mod: -3, Rm: -1, Mem16: true, VexP: -1},
{Name: "FIMUL", Extension: "X87", Mode: 15, Opcode: []uint8{222}, Modrm: true, Mod: -3, Reg: 1, Rm: -1, Mem16: true, VexP: -1},
{Name: "FICOM", Extension: "X87", Mode: 15, Opcode: []uint8{222}, Modrm: true, Mod: -3, Reg: 2, Rm: -1, Mem16: true, VexP: -1},
{Name: "FICOMP", Extension: "X87", Mode: 15, Opcode: []uint8{222}, Modrm: true, Mod: -3, Reg: 3, Rm: -1, Mem16: true, VexP: -1},
{Name: "FISUB", Extension: "X87", Mode: 15, Opcode: []uint8{222}, Modrm: true, Mod: -3, Reg: 4, Rm: -1, Mem16: true, VexP: -1},
{Name: "FISUBR", Extension: "X87", Mode: 15, Opcode: []uint8{222}, Modrm: true, Mod: -3, Reg: 5, Rm: -1, Mem16: true, VexP: -1},
{Name: "FIDIV", Extension: "X87", Mode: 15, Opcode: []uint8{222}, Modrm: true, Mod: -3, Reg: 6, Rm: -1, Mem16: true, VexP: -1},
{Name: "FIDIVR", Extension: "X87", Mode: 15, Opcode: []uint8{222}, Modrm: true, Mod: -3, Reg: 7, Rm: -1, Mem16: true, VexP: -1},
{Name: "FADDP", Extension: "X87", Mode: 15, Opcode: []uint8{222}, Modrm: true, Mod: 3, Rm: -1, VexP: -1},
{Name: "FMULP", Extension: "X87", Mode: 15, Opcode: []uint8{222}, Modrm: true, Mod: 3, Reg: 1, Rm: -1, VexP: -1},
{Name: "FCOMPP", Extension: "X87", Mode: 15, Opcode: []uint8{222}, Modrm: true, Mod: 3, Reg: 3, Rm: 1, VexP: -1},
{Name: "FSUBRP", Extension: "X87", Mode: 15, Opcode: []uint8{222}, Modrm: true, Mod: 3, Reg: 4, Rm: -1, VexP: -1},
{Name: "FSUBP", Extension: "X87", Mode: 15, Opcode: []uint8{222}, Modrm: true, Mod: 3, Reg: 5, Rm: -1, VexP: -1},
{Name: "FDIVRP", Extension: "X87", Mode: 15, Opcode: []uint8{222}, Modrm: true, Mod: 3, Reg: 6, Rm: -1, VexP: -1},
{Name: "FDIVP", Extension: "X87", Mode: 15, Opcode: []uint8{222}, Modrm: true, Mod: 3, Reg: 7, Rm: -1, VexP: -1},
{Name: "FILD", Extension: "X87", Mode: 15, Opcode: []uint8{223}, Modrm: true, Mod: -3, Rm: -1, Mem16: true, VexP: -1},
{Name: "FISTTP", Extension: "SSE3", Mode: 15, Opcode: []uint8{223}, Modrm: true, Mod: -3, Reg: 1, Rm: -1, Mem16: true, VexP: -1},
{Name: "FIST", Extension: "X87", Mode: 15, Opcode: []uint8{223}, Modrm: true, Mod: -3, Reg: 2, Rm: -1, Mem16: true, VexP: -1},
{Name: "FISTP", Extension: "X87", Mode: 15, Opcode: []uint8{223}, Modrm: true, Mod: -3, Reg: 3, Rm: -1, Mem16: true, VexP: -1},
{Name: "FBLD", Extension: "X87", Mode: 15, Opcode: []uint8{223}, Modrm: true, Mod: -3, Reg: 4, Rm: -1, VexP: -1},
{Name: "FILD", Extension: "X87", Mode: 15, Opcode: []uint8{223}, Modrm: true, Mod: -3, Reg: 5, Rm: -1, VexP: -1},
{Name: "FBSTP", Extension: "X87", Mode: 15, Opcode: []uint8{223}, Modrm: true, Mod: -3, Reg: 6, Rm: -1, VexP: -1},
{Name: "FISTP", Extension: "X87", Mode: 15, Opcode: []uint8{223}, Modrm: true, Mod: -3, Reg: 7, Rm: -1, VexP: -1},
{Name: "FFREEP", Extension: "X87", Mode: 15, Opcode: []uint8{223}, Modrm: true, Mod: 3, Rm: -1, VexP: -1},
{Name: "FNSTSW", Extension: "X87", Mode: 15, Opcode: []uint8{223}, Modrm: true, Mod: 3, Reg: 4, VexP: -1},
{Name: "FUCOMIP", Extension: "X87", Mode: 15, Opcode: []uint8{223}, Modrm: true, Mod: 3, Reg: 5, Rm: -1, VexP: -1},
{Name: "FCOMIP", Extension: "X87", Mode: 15, Opcode: []uint8{223}, Modrm: true, Mod: 3, Reg: 6, Rm: -1, VexP: -1},
{Name: "ADD_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{128}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Rm: -1, Imm: 1, VexP: -1},
{Name: "ADD", Extension: "BASE", Mode: 15, Opcode: []uint8{128}, Modrm: true, Mod: -1, Rm: -1, Imm: 1, VexP: -1},
{Name: "OR_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{128}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: 1, Rm: -1, Imm: 1, VexP: -1},
{Name: "OR", Extension: "BASE", Mode: 15, Opcode: []uint8{128}, Modrm: true, Mod: -1, Reg: 1, Rm: -1, Imm: 1, VexP: -1},
{Name: "ADC_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{128}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: 2, Rm: -1, Imm: 1, VexP: -1},
{Name: "ADC", Extension: "BASE", Mode: 15, Opcode: []uint8{128}, Modrm: true, Mod: -1, Reg: 2, Rm: -1, Imm: 1, VexP: -1},
{Name: "SBB_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{128}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: 3, Rm: -1, Imm: 1, VexP: -1},
{Name: "SBB", Extension: "BASE", Mode: 15, Opcode: []uint8{128}, Modrm: true, Mod: -1, Reg: 3, Rm: -1, Imm: 1, VexP: -1},
{Name: "AND_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{128}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: 4, Rm: -1, Imm: 1, VexP: -1},
{Name: "AND", Extension: "BASE", Mode: 15, Opcode: []uint8{128}, Modrm: true, Mod: -1, Reg: 4, Rm: -1, Imm: 1, VexP: -1},
{Name: "SUB_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{128}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: 5, Rm: -1, Imm: 1, VexP: -1},
{Name: "SUB", Extension: "BASE", Mode: 15, Opcode: []uint8{128}, Modrm: true, Mod: -1, Reg: 5, Rm: -1, Imm: 1, VexP: -1},
{Name: "XOR_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{128}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: 6, Rm: -1, Imm: 1, VexP: -1},
{Name: "XOR", Extension: "BASE", Mode: 15, Opcode: []uint8{128}, Modrm: true, Mod: -1, Reg: 6, Rm: -1, Imm: 1, VexP: -1},
{Name: "CMP", Extension: "BASE", Mode: 15, Opcode: []uint8{128}, Modrm: true, Mod: -1, Reg: 7, Rm: -1, Imm: 1, VexP: -1},
{Name: "ADD_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{129}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Rm: -1, Imm: -1, VexP: -1},
{Name: "ADD", Extension: "BASE", Mode: 15, Opcode: []uint8{129}, Modrm: true, Mod: -1, Rm: -1, Imm: -1, VexP: -1},
{Name: "OR_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{129}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: 1, Rm: -1, Imm: -1, VexP: -1},
{Name: "OR", Extension: "BASE", Mode: 15, Opcode: []uint8{129}, Modrm: true, Mod: -1, Reg: 1, Rm: -1, Imm: -1, VexP: -1},
{Name: "ADC_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{129}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: 2, Rm: -1, Imm: -1, VexP: -1},
{Name: "ADC", Extension: "BASE", Mode: 15, Opcode: []uint8{129}, Modrm: true, Mod: -1, Reg: 2, Rm: -1, Imm: -1, VexP: -1},
{Name: "SBB_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{129}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: 3, Rm: -1, Imm: -1, VexP: -1},
{Name: "SBB", Extension: "BASE", Mode: 15, Opcode: []uint8{129}, Modrm: true, Mod: -1, Reg: 3, Rm: -1, Imm: -1, VexP: -1},
{Name: "AND_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{129}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: 4, Rm: -1, Imm: -1, VexP: -1},
{Name: "AND", Extension: "BASE", Mode: 15, Opcode: []uint8{129}, Modrm: true, Mod: -1, Reg: 4, Rm: -1, Imm: -1, VexP: -1},
{Name: "SUB_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{129}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: 5, Rm: -1, Imm: -1, VexP: -1},
{Name: "SUB", Extension: "BASE", Mode: 15, Opcode: []uint8{129}, Modrm: true, Mod: -1, Reg: 5, Rm: -1, Imm: -1, VexP: -1},
{Name: "XOR_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{129}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: 6, Rm: -1, Imm: -1, VexP: -1},
{Name: "XOR", Extension: "BASE", Mode: 15, Opcode: []uint8{129}, Modrm: true, Mod: -1, Reg: 6, Rm: -1, Imm: -1, VexP: -1},
{Name: "CMP", Extension: "BASE", Mode: 15, Opcode: []uint8{129}, Modrm: true, Mod: -1, Reg: 7, Rm: -1, Imm: -1, VexP: -1},
{Name: "ADD_LOCK", Extension: "BASE", Mode: 14, Opcode: []uint8{130}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Rm: -1, Imm: 1, VexP: -1},
{Name: "ADD", Extension: "BASE", Mode: 14, Opcode: []uint8{130}, Modrm: true, Mod: -1, Rm: -1, Imm: 1, VexP: -1},
{Name: "OR_LOCK", Extension: "BASE", Mode: 14, Opcode: []uint8{130}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: 1, Rm: -1, Imm: 1, VexP: -1},
{Name: "OR", Extension: "BASE", Mode: 14, Opcode: []uint8{130}, Modrm: true, Mod: -1, Reg: 1, Rm: -1, Imm: 1, VexP: -1},
{Name: "ADC_LOCK", Extension: "BASE", Mode: 14, Opcode: []uint8{130}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: 2, Rm: -1, Imm: 1, VexP: -1},
{Name: "ADC", Extension: "BASE", Mode: 14, Opcode: []uint8{130}, Modrm: true, Mod: -1, Reg: 2, Rm: -1, Imm: 1, VexP: -1},
{Name: "SBB_LOCK", Extension: "BASE", Mode: 14, Opcode: []uint8{130}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: 3, Rm: -1, Imm: 1, VexP: -1},
{Name: "SBB", Extension: "BASE", Mode: 14, Opcode: []uint8{130}, Modrm: true, Mod: -1, Reg: 3, Rm: -1, Imm: 1, VexP: -1},
{Name: "AND_LOCK", Extension: "BASE", Mode: 14, Opcode: []uint8{130}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: 4, Rm: -1, Imm: 1, VexP: -1},
{Name: "AND", Extension: "BASE", Mode: 14, Opcode: []uint8{130}, Modrm: true, Mod: -1, Reg: 4, Rm: -1, Imm: 1, VexP: -1},
{Name: "SUB_LOCK", Extension: "BASE", Mode: 14, Opcode: []uint8{130}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: 5, Rm: -1, Imm: 1, VexP: -1},
{Name: "SUB", Extension: "BASE", Mode: 14, Opcode: []uint8{130}, Modrm: true, Mod: -1, Reg: 5, Rm: -1, Imm: 1, VexP: -1},
{Name: "XOR_LOCK", Extension: "BASE", Mode: 14, Opcode: []uint8{130}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: 6, Rm: -1, Imm: 1, VexP: -1},
{Name: "XOR", Extension: "BASE", Mode: 14, Opcode: []uint8{130}, Modrm: true, Mod: -1, Reg: 6, Rm: -1, Imm: 1, VexP: -1},
{Name: "CMP", Extension: "BASE", Mode: 14, Opcode: []uint8{130}, Modrm: true, Mod: -1, Reg: 7, Rm: -1, Imm: 1, VexP: -1},
{Name: "ADD_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{131}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Rm: -1, Imm: 1, VexP: -1},
{Name: "ADD", Extension: "BASE", Mode: 15, Opcode: []uint8{131}, Modrm: true, Mod: -1, Rm: -1, Imm: 1, VexP: -1},
{Name: "OR_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{131}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: 1, Rm: -1, Imm: 1, VexP: -1},
{Name: "OR", Extension: "BASE", Mode: 15, Opcode: []uint8{131}, Modrm: true, Mod: -1, Reg: 1, Rm: -1, Imm: 1, VexP: -1},
{Name: "ADC_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{131}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: 2, Rm: -1, Imm: 1, VexP: -1},
{Name: "ADC", Extension: "BASE", Mode: 15, Opcode: []uint8{131}, Modrm: true, Mod: -1, Reg: 2, Rm: -1, Imm: 1, VexP: -1},
{Name: "SBB_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{131}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: 3, Rm: -1, Imm: 1, VexP: -1},
{Name: "SBB", Extension: "BASE", Mode: 15, Opcode: []uint8{131}, Modrm: true, Mod: -1, Reg: 3, Rm: -1, Imm: 1, VexP: -1},
{Name: "AND_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{131}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: 4, Rm: -1, Imm: 1, VexP: -1},
{Name: "AND", Extension: "BASE", Mode: 15, Opcode: []uint8{131}, Modrm: true, Mod: -1, Reg: 4, Rm: -1, Imm: 1, VexP: -1},
{Name: "SUB_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{131}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: 5, Rm: -1, Imm: 1, VexP: -1},
{Name: "SUB", Extension: "BASE", Mode: 15, Opcode: []uint8{131}, Modrm: true, Mod: -1, Reg: 5, Rm: -1, Imm: 1, VexP: -1},
{Name: "XOR_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{131}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: 6, Rm: -1, Imm: 1, VexP: -1},
{Name: "XOR", Extension: "BASE", Mode: 15, Opcode: []uint8{131}, Modrm: true, Mod: -1, Reg: 6, Rm: -1, Imm: 1, VexP: -1},
{Name: "CMP", Extension: "BASE", Mode: 15, Opcode: []uint8{131}, Modrm: true, Mod: -1, Reg: 7, Rm: -1, Imm: 1, VexP: -1},
{Name: "POP", Extension: "BASE", Mode: 15, Opcode: []uint8{143}, Modrm: true, Mod: -1, Rm: -1, VexP: -1},
{Name: "ROL", Extension: "BASE", Mode: 15, Opcode: []uint8{192}, Modrm: true, Mod: -1, Rm: -1, Imm: 1, VexP: -1},
{Name: "ROL", Extension: "BASE", Mode: 15, Opcode: []uint8{193}, Modrm: true, Mod: -1, Rm: -1, Imm: 1, VexP: -1},
{Name: "ROR", Extension: "BASE", Mode: 15, Opcode: []uint8{192}, Modrm: true, Mod: -1, Reg: 1, Rm: -1, Imm: 1, VexP: -1},
{Name: "ROR", Extension: "BASE", Mode: 15, Opcode: []uint8{193}, Modrm: true, Mod: -1, Reg: 1, Rm: -1, Imm: 1, VexP: -1},
{Name: "ROR", Extension: "BASE", Mode: 15, Opcode: []uint8{208}, Modrm: true, Mod: -1, Reg: 1, Rm: -1, VexP: -1},
{Name: "ROR", Extension: "BASE", Mode: 15, Opcode: []uint8{209}, Modrm: true, Mod: -1, Reg: 1, Rm: -1, VexP: -1},
{Name: "ROR", Extension: "BASE", Mode: 15, Opcode: []uint8{210}, Modrm: true, Mod: -1, Reg: 1, Rm: -1, VexP: -1},
{Name: "ROR", Extension: "BASE", Mode: 15, Opcode: []uint8{211}, Modrm: true, Mod: -1, Reg: 1, Rm: -1, VexP: -1},
{Name: "ROL", Extension: "BASE", Mode: 15, Opcode: []uint8{208}, Modrm: true, Mod: -1, Rm: -1, VexP: -1},
{Name: "ROL", Extension: "BASE", Mode: 15, Opcode: []uint8{209}, Modrm: true, Mod: -1, Rm: -1, VexP: -1},
{Name: "ROL", Extension: "BASE", Mode: 15, Opcode: []uint8{210}, Modrm: true, Mod: -1, Rm: -1, VexP: -1},
{Name: "ROL", Extension: "BASE", Mode: 15, Opcode: []uint8{211}, Modrm: true, Mod: -1, Rm: -1, VexP: -1},
{Name: "RCL", Extension: "BASE", Mode: 15, Opcode: []uint8{192}, Modrm: true, Mod: -1, Reg: 2, Rm: -1, Imm: 1, VexP: -1},
{Name: "RCR", Extension: "BASE", Mode: 15, Opcode: []uint8{192}, Modrm: true, Mod: -1, Reg: 3, Rm: -1, Imm: 1, VexP: -1},
{Name: "SHL", Extension: "BASE", Mode: 15, Opcode: []uint8{192}, Modrm: true, Mod: -1, Reg: 4, Rm: -1, Imm: 1, VexP: -1},
{Name: "SHR", Extension: "BASE", Mode: 15, Opcode: []uint8{192}, Modrm: true, Mod: -1, Reg: 5, Rm: -1, Imm: 1, VexP: -1},
{Name: "SHL", Extension: "BASE", Mode: 15, Opcode: []uint8{192}, Modrm: true, Mod: -1, Reg: 6, Rm: -1, Imm: 1, VexP: -1},
{Name: "SAR", Extension: "BASE", Mode: 15, Opcode: []uint8{192}, Modrm: true, Mod: -1, Reg: 7, Rm: -1, Imm: 1, VexP: -1},
{Name: "RCL", Extension: "BASE", Mode: 15, Opcode: []uint8{193}, Modrm: true, Mod: -1, Reg: 2, Rm: -1, Imm: 1, VexP: -1},
{Name: "RCR", Extension: "BASE", Mode: 15, Opcode: []uint8{193}, Modrm: true, Mod: -1, Reg: 3, Rm: -1, Imm: 1, VexP: -1},
{Name: "SHL", Extension: "BASE", Mode: 15, Opcode: []uint8{193}, Modrm: true, Mod: -1, Reg: 4, Rm: -1, Imm: 1, VexP: -1},
{Name: "SHR", Extension: "BASE", Mode: 15, Opcode: []uint8{193}, Modrm: true, Mod: -1, Reg: 5, Rm: -1, Imm: 1, VexP: -1},
{Name: "SHL", Extension: "BASE", Mode: 15, Opcode: []uint8{193}, Modrm: true, Mod: -1, Reg: 6, Rm: -1, Imm: 1, VexP: -1},
{Name: "SAR", Extension: "BASE", Mode: 15, Opcode: []uint8{193}, Modrm: true, Mod: -1, Reg: 7, Rm: -1, Imm: 1, VexP: -1},
{Name: "RCL", Extension: "BASE", Mode: 15, Opcode: []uint8{208}, Modrm: true, Mod: -1, Reg: 2, Rm: -1, VexP: -1},
{Name: "RCR", Extension: "BASE", Mode: 15, Opcode: []uint8{208}, Modrm: true, Mod: -1, Reg: 3, Rm: -1, VexP: -1},
{Name: "SHL", Extension: "BASE", Mode: 15, Opcode: []uint8{208}, Modrm: true, Mod: -1, Reg: 4, Rm: -1, VexP: -1},
{Name: "SHL", Extension: "BASE", Mode: 15, Opcode: []uint8{208}, Modrm: true, Mod: -1, Reg: 6, Rm: -1, VexP: -1},
{Name: "SHR", Extension: "BASE", Mode: 15, Opcode: []uint8{208}, Modrm: true, Mod: -1, Reg: 5, Rm: -1, VexP: -1},
{Name: "SAR", Extension: "BASE", Mode: 15, Opcode: []uint8{208}, Modrm: true, Mod: -1, Reg: 7, Rm: -1, VexP: -1},
{Name: "RCL", Extension: "BASE", Mode: 15, Opcode: []uint8{209}, Modrm: true, Mod: -1, Reg: 2, Rm: -1, VexP: -1},
{Name: "RCR", Extension: "BASE", Mode: 15, Opcode: []uint8{209}, Modrm: true, Mod: -1, Reg: 3, Rm: -1, VexP: -1},
{Name: "SHR", Extension: "BASE", Mode: 15, Opcode: []uint8{209}, Modrm: true, Mod: -1, Reg: 5, Rm: -1, VexP: -1},
{Name: "SHL", Extension: "BASE", Mode: 15, Opcode: []uint8{209}, Modrm: true, Mod: -1, Reg: 6, Rm: -1, VexP: -1},
{Name: "SHL", Extension: "BASE", Mode: 15, Opcode: []uint8{209}, Modrm: true, Mod: -1, Reg: 4, Rm: -1, VexP: -1},
{Name: "SAR", Extension: "BASE", Mode: 15, Opcode: []uint8{209}, Modrm: true, Mod: -1, Reg: 7, Rm: -1, VexP: -1},
{Name: "RCL", Extension: "BASE", Mode: 15, Opcode: []uint8{210}, Modrm: true, Mod: -1, Reg: 2, Rm: -1, VexP: -1},
{Name: "RCR", Extension: "BASE", Mode: 15, Opcode: []uint8{210}, Modrm: true, Mod: -1, Reg: 3, Rm: -1, VexP: -1},
{Name: "SHL", Extension: "BASE", Mode: 15, Opcode: []uint8{210}, Modrm: true, Mod: -1, Reg: 4, Rm: -1, VexP: -1},
{Name: "SHR", Extension: "BASE", Mode: 15, Opcode: []uint8{210}, Modrm: true, Mod: -1, Reg: 5, Rm: -1, VexP: -1},
{Name: "SHL", Extension: "BASE", Mode: 15, Opcode: []uint8{210}, Modrm: true, Mod: -1, Reg: 6, Rm: -1, VexP: -1},
{Name: "SAR", Extension: "BASE", Mode: 15, Opcode: []uint8{210}, Modrm: true, Mod: -1, Reg: 7, Rm: -1, VexP: -1},
{Name: "RCL", Extension: "BASE", Mode: 15, Opcode: []uint8{211}, Modrm: true, Mod: -1, Reg: 2, Rm: -1, VexP: -1},
{Name: "RCR", Extension: "BASE", Mode: 15, Opcode: []uint8{211}, Modrm: true, Mod: -1, Reg: 3, Rm: -1, VexP: -1},
{Name: "SHL", Extension: "BASE", Mode: 15, Opcode: []uint8{211}, Modrm: true, Mod: -1, Reg: 4, Rm: -1, VexP: -1},
{Name: "SHR", Extension: "BASE", Mode: 15, Opcode: []uint8{211}, Modrm: true, Mod: -1, Reg: 5, Rm: -1, VexP: -1},
{Name: "SHL", Extension: "BASE", Mode: 15, Opcode: []uint8{211}, Modrm: true, Mod: -1, Reg: 6, Rm: -1, VexP: -1},
{Name: "SAR", Extension: "BASE", Mode: 15, Opcode: []uint8{211}, Modrm: true, Mod: -1, Reg: 7, Rm: -1, VexP: -1},
{Name: "TEST", Extension: "BASE", Mode: 15, Opcode: []uint8{246}, Modrm: true, Mod: -1, Rm: -1, Imm: 1, VexP: -1},
{Name: "TEST", Extension: "BASE", Mode: 15, Opcode: []uint8{246}, Modrm: true, Mod: -1, Reg: 1, Rm: -1, Imm: 1, VexP: -1},
{Name: "NOT_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{246}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: 2, Rm: -1, VexP: -1},
{Name: "NOT", Extension: "BASE", Mode: 15, Opcode: []uint8{246}, Modrm: true, Mod: -1, Reg: 2, Rm: -1, VexP: -1},
{Name: "NEG_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{246}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: 3, Rm: -1, VexP: -1},
{Name: "NEG", Extension: "BASE", Mode: 15, Opcode: []uint8{246}, Modrm: true, Mod: -1, Reg: 3, Rm: -1, VexP: -1},
{Name: "MUL", Extension: "BASE", Mode: 15, Opcode: []uint8{246}, Modrm: true, Mod: -1, Reg: 4, Rm: -1, VexP: -1},
{Name: "IMUL", Extension: "BASE", Mode: 15, Opcode: []uint8{246}, Modrm: true, Mod: -1, Reg: 5, Rm: -1, VexP: -1},
{Name: "DIV", Extension: "BASE", Mode: 15, Opcode: []uint8{246}, Modrm: true, Mod: -1, Reg: 6, Rm: -1, VexP: -1},
{Name: "IDIV", Extension: "BASE", Mode: 15, Opcode: []uint8{246}, Modrm: true, Mod: -1, Reg: 7, Rm: -1, VexP: -1},
{Name: "TEST", Extension: "BASE", Mode: 15, Opcode: []uint8{247}, Modrm: true, Mod: -1, Rm: -1, Imm: -1, VexP: -1},
{Name: "TEST", Extension: "BASE", Mode: 15, Opcode: []uint8{247}, Modrm: true, Mod: -1, Reg: 1, Rm: -1, Imm: -1, VexP: -1},
{Name: "NOT_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{247}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: 2, Rm: -1, VexP: -1},
{Name: "NOT", Extension: "BASE", Mode: 15, Opcode: []uint8{247}, Modrm: true, Mod: -1, Reg: 2, Rm: -1, VexP: -1},
{Name: "NEG_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{247}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: 3, Rm: -1, VexP: -1},
{Name: "NEG", Extension: "BASE", Mode: 15, Opcode: []uint8{247}, Modrm: true, Mod: -1, Reg: 3, Rm: -1, VexP: -1},
{Name: "MUL", Extension: "BASE", Mode: 15, Opcode: []uint8{247}, Modrm: true, Mod: -1, Reg: 4, Rm: -1, VexP: -1},
{Name: "IMUL", Extension: "BASE", Mode: 15, Opcode: []uint8{247}, Modrm: true, Mod: -1, Reg: 5, Rm: -1, VexP: -1},
{Name: "DIV", Extension: "BASE", Mode: 15, Opcode: []uint8{247}, Modrm: true, Mod: -1, Reg: 6, Rm: -1, VexP: -1},
{Name: "IDIV", Extension: "BASE", Mode: 15, Opcode: []uint8{247}, Modrm: true, Mod: -1, Reg: 7, Rm: -1, VexP: -1},
{Name: "INC_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{254}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Rm: -1, VexP: -1},
{Name: "INC", Extension: "BASE", Mode: 15, Opcode: []uint8{254}, Modrm: true, Mod: -1, Rm: -1, VexP: -1},
{Name: "DEC_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{254}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: 1, Rm: -1, VexP: -1},
{Name: "DEC", Extension: "BASE", Mode: 15, Opcode: []uint8{254}, Modrm: true, Mod: -1, Reg: 1, Rm: -1, VexP: -1},
{Name: "INC_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{255}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Rm: -1, VexP: -1},
{Name: "INC", Extension: "BASE", Mode: 15, Opcode: []uint8{255}, Modrm: true, Mod: -1, Rm: -1, VexP: -1},
{Name: "DEC_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{255}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: 1, Rm: -1, VexP: -1},
{Name: "DEC", Extension: "BASE", Mode: 15, Opcode: []uint8{255}, Modrm: true, Mod: -1, Reg: 1, Rm: -1, VexP: -1},
{Name: "CALL_NEAR", Extension: "BASE", Mode: 15, Opcode: []uint8{255}, Modrm: true, Mod: -1, Reg: 2, Rm: -1, VexP: -1},
{Name: "CALL_NEAR", Extension: "BASE", Mode: 14, Opcode: []uint8{232}, Mod: -100, Reg: -100, Rm: -100, Imm: -1, VexP: -1},
{Name: "CALL_NEAR", Extension: "BASE", Mode: 1, Opcode: []uint8{232}, Mod: -100, Reg: -100, Rm: -100, Imm: 4, VexP: -1},
{Name: "JMP", Extension: "BASE", Mode: 15, Opcode: []uint8{255}, Modrm: true, Mod: -1, Reg: 4, Rm: -1, VexP: -1},
{Name: "JMP_FAR", Extension: "BASE", Mode: 15, Opcode: []uint8{255}, Modrm: true, Mod: -3, Reg: 5, Rm: -1, VexP: -1},
{Name: "PUSH", Extension: "BASE", Mode: 15, Opcode: []uint8{255}, Modrm: true, Mod: -1, Reg: 6, Rm: -1, VexP: -1},
{Name: "SLDT", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 0}, Modrm: true, Mod: -1, Rm: -1, VexP: -1},
{Name: "STR", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 0}, Modrm: true, Mod: -1, Reg: 1, Rm: -1, VexP: -1},
{Name: "LLDT", Extension: "BASE", Mode: 15, Priv: true, Opcode: []uint8{15, 0}, Modrm: true, Mod: -1, Reg: 2, Rm: -1, VexP: -1},
{Name: "LTR", Extension: "BASE", Mode: 15, Priv: true, Opcode: []uint8{15, 0}, Modrm: true, Mod: -1, Reg: 3, Rm: -1, VexP: -1},
{Name: "VERR", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 0}, Modrm: true, Mod: -1, Reg: 4, Rm: -1, VexP: -1},
{Name: "VERW", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 0}, Modrm: true, Mod: -1, Reg: 5, Rm: -1, VexP: -1},
{Name: "LGDT", Extension: "BASE", Mode: 1, Opcode: []uint8{15, 1}, Modrm: true, Mod: -3, Reg: 2, Rm: -1, VexP: -1},
{Name: "LGDT", Extension: "BASE", Mode: 14, Opcode: []uint8{15, 1}, Modrm: true, Mod: -3, Reg: 2, Rm: -1, VexP: -1},
{Name: "SMSW", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 1}, Modrm: true, Mod: -1, Reg: 4, Rm: -1, VexP: -1},
{Name: "LMSW", Extension: "BASE", Mode: 15, Priv: true, Opcode: []uint8{15, 1}, Modrm: true, Mod: -1, Reg: 6, Rm: -1, VexP: -1},
{Name: "BT", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 186}, Modrm: true, Mod: -1, Reg: 4, Rm: -1, Imm: 1, VexP: -1},
{Name: "BTS_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 186}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: 5, Rm: -1, Imm: 1, VexP: -1},
{Name: "BTS", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 186}, Modrm: true, Mod: -1, Reg: 5, Rm: -1, Imm: 1, VexP: -1},
{Name: "BTR_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 186}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: 6, Rm: -1, Imm: 1, VexP: -1},
{Name: "BTR", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 186}, Modrm: true, Mod: -1, Reg: 6, Rm: -1, Imm: 1, VexP: -1},
{Name: "BTC_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 186}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: 7, Rm: -1, Imm: 1, VexP: -1},
{Name: "BTC", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 186}, Modrm: true, Mod: -1, Reg: 7, Rm: -1, Imm: 1, VexP: -1},
{Name: "VMCLEAR", Extension: "VTX", Mode: 15, Priv: true, Opcode: []uint8{15, 199}, Prefix: []uint8{102}, Modrm: true, Mod: -3, Reg: 6, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "VMPTRLD", Extension: "VTX", Mode: 15, Priv: true, Opcode: []uint8{15, 199}, Modrm: true, Mod: -3, Reg: 6, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "VMPTRST", Extension: "VTX", Mode: 15, Priv: true, Opcode: []uint8{15, 199}, Modrm: true, Mod: -3, Reg: 7, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "VMXON", Extension: "VTX", Mode: 15, Priv: true, Opcode: []uint8{15, 199}, Prefix: []uint8{243}, Modrm: true, Mod: -3, Reg: 6, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "CMPXCHG8B_LOCK", Extension: "BASE", Mode: 14, Opcode: []uint8{15, 199}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: 1, Rm: -1, VexP: -1},
{Name: "CMPXCHG8B_LOCK", Extension: "BASE", Mode: 1, Opcode: []uint8{15, 199}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: 1, Rm: -1, Rexw: -1, VexP: -1},
{Name: "CMPXCHG8B", Extension: "BASE", Mode: 14, Opcode: []uint8{15, 199}, Modrm: true, Mod: -3, Reg: 1, Rm: -1, VexP: -1},
{Name: "CMPXCHG8B", Extension: "BASE", Mode: 1, Opcode: []uint8{15, 199}, Modrm: true, Mod: -3, Reg: 1, Rm: -1, Rexw: -1, VexP: -1},
{Name: "CMPXCHG16B_LOCK", Extension: "LONGMODE", Mode: 1, Opcode: []uint8{15, 199}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: 1, Rm: -1, Rexw: 1, VexP: -1},
{Name: "CMPXCHG16B", Extension: "LONGMODE", Mode: 1, Opcode: []uint8{15, 199}, Modrm: true, Mod: -3, Reg: 1, Rm: -1, Rexw: 1, VexP: -1},
{Name: "MOV", Extension: "BASE", Mode: 15, Opcode: []uint8{198}, Modrm: true, Mod: -1, Rm: -1, Imm: 1, VexP: -1},
{Name: "MOV", Extension: "BASE", Mode: 15, Opcode: []uint8{199}, Modrm: true, Mod: -1, Rm: -1, Imm: -1, VexP: -1},
{Name: "PSRLW", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 113}, Modrm: true, Mod: 3, Reg: 2, Rm: -1, Imm: 1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PSRAW", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 113}, Modrm: true, Mod: 3, Reg: 4, Rm: -1, Imm: 1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PSLLW", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 113}, Modrm: true, Mod: 3, Reg: 6, Rm: -1, Imm: 1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PSRLW", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 113}, Prefix: []uint8{102}, Modrm: true, Mod: 3, Reg: 2, Rm: -1, Imm: 1, NoRepPrefix: true, VexP: -1},
{Name: "PSRAW", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 113}, Prefix: []uint8{102}, Modrm: true, Mod: 3, Reg: 4, Rm: -1, Imm: 1, NoRepPrefix: true, VexP: -1},
{Name: "PSLLW", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 113}, Prefix: []uint8{102}, Modrm: true, Mod: 3, Reg: 6, Rm: -1, Imm: 1, NoRepPrefix: true, VexP: -1},
{Name: "PSRLD", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 114}, Modrm: true, Mod: 3, Reg: 2, Rm: -1, Imm: 1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PSRAD", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 114}, Modrm: true, Mod: 3, Reg: 4, Rm: -1, Imm: 1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PSLLD", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 114}, Modrm: true, Mod: 3, Reg: 6, Rm: -1, Imm: 1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PSRLD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 114}, Prefix: []uint8{102}, Modrm: true, Mod: 3, Reg: 2, Rm: -1, Imm: 1, NoRepPrefix: true, VexP: -1},
{Name: "PSRAD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 114}, Prefix: []uint8{102}, Modrm: true, Mod: 3, Reg: 4, Rm: -1, Imm: 1, NoRepPrefix: true, VexP: -1},
{Name: "PSLLD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 114}, Prefix: []uint8{102}, Modrm: true, Mod: 3, Reg: 6, Rm: -1, Imm: 1, NoRepPrefix: true, VexP: -1},
{Name: "PSRLQ", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 115}, Modrm: true, Mod: 3, Reg: 2, Rm: -1, Imm: 1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PSLLQ", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 115}, Modrm: true, Mod: 3, Reg: 6, Rm: -1, Imm: 1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PSRLQ", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 115}, Prefix: []uint8{102}, Modrm: true, Mod: 3, Reg: 2, Rm: -1, Imm: 1, NoRepPrefix: true, VexP: -1},
{Name: "PSRLDQ", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 115}, Prefix: []uint8{102}, Modrm: true, Mod: 3, Reg: 3, Rm: -1, Imm: 1, NoRepPrefix: true, VexP: -1},
{Name: "PSLLQ", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 115}, Prefix: []uint8{102}, Modrm: true, Mod: 3, Reg: 6, Rm: -1, Imm: 1, NoRepPrefix: true, VexP: -1},
{Name: "PSLLDQ", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 115}, Prefix: []uint8{102}, Modrm: true, Mod: 3, Reg: 7, Rm: -1, Imm: 1, NoRepPrefix: true, VexP: -1},
{Name: "FXSAVE", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 174}, Modrm: true, Mod: -3, Rm: -1, NoRepPrefix: true, No66Prefix: true, Rexw: -1, VexP: -1},
{Name: "FXRSTOR", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 174}, Modrm: true, Mod: -3, Reg: 1, Rm: -1, NoRepPrefix: true, No66Prefix: true, Rexw: -1, VexP: -1},
{Name: "FXSAVE64", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 174}, Modrm: true, Mod: -3, Rm: -1, NoRepPrefix: true, No66Prefix: true, Rexw: 1, VexP: -1},
{Name: "FXRSTOR64", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 174}, Modrm: true, Mod: -3, Reg: 1, Rm: -1, NoRepPrefix: true, No66Prefix: true, Rexw: 1, VexP: -1},
{Name: "LDMXCSR", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 174}, Modrm: true, Mod: -3, Reg: 2, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "STMXCSR", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 174}, Modrm: true, Mod: -3, Reg: 3, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PREFETCHNTA", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 24}, Modrm: true, Mod: -3, Rm: -1, VexP: -1},
{Name: "PREFETCHT0", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 24}, Modrm: true, Mod: -3, Reg: 1, Rm: -1, VexP: -1},
{Name: "PREFETCHT1", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 24}, Modrm: true, Mod: -3, Reg: 2, Rm: -1, VexP: -1},
{Name: "PREFETCHT2", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 24}, Modrm: true, Mod: -3, Reg: 3, Rm: -1, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 24}, Modrm: true, Mod: 3, Rm: -1, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 24}, Modrm: true, Mod: 3, Reg: 1, Rm: -1, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 24}, Modrm: true, Mod: 3, Reg: 2, Rm: -1, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 24}, Modrm: true, Mod: 3, Reg: 3, Rm: -1, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 24}, Modrm: true, Mod: -1, Reg: 4, Rm: -1, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 24}, Modrm: true, Mod: -1, Reg: 5, Rm: -1, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 24}, Modrm: true, Mod: -1, Reg: 6, Rm: -1, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 24}, Modrm: true, Mod: -1, Reg: 7, Rm: -1, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 25}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 26}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 27}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 28}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 29}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 30}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 31}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "VMCALL", Extension: "VTX", Mode: 15, Opcode: []uint8{15, 1}, Modrm: true, Mod: 3, Rm: 1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "VMLAUNCH", Extension: "VTX", Mode: 15, Priv: true, Opcode: []uint8{15, 1}, Modrm: true, Mod: 3, Rm: 2, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "VMRESUME", Extension: "VTX", Mode: 15, Priv: true, Opcode: []uint8{15, 1}, Modrm: true, Mod: 3, Rm: 3, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "VMXOFF", Extension: "VTX", Mode: 15, Priv: true, Opcode: []uint8{15, 1}, Modrm: true, Mod: 3, Rm: 4, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "SGDT", Extension: "BASE", Mode: 1, Opcode: []uint8{15, 1}, Modrm: true, Mod: -3, Rm: -1, VexP: -1},
{Name: "SGDT", Extension: "BASE", Mode: 14, Opcode: []uint8{15, 1}, Modrm: true, Mod: -3, Rm: -1, VexP: -1},
{Name: "LIDT", Extension: "BASE", Mode: 1, Priv: true, Opcode: []uint8{15, 1}, Modrm: true, Mod: -3, Reg: 3, Rm: -1, VexP: -1},
{Name: "LIDT", Extension: "BASE", Mode: 14, Priv: true, Opcode: []uint8{15, 1}, Modrm: true, Mod: -3, Reg: 3, Rm: -1, VexP: -1},
{Name: "MONITOR", Extension: "MONITOR", Mode: 14, Priv: true, Opcode: []uint8{15, 1}, Modrm: true, Mod: 3, Reg: 1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "MONITOR", Extension: "MONITOR", Mode: 1, Priv: true, Opcode: []uint8{15, 1}, Modrm: true, Mod: 3, Reg: 1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "MWAIT", Extension: "MONITOR", Mode: 15, Priv: true, Opcode: []uint8{15, 1}, Modrm: true, Mod: 3, Reg: 1, Rm: 1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "SIDT", Extension: "BASE", Mode: 14, Opcode: []uint8{15, 1}, Modrm: true, Mod: -3, Reg: 1, Rm: -1, VexP: -1},
{Name: "SIDT", Extension: "BASE", Mode: 1, Opcode: []uint8{15, 1}, Modrm: true, Mod: -3, Reg: 1, Rm: -1, VexP: -1},
{Name: "INVLPG", Extension: "BASE", Mode: 15, Priv: true, Opcode: []uint8{15, 1}, Modrm: true, Mod: -3, Reg: 7, Rm: -1, VexP: -1},
{Name: "SWAPGS", Extension: "LONGMODE", Mode: 1, Priv: true, Opcode: []uint8{15, 1}, Modrm: true, Mod: 3, Reg: 7, VexP: -1},
{Name: "RDTSCP", Extension: "RDTSCP", Mode: 15, Opcode: []uint8{15, 1}, Modrm: true, Mod: 3, Reg: 7, Rm: 1, VexP: -1},
{Name: "SFENCE", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 174}, Modrm: true, Mod: 3, Reg: 7, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "CLFLUSH", Extension: "CLFSH", Mode: 15, Opcode: []uint8{15, 174}, Modrm: true, Mod: -3, Reg: 7, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "LFENCE", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 174}, Modrm: true, Mod: 3, Reg: 5, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "MFENCE", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 174}, Modrm: true, Mod: 3, Reg: 6, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "MOVHLPS", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 18}, Modrm: true, Mod: 3, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "MOVLPS", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 18}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "MOVLHPS", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 22}, Modrm: true, Mod: 3, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "MOVHPS", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 22}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "ADD_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{0}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, VexP: -1},
{Name: "ADD", Extension: "BASE", Mode: 15, Opcode: []uint8{0}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "ADD_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{1}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, VexP: -1},
{Name: "ADD", Extension: "BASE", Mode: 15, Opcode: []uint8{1}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "ADD", Extension: "BASE", Mode: 15, Opcode: []uint8{2}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "ADD", Extension: "BASE", Mode: 15, Opcode: []uint8{3}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "ADD", Extension: "BASE", Mode: 15, Opcode: []uint8{4}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "ADD", Extension: "BASE", Mode: 15, Opcode: []uint8{5}, Mod: -100, Reg: -100, Rm: -100, Imm: -1, VexP: -1},
{Name: "PUSH", Extension: "BASE", Mode: 14, Opcode: []uint8{6}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "POP", Extension: "BASE", Mode: 14, Opcode: []uint8{7}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "OR_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{8}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, VexP: -1},
{Name: "OR", Extension: "BASE", Mode: 15, Opcode: []uint8{8}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "OR_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{9}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, VexP: -1},
{Name: "OR", Extension: "BASE", Mode: 15, Opcode: []uint8{9}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "OR", Extension: "BASE", Mode: 15, Opcode: []uint8{10}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "OR", Extension: "BASE", Mode: 15, Opcode: []uint8{11}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "OR", Extension: "BASE", Mode: 15, Opcode: []uint8{12}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "OR", Extension: "BASE", Mode: 15, Opcode: []uint8{13}, Mod: -100, Reg: -100, Rm: -100, Imm: -1, VexP: -1},
{Name: "PUSH", Extension: "BASE", Mode: 14, Opcode: []uint8{14}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "ADC_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{16}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, VexP: -1},
{Name: "ADC", Extension: "BASE", Mode: 15, Opcode: []uint8{16}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "ADC_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{17}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, VexP: -1},
{Name: "ADC", Extension: "BASE", Mode: 15, Opcode: []uint8{17}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "ADC", Extension: "BASE", Mode: 15, Opcode: []uint8{18}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "ADC", Extension: "BASE", Mode: 15, Opcode: []uint8{19}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "ADC", Extension: "BASE", Mode: 15, Opcode: []uint8{20}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "ADC", Extension: "BASE", Mode: 15, Opcode: []uint8{21}, Mod: -100, Reg: -100, Rm: -100, Imm: -1, VexP: -1},
{Name: "PUSH", Extension: "BASE", Mode: 14, Opcode: []uint8{22}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "POP", Extension: "BASE", Mode: 14, Opcode: []uint8{23}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "SBB_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{24}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, VexP: -1},
{Name: "SBB", Extension: "BASE", Mode: 15, Opcode: []uint8{24}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "SBB_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{25}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, VexP: -1},
{Name: "SBB", Extension: "BASE", Mode: 15, Opcode: []uint8{25}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "SBB", Extension: "BASE", Mode: 15, Opcode: []uint8{26}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "SBB", Extension: "BASE", Mode: 15, Opcode: []uint8{27}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "SBB", Extension: "BASE", Mode: 15, Opcode: []uint8{28}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "SBB", Extension: "BASE", Mode: 15, Opcode: []uint8{29}, Mod: -100, Reg: -100, Rm: -100, Imm: -1, VexP: -1},
{Name: "PUSH", Extension: "BASE", Mode: 14, Opcode: []uint8{30}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "POP", Extension: "BASE", Mode: 14, Opcode: []uint8{31}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "AND_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{32}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, VexP: -1},
{Name: "AND", Extension: "BASE", Mode: 15, Opcode: []uint8{32}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "AND_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{33}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, VexP: -1},
{Name: "AND", Extension: "BASE", Mode: 15, Opcode: []uint8{33}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "AND", Extension: "BASE", Mode: 15, Opcode: []uint8{34}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "AND", Extension: "BASE", Mode: 15, Opcode: []uint8{35}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "AND", Extension: "BASE", Mode: 15, Opcode: []uint8{36}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "AND", Extension: "BASE", Mode: 15, Opcode: []uint8{37}, Mod: -100, Reg: -100, Rm: -100, Imm: -1, VexP: -1},
{Name: "DAA", Extension: "BASE", Mode: 14, Opcode: []uint8{39}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "SUB_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{40}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, VexP: -1},
{Name: "SUB", Extension: "BASE", Mode: 15, Opcode: []uint8{40}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "SUB_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{41}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, VexP: -1},
{Name: "SUB", Extension: "BASE", Mode: 15, Opcode: []uint8{41}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "SUB", Extension: "BASE", Mode: 15, Opcode: []uint8{42}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "SUB", Extension: "BASE", Mode: 15, Opcode: []uint8{43}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "SUB", Extension: "BASE", Mode: 15, Opcode: []uint8{44}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "SUB", Extension: "BASE", Mode: 15, Opcode: []uint8{45}, Mod: -100, Reg: -100, Rm: -100, Imm: -1, VexP: -1},
{Name: "DAS", Extension: "BASE", Mode: 14, Opcode: []uint8{47}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "XOR_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{48}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, VexP: -1},
{Name: "XOR", Extension: "BASE", Mode: 15, Opcode: []uint8{48}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "XOR_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{49}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, VexP: -1},
{Name: "XOR", Extension: "BASE", Mode: 15, Opcode: []uint8{49}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "XOR", Extension: "BASE", Mode: 15, Opcode: []uint8{50}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "XOR", Extension: "BASE", Mode: 15, Opcode: []uint8{51}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "XOR", Extension: "BASE", Mode: 15, Opcode: []uint8{52}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "XOR", Extension: "BASE", Mode: 15, Opcode: []uint8{53}, Mod: -100, Reg: -100, Rm: -100, Imm: -1, VexP: -1},
{Name: "AAA", Extension: "BASE", Mode: 14, Opcode: []uint8{55}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "CMP", Extension: "BASE", Mode: 15, Opcode: []uint8{56}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "CMP", Extension: "BASE", Mode: 15, Opcode: []uint8{57}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "CMP", Extension: "BASE", Mode: 15, Opcode: []uint8{58}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "CMP", Extension: "BASE", Mode: 15, Opcode: []uint8{59}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "CMP", Extension: "BASE", Mode: 15, Opcode: []uint8{60}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "CMP", Extension: "BASE", Mode: 15, Opcode: []uint8{61}, Mod: -100, Reg: -100, Rm: -100, Imm: -1, VexP: -1},
{Name: "AAS", Extension: "BASE", Mode: 14, Opcode: []uint8{63}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "INC", Extension: "BASE", Mode: 14, Opcode: []uint8{64}, Mod: -100, Reg: -100, Rm: -1, Srm: true, VexP: -1},
{Name: "DEC", Extension: "BASE", Mode: 14, Opcode: []uint8{72}, Mod: -100, Reg: -100, Rm: -1, Srm: true, VexP: -1},
{Name: "PUSH", Extension: "BASE", Mode: 15, Opcode: []uint8{80}, Mod: -100, Reg: -100, Rm: -1, Srm: true, VexP: -1},
{Name: "POP", Extension: "BASE", Mode: 15, Opcode: []uint8{88}, Mod: -100, Reg: -100, Rm: -1, Srm: true, VexP: -1},
{Name: "PUSHA", Extension: "BASE", Mode: 14, Opcode: []uint8{96}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "PUSHAD", Extension: "BASE", Mode: 14, Opcode: []uint8{96}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "POPA", Extension: "BASE", Mode: 14, Opcode: []uint8{97}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "POPAD", Extension: "BASE", Mode: 14, Opcode: []uint8{97}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "BOUND", Extension: "BASE", Mode: 14, Opcode: []uint8{98}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, VexP: -1},
{Name: "BOUND", Extension: "BASE", Mode: 14, Opcode: []uint8{98}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, No66Prefix: true, VexP: -1},
{Name: "ARPL", Extension: "BASE", Mode: 14, Opcode: []uint8{99}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "MOVSXD", Extension: "LONGMODE", Mode: 1, Opcode: []uint8{99}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "PUSH", Extension: "BASE", Mode: 15, Opcode: []uint8{104}, Mod: -100, Reg: -100, Rm: -100, Imm: -1, VexP: -1},
{Name: "IMUL", Extension: "BASE", Mode: 15, Opcode: []uint8{105}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: -1, VexP: -1},
{Name: "PUSH", Extension: "BASE", Mode: 15, Opcode: []uint8{106}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "IMUL", Extension: "BASE", Mode: 15, Opcode: []uint8{107}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, VexP: -1},
{Name: "REP_INSB", Extension: "BASE", Mode: 15, Opcode: []uint8{108}, Prefix: []uint8{243}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "REP_INSB", Extension: "BASE", Mode: 15, Opcode: []uint8{108}, Prefix: []uint8{242}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "INSB", Extension: "BASE", Mode: 15, Opcode: []uint8{108}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "REP_INSW", Extension: "BASE", Mode: 15, Opcode: []uint8{109}, Prefix: []uint8{243}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "REP_INSW", Extension: "BASE", Mode: 15, Opcode: []uint8{109}, Prefix: []uint8{242}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "INSW", Extension: "BASE", Mode: 15, Opcode: []uint8{109}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "REP_INSD", Extension: "BASE", Mode: 15, Opcode: []uint8{109}, Prefix: []uint8{243}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "REP_INSD", Extension: "BASE", Mode: 15, Opcode: []uint8{109}, Prefix: []uint8{242}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "INSD", Extension: "BASE", Mode: 15, Opcode: []uint8{109}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "REP_OUTSB", Extension: "BASE", Mode: 15, Opcode: []uint8{110}, Prefix: []uint8{243}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "REP_OUTSB", Extension: "BASE", Mode: 15, Opcode: []uint8{110}, Prefix: []uint8{242}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "OUTSB", Extension: "BASE", Mode: 15, Opcode: []uint8{110}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "REP_OUTSW", Extension: "BASE", Mode: 15, Opcode: []uint8{111}, Prefix: []uint8{243}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "REP_OUTSW", Extension: "BASE", Mode: 15, Opcode: []uint8{111}, Prefix: []uint8{242}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "OUTSW", Extension: "BASE", Mode: 15, Opcode: []uint8{111}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "REP_OUTSD", Extension: "BASE", Mode: 15, Opcode: []uint8{111}, Prefix: []uint8{243}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "REP_OUTSD", Extension: "BASE", Mode: 15, Opcode: []uint8{111}, Prefix: []uint8{242}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "OUTSD", Extension: "BASE", Mode: 15, Opcode: []uint8{111}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "JO", Extension: "BASE", Mode: 1, Opcode: []uint8{112}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "JO", Extension: "BASE", Mode: 14, Opcode: []uint8{112}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "JNO", Extension: "BASE", Mode: 1, Opcode: []uint8{113}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "JNO", Extension: "BASE", Mode: 14, Opcode: []uint8{113}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "JB", Extension: "BASE", Mode: 1, Opcode: []uint8{114}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "JB", Extension: "BASE", Mode: 14, Opcode: []uint8{114}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "JNB", Extension: "BASE", Mode: 1, Opcode: []uint8{115}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "JNB", Extension: "BASE", Mode: 14, Opcode: []uint8{115}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "JZ", Extension: "BASE", Mode: 1, Opcode: []uint8{116}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "JZ", Extension: "BASE", Mode: 14, Opcode: []uint8{116}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "JNZ", Extension: "BASE", Mode: 1, Opcode: []uint8{117}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "JNZ", Extension: "BASE", Mode: 14, Opcode: []uint8{117}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "JBE", Extension: "BASE", Mode: 1, Opcode: []uint8{118}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "JBE", Extension: "BASE", Mode: 14, Opcode: []uint8{118}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "JNBE", Extension: "BASE", Mode: 1, Opcode: []uint8{119}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "JNBE", Extension: "BASE", Mode: 14, Opcode: []uint8{119}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "JS", Extension: "BASE", Mode: 1, Opcode: []uint8{120}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "JS", Extension: "BASE", Mode: 14, Opcode: []uint8{120}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "JNS", Extension: "BASE", Mode: 1, Opcode: []uint8{121}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "JNS", Extension: "BASE", Mode: 14, Opcode: []uint8{121}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "JP", Extension: "BASE", Mode: 1, Opcode: []uint8{122}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "JP", Extension: "BASE", Mode: 14, Opcode: []uint8{122}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "JNP", Extension: "BASE", Mode: 1, Opcode: []uint8{123}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "JNP", Extension: "BASE", Mode: 14, Opcode: []uint8{123}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "JL", Extension: "BASE", Mode: 1, Opcode: []uint8{124}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "JL", Extension: "BASE", Mode: 14, Opcode: []uint8{124}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "JNL", Extension: "BASE", Mode: 1, Opcode: []uint8{125}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "JNL", Extension: "BASE", Mode: 14, Opcode: []uint8{125}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "JLE", Extension: "BASE", Mode: 1, Opcode: []uint8{126}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "JLE", Extension: "BASE", Mode: 14, Opcode: []uint8{126}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "JNLE", Extension: "BASE", Mode: 1, Opcode: []uint8{127}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "JNLE", Extension: "BASE", Mode: 14, Opcode: []uint8{127}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "TEST", Extension: "BASE", Mode: 15, Opcode: []uint8{132}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "TEST", Extension: "BASE", Mode: 15, Opcode: []uint8{133}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "XCHG", Extension: "BASE", Mode: 15, Opcode: []uint8{134}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, VexP: -1},
{Name: "XCHG", Extension: "BASE", Mode: 15, Opcode: []uint8{134}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "XCHG", Extension: "BASE", Mode: 15, Opcode: []uint8{135}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, VexP: -1},
{Name: "XCHG", Extension: "BASE", Mode: 15, Opcode: []uint8{135}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "MOV", Extension: "BASE", Mode: 15, Opcode: []uint8{136}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "MOV", Extension: "BASE", Mode: 15, Opcode: []uint8{137}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "MOV", Extension: "BASE", Mode: 15, Opcode: []uint8{138}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "MOV", Extension: "BASE", Mode: 15, Opcode: []uint8{139}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "MOV", Extension: "BASE", Mode: 15, Opcode: []uint8{140}, Modrm: true, Mod: -1, Reg: -6, Rm: -1, VexP: -1},
{Name: "LEA", Extension: "BASE", Mode: 15, Opcode: []uint8{141}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, VexP: -1},
{Name: "MOV", Extension: "BASE", Mode: 15, Opcode: []uint8{142}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 15, Opcode: []uint8{144}, Mod: -100, Reg: -100, Srm: true, VexP: -1},
{Name: "PAUSE", Extension: "PAUSE", Mode: 15, Opcode: []uint8{144}, Prefix: []uint8{243}, Mod: -100, Reg: -100, Srm: true, NoRepPrefix: true, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 15, Opcode: []uint8{144}, Prefix: []uint8{243}, Mod: -100, Reg: -100, Srm: true, NoRepPrefix: true, VexP: -1},
{Name: "XCHG", Extension: "BASE", Mode: 15, Opcode: []uint8{144}, Mod: -100, Reg: -100, Rm: -1, Srm: true, VexP: -1},
{Name: "CBW", Extension: "BASE", Mode: 15, Opcode: []uint8{152}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "CDQE", Extension: "LONGMODE", Mode: 1, Opcode: []uint8{152}, Mod: -100, Reg: -100, Rm: -100, Rexw: 1, VexP: -1},
{Name: "CWDE", Extension: "BASE", Mode: 15, Opcode: []uint8{152}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "CWD", Extension: "BASE", Mode: 15, Opcode: []uint8{153}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "CQO", Extension: "LONGMODE", Mode: 1, Opcode: []uint8{153}, Mod: -100, Reg: -100, Rm: -100, Rexw: 1, VexP: -1},
{Name: "CDQ", Extension: "BASE", Mode: 15, Opcode: []uint8{153}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "CALL_FAR", Extension: "BASE", Mode: 15, Opcode: []uint8{255}, Modrm: true, Mod: -3, Reg: 3, Rm: -1, VexP: -1},
{Name: "CALL_FAR", Extension: "BASE", Mode: 14, Opcode: []uint8{154}, Mod: -100, Reg: -100, Rm: -100, Imm: -1, Imm2: 2, VexP: -1},
{Name: "FWAIT", Extension: "X87", Mode: 15, Opcode: []uint8{155}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "PUSHF", Extension: "BASE", Mode: 15, Opcode: []uint8{156}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "PUSHFD", Extension: "BASE", Mode: 14, Opcode: []uint8{156}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "PUSHFQ", Extension: "LONGMODE", Mode: 1, Opcode: []uint8{156}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "POPF", Extension: "BASE", Mode: 15, Opcode: []uint8{157}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "POPFD", Extension: "BASE", Mode: 14, Opcode: []uint8{157}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "POPFQ", Extension: "LONGMODE", Mode: 1, Opcode: []uint8{157}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "SAHF", Extension: "BASE", Mode: 15, Opcode: []uint8{158}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "LAHF", Extension: "BASE", Mode: 15, Opcode: []uint8{159}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "MOV", Extension: "BASE", Mode: 15, Opcode: []uint8{160}, Mod: -100, Reg: -100, Rm: -100, Imm: -2, VexP: -1},
{Name: "MOV", Extension: "BASE", Mode: 15, Opcode: []uint8{161}, Mod: -100, Reg: -100, Rm: -100, Imm: -2, VexP: -1},
{Name: "MOV", Extension: "BASE", Mode: 15, Opcode: []uint8{162}, Mod: -100, Reg: -100, Rm: -100, Imm: -2, VexP: -1},
{Name: "MOV", Extension: "BASE", Mode: 15, Opcode: []uint8{163}, Mod: -100, Reg: -100, Rm: -100, Imm: -2, VexP: -1},
{Name: "REP_MOVSB", Extension: "BASE", Mode: 15, Opcode: []uint8{164}, Prefix: []uint8{243}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "REP_MOVSB", Extension: "BASE", Mode: 15, Opcode: []uint8{164}, Prefix: []uint8{242}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "MOVSB", Extension: "BASE", Mode: 15, Opcode: []uint8{164}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "REP_MOVSW", Extension: "BASE", Mode: 15, Opcode: []uint8{165}, Prefix: []uint8{243}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "REP_MOVSW", Extension: "BASE", Mode: 15, Opcode: []uint8{165}, Prefix: []uint8{242}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "MOVSW", Extension: "BASE", Mode: 15, Opcode: []uint8{165}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "REP_MOVSD", Extension: "BASE", Mode: 15, Opcode: []uint8{165}, Prefix: []uint8{243}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "REP_MOVSD", Extension: "BASE", Mode: 15, Opcode: []uint8{165}, Prefix: []uint8{242}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "MOVSD", Extension: "BASE", Mode: 15, Opcode: []uint8{165}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "REP_MOVSQ", Extension: "LONGMODE", Mode: 15, Opcode: []uint8{165}, Prefix: []uint8{243}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "REP_MOVSQ", Extension: "LONGMODE", Mode: 15, Opcode: []uint8{165}, Prefix: []uint8{242}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "MOVSQ", Extension: "LONGMODE", Mode: 15, Opcode: []uint8{165}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "REPE_CMPSB", Extension: "BASE", Mode: 15, Opcode: []uint8{166}, Prefix: []uint8{243}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "REPNE_CMPSB", Extension: "BASE", Mode: 15, Opcode: []uint8{166}, Prefix: []uint8{242}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "CMPSB", Extension: "BASE", Mode: 15, Opcode: []uint8{166}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "REPE_CMPSW", Extension: "BASE", Mode: 15, Opcode: []uint8{167}, Prefix: []uint8{243}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "REPNE_CMPSW", Extension: "BASE", Mode: 15, Opcode: []uint8{167}, Prefix: []uint8{242}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "CMPSW", Extension: "BASE", Mode: 15, Opcode: []uint8{167}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "REPE_CMPSD", Extension: "BASE", Mode: 15, Opcode: []uint8{167}, Prefix: []uint8{243}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "REPNE_CMPSD", Extension: "BASE", Mode: 15, Opcode: []uint8{167}, Prefix: []uint8{242}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "CMPSD", Extension: "BASE", Mode: 15, Opcode: []uint8{167}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "REPE_CMPSQ", Extension: "LONGMODE", Mode: 15, Opcode: []uint8{167}, Prefix: []uint8{243}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "REPNE_CMPSQ", Extension: "LONGMODE", Mode: 15, Opcode: []uint8{167}, Prefix: []uint8{242}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "CMPSQ", Extension: "LONGMODE", Mode: 15, Opcode: []uint8{167}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "TEST", Extension: "BASE", Mode: 15, Opcode: []uint8{168}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "TEST", Extension: "BASE", Mode: 15, Opcode: []uint8{169}, Mod: -100, Reg: -100, Rm: -100, Imm: -1, VexP: -1},
{Name: "REP_STOSB", Extension: "BASE", Mode: 15, Opcode: []uint8{170}, Prefix: []uint8{243}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "REP_STOSB", Extension: "BASE", Mode: 15, Opcode: []uint8{170}, Prefix: []uint8{242}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "STOSB", Extension: "BASE", Mode: 15, Opcode: []uint8{170}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "REP_STOSW", Extension: "BASE", Mode: 15, Opcode: []uint8{171}, Prefix: []uint8{243}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "REP_STOSW", Extension: "BASE", Mode: 15, Opcode: []uint8{171}, Prefix: []uint8{242}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "STOSW", Extension: "BASE", Mode: 15, Opcode: []uint8{171}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "REP_STOSD", Extension: "BASE", Mode: 15, Opcode: []uint8{171}, Prefix: []uint8{243}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "REP_STOSD", Extension: "BASE", Mode: 15, Opcode: []uint8{171}, Prefix: []uint8{242}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "STOSD", Extension: "BASE", Mode: 15, Opcode: []uint8{171}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "REP_STOSQ", Extension: "LONGMODE", Mode: 15, Opcode: []uint8{171}, Prefix: []uint8{243}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "REP_STOSQ", Extension: "LONGMODE", Mode: 15, Opcode: []uint8{171}, Prefix: []uint8{242}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "STOSQ", Extension: "LONGMODE", Mode: 15, Opcode: []uint8{171}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "REP_LODSB", Extension: "BASE", Mode: 15, Opcode: []uint8{172}, Prefix: []uint8{243}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "REP_LODSB", Extension: "BASE", Mode: 15, Opcode: []uint8{172}, Prefix: []uint8{242}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "LODSB", Extension: "BASE", Mode: 15, Opcode: []uint8{172}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "REP_LODSW", Extension: "BASE", Mode: 15, Opcode: []uint8{173}, Prefix: []uint8{243}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "REP_LODSW", Extension: "BASE", Mode: 15, Opcode: []uint8{173}, Prefix: []uint8{242}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "LODSW", Extension: "BASE", Mode: 15, Opcode: []uint8{173}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "REP_LODSD", Extension: "BASE", Mode: 15, Opcode: []uint8{173}, Prefix: []uint8{243}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "REP_LODSD", Extension: "BASE", Mode: 15, Opcode: []uint8{173}, Prefix: []uint8{242}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "LODSD", Extension: "BASE", Mode: 15, Opcode: []uint8{173}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "REP_LODSQ", Extension: "LONGMODE", Mode: 15, Opcode: []uint8{173}, Prefix: []uint8{243}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "REP_LODSQ", Extension: "LONGMODE", Mode: 15, Opcode: []uint8{173}, Prefix: []uint8{242}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "LODSQ", Extension: "LONGMODE", Mode: 15, Opcode: []uint8{173}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "REPE_SCASB", Extension: "BASE", Mode: 15, Opcode: []uint8{174}, Prefix: []uint8{243}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "REPNE_SCASB", Extension: "BASE", Mode: 15, Opcode: []uint8{174}, Prefix: []uint8{242}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "SCASB", Extension: "BASE", Mode: 15, Opcode: []uint8{174}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "REPE_SCASW", Extension: "BASE", Mode: 15, Opcode: []uint8{175}, Prefix: []uint8{243}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "REPNE_SCASW", Extension: "BASE", Mode: 15, Opcode: []uint8{175}, Prefix: []uint8{242}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "SCASW", Extension: "BASE", Mode: 15, Opcode: []uint8{175}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "REPE_SCASD", Extension: "BASE", Mode: 15, Opcode: []uint8{175}, Prefix: []uint8{243}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "REPNE_SCASD", Extension: "BASE", Mode: 15, Opcode: []uint8{175}, Prefix: []uint8{242}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "SCASD", Extension: "BASE", Mode: 15, Opcode: []uint8{175}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "REPE_SCASQ", Extension: "LONGMODE", Mode: 15, Opcode: []uint8{175}, Prefix: []uint8{243}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "REPNE_SCASQ", Extension: "LONGMODE", Mode: 15, Opcode: []uint8{175}, Prefix: []uint8{242}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "SCASQ", Extension: "LONGMODE", Mode: 15, Opcode: []uint8{175}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "MOV", Extension: "BASE", Mode: 15, Opcode: []uint8{176}, Mod: -100, Reg: -100, Rm: -1, Srm: true, Imm: 1, VexP: -1},
{Name: "MOV", Extension: "BASE", Mode: 15, Opcode: []uint8{184}, Mod: -100, Reg: -100, Rm: -1, Srm: true, Imm: -3, VexP: -1},
{Name: "RET_NEAR", Extension: "BASE", Mode: 15, Opcode: []uint8{194}, Mod: -100, Reg: -100, Rm: -100, Imm: 2, VexP: -1},
{Name: "RET_NEAR", Extension: "BASE", Mode: 15, Opcode: []uint8{195}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "LES", Extension: "BASE", Mode: 14, Opcode: []uint8{196}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, VexP: -1},
{Name: "LDS", Extension: "BASE", Mode: 14, Opcode: []uint8{197}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, VexP: -1},
{Name: "ENTER", Extension: "BASE", Mode: 15, Opcode: []uint8{200}, Mod: -100, Reg: -100, Rm: -100, Imm: 2, Imm2: 1, VexP: -1},
{Name: "LEAVE", Extension: "BASE", Mode: 15, Opcode: []uint8{201}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "RET_FAR", Extension: "BASE", Mode: 15, Opcode: []uint8{202}, Mod: -100, Reg: -100, Rm: -100, Imm: 2, VexP: -1},
{Name: "RET_FAR", Extension: "BASE", Mode: 15, Opcode: []uint8{203}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "INT3", Extension: "BASE", Mode: 15, Opcode: []uint8{204}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "INT", Extension: "BASE", Mode: 15, Opcode: []uint8{205}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "INTO", Extension: "BASE", Mode: 14, Opcode: []uint8{206}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "IRET", Extension: "BASE", Mode: 15, Opcode: []uint8{207}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "IRETD", Extension: "BASE", Mode: 15, Opcode: []uint8{207}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "IRETQ", Extension: "LONGMODE", Mode: 1, Opcode: []uint8{207}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "AAM", Extension: "BASE", Mode: 14, Opcode: []uint8{212}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "AAD", Extension: "BASE", Mode: 14, Opcode: []uint8{213}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "SALC", Extension: "BASE", Mode: 14, Opcode: []uint8{214}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "XLAT", Extension: "BASE", Mode: 15, Opcode: []uint8{215}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "LOOPNE", Extension: "BASE", Mode: 15, Opcode: []uint8{224}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, NoRepPrefix: true, VexP: -1},
{Name: "LOOPNE", Extension: "BASE", Mode: 15, Opcode: []uint8{224}, Prefix: []uint8{242}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, NoRepPrefix: true, VexP: -1},
{Name: "LOOPNE", Extension: "BASE", Mode: 15, Opcode: []uint8{224}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "LOOPNE", Extension: "BASE", Mode: 15, Opcode: []uint8{225}, Prefix: []uint8{242}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, NoRepPrefix: true, VexP: -1},
{Name: "LOOPE", Extension: "BASE", Mode: 15, Opcode: []uint8{225}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, NoRepPrefix: true, VexP: -1},
{Name: "LOOPE", Extension: "BASE", Mode: 15, Opcode: []uint8{225}, Prefix: []uint8{243}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, NoRepPrefix: true, VexP: -1},
{Name: "LOOPE", Extension: "BASE", Mode: 15, Opcode: []uint8{225}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "LOOPE", Extension: "BASE", Mode: 15, Opcode: []uint8{224}, Prefix: []uint8{243}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, NoRepPrefix: true, VexP: -1},
{Name: "LOOP", Extension: "BASE", Mode: 15, Opcode: []uint8{226}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "JCXZ", Extension: "BASE", Mode: 15, Opcode: []uint8{227}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "JECXZ", Extension: "BASE", Mode: 14, Opcode: []uint8{227}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "JECXZ", Extension: "BASE", Mode: 1, Opcode: []uint8{227}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "JRCXZ", Extension: "BASE", Mode: 15, Opcode: []uint8{227}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "IN", Extension: "BASE", Mode: 15, Opcode: []uint8{228}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "IN", Extension: "BASE", Mode: 15, Opcode: []uint8{229}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "OUT", Extension: "BASE", Mode: 15, Opcode: []uint8{230}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "OUT", Extension: "BASE", Mode: 15, Opcode: []uint8{231}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "JMP", Extension: "BASE", Mode: 14, Opcode: []uint8{233}, Mod: -100, Reg: -100, Rm: -100, Imm: -1, VexP: -1},
{Name: "JMP", Extension: "BASE", Mode: 1, Opcode: []uint8{233}, Mod: -100, Reg: -100, Rm: -100, Imm: 4, VexP: -1},
{Name: "JMP_FAR", Extension: "BASE", Mode: 14, Opcode: []uint8{234}, Mod: -100, Reg: -100, Rm: -100, Imm: -1, Imm2: 2, VexP: -1},
{Name: "JMP", Extension: "BASE", Mode: 14, Opcode: []uint8{235}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "JMP", Extension: "BASE", Mode: 1, Opcode: []uint8{235}, Mod: -100, Reg: -100, Rm: -100, Imm: 1, VexP: -1},
{Name: "IN", Extension: "BASE", Mode: 15, Opcode: []uint8{236}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "IN", Extension: "BASE", Mode: 15, Opcode: []uint8{237}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "OUT", Extension: "BASE", Mode: 15, Opcode: []uint8{238}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "OUT", Extension: "BASE", Mode: 15, Opcode: []uint8{239}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "INT1", Extension: "BASE", Mode: 15, Opcode: []uint8{241}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "HLT", Extension: "BASE", Mode: 15, Priv: true, Opcode: []uint8{244}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "CMC", Extension: "BASE", Mode: 15, Opcode: []uint8{245}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "CLC", Extension: "BASE", Mode: 15, Opcode: []uint8{248}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "STC", Extension: "BASE", Mode: 15, Opcode: []uint8{249}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "CLI", Extension: "BASE", Mode: 15, Opcode: []uint8{250}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "STI", Extension: "BASE", Mode: 15, Opcode: []uint8{251}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "CLD", Extension: "BASE", Mode: 15, Opcode: []uint8{252}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "STD", Extension: "BASE", Mode: 15, Opcode: []uint8{253}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "LAR", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 2}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "LSL", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 3}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "SYSCALL", Extension: "LONGMODE", Mode: 1, Opcode: []uint8{15, 5}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "CLTS", Extension: "BASE", Mode: 15, Priv: true, Opcode: []uint8{15, 6}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "SYSRET", Extension: "LONGMODE", Mode: 1, Priv: true, Opcode: []uint8{15, 7}, Mod: -100, Reg: -100, Rm: -100, No66Prefix: true, VexP: -1},
{Name: "SYSRET", Extension: "LONGMODE", Mode: 1, Priv: true, Opcode: []uint8{15, 7}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "MOVUPS", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 16}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "MOVUPS", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 17}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "MOVLPS", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 19}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "UNPCKLPS", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 20}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "UNPCKHPS", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 21}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "MOVHPS", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 23}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "MOVSS", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 16}, Prefix: []uint8{243}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "MOVSS", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 17}, Prefix: []uint8{243}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "MOVSLDUP", Extension: "SSE3", Mode: 15, Opcode: []uint8{15, 18}, Prefix: []uint8{243}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "MOVSHDUP", Extension: "SSE3", Mode: 15, Opcode: []uint8{15, 22}, Prefix: []uint8{243}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "MOVUPD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 16}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "MOVUPD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 17}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "MOVLPD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 18}, Prefix: []uint8{102}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "MOVLPD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 19}, Prefix: []uint8{102}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "UNPCKLPD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 20}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "UNPCKHPD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 21}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "MOVHPD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 22}, Prefix: []uint8{102}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "MOVHPD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 23}, Prefix: []uint8{102}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "MOVSD_XMM", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 16}, Prefix: []uint8{242}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "MOVSD_XMM", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 17}, Prefix: []uint8{242}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "MOVDDUP", Extension: "SSE3", Mode: 15, Opcode: []uint8{15, 18}, Prefix: []uint8{242}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "MOV_CR", Extension: "BASE", Mode: 14, Priv: true, Opcode: []uint8{15, 34}, Modrm: true, Mod: -1, Reg: -8, Rm: -1, NoSibDisp: true, VexP: -1},
{Name: "MOV_CR", Extension: "BASE", Mode: 1, Priv: true, Opcode: []uint8{15, 34}, Modrm: true, Mod: -1, Reg: -8, Rm: -1, NoSibDisp: true, VexP: -1},
{Name: "MOV_CR", Extension: "BASE", Mode: 14, Priv: true, Opcode: []uint8{15, 32}, Modrm: true, Mod: -1, Reg: -8, Rm: -1, NoSibDisp: true, VexP: -1},
{Name: "MOV_CR", Extension: "BASE", Mode: 1, Priv: true, Opcode: []uint8{15, 32}, Modrm: true, Mod: -1, Reg: -8, Rm: -1, NoSibDisp: true, VexP: -1},
{Name: "MOV_DR", Extension: "BASE", Mode: 14, Priv: true, Opcode: []uint8{15, 35}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoSibDisp: true, VexP: -1},
{Name: "MOV_DR", Extension: "BASE", Mode: 1, Priv: true, Opcode: []uint8{15, 35}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoSibDisp: true, VexP: -1},
{Name: "MOV_DR", Extension: "BASE", Mode: 14, Priv: true, Opcode: []uint8{15, 33}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoSibDisp: true, VexP: -1},
{Name: "MOV_DR", Extension: "BASE", Mode: 1, Priv: true, Opcode: []uint8{15, 33}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoSibDisp: true, VexP: -1},
{Name: "WRMSR", Extension: "BASE", Mode: 15, Priv: true, Opcode: []uint8{15, 48}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "RDTSC", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 49}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "RDMSR", Extension: "BASE", Mode: 15, Priv: true, Opcode: []uint8{15, 50}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "RDPMC", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 51}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "SYSENTER", Extension: "BASE", Mode: 14, Opcode: []uint8{15, 52}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "SYSENTER", Extension: "BASE", Mode: 1, Opcode: []uint8{15, 52}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "SYSEXIT", Extension: "BASE", Mode: 14, Priv: true, Opcode: []uint8{15, 53}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "SYSEXIT", Extension: "BASE", Mode: 1, Priv: true, Opcode: []uint8{15, 53}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "CMOVO", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 64}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "CMOVNO", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 65}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "CMOVB", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 66}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "CMOVNB", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 67}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "CMOVZ", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 68}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "CMOVNZ", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 69}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "CMOVBE", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 70}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "CMOVNBE", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 71}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "MOVMSKPS", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 80}, Modrm: true, Mod: 3, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "SQRTPS", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 81}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "RSQRTPS", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 82}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "RCPPS", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 83}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "ANDPS", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 84}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "ANDNPS", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 85}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "ORPS", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 86}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "XORPS", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 87}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "SQRTSS", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 81}, Prefix: []uint8{243}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "RSQRTSS", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 82}, Prefix: []uint8{243}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "RCPSS", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 83}, Prefix: []uint8{243}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "MOVMSKPD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 80}, Prefix: []uint8{102}, Modrm: true, Mod: 3, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "SQRTPD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 81}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "ANDPD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 84}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "ANDNPD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 85}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "ORPD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 86}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "XORPD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 87}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "SQRTSD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 81}, Prefix: []uint8{242}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PUNPCKLBW", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 96}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PUNPCKLWD", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 97}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PUNPCKLDQ", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 98}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PACKSSWB", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 99}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PCMPGTB", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 100}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PCMPGTW", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 101}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PCMPGTD", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PACKUSWB", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 103}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PUNPCKLBW", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 96}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PUNPCKLWD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 97}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PUNPCKLDQ", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 98}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PACKSSWB", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 99}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PCMPGTB", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 100}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PCMPGTW", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 101}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PCMPGTD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 102}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PACKUSWB", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 103}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PSHUFW", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 112}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PCMPEQB", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 116}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PCMPEQW", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 117}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PCMPEQD", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 118}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "EMMS", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 119}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PSHUFD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 112}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, NoRepPrefix: true, VexP: -1},
{Name: "PCMPEQB", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 116}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PCMPEQW", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 117}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PCMPEQD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 118}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PSHUFLW", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 112}, Prefix: []uint8{242}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, NoRepPrefix: true, VexP: -1},
{Name: "PSHUFHW", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 112}, Prefix: []uint8{243}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, NoRepPrefix: true, VexP: -1},
{Name: "JO", Extension: "BASE", Mode: 1, Opcode: []uint8{15, 128}, Mod: -100, Reg: -100, Rm: -100, Imm: 4, VexP: -1},
{Name: "JO", Extension: "BASE", Mode: 14, Opcode: []uint8{15, 128}, Mod: -100, Reg: -100, Rm: -100, Imm: -1, VexP: -1},
{Name: "JNO", Extension: "BASE", Mode: 14, Opcode: []uint8{15, 129}, Mod: -100, Reg: -100, Rm: -100, Imm: -1, VexP: -1},
{Name: "JNO", Extension: "BASE", Mode: 1, Opcode: []uint8{15, 129}, Mod: -100, Reg: -100, Rm: -100, Imm: 4, VexP: -1},
{Name: "JB", Extension: "BASE", Mode: 14, Opcode: []uint8{15, 130}, Mod: -100, Reg: -100, Rm: -100, Imm: -1, VexP: -1},
{Name: "JB", Extension: "BASE", Mode: 1, Opcode: []uint8{15, 130}, Mod: -100, Reg: -100, Rm: -100, Imm: 4, VexP: -1},
{Name: "JNB", Extension: "BASE", Mode: 14, Opcode: []uint8{15, 131}, Mod: -100, Reg: -100, Rm: -100, Imm: -1, VexP: -1},
{Name: "JNB", Extension: "BASE", Mode: 1, Opcode: []uint8{15, 131}, Mod: -100, Reg: -100, Rm: -100, Imm: 4, VexP: -1},
{Name: "JZ", Extension: "BASE", Mode: 14, Opcode: []uint8{15, 132}, Mod: -100, Reg: -100, Rm: -100, Imm: -1, VexP: -1},
{Name: "JZ", Extension: "BASE", Mode: 1, Opcode: []uint8{15, 132}, Mod: -100, Reg: -100, Rm: -100, Imm: 4, VexP: -1},
{Name: "JNZ", Extension: "BASE", Mode: 14, Opcode: []uint8{15, 133}, Mod: -100, Reg: -100, Rm: -100, Imm: -1, VexP: -1},
{Name: "JNZ", Extension: "BASE", Mode: 1, Opcode: []uint8{15, 133}, Mod: -100, Reg: -100, Rm: -100, Imm: 4, VexP: -1},
{Name: "JBE", Extension: "BASE", Mode: 14, Opcode: []uint8{15, 134}, Mod: -100, Reg: -100, Rm: -100, Imm: -1, VexP: -1},
{Name: "JBE", Extension: "BASE", Mode: 1, Opcode: []uint8{15, 134}, Mod: -100, Reg: -100, Rm: -100, Imm: 4, VexP: -1},
{Name: "JNBE", Extension: "BASE", Mode: 14, Opcode: []uint8{15, 135}, Mod: -100, Reg: -100, Rm: -100, Imm: -1, VexP: -1},
{Name: "JNBE", Extension: "BASE", Mode: 1, Opcode: []uint8{15, 135}, Mod: -100, Reg: -100, Rm: -100, Imm: 4, VexP: -1},
{Name: "SETO", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 144}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "SETNO", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 145}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "SETB", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 146}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "SETNB", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 147}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "SETZ", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 148}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "SETNZ", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 149}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "SETBE", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 150}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "SETNBE", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 151}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "PUSH", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 160}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "POP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 161}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "CPUID", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 162}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "BT", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 163}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "CMPXCHG_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 176}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, VexP: -1},
{Name: "CMPXCHG", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 176}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "CMPXCHG_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 177}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, VexP: -1},
{Name: "CMPXCHG", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 177}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "LSS", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 178}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, VexP: -1},
{Name: "BTR_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 179}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, VexP: -1},
{Name: "BTR", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 179}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "LFS", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 180}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, VexP: -1},
{Name: "LGS", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 181}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, VexP: -1},
{Name: "MOVZX", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 182}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "MOVZX", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 183}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "XADD_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 192}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, VexP: -1},
{Name: "XADD", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 192}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "XADD_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 193}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, VexP: -1},
{Name: "XADD", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 193}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "CMPPS", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 194}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "MOVNTI", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 195}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PINSRW", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 196}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PEXTRW", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 197}, Modrm: true, Mod: 3, Reg: -1, Rm: -1, Imm: 1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "SHUFPS", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 198}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "CMPSS", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 194}, Prefix: []uint8{243}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, NoRepPrefix: true, VexP: -1},
{Name: "CMPPD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 194}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, NoRepPrefix: true, VexP: -1},
{Name: "PINSRW", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 196}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, NoRepPrefix: true, VexP: -1},
{Name: "PEXTRW", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 197}, Prefix: []uint8{102}, Modrm: true, Mod: 3, Reg: -1, Rm: -1, Imm: 1, NoRepPrefix: true, VexP: -1},
{Name: "SHUFPD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 198}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, NoRepPrefix: true, VexP: -1},
{Name: "CMPSD_XMM", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 194}, Prefix: []uint8{242}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, NoRepPrefix: true, VexP: -1},
{Name: "PSRLW", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 209}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PSRLD", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 210}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PSRLQ", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 211}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PADDQ", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 212}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PMULLW", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 213}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PMOVMSKB", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 215}, Modrm: true, Mod: 3, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "ADDSUBPD", Extension: "SSE3", Mode: 15, Opcode: []uint8{15, 208}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PSRLW", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 209}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PSRLD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 210}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PSRLQ", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 211}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PADDQ", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 212}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PMULLW", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 213}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PMOVMSKB", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 215}, Prefix: []uint8{102}, Modrm: true, Mod: 3, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "MOVQ2DQ", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 214}, Prefix: []uint8{243}, Modrm: true, Mod: 3, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "ADDSUBPS", Extension: "SSE3", Mode: 15, Opcode: []uint8{15, 208}, Prefix: []uint8{242}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "MOVDQ2Q", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 214}, Prefix: []uint8{242}, Modrm: true, Mod: 3, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PAVGB", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 224}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PSRAW", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 225}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PSRAD", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 226}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PAVGW", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 227}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PMULHUW", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 228}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PMULHW", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 229}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "MOVNTQ", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 231}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PAVGB", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 224}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PSRAW", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 225}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PSRAD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 226}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PAVGW", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 227}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PMULHUW", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 228}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PMULHW", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 229}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "CVTTPD2DQ", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 230}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "MOVNTDQ", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 231}, Prefix: []uint8{102}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "CVTDQ2PD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 230}, Prefix: []uint8{243}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "CVTPD2DQ", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 230}, Prefix: []uint8{242}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PSLLW", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 241}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PSLLD", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 242}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PSLLQ", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 243}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PMULUDQ", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 244}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PMADDWD", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 245}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PSADBW", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 246}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "MASKMOVQ", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 247}, Modrm: true, Mod: 3, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PSLLW", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 241}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PSLLD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 242}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PSLLQ", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 243}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PMULUDQ", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 244}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PMADDWD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 245}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PSADBW", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 246}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "MASKMOVDQU", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 247}, Prefix: []uint8{102}, Modrm: true, Mod: 3, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "LDDQU", Extension: "SSE3", Mode: 15, Opcode: []uint8{15, 240}, Prefix: []uint8{242}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "INVD", Extension: "BASE", Mode: 15, Priv: true, Opcode: []uint8{15, 8}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "WBINVD", Extension: "BASE", Mode: 15, Priv: true, Opcode: []uint8{15, 9}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "UD0", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 255}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "UD1", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 185}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "UD2", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 11}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "MOVAPS", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 40}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "MOVAPS", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 41}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "CVTPI2PS", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 42}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "MOVNTPS", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 43}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "CVTTPS2PI", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 44}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "CVTPS2PI", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 45}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "UCOMISS", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 46}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "COMISS", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 47}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "CVTSI2SS", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 42}, Prefix: []uint8{243}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, Rexw: -1, VexP: -1},
{Name: "CVTSI2SS", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 42}, Prefix: []uint8{243}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, Rexw: 1, VexP: -1},
{Name: "CVTTSS2SI", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 44}, Prefix: []uint8{243}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, Rexw: -1, VexP: -1},
{Name: "CVTTSS2SI", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 44}, Prefix: []uint8{243}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, Rexw: 1, VexP: -1},
{Name: "CVTSS2SI", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 45}, Prefix: []uint8{243}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, Rexw: -1, VexP: -1},
{Name: "CVTSS2SI", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 45}, Prefix: []uint8{243}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, Rexw: 1, VexP: -1},
{Name: "MOVAPD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 40}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "MOVAPD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 41}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "CVTPI2PD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 42}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "MOVNTPD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 43}, Prefix: []uint8{102}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "CVTTPD2PI", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 44}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "CVTPD2PI", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 45}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "UCOMISD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 46}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "COMISD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 47}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "CVTSI2SD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 42}, Prefix: []uint8{242}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, Rexw: -1, VexP: -1},
{Name: "CVTSI2SD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 42}, Prefix: []uint8{242}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, Rexw: 1, VexP: -1},
{Name: "CVTTSD2SI", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 44}, Prefix: []uint8{242}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, Rexw: -1, VexP: -1},
{Name: "CVTTSD2SI", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 44}, Prefix: []uint8{242}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, Rexw: 1, VexP: -1},
{Name: "CVTSD2SI", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 45}, Prefix: []uint8{242}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, Rexw: -1, VexP: -1},
{Name: "CVTSD2SI", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 45}, Prefix: []uint8{242}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, Rexw: 1, VexP: -1},
{Name: "CMOVS", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 72}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "CMOVNS", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 73}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "CMOVP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 74}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "CMOVNP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 75}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "CMOVL", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 76}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "CMOVNL", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 77}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "CMOVLE", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 78}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "CMOVNLE", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 79}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "ADDPS", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 88}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "MULPS", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 89}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "CVTPS2PD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 90}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "CVTDQ2PS", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 91}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "SUBPS", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 92}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "MINPS", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 93}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "DIVPS", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 94}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "MAXPS", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 95}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "ADDSS", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 88}, Prefix: []uint8{243}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "MULSS", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 89}, Prefix: []uint8{243}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "CVTSS2SD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 90}, Prefix: []uint8{243}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "CVTTPS2DQ", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 91}, Prefix: []uint8{243}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "SUBSS", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 92}, Prefix: []uint8{243}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "MINSS", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 93}, Prefix: []uint8{243}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "DIVSS", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 94}, Prefix: []uint8{243}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "MAXSS", Extension: "SSE", Mode: 15, Opcode: []uint8{15, 95}, Prefix: []uint8{243}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "ADDPD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 88}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "MULPD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 89}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "CVTPD2PS", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 90}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "CVTPS2DQ", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 91}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "SUBPD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 92}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "MINPD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 93}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "DIVPD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 94}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "MAXPD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 95}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "ADDSD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 88}, Prefix: []uint8{242}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "MULSD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 89}, Prefix: []uint8{242}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "CVTSD2SS", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 90}, Prefix: []uint8{242}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "SUBSD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 92}, Prefix: []uint8{242}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "MINSD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 93}, Prefix: []uint8{242}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "DIVSD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 94}, Prefix: []uint8{242}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "MAXSD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 95}, Prefix: []uint8{242}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PUNPCKHBW", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 104}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PUNPCKHWD", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 105}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PUNPCKHDQ", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 106}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PACKSSDW", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 107}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "MOVD", Extension: "SSE2", Mode: 1, Opcode: []uint8{15, 110}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, Rexw: -1, VexP: -1},
{Name: "MOVD", Extension: "SSE2", Mode: 14, Opcode: []uint8{15, 110}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "MOVD", Extension: "SSE2", Mode: 1, Opcode: []uint8{15, 126}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, Rexw: -1, VexP: -1},
{Name: "MOVD", Extension: "SSE2", Mode: 14, Opcode: []uint8{15, 126}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "MOVD", Extension: "MMX", Mode: 1, Opcode: []uint8{15, 110}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, Rexw: -1, VexP: -1},
{Name: "MOVD", Extension: "MMX", Mode: 14, Opcode: []uint8{15, 110}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "MOVD", Extension: "MMX", Mode: 1, Opcode: []uint8{15, 126}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, Rexw: -1, VexP: -1},
{Name: "MOVD", Extension: "MMX", Mode: 14, Opcode: []uint8{15, 126}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "MOVQ", Extension: "SSE2", Mode: 1, Opcode: []uint8{15, 110}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, Rexw: 1, VexP: -1},
{Name: "MOVQ", Extension: "SSE2", Mode: 1, Opcode: []uint8{15, 126}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, Rexw: 1, VexP: -1},
{Name: "MOVQ", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 214}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "MOVQ", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 126}, Prefix: []uint8{243}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "MOVQ", Extension: "MMX", Mode: 1, Opcode: []uint8{15, 110}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, Rexw: 1, VexP: -1},
{Name: "MOVQ", Extension: "MMX", Mode: 1, Opcode: []uint8{15, 126}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, Rexw: 1, VexP: -1},
{Name: "MOVQ", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 111}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "MOVQ", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 127}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PUNPCKHBW", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 104}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PUNPCKHWD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 105}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PUNPCKHDQ", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 106}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PACKSSDW", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 107}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PUNPCKLQDQ", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 108}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PUNPCKHQDQ", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 109}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "MOVDQU", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 111}, Prefix: []uint8{243}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "MOVDQU", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 127}, Prefix: []uint8{243}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "VMREAD", Extension: "VTX", Mode: 1, Priv: true, Opcode: []uint8{15, 120}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "VMREAD", Extension: "VTX", Mode: 14, Priv: true, Opcode: []uint8{15, 120}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "VMWRITE", Extension: "VTX", Mode: 1, Priv: true, Opcode: []uint8{15, 121}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "VMWRITE", Extension: "VTX", Mode: 14, Priv: true, Opcode: []uint8{15, 121}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "HADDPD", Extension: "SSE3", Mode: 15, Opcode: []uint8{15, 124}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "HSUBPD", Extension: "SSE3", Mode: 15, Opcode: []uint8{15, 125}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "MOVDQA", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 127}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "MOVDQA", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 111}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "HADDPS", Extension: "SSE3", Mode: 15, Opcode: []uint8{15, 124}, Prefix: []uint8{242}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "HSUBPS", Extension: "SSE3", Mode: 15, Opcode: []uint8{15, 125}, Prefix: []uint8{242}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "JS", Extension: "BASE", Mode: 14, Opcode: []uint8{15, 136}, Mod: -100, Reg: -100, Rm: -100, Imm: -1, VexP: -1},
{Name: "JS", Extension: "BASE", Mode: 1, Opcode: []uint8{15, 136}, Mod: -100, Reg: -100, Rm: -100, Imm: 4, VexP: -1},
{Name: "JNS", Extension: "BASE", Mode: 14, Opcode: []uint8{15, 137}, Mod: -100, Reg: -100, Rm: -100, Imm: -1, VexP: -1},
{Name: "JNS", Extension: "BASE", Mode: 1, Opcode: []uint8{15, 137}, Mod: -100, Reg: -100, Rm: -100, Imm: 4, VexP: -1},
{Name: "JP", Extension: "BASE", Mode: 14, Opcode: []uint8{15, 138}, Mod: -100, Reg: -100, Rm: -100, Imm: -1, VexP: -1},
{Name: "JP", Extension: "BASE", Mode: 1, Opcode: []uint8{15, 138}, Mod: -100, Reg: -100, Rm: -100, Imm: 4, VexP: -1},
{Name: "JNP", Extension: "BASE", Mode: 14, Opcode: []uint8{15, 139}, Mod: -100, Reg: -100, Rm: -100, Imm: -1, VexP: -1},
{Name: "JNP", Extension: "BASE", Mode: 1, Opcode: []uint8{15, 139}, Mod: -100, Reg: -100, Rm: -100, Imm: 4, VexP: -1},
{Name: "JL", Extension: "BASE", Mode: 14, Opcode: []uint8{15, 140}, Mod: -100, Reg: -100, Rm: -100, Imm: -1, VexP: -1},
{Name: "JL", Extension: "BASE", Mode: 1, Opcode: []uint8{15, 140}, Mod: -100, Reg: -100, Rm: -100, Imm: 4, VexP: -1},
{Name: "JNL", Extension: "BASE", Mode: 14, Opcode: []uint8{15, 141}, Mod: -100, Reg: -100, Rm: -100, Imm: -1, VexP: -1},
{Name: "JNL", Extension: "BASE", Mode: 1, Opcode: []uint8{15, 141}, Mod: -100, Reg: -100, Rm: -100, Imm: 4, VexP: -1},
{Name: "JLE", Extension: "BASE", Mode: 14, Opcode: []uint8{15, 142}, Mod: -100, Reg: -100, Rm: -100, Imm: -1, VexP: -1},
{Name: "JLE", Extension: "BASE", Mode: 1, Opcode: []uint8{15, 142}, Mod: -100, Reg: -100, Rm: -100, Imm: 4, VexP: -1},
{Name: "JNLE", Extension: "BASE", Mode: 14, Opcode: []uint8{15, 143}, Mod: -100, Reg: -100, Rm: -100, Imm: -1, VexP: -1},
{Name: "JNLE", Extension: "BASE", Mode: 1, Opcode: []uint8{15, 143}, Mod: -100, Reg: -100, Rm: -100, Imm: 4, VexP: -1},
{Name: "SETS", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 152}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "SETNS", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 153}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "SETP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 154}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "SETNP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 155}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "SETL", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 156}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "SETNL", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 157}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "SETLE", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 158}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "SETNLE", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 159}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "PUSH", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 168}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "POP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 169}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "RSM", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 170}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "BTS_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 171}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, VexP: -1},
{Name: "BTS", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 171}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "SHRD", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 172}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, VexP: -1},
{Name: "SHRD", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 173}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "SHLD", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 164}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, VexP: -1},
{Name: "SHLD", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 165}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "IMUL", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 175}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "BTC_LOCK", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 187}, Prefix: []uint8{240}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, VexP: -1},
{Name: "BTC", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 187}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "BSF", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 188}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "BSR", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 189}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "MOVSX", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 190}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "MOVSX", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 191}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "BSWAP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 200}, Mod: -100, Reg: -100, Rm: -1, Srm: true, VexP: -1},
{Name: "PSUBUSB", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 216}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PSUBUSW", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 217}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PMINUB", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 218}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PAND", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 219}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PADDUSB", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 220}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PADDUSW", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 221}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PMAXUB", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 222}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PANDN", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 223}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PSUBUSB", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 216}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PSUBUSW", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 217}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PMINUB", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 218}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PAND", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 219}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PADDUSB", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 220}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PADDUSW", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 221}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PMAXUB", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 222}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PANDN", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 223}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PSUBSB", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 232}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PSUBSW", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 233}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PMINSW", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 234}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "POR", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 235}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PADDSB", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 236}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PADDSW", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 237}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PMAXSW", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 238}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PXOR", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 239}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PSUBSB", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 232}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PSUBSW", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 233}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PMINSW", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 234}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "POR", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 235}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PADDSB", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 236}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PADDSW", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 237}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PMAXSW", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 238}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PXOR", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 239}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PSUBB", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 248}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PSUBW", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 249}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PSUBD", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 250}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PSUBQ", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 251}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PADDB", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 252}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PADDW", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 253}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PADDD", Extension: "MMX", Mode: 15, Opcode: []uint8{15, 254}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PSUBB", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 248}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PSUBW", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 249}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PSUBD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 250}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PSUBQ", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 251}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PADDB", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 252}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PADDW", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 253}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PADDD", Extension: "SSE2", Mode: 15, Opcode: []uint8{15, 254}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PHADDW", Extension: "SSSE3", Mode: 15, Opcode: []uint8{15, 56, 1}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PHADDW", Extension: "SSSE3", Mode: 15, Opcode: []uint8{15, 56, 1}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PHADDD", Extension: "SSSE3", Mode: 15, Opcode: []uint8{15, 56, 2}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PHADDD", Extension: "SSSE3", Mode: 15, Opcode: []uint8{15, 56, 2}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PHADDSW", Extension: "SSSE3", Mode: 15, Opcode: []uint8{15, 56, 3}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PHADDSW", Extension: "SSSE3", Mode: 15, Opcode: []uint8{15, 56, 3}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PHSUBW", Extension: "SSSE3", Mode: 15, Opcode: []uint8{15, 56, 5}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PHSUBW", Extension: "SSSE3", Mode: 15, Opcode: []uint8{15, 56, 5}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PHSUBD", Extension: "SSSE3", Mode: 15, Opcode: []uint8{15, 56, 6}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PHSUBD", Extension: "SSSE3", Mode: 15, Opcode: []uint8{15, 56, 6}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PHSUBSW", Extension: "SSSE3", Mode: 15, Opcode: []uint8{15, 56, 7}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PHSUBSW", Extension: "SSSE3", Mode: 15, Opcode: []uint8{15, 56, 7}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PMADDUBSW", Extension: "SSSE3", Mode: 15, Opcode: []uint8{15, 56, 4}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PMADDUBSW", Extension: "SSSE3", Mode: 15, Opcode: []uint8{15, 56, 4}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PMULHRSW", Extension: "SSSE3", Mode: 15, Opcode: []uint8{15, 56, 11}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PMULHRSW", Extension: "SSSE3", Mode: 15, Opcode: []uint8{15, 56, 11}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PSHUFB", Extension: "SSSE3", Mode: 15, Opcode: []uint8{15, 56, 0}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PSHUFB", Extension: "SSSE3", Mode: 15, Opcode: []uint8{15, 56, 0}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PSIGNB", Extension: "SSSE3", Mode: 15, Opcode: []uint8{15, 56, 8}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PSIGNB", Extension: "SSSE3", Mode: 15, Opcode: []uint8{15, 56, 8}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PSIGNW", Extension: "SSSE3", Mode: 15, Opcode: []uint8{15, 56, 9}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PSIGNW", Extension: "SSSE3", Mode: 15, Opcode: []uint8{15, 56, 9}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PSIGND", Extension: "SSSE3", Mode: 15, Opcode: []uint8{15, 56, 10}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PSIGND", Extension: "SSSE3", Mode: 15, Opcode: []uint8{15, 56, 10}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PALIGNR", Extension: "SSSE3", Mode: 15, Opcode: []uint8{15, 58, 15}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PALIGNR", Extension: "SSSE3", Mode: 15, Opcode: []uint8{15, 58, 15}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, NoRepPrefix: true, VexP: -1},
{Name: "PABSB", Extension: "SSSE3", Mode: 15, Opcode: []uint8{15, 56, 28}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PABSB", Extension: "SSSE3", Mode: 15, Opcode: []uint8{15, 56, 28}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PABSW", Extension: "SSSE3", Mode: 15, Opcode: []uint8{15, 56, 29}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PABSW", Extension: "SSSE3", Mode: 15, Opcode: []uint8{15, 56, 29}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PABSD", Extension: "SSSE3", Mode: 15, Opcode: []uint8{15, 56, 30}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "PABSD", Extension: "SSSE3", Mode: 15, Opcode: []uint8{15, 56, 30}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "POPCNT", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 184}, Prefix: []uint8{243}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PCMPGTQ", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 56, 55}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "CRC32", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 56, 240}, Prefix: []uint8{242}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "CRC32", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 56, 241}, Prefix: []uint8{242}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "BLENDPD", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 58, 13}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, NoRepPrefix: true, VexP: -1},
{Name: "BLENDPS", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 58, 12}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, NoRepPrefix: true, VexP: -1},
{Name: "BLENDVPD", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 56, 21}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "BLENDVPS", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 56, 20}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PCMPEQQ", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 56, 41}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "DPPD", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 58, 65}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, NoRepPrefix: true, VexP: -1},
{Name: "DPPS", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 58, 64}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, NoRepPrefix: true, VexP: -1},
{Name: "MOVNTDQA", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 56, 42}, Prefix: []uint8{102}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "EXTRACTPS", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 58, 23}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, NoRepPrefix: true, VexP: -1},
{Name: "INSERTPS", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 58, 33}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, NoRepPrefix: true, VexP: -1},
{Name: "MPSADBW", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 58, 66}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, NoRepPrefix: true, VexP: -1},
{Name: "PACKUSDW", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 56, 43}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PBLENDW", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 58, 14}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, NoRepPrefix: true, VexP: -1},
{Name: "PBLENDVB", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 56, 16}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PEXTRB", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 58, 20}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, NoRepPrefix: true, VexP: -1},
{Name: "PEXTRW_SSE4", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 58, 21}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, NoRepPrefix: true, VexP: -1},
{Name: "PEXTRQ", Extension: "SSE4", Mode: 1, Opcode: []uint8{15, 58, 22}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, NoRepPrefix: true, Rexw: 1, VexP: -1},
{Name: "PEXTRD", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 58, 22}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, NoRepPrefix: true, Rexw: -1, VexP: -1},
{Name: "PINSRB", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 58, 32}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, NoRepPrefix: true, VexP: -1},
{Name: "PINSRD", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 58, 34}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, NoRepPrefix: true, Rexw: -1, VexP: -1},
{Name: "PINSRQ", Extension: "SSE4", Mode: 1, Opcode: []uint8{15, 58, 34}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, NoRepPrefix: true, Rexw: 1, VexP: -1},
{Name: "ROUNDPD", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 58, 9}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, NoRepPrefix: true, VexP: -1},
{Name: "ROUNDPS", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 58, 8}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, NoRepPrefix: true, VexP: -1},
{Name: "ROUNDSD", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 58, 11}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, NoRepPrefix: true, VexP: -1},
{Name: "ROUNDSS", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 58, 10}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, NoRepPrefix: true, VexP: -1},
{Name: "PTEST", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 56, 23}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PHMINPOSUW", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 56, 65}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PMAXSB", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 56, 60}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PMAXSD", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 56, 61}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PMAXUD", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 56, 63}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PMAXUW", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 56, 62}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PMINSB", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 56, 56}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PMINSD", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 56, 57}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PMINUD", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 56, 59}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PMINUW", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 56, 58}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PMULLD", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 56, 64}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PMULDQ", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 56, 40}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PMOVSXBW", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 56, 32}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PMOVSXBD", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 56, 33}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PMOVSXBQ", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 56, 34}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PMOVSXWD", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 56, 35}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PMOVSXWQ", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 56, 36}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PMOVSXDQ", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 56, 37}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PMOVZXBW", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 56, 48}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PMOVZXBD", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 56, 49}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PMOVZXBQ", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 56, 50}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PMOVZXWD", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 56, 51}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PMOVZXWQ", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 56, 52}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PMOVZXDQ", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 56, 53}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PCMPESTRI", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 58, 97}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, NoRepPrefix: true, VexP: -1},
{Name: "PCMPISTRI", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 58, 99}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, NoRepPrefix: true, VexP: -1},
{Name: "PCMPESTRM", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 58, 96}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, NoRepPrefix: true, VexP: -1},
{Name: "PCMPISTRM", Extension: "SSE4", Mode: 15, Opcode: []uint8{15, 58, 98}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, NoRepPrefix: true, VexP: -1},
{Name: "XGETBV", Extension: "XSAVE", Mode: 15, Opcode: []uint8{15, 1}, Modrm: true, Mod: 3, Reg: 2, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "XSETBV", Extension: "XSAVE", Mode: 15, Priv: true, Opcode: []uint8{15, 1}, Modrm: true, Mod: 3, Reg: 2, Rm: 1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "XSAVE", Extension: "XSAVE", Mode: 15, Opcode: []uint8{15, 174}, Modrm: true, Mod: -3, Reg: 4, Rm: -1, NoRepPrefix: true, No66Prefix: true, Rexw: -1, VexP: -1},
{Name: "XRSTOR", Extension: "XSAVE", Mode: 15, Opcode: []uint8{15, 174}, Modrm: true, Mod: -3, Reg: 5, Rm: -1, NoRepPrefix: true, No66Prefix: true, Rexw: -1, VexP: -1},
{Name: "XSAVE64", Extension: "XSAVE", Mode: 15, Opcode: []uint8{15, 174}, Modrm: true, Mod: -3, Reg: 4, Rm: -1, NoRepPrefix: true, No66Prefix: true, Rexw: 1, VexP: -1},
{Name: "XRSTOR64", Extension: "XSAVE", Mode: 15, Opcode: []uint8{15, 174}, Modrm: true, Mod: -3, Reg: 5, Rm: -1, NoRepPrefix: true, No66Prefix: true, Rexw: 1, VexP: -1},
{Name: "MOVBE", Extension: "MOVBE", Mode: 15, Opcode: []uint8{15, 56, 240}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "MOVBE", Extension: "MOVBE", Mode: 15, Opcode: []uint8{15, 56, 241}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "GETSEC", Extension: "SMX", Mode: 15, Opcode: []uint8{15, 55}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "AESKEYGENASSIST", Extension: "AES", Mode: 15, Opcode: []uint8{15, 58, 223}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, NoRepPrefix: true, VexP: -1},
{Name: "AESENC", Extension: "AES", Mode: 15, Opcode: []uint8{15, 56, 220}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "AESENCLAST", Extension: "AES", Mode: 15, Opcode: []uint8{15, 56, 221}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "AESDEC", Extension: "AES", Mode: 15, Opcode: []uint8{15, 56, 222}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "AESDECLAST", Extension: "AES", Mode: 15, Opcode: []uint8{15, 56, 223}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "AESIMC", Extension: "AES", Mode: 15, Opcode: []uint8{15, 56, 219}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PCLMULQDQ", Extension: "PCLMULQDQ", Mode: 15, Opcode: []uint8{15, 58, 68}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, NoRepPrefix: true, VexP: -1},
{Name: "INVEPT", Extension: "VTX", Mode: 1, Priv: true, Opcode: []uint8{15, 56, 128}, Prefix: []uint8{102}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "INVEPT", Extension: "VTX", Mode: 14, Priv: true, Opcode: []uint8{15, 56, 128}, Prefix: []uint8{102}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "INVVPID", Extension: "VTX", Mode: 1, Priv: true, Opcode: []uint8{15, 56, 129}, Prefix: []uint8{102}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "INVVPID", Extension: "VTX", Mode: 14, Priv: true, Opcode: []uint8{15, 56, 129}, Prefix: []uint8{102}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 13}, Modrm: true, Mod: 3, Reg: -1, Rm: -1, VexP: -1},
{Name: "PREFETCH_EXCLUSIVE", Extension: "3DNOW", Mode: 15, Opcode: []uint8{15, 13}, Modrm: true, Mod: -3, Rm: -1, VexP: -1},
{Name: "PREFETCHW", Extension: "3DNOW", Mode: 15, Opcode: []uint8{15, 13}, Modrm: true, Mod: -3, Reg: 1, Rm: -1, VexP: -1},
{Name: "PREFETCH_RESERVED", Extension: "3DNOW", Mode: 15, Opcode: []uint8{15, 13}, Modrm: true, Mod: -3, Reg: 2, Rm: -1, VexP: -1},
{Name: "PREFETCHW", Extension: "3DNOW", Mode: 15, Opcode: []uint8{15, 13}, Modrm: true, Mod: -3, Reg: 3, Rm: -1, VexP: -1},
{Name: "PREFETCH_RESERVED", Extension: "3DNOW", Mode: 15, Opcode: []uint8{15, 13}, Modrm: true, Mod: -3, Reg: 4, Rm: -1, VexP: -1},
{Name: "PREFETCH_RESERVED", Extension: "3DNOW", Mode: 15, Opcode: []uint8{15, 13}, Modrm: true, Mod: -3, Reg: 5, Rm: -1, VexP: -1},
{Name: "PREFETCH_RESERVED", Extension: "3DNOW", Mode: 15, Opcode: []uint8{15, 13}, Modrm: true, Mod: -3, Reg: 6, Rm: -1, VexP: -1},
{Name: "PREFETCH_RESERVED", Extension: "3DNOW", Mode: 15, Opcode: []uint8{15, 13}, Modrm: true, Mod: -3, Reg: 7, Rm: -1, VexP: -1},
{Name: "NOP2", Extension: "BASE", Mode: 15, Opcode: []uint8{102, 144}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "NOP3", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 31, 0}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "NOP4", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 31, 64, 0}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "XSTORE", Extension: "VIA_PADLOCK_RNG", Mode: 15, Opcode: []uint8{15, 167}, Modrm: true, Mod: 3, NoRepPrefix: true, VexP: -1},
{Name: "REP_XSTORE", Extension: "VIA_PADLOCK_RNG", Mode: 15, Opcode: []uint8{15, 167}, Prefix: []uint8{243}, Modrm: true, Mod: 3, NoRepPrefix: true, VexP: -1},
{Name: "REP_XCRYPTECB", Extension: "VIA_PADLOCK_AES", Mode: 15, Opcode: []uint8{15, 167}, Prefix: []uint8{243}, Modrm: true, Mod: 3, Reg: 1, NoRepPrefix: true, VexP: -1},
{Name: "REP_XCRYPTCBC", Extension: "VIA_PADLOCK_AES", Mode: 15, Opcode: []uint8{15, 167}, Prefix: []uint8{243}, Modrm: true, Mod: 3, Reg: 2, NoRepPrefix: true, VexP: -1},
{Name: "REP_XCRYPTCTR", Extension: "VIA_PADLOCK_AES", Mode: 15, Opcode: []uint8{15, 167}, Prefix: []uint8{243}, Modrm: true, Mod: 3, Reg: 3, NoRepPrefix: true, VexP: -1},
{Name: "REP_XCRYPTCFB", Extension: "VIA_PADLOCK_AES", Mode: 15, Opcode: []uint8{15, 167}, Prefix: []uint8{243}, Modrm: true, Mod: 3, Reg: 4, NoRepPrefix: true, VexP: -1},
{Name: "REP_XCRYPTOFB", Extension: "VIA_PADLOCK_AES", Mode: 15, Opcode: []uint8{15, 167}, Prefix: []uint8{243}, Modrm: true, Mod: 3, Reg: 5, NoRepPrefix: true, VexP: -1},
{Name: "REP_XSHA1", Extension: "VIA_PADLOCK_SHA", Mode: 15, Opcode: []uint8{15, 166}, Prefix: []uint8{243}, Modrm: true, Mod: 3, Reg: 1, NoRepPrefix: true, VexP: -1},
{Name: "REP_XSHA256", Extension: "VIA_PADLOCK_SHA", Mode: 15, Opcode: []uint8{15, 166}, Prefix: []uint8{243}, Modrm: true, Mod: 3, Reg: 2, NoRepPrefix: true, VexP: -1},
{Name: "REP_MONTMUL", Extension: "VIA_PADLOCK_MONTMUL", Mode: 15, Opcode: []uint8{15, 166}, Prefix: []uint8{243}, Modrm: true, Mod: 3, NoRepPrefix: true, VexP: -1},
{Name: "FEMMS", Extension: "3DNOW", Mode: 15, Opcode: []uint8{15, 14}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "PI2FW", Extension: "3DNOW", Mode: 15, Opcode: []uint8{15, 15}, Suffix: []uint8{12}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "PI2FD", Extension: "3DNOW", Mode: 15, Opcode: []uint8{15, 15}, Suffix: []uint8{13}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "PF2IW", Extension: "3DNOW", Mode: 15, Opcode: []uint8{15, 15}, Suffix: []uint8{28}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "PF2ID", Extension: "3DNOW", Mode: 15, Opcode: []uint8{15, 15}, Suffix: []uint8{29}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "PFNACC", Extension: "3DNOW", Mode: 15, Opcode: []uint8{15, 15}, Suffix: []uint8{138}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "PFPNACC", Extension: "3DNOW", Mode: 15, Opcode: []uint8{15, 15}, Suffix: []uint8{142}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "PFCMPGE", Extension: "3DNOW", Mode: 15, Opcode: []uint8{15, 15}, Suffix: []uint8{144}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "PFMIN", Extension: "3DNOW", Mode: 15, Opcode: []uint8{15, 15}, Suffix: []uint8{148}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "PFRCP", Extension: "3DNOW", Mode: 15, Opcode: []uint8{15, 15}, Suffix: []uint8{150}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "PFRSQRT", Extension: "3DNOW", Mode: 15, Opcode: []uint8{15, 15}, Suffix: []uint8{151}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "PFSUB", Extension: "3DNOW", Mode: 15, Opcode: []uint8{15, 15}, Suffix: []uint8{154}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "PFADD", Extension: "3DNOW", Mode: 15, Opcode: []uint8{15, 15}, Suffix: []uint8{158}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "PFCMPGT", Extension: "3DNOW", Mode: 15, Opcode: []uint8{15, 15}, Suffix: []uint8{160}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "PFMAX", Extension: "3DNOW", Mode: 15, Opcode: []uint8{15, 15}, Suffix: []uint8{164}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "PFRCPIT1", Extension: "3DNOW", Mode: 15, Opcode: []uint8{15, 15}, Suffix: []uint8{166}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "PFRSQIT1", Extension: "3DNOW", Mode: 15, Opcode: []uint8{15, 15}, Suffix: []uint8{167}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "PFSUBR", Extension: "3DNOW", Mode: 15, Opcode: []uint8{15, 15}, Suffix: []uint8{170}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "PFACC", Extension: "3DNOW", Mode: 15, Opcode: []uint8{15, 15}, Suffix: []uint8{174}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "PFCMPEQ", Extension: "3DNOW", Mode: 15, Opcode: []uint8{15, 15}, Suffix: []uint8{176}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "PFMUL", Extension: "3DNOW", Mode: 15, Opcode: []uint8{15, 15}, Suffix: []uint8{180}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "PFRCPIT2", Extension: "3DNOW", Mode: 15, Opcode: []uint8{15, 15}, Suffix: []uint8{182}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "PMULHRW", Extension: "3DNOW", Mode: 15, Opcode: []uint8{15, 15}, Suffix: []uint8{183}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "PSWAPD", Extension: "3DNOW", Mode: 15, Opcode: []uint8{15, 15}, Suffix: []uint8{187}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "PAVGUSB", Extension: "3DNOW", Mode: 15, Opcode: []uint8{15, 15}, Suffix: []uint8{191}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, VexP: -1},
{Name: "SYSCALL_AMD", Extension: "BASE", Mode: 14, Opcode: []uint8{15, 5}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "SYSRET_AMD", Extension: "BASE", Mode: 14, Priv: true, Opcode: []uint8{15, 7}, Mod: -100, Reg: -100, Rm: -100, VexP: -1},
{Name: "VMRUN", Extension: "SVM", Mode: 15, Opcode: []uint8{15, 1}, Modrm: true, Mod: 3, Reg: 3, VexP: -1},
{Name: "VMMCALL", Extension: "SVM", Mode: 15, Opcode: []uint8{15, 1}, Modrm: true, Mod: 3, Reg: 3, Rm: 1, VexP: -1},
{Name: "VMLOAD", Extension: "SVM", Mode: 15, Opcode: []uint8{15, 1}, Modrm: true, Mod: 3, Reg: 3, Rm: 2, VexP: -1},
{Name: "VMSAVE", Extension: "SVM", Mode: 15, Opcode: []uint8{15, 1}, Modrm: true, Mod: 3, Reg: 3, Rm: 3, VexP: -1},
{Name: "STGI", Extension: "SVM", Mode: 15, Opcode: []uint8{15, 1}, Modrm: true, Mod: 3, Reg: 3, Rm: 4, VexP: -1},
{Name: "CLGI", Extension: "SVM", Mode: 15, Opcode: []uint8{15, 1}, Modrm: true, Mod: 3, Reg: 3, Rm: 5, VexP: -1},
{Name: "SKINIT", Extension: "SVM", Mode: 15, Opcode: []uint8{15, 1}, Modrm: true, Mod: 3, Reg: 3, Rm: 6, VexP: -1},
{Name: "INVLPGA", Extension: "SVM", Mode: 15, Priv: true, Opcode: []uint8{15, 1}, Modrm: true, Mod: 3, Reg: 3, Rm: 7, VexP: -1},
{Name: "EXTRQ", Extension: "SSE4a", Mode: 15, Opcode: []uint8{15, 120}, Prefix: []uint8{102}, Modrm: true, Mod: 3, Rm: -1, Imm: 1, Imm2: 1, NoRepPrefix: true, VexP: -1},
{Name: "EXTRQ", Extension: "SSE4a", Mode: 15, Opcode: []uint8{15, 121}, Prefix: []uint8{102}, Modrm: true, Mod: 3, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "INSERTQ", Extension: "SSE4a", Mode: 15, Opcode: []uint8{15, 120}, Prefix: []uint8{242}, Modrm: true, Mod: 3, Reg: -1, Rm: -1, Imm: 1, Imm2: 1, NoRepPrefix: true, VexP: -1},
{Name: "INSERTQ", Extension: "SSE4a", Mode: 15, Opcode: []uint8{15, 121}, Prefix: []uint8{242}, Modrm: true, Mod: 3, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "MOVNTSD", Extension: "SSE4a", Mode: 15, Opcode: []uint8{15, 43}, Prefix: []uint8{242}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "MOVNTSS", Extension: "SSE4a", Mode: 15, Opcode: []uint8{15, 43}, Prefix: []uint8{243}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "LZCNT", Extension: "AMD", Mode: 15, Opcode: []uint8{15, 189}, Prefix: []uint8{243}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "CLZERO", Extension: "CLZERO", Mode: 15, Opcode: []uint8{15, 1}, Modrm: true, Mod: 3, Reg: 7, Rm: 4, VexP: -1},
{Name: "MONITORX", Extension: "MONITORX", Mode: 14, Opcode: []uint8{15, 1}, Modrm: true, Mod: 3, Reg: 7, Rm: 2, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "MONITORX", Extension: "MONITORX", Mode: 1, Opcode: []uint8{15, 1}, Modrm: true, Mod: 3, Reg: 7, Rm: 2, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "MWAITX", Extension: "MONITORX", Mode: 15, Opcode: []uint8{15, 1}, Modrm: true, Mod: 3, Reg: 7, Rm: 3, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "VPMACSSWW", Extension: "XOP", Mode: 3, Opcode: []uint8{133}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 143, VexMap: 8, VexL: -1},
{Name: "VPMACSSWD", Extension: "XOP", Mode: 3, Opcode: []uint8{134}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 143, VexMap: 8, VexL: -1},
{Name: "VPMACSSDQL", Extension: "XOP", Mode: 3, Opcode: []uint8{135}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 143, VexMap: 8, VexL: -1},
{Name: "VPMACSWW", Extension: "XOP", Mode: 3, Opcode: []uint8{149}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 143, VexMap: 8, VexL: -1},
{Name: "VPMACSWD", Extension: "XOP", Mode: 3, Opcode: []uint8{150}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 143, VexMap: 8, VexL: -1},
{Name: "VPMACSDQL", Extension: "XOP", Mode: 3, Opcode: []uint8{151}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 143, VexMap: 8, VexL: -1},
{Name: "VPCMOV", Extension: "XOP", Mode: 3, Opcode: []uint8{162}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 143, VexMap: 8, VexL: -1},
{Name: "VPCMOV", Extension: "XOP", Mode: 3, Opcode: []uint8{162}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: 1, Vex: 143, VexMap: 8, VexL: -1},
{Name: "VPCMOV", Extension: "XOP", Mode: 3, Opcode: []uint8{162}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 143, VexMap: 8, VexL: 1},
{Name: "VPCMOV", Extension: "XOP", Mode: 3, Opcode: []uint8{162}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: 1, Vex: 143, VexMap: 8, VexL: 1},
{Name: "VPPERM", Extension: "XOP", Mode: 3, Opcode: []uint8{163}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 143, VexMap: 8, VexL: -1},
{Name: "VPPERM", Extension: "XOP", Mode: 3, Opcode: []uint8{163}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: 1, Vex: 143, VexMap: 8, VexL: -1},
{Name: "VPMADCSSWD", Extension: "XOP", Mode: 3, Opcode: []uint8{166}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 143, VexMap: 8, VexL: -1},
{Name: "VPMADCSWD", Extension: "XOP", Mode: 3, Opcode: []uint8{182}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 143, VexMap: 8, VexL: -1},
{Name: "VPROTB", Extension: "XOP", Mode: 3, Opcode: []uint8{192}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 143, VexMap: 8, VexL: -1, VexNoR: true},
{Name: "VPROTW", Extension: "XOP", Mode: 3, Opcode: []uint8{193}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 143, VexMap: 8, VexL: -1, VexNoR: true},
{Name: "VPROTD", Extension: "XOP", Mode: 3, Opcode: []uint8{194}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 143, VexMap: 8, VexL: -1, VexNoR: true},
{Name: "VPROTQ", Extension: "XOP", Mode: 3, Opcode: []uint8{195}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 143, VexMap: 8, VexL: -1, VexNoR: true},
{Name: "VPMACSSDD", Extension: "XOP", Mode: 3, Opcode: []uint8{142}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 143, VexMap: 8, VexL: -1},
{Name: "VPMACSSDQH", Extension: "XOP", Mode: 3, Opcode: []uint8{143}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 143, VexMap: 8, VexL: -1},
{Name: "VPMACSDD", Extension: "XOP", Mode: 3, Opcode: []uint8{158}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 143, VexMap: 8, VexL: -1},
{Name: "VPMACSDQH", Extension: "XOP", Mode: 3, Opcode: []uint8{159}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 143, VexMap: 8, VexL: -1},
{Name: "VPCOMB", Extension: "XOP", Mode: 3, Opcode: []uint8{204}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 143, VexMap: 8, VexL: -1},
{Name: "VPCOMW", Extension: "XOP", Mode: 3, Opcode: []uint8{205}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 143, VexMap: 8, VexL: -1},
{Name: "VPCOMD", Extension: "XOP", Mode: 3, Opcode: []uint8{206}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 143, VexMap: 8, VexL: -1},
{Name: "VPCOMQ", Extension: "XOP", Mode: 3, Opcode: []uint8{207}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 143, VexMap: 8, VexL: -1},
{Name: "VPCOMUB", Extension: "XOP", Mode: 3, Opcode: []uint8{236}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 143, VexMap: 8, VexL: -1},
{Name: "VPCOMUW", Extension: "XOP", Mode: 3, Opcode: []uint8{237}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 143, VexMap: 8, VexL: -1},
{Name: "VPCOMUD", Extension: "XOP", Mode: 3, Opcode: []uint8{238}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 143, VexMap: 8, VexL: -1},
{Name: "VPCOMUQ", Extension: "XOP", Mode: 3, Opcode: []uint8{239}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 143, VexMap: 8, VexL: -1},
{Name: "VFRCZPS", Extension: "XOP", Mode: 3, Opcode: []uint8{128}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 143, VexMap: 9, VexL: -1, VexNoR: true},
{Name: "VFRCZPS", Extension: "XOP", Mode: 3, Opcode: []uint8{128}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 143, VexMap: 9, VexL: 1, VexNoR: true},
{Name: "VFRCZPD", Extension: "XOP", Mode: 3, Opcode: []uint8{129}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 143, VexMap: 9, VexL: -1, VexNoR: true},
{Name: "VFRCZPD", Extension: "XOP", Mode: 3, Opcode: []uint8{129}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 143, VexMap: 9, VexL: 1, VexNoR: true},
{Name: "VFRCZSS", Extension: "XOP", Mode: 3, Opcode: []uint8{130}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 143, VexMap: 9, VexL: -1, VexNoR: true},
{Name: "VFRCZSD", Extension: "XOP", Mode: 3, Opcode: []uint8{131}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 143, VexMap: 9, VexL: -1, VexNoR: true},
{Name: "VPROTB", Extension: "XOP", Mode: 3, Opcode: []uint8{144}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 143, VexMap: 9, VexL: -1},
{Name: "VPROTB", Extension: "XOP", Mode: 3, Opcode: []uint8{144}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 143, VexMap: 9, VexL: -1},
{Name: "VPROTW", Extension: "XOP", Mode: 3, Opcode: []uint8{145}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 143, VexMap: 9, VexL: -1},
{Name: "VPROTW", Extension: "XOP", Mode: 3, Opcode: []uint8{145}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 143, VexMap: 9, VexL: -1},
{Name: "VPROTD", Extension: "XOP", Mode: 3, Opcode: []uint8{146}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 143, VexMap: 9, VexL: -1},
{Name: "VPROTD", Extension: "XOP", Mode: 3, Opcode: []uint8{146}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 143, VexMap: 9, VexL: -1},
{Name: "VPROTQ", Extension: "XOP", Mode: 3, Opcode: []uint8{147}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 143, VexMap: 9, VexL: -1},
{Name: "VPROTQ", Extension: "XOP", Mode: 3, Opcode: []uint8{147}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 143, VexMap: 9, VexL: -1},
{Name: "VPSHLB", Extension: "XOP", Mode: 3, Opcode: []uint8{148}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 143, VexMap: 9, VexL: -1},
{Name: "VPSHLB", Extension: "XOP", Mode: 3, Opcode: []uint8{148}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 143, VexMap: 9, VexL: -1},
{Name: "VPSHLW", Extension: "XOP", Mode: 3, Opcode: []uint8{149}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 143, VexMap: 9, VexL: -1},
{Name: "VPSHLW", Extension: "XOP", Mode: 3, Opcode: []uint8{149}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 143, VexMap: 9, VexL: -1},
{Name: "VPSHLD", Extension: "XOP", Mode: 3, Opcode: []uint8{150}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 143, VexMap: 9, VexL: -1},
{Name: "VPSHLD", Extension: "XOP", Mode: 3, Opcode: []uint8{150}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 143, VexMap: 9, VexL: -1},
{Name: "VPSHLQ", Extension: "XOP", Mode: 3, Opcode: []uint8{151}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 143, VexMap: 9, VexL: -1},
{Name: "VPSHLQ", Extension: "XOP", Mode: 3, Opcode: []uint8{151}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 143, VexMap: 9, VexL: -1},
{Name: "VPHADDBW", Extension: "XOP", Mode: 3, Opcode: []uint8{193}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 143, VexMap: 9, VexL: -1, VexNoR: true},
{Name: "VPHADDBD", Extension: "XOP", Mode: 3, Opcode: []uint8{194}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 143, VexMap: 9, VexL: -1, VexNoR: true},
{Name: "VPHADDBQ", Extension: "XOP", Mode: 3, Opcode: []uint8{195}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 143, VexMap: 9, VexL: -1, VexNoR: true},
{Name: "VPHADDWD", Extension: "XOP", Mode: 3, Opcode: []uint8{198}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 143, VexMap: 9, VexL: -1, VexNoR: true},
{Name: "VPHADDWQ", Extension: "XOP", Mode: 3, Opcode: []uint8{199}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 143, VexMap: 9, VexL: -1, VexNoR: true},
{Name: "VPHADDUBW", Extension: "XOP", Mode: 3, Opcode: []uint8{209}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 143, VexMap: 9, VexL: -1, VexNoR: true},
{Name: "VPHADDUBD", Extension: "XOP", Mode: 3, Opcode: []uint8{210}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 143, VexMap: 9, VexL: -1, VexNoR: true},
{Name: "VPHADDUBQ", Extension: "XOP", Mode: 3, Opcode: []uint8{211}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 143, VexMap: 9, VexL: -1, VexNoR: true},
{Name: "VPHADDUWD", Extension: "XOP", Mode: 3, Opcode: []uint8{214}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 143, VexMap: 9, VexL: -1, VexNoR: true},
{Name: "VPHADDUWQ", Extension: "XOP", Mode: 3, Opcode: []uint8{215}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 143, VexMap: 9, VexL: -1, VexNoR: true},
{Name: "VPHSUBBW", Extension: "XOP", Mode: 3, Opcode: []uint8{225}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 143, VexMap: 9, VexL: -1, VexNoR: true},
{Name: "VPHSUBWD", Extension: "XOP", Mode: 3, Opcode: []uint8{226}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 143, VexMap: 9, VexL: -1, VexNoR: true},
{Name: "VPHSUBDQ", Extension: "XOP", Mode: 3, Opcode: []uint8{227}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 143, VexMap: 9, VexL: -1, VexNoR: true},
{Name: "VPSHAB", Extension: "XOP", Mode: 3, Opcode: []uint8{152}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 143, VexMap: 9, VexL: -1},
{Name: "VPSHAB", Extension: "XOP", Mode: 3, Opcode: []uint8{152}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 143, VexMap: 9, VexL: -1},
{Name: "VPSHAW", Extension: "XOP", Mode: 3, Opcode: []uint8{153}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 143, VexMap: 9, VexL: -1},
{Name: "VPSHAW", Extension: "XOP", Mode: 3, Opcode: []uint8{153}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 143, VexMap: 9, VexL: -1},
{Name: "VPSHAD", Extension: "XOP", Mode: 3, Opcode: []uint8{154}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 143, VexMap: 9, VexL: -1},
{Name: "VPSHAD", Extension: "XOP", Mode: 3, Opcode: []uint8{154}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 143, VexMap: 9, VexL: -1},
{Name: "VPSHAQ", Extension: "XOP", Mode: 3, Opcode: []uint8{155}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 143, VexMap: 9, VexL: -1},
{Name: "VPSHAQ", Extension: "XOP", Mode: 3, Opcode: []uint8{155}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 143, VexMap: 9, VexL: -1},
{Name: "VPHADDDQ", Extension: "XOP", Mode: 3, Opcode: []uint8{203}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 143, VexMap: 9, VexL: -1, VexNoR: true},
{Name: "VPHADDUDQ", Extension: "XOP", Mode: 3, Opcode: []uint8{219}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 143, VexMap: 9, VexL: -1, VexNoR: true},
{Name: "BEXTR_XOP", Extension: "TBM", Mode: 6, Opcode: []uint8{16}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 4, Vex: 143, VexMap: 10, VexL: -1, VexNoR: true},
{Name: "BEXTR_XOP", Extension: "TBM", Mode: 1, Opcode: []uint8{16}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 4, Vex: 143, VexMap: 10, VexL: -1, VexNoR: true},
{Name: "BLCFILL", Extension: "TBM", Mode: 6, Opcode: []uint8{1}, Modrm: true, Mod: -1, Reg: 1, Rm: -1, Vex: 143, VexMap: 9, VexL: -1},
{Name: "BLCFILL", Extension: "TBM", Mode: 1, Opcode: []uint8{1}, Modrm: true, Mod: -1, Reg: 1, Rm: -1, Vex: 143, VexMap: 9, VexL: -1},
{Name: "BLSFILL", Extension: "TBM", Mode: 6, Opcode: []uint8{1}, Modrm: true, Mod: -1, Reg: 2, Rm: -1, Vex: 143, VexMap: 9, VexL: -1},
{Name: "BLSFILL", Extension: "TBM", Mode: 1, Opcode: []uint8{1}, Modrm: true, Mod: -1, Reg: 2, Rm: -1, Vex: 143, VexMap: 9, VexL: -1},
{Name: "BLCS", Extension: "TBM", Mode: 6, Opcode: []uint8{1}, Modrm: true, Mod: -1, Reg: 3, Rm: -1, Vex: 143, VexMap: 9, VexL: -1},
{Name: "BLCS", Extension: "TBM", Mode: 1, Opcode: []uint8{1}, Modrm: true, Mod: -1, Reg: 3, Rm: -1, Vex: 143, VexMap: 9, VexL: -1},
{Name: "TZMSK", Extension: "TBM", Mode: 6, Opcode: []uint8{1}, Modrm: true, Mod: -1, Reg: 4, Rm: -1, Vex: 143, VexMap: 9, VexL: -1},
{Name: "TZMSK", Extension: "TBM", Mode: 1, Opcode: []uint8{1}, Modrm: true, Mod: -1, Reg: 4, Rm: -1, Vex: 143, VexMap: 9, VexL: -1},
{Name: "BLCIC", Extension: "TBM", Mode: 6, Opcode: []uint8{1}, Modrm: true, Mod: -1, Reg: 5, Rm: -1, Vex: 143, VexMap: 9, VexL: -1},
{Name: "BLCIC", Extension: "TBM", Mode: 1, Opcode: []uint8{1}, Modrm: true, Mod: -1, Reg: 5, Rm: -1, Vex: 143, VexMap: 9, VexL: -1},
{Name: "BLSIC", Extension: "TBM", Mode: 6, Opcode: []uint8{1}, Modrm: true, Mod: -1, Reg: 6, Rm: -1, Vex: 143, VexMap: 9, VexL: -1},
{Name: "BLSIC", Extension: "TBM", Mode: 1, Opcode: []uint8{1}, Modrm: true, Mod: -1, Reg: 6, Rm: -1, Vex: 143, VexMap: 9, VexL: -1},
{Name: "T1MSKC", Extension: "TBM", Mode: 6, Opcode: []uint8{1}, Modrm: true, Mod: -1, Reg: 7, Rm: -1, Vex: 143, VexMap: 9, VexL: -1},
{Name: "T1MSKC", Extension: "TBM", Mode: 1, Opcode: []uint8{1}, Modrm: true, Mod: -1, Reg: 7, Rm: -1, Vex: 143, VexMap: 9, VexL: -1},
{Name: "BLCMSK", Extension: "TBM", Mode: 6, Opcode: []uint8{2}, Modrm: true, Mod: -1, Reg: 1, Rm: -1, Vex: 143, VexMap: 9, VexL: -1},
{Name: "BLCMSK", Extension: "TBM", Mode: 1, Opcode: []uint8{2}, Modrm: true, Mod: -1, Reg: 1, Rm: -1, Vex: 143, VexMap: 9, VexL: -1},
{Name: "BLCI", Extension: "TBM", Mode: 6, Opcode: []uint8{2}, Modrm: true, Mod: -1, Reg: 6, Rm: -1, Vex: 143, VexMap: 9, VexL: -1},
{Name: "BLCI", Extension: "TBM", Mode: 1, Opcode: []uint8{2}, Modrm: true, Mod: -1, Reg: 6, Rm: -1, Vex: 143, VexMap: 9, VexL: -1},
{Name: "LLWPCB", Extension: "XOP", Mode: 3, Opcode: []uint8{18}, Modrm: true, Mod: 3, Rm: -1, Vex: 143, VexMap: 9, VexL: -1, VexNoR: true},
{Name: "SLWPCB", Extension: "XOP", Mode: 3, Opcode: []uint8{18}, Modrm: true, Mod: 3, Reg: 1, Rm: -1, Vex: 143, VexMap: 9, VexL: -1, VexNoR: true},
{Name: "LWPINS", Extension: "XOP", Mode: 3, Opcode: []uint8{18}, Modrm: true, Mod: -1, Rm: -1, Imm: 4, Vex: 143, VexMap: 10, VexL: -1},
{Name: "LWPVAL", Extension: "XOP", Mode: 3, Opcode: []uint8{18}, Modrm: true, Mod: -1, Reg: 1, Rm: -1, Imm: 4, Vex: 143, VexMap: 10, VexL: -1},
{Name: "VFMADDSUBPS", Extension: "FMA4", Mode: 3, Opcode: []uint8{92}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: -1, VexP: 1},
{Name: "VFMADDSUBPS", Extension: "FMA4", Mode: 3, Opcode: []uint8{92}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: 1, Vex: 196, VexMap: 3, VexL: -1, VexP: 1},
{Name: "VFMADDSUBPS", Extension: "FMA4", Mode: 3, Opcode: []uint8{92}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: 1, VexP: 1},
{Name: "VFMADDSUBPS", Extension: "FMA4", Mode: 3, Opcode: []uint8{92}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: 1, Vex: 196, VexMap: 3, VexL: 1, VexP: 1},
{Name: "VFMADDSUBPD", Extension: "FMA4", Mode: 3, Opcode: []uint8{93}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: -1, VexP: 1},
{Name: "VFMADDSUBPD", Extension: "FMA4", Mode: 3, Opcode: []uint8{93}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: 1, Vex: 196, VexMap: 3, VexL: -1, VexP: 1},
{Name: "VFMADDSUBPD", Extension: "FMA4", Mode: 3, Opcode: []uint8{93}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: 1, VexP: 1},
{Name: "VFMADDSUBPD", Extension: "FMA4", Mode: 3, Opcode: []uint8{93}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: 1, Vex: 196, VexMap: 3, VexL: 1, VexP: 1},
{Name: "VFMSUBADDPS", Extension: "FMA4", Mode: 3, Opcode: []uint8{94}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: -1, VexP: 1},
{Name: "VFMSUBADDPS", Extension: "FMA4", Mode: 3, Opcode: []uint8{94}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: 1, Vex: 196, VexMap: 3, VexL: -1, VexP: 1},
{Name: "VFMSUBADDPS", Extension: "FMA4", Mode: 3, Opcode: []uint8{94}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: 1, VexP: 1},
{Name: "VFMSUBADDPS", Extension: "FMA4", Mode: 3, Opcode: []uint8{94}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: 1, Vex: 196, VexMap: 3, VexL: 1, VexP: 1},
{Name: "VFMSUBADDPD", Extension: "FMA4", Mode: 3, Opcode: []uint8{95}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: -1, VexP: 1},
{Name: "VFMSUBADDPD", Extension: "FMA4", Mode: 3, Opcode: []uint8{95}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: 1, Vex: 196, VexMap: 3, VexL: -1, VexP: 1},
{Name: "VFMSUBADDPD", Extension: "FMA4", Mode: 3, Opcode: []uint8{95}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: 1, VexP: 1},
{Name: "VFMSUBADDPD", Extension: "FMA4", Mode: 3, Opcode: []uint8{95}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: 1, Vex: 196, VexMap: 3, VexL: 1, VexP: 1},
{Name: "VFMADDPS", Extension: "FMA4", Mode: 3, Opcode: []uint8{104}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: -1, VexP: 1},
{Name: "VFMADDPS", Extension: "FMA4", Mode: 3, Opcode: []uint8{104}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: 1, Vex: 196, VexMap: 3, VexL: -1, VexP: 1},
{Name: "VFMADDPS", Extension: "FMA4", Mode: 3, Opcode: []uint8{104}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: 1, VexP: 1},
{Name: "VFMADDPS", Extension: "FMA4", Mode: 3, Opcode: []uint8{104}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: 1, Vex: 196, VexMap: 3, VexL: 1, VexP: 1},
{Name: "VFMADDPD", Extension: "FMA4", Mode: 3, Opcode: []uint8{105}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: -1, VexP: 1},
{Name: "VFMADDPD", Extension: "FMA4", Mode: 3, Opcode: []uint8{105}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: 1, Vex: 196, VexMap: 3, VexL: -1, VexP: 1},
{Name: "VFMADDPD", Extension: "FMA4", Mode: 3, Opcode: []uint8{105}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: 1, VexP: 1},
{Name: "VFMADDPD", Extension: "FMA4", Mode: 3, Opcode: []uint8{105}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: 1, Vex: 196, VexMap: 3, VexL: 1, VexP: 1},
{Name: "VFMADDSS", Extension: "FMA4", Mode: 3, Opcode: []uint8{106}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexP: 1},
{Name: "VFMADDSS", Extension: "FMA4", Mode: 3, Opcode: []uint8{106}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: 1, Vex: 196, VexMap: 3, VexP: 1},
{Name: "VFMADDSD", Extension: "FMA4", Mode: 3, Opcode: []uint8{107}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexP: 1},
{Name: "VFMADDSD", Extension: "FMA4", Mode: 3, Opcode: []uint8{107}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: 1, Vex: 196, VexMap: 3, VexP: 1},
{Name: "VFMSUBPS", Extension: "FMA4", Mode: 3, Opcode: []uint8{108}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: -1, VexP: 1},
{Name: "VFMSUBPS", Extension: "FMA4", Mode: 3, Opcode: []uint8{108}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: 1, Vex: 196, VexMap: 3, VexL: -1, VexP: 1},
{Name: "VFMSUBPS", Extension: "FMA4", Mode: 3, Opcode: []uint8{108}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: 1, VexP: 1},
{Name: "VFMSUBPS", Extension: "FMA4", Mode: 3, Opcode: []uint8{108}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: 1, Vex: 196, VexMap: 3, VexL: 1, VexP: 1},
{Name: "VFMSUBPD", Extension: "FMA4", Mode: 3, Opcode: []uint8{109}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: -1, VexP: 1},
{Name: "VFMSUBPD", Extension: "FMA4", Mode: 3, Opcode: []uint8{109}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: 1, Vex: 196, VexMap: 3, VexL: -1, VexP: 1},
{Name: "VFMSUBPD", Extension: "FMA4", Mode: 3, Opcode: []uint8{109}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: 1, VexP: 1},
{Name: "VFMSUBPD", Extension: "FMA4", Mode: 3, Opcode: []uint8{109}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: 1, Vex: 196, VexMap: 3, VexL: 1, VexP: 1},
{Name: "VFMSUBSS", Extension: "FMA4", Mode: 3, Opcode: []uint8{110}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexP: 1},
{Name: "VFMSUBSS", Extension: "FMA4", Mode: 3, Opcode: []uint8{110}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: 1, Vex: 196, VexMap: 3, VexP: 1},
{Name: "VFMSUBSD", Extension: "FMA4", Mode: 3, Opcode: []uint8{111}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexP: 1},
{Name: "VFMSUBSD", Extension: "FMA4", Mode: 3, Opcode: []uint8{111}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: 1, Vex: 196, VexMap: 3, VexP: 1},
{Name: "VFNMADDPS", Extension: "FMA4", Mode: 3, Opcode: []uint8{120}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: -1, VexP: 1},
{Name: "VFNMADDPS", Extension: "FMA4", Mode: 3, Opcode: []uint8{120}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: 1, Vex: 196, VexMap: 3, VexL: -1, VexP: 1},
{Name: "VFNMADDPS", Extension: "FMA4", Mode: 3, Opcode: []uint8{120}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: 1, VexP: 1},
{Name: "VFNMADDPS", Extension: "FMA4", Mode: 3, Opcode: []uint8{120}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: 1, Vex: 196, VexMap: 3, VexL: 1, VexP: 1},
{Name: "VFNMADDPD", Extension: "FMA4", Mode: 3, Opcode: []uint8{121}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: -1, VexP: 1},
{Name: "VFNMADDPD", Extension: "FMA4", Mode: 3, Opcode: []uint8{121}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: 1, Vex: 196, VexMap: 3, VexL: -1, VexP: 1},
{Name: "VFNMADDPD", Extension: "FMA4", Mode: 3, Opcode: []uint8{121}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: 1, VexP: 1},
{Name: "VFNMADDPD", Extension: "FMA4", Mode: 3, Opcode: []uint8{121}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: 1, Vex: 196, VexMap: 3, VexL: 1, VexP: 1},
{Name: "VFNMADDSS", Extension: "FMA4", Mode: 3, Opcode: []uint8{122}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexP: 1},
{Name: "VFNMADDSS", Extension: "FMA4", Mode: 3, Opcode: []uint8{122}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: 1, Vex: 196, VexMap: 3, VexP: 1},
{Name: "VFNMADDSD", Extension: "FMA4", Mode: 3, Opcode: []uint8{123}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexP: 1},
{Name: "VFNMADDSD", Extension: "FMA4", Mode: 3, Opcode: []uint8{123}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: 1, Vex: 196, VexMap: 3, VexP: 1},
{Name: "VFNMSUBPS", Extension: "FMA4", Mode: 3, Opcode: []uint8{124}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: -1, VexP: 1},
{Name: "VFNMSUBPS", Extension: "FMA4", Mode: 3, Opcode: []uint8{124}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: 1, Vex: 196, VexMap: 3, VexL: -1, VexP: 1},
{Name: "VFNMSUBPS", Extension: "FMA4", Mode: 3, Opcode: []uint8{124}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: 1, VexP: 1},
{Name: "VFNMSUBPS", Extension: "FMA4", Mode: 3, Opcode: []uint8{124}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: 1, Vex: 196, VexMap: 3, VexL: 1, VexP: 1},
{Name: "VFNMSUBPD", Extension: "FMA4", Mode: 3, Opcode: []uint8{125}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: -1, VexP: 1},
{Name: "VFNMSUBPD", Extension: "FMA4", Mode: 3, Opcode: []uint8{125}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: 1, Vex: 196, VexMap: 3, VexL: -1, VexP: 1},
{Name: "VFNMSUBPD", Extension: "FMA4", Mode: 3, Opcode: []uint8{125}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: 1, VexP: 1},
{Name: "VFNMSUBPD", Extension: "FMA4", Mode: 3, Opcode: []uint8{125}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: 1, Vex: 196, VexMap: 3, VexL: 1, VexP: 1},
{Name: "VFNMSUBSS", Extension: "FMA4", Mode: 3, Opcode: []uint8{126}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexP: 1},
{Name: "VFNMSUBSS", Extension: "FMA4", Mode: 3, Opcode: []uint8{126}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: 1, Vex: 196, VexMap: 3, VexP: 1},
{Name: "VFNMSUBSD", Extension: "FMA4", Mode: 3, Opcode: []uint8{127}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexP: 1},
{Name: "VFNMSUBSD", Extension: "FMA4", Mode: 3, Opcode: []uint8{127}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: 1, Vex: 196, VexMap: 3, VexP: 1},
{Name: "VPERMIL2PS", Extension: "XOP", Mode: 3, Opcode: []uint8{72}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: -1, VexP: 1},
{Name: "VPERMIL2PS", Extension: "XOP", Mode: 3, Opcode: []uint8{72}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: 1, VexP: 1},
{Name: "VPERMIL2PS", Extension: "XOP", Mode: 3, Opcode: []uint8{72}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: 1, Vex: 196, VexMap: 3, VexL: -1, VexP: 1},
{Name: "VPERMIL2PS", Extension: "XOP", Mode: 3, Opcode: []uint8{72}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: 1, Vex: 196, VexMap: 3, VexL: 1, VexP: 1},
{Name: "VPERMIL2PD", Extension: "XOP", Mode: 3, Opcode: []uint8{73}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: -1, VexP: 1},
{Name: "VPERMIL2PD", Extension: "XOP", Mode: 3, Opcode: []uint8{73}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: 1, VexP: 1},
{Name: "VPERMIL2PD", Extension: "XOP", Mode: 3, Opcode: []uint8{73}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: 1, Vex: 196, VexMap: 3, VexL: -1, VexP: 1},
{Name: "VPERMIL2PD", Extension: "XOP", Mode: 3, Opcode: []uint8{73}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: 1, Vex: 196, VexMap: 3, VexL: 1, VexP: 1},
{Name: "BNDMK", Extension: "MPX", Mode: 15, Opcode: []uint8{15, 27}, Prefix: []uint8{243}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "BNDCL", Extension: "MPX", Mode: 15, Opcode: []uint8{15, 26}, Prefix: []uint8{243}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "BNDCL", Extension: "MPX", Mode: 1, Opcode: []uint8{15, 26}, Prefix: []uint8{243}, Modrm: true, Mod: 3, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "BNDCL", Extension: "MPX", Mode: 14, Opcode: []uint8{15, 26}, Prefix: []uint8{243}, Modrm: true, Mod: 3, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "BNDCU", Extension: "MPX", Mode: 15, Opcode: []uint8{15, 26}, Prefix: []uint8{242}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "BNDCU", Extension: "MPX", Mode: 1, Opcode: []uint8{15, 26}, Prefix: []uint8{242}, Modrm: true, Mod: 3, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "BNDCU", Extension: "MPX", Mode: 14, Opcode: []uint8{15, 26}, Prefix: []uint8{242}, Modrm: true, Mod: 3, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "BNDCN", Extension: "MPX", Mode: 15, Opcode: []uint8{15, 27}, Prefix: []uint8{242}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "BNDCN", Extension: "MPX", Mode: 1, Opcode: []uint8{15, 27}, Prefix: []uint8{242}, Modrm: true, Mod: 3, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "BNDCN", Extension: "MPX", Mode: 14, Opcode: []uint8{15, 27}, Prefix: []uint8{242}, Modrm: true, Mod: 3, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "BNDMOV", Extension: "MPX", Mode: 15, Opcode: []uint8{15, 26}, Prefix: []uint8{102}, Modrm: true, Mod: 3, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "BNDMOV", Extension: "MPX", Mode: 12, Opcode: []uint8{15, 26}, Prefix: []uint8{102}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "BNDMOV", Extension: "MPX", Mode: 2, Opcode: []uint8{15, 26}, Prefix: []uint8{102}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "BNDMOV", Extension: "MPX", Mode: 1, Opcode: []uint8{15, 26}, Prefix: []uint8{102}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "BNDMOV", Extension: "MPX", Mode: 15, Opcode: []uint8{15, 27}, Prefix: []uint8{102}, Modrm: true, Mod: 3, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "BNDMOV", Extension: "MPX", Mode: 12, Opcode: []uint8{15, 27}, Prefix: []uint8{102}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "BNDMOV", Extension: "MPX", Mode: 2, Opcode: []uint8{15, 27}, Prefix: []uint8{102}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "BNDMOV", Extension: "MPX", Mode: 1, Opcode: []uint8{15, 27}, Prefix: []uint8{102}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "BNDLDX", Extension: "MPX", Mode: 14, Opcode: []uint8{15, 26}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "BNDLDX", Extension: "MPX", Mode: 1, Opcode: []uint8{15, 26}, Modrm: true, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "BNDLDX", Extension: "MPX", Mode: 1, Opcode: []uint8{15, 26}, Modrm: true, Mod: 1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "BNDLDX", Extension: "MPX", Mode: 1, Opcode: []uint8{15, 26}, Modrm: true, Mod: 2, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "BNDSTX", Extension: "MPX", Mode: 14, Opcode: []uint8{15, 27}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "BNDSTX", Extension: "MPX", Mode: 1, Opcode: []uint8{15, 27}, Modrm: true, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "BNDSTX", Extension: "MPX", Mode: 1, Opcode: []uint8{15, 27}, Modrm: true, Mod: 1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "BNDSTX", Extension: "MPX", Mode: 1, Opcode: []uint8{15, 27}, Modrm: true, Mod: 2, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 26}, Modrm: true, Mod: 3, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 27}, Modrm: true, Mod: 3, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 27}, Prefix: []uint8{243}, Modrm: true, Mod: 3, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 30}, Modrm: true, Mod: 3, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 30}, Prefix: []uint8{242}, Modrm: true, Mod: 3, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 30}, Prefix: []uint8{102}, Modrm: true, Mod: 3, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 30}, Prefix: []uint8{243}, Modrm: true, Mod: 3, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 30}, Prefix: []uint8{243}, Modrm: true, Mod: 3, Reg: 2, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 30}, Prefix: []uint8{243}, Modrm: true, Mod: 3, Reg: 3, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 30}, Prefix: []uint8{243}, Modrm: true, Mod: 3, Reg: 4, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 30}, Prefix: []uint8{243}, Modrm: true, Mod: 3, Reg: 5, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 30}, Prefix: []uint8{243}, Modrm: true, Mod: 3, Reg: 6, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 30}, Prefix: []uint8{243}, Modrm: true, Mod: 3, Reg: 7, NoRepPrefix: true, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 30}, Prefix: []uint8{243}, Modrm: true, Mod: 3, Reg: 7, Rm: 1, NoRepPrefix: true, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 30}, Prefix: []uint8{243}, Modrm: true, Mod: 3, Reg: 7, Rm: 4, NoRepPrefix: true, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 30}, Prefix: []uint8{243}, Modrm: true, Mod: 3, Reg: 7, Rm: 5, NoRepPrefix: true, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 30}, Prefix: []uint8{243}, Modrm: true, Mod: 3, Reg: 7, Rm: 6, NoRepPrefix: true, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 30}, Prefix: []uint8{243}, Modrm: true, Mod: 3, Reg: 7, Rm: 7, NoRepPrefix: true, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 30}, Prefix: []uint8{243}, Modrm: true, Mod: 3, Reg: 7, Rm: 2, NoRepPrefix: true, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 30}, Prefix: []uint8{243}, Modrm: true, Mod: 3, Reg: 7, Rm: 3, NoRepPrefix: true, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 30}, Prefix: []uint8{243}, Modrm: true, Mod: 3, Reg: 1, Rm: -1, NoRepPrefix: true, Rexw: -1, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 1, Opcode: []uint8{15, 30}, Prefix: []uint8{243}, Modrm: true, Mod: 3, Reg: 1, Rm: -1, NoRepPrefix: true, Rexw: 1, VexP: -1},
{Name: "CLRSSBSY", Extension: "CET", Mode: 15, Opcode: []uint8{15, 174}, Prefix: []uint8{243}, Modrm: true, Mod: -3, Reg: 6, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "ENDBR32", Extension: "CET", Mode: 15, Opcode: []uint8{15, 30}, Prefix: []uint8{243}, Modrm: true, Mod: 3, Reg: 7, Rm: 3, NoRepPrefix: true, VexP: -1},
{Name: "ENDBR64", Extension: "CET", Mode: 15, Opcode: []uint8{15, 30}, Prefix: []uint8{243}, Modrm: true, Mod: 3, Reg: 7, Rm: 2, NoRepPrefix: true, VexP: -1},
{Name: "INCSSPD", Extension: "CET", Mode: 15, Opcode: []uint8{15, 174}, Prefix: []uint8{243}, Modrm: true, Mod: 3, Reg: 5, Rm: -1, NoRepPrefix: true, Rexw: -1, VexP: -1},
{Name: "INCSSPQ", Extension: "CET", Mode: 1, Opcode: []uint8{15, 174}, Prefix: []uint8{243}, Modrm: true, Mod: 3, Reg: 5, Rm: -1, NoRepPrefix: true, Rexw: 1, VexP: -1},
{Name: "RDSSPD", Extension: "CET", Mode: 15, Opcode: []uint8{15, 30}, Prefix: []uint8{243}, Modrm: true, Mod: 3, Reg: 1, Rm: -1, NoRepPrefix: true, Rexw: -1, VexP: -1},
{Name: "RDSSPQ", Extension: "CET", Mode: 1, Opcode: []uint8{15, 30}, Prefix: []uint8{243}, Modrm: true, Mod: 3, Reg: 1, Rm: -1, NoRepPrefix: true, Rexw: 1, VexP: -1},
{Name: "RSTORSSP", Extension: "CET", Mode: 15, Opcode: []uint8{15, 1}, Prefix: []uint8{243}, Modrm: true, Mod: -3, Reg: 5, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "SAVEPREVSSP", Extension: "CET", Mode: 15, Opcode: []uint8{15, 1}, Prefix: []uint8{243}, Modrm: true, Mod: 3, Reg: 5, Rm: 2, NoRepPrefix: true, VexP: -1},
{Name: "SETSSBSY", Extension: "CET", Mode: 15, Opcode: []uint8{15, 1}, Prefix: []uint8{243}, Modrm: true, Mod: 3, Reg: 5, NoRepPrefix: true, VexP: -1},
{Name: "WRSSD", Extension: "CET", Mode: 15, Opcode: []uint8{15, 56, 246}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, Rexw: -1, VexP: -1},
{Name: "WRSSQ", Extension: "CET", Mode: 1, Opcode: []uint8{15, 56, 246}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, Rexw: 1, VexP: -1},
{Name: "WRUSSD", Extension: "CET", Mode: 15, Opcode: []uint8{15, 56, 245}, Prefix: []uint8{102}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, NoRepPrefix: true, Rexw: -1, VexP: -1},
{Name: "WRUSSQ", Extension: "CET", Mode: 1, Opcode: []uint8{15, 56, 245}, Prefix: []uint8{102}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, NoRepPrefix: true, Rexw: 1, VexP: -1},
{Name: "RDRAND", Extension: "RDRAND", Mode: 15, Opcode: []uint8{15, 199}, Modrm: true, Mod: 3, Reg: 6, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "SHA1MSG1", Extension: "SHA", Mode: 15, Opcode: []uint8{15, 56, 201}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "SHA1MSG2", Extension: "SHA", Mode: 15, Opcode: []uint8{15, 56, 202}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "SHA1NEXTE", Extension: "SHA", Mode: 15, Opcode: []uint8{15, 56, 200}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "SHA1RNDS4", Extension: "SHA", Mode: 15, Opcode: []uint8{15, 58, 204}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "SHA256MSG1", Extension: "SHA", Mode: 15, Opcode: []uint8{15, 56, 204}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "SHA256MSG2", Extension: "SHA", Mode: 15, Opcode: []uint8{15, 56, 205}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "SHA256RNDS2", Extension: "SHA", Mode: 15, Opcode: []uint8{15, 56, 203}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "XSAVEOPT", Extension: "XSAVEOPT", Mode: 15, Opcode: []uint8{15, 174}, Modrm: true, Mod: -3, Reg: 6, Rm: -1, NoRepPrefix: true, No66Prefix: true, Rexw: -1, VexP: -1},
{Name: "XSAVEOPT64", Extension: "XSAVEOPT", Mode: 15, Opcode: []uint8{15, 174}, Modrm: true, Mod: -3, Reg: 6, Rm: -1, NoRepPrefix: true, No66Prefix: true, Rexw: 1, VexP: -1},
{Name: "XSAVES", Extension: "XSAVES", Mode: 15, Priv: true, Opcode: []uint8{15, 199}, Modrm: true, Mod: -3, Reg: 5, Rm: -1, NoRepPrefix: true, No66Prefix: true, Rexw: -1, VexP: -1},
{Name: "XSAVES64", Extension: "XSAVES", Mode: 15, Priv: true, Opcode: []uint8{15, 199}, Modrm: true, Mod: -3, Reg: 5, Rm: -1, NoRepPrefix: true, No66Prefix: true, Rexw: 1, VexP: -1},
{Name: "XRSTORS", Extension: "XSAVES", Mode: 15, Priv: true, Opcode: []uint8{15, 199}, Modrm: true, Mod: -3, Reg: 3, Rm: -1, NoRepPrefix: true, No66Prefix: true, Rexw: -1, VexP: -1},
{Name: "XRSTORS64", Extension: "XSAVES", Mode: 15, Priv: true, Opcode: []uint8{15, 199}, Modrm: true, Mod: -3, Reg: 3, Rm: -1, NoRepPrefix: true, No66Prefix: true, Rexw: 1, VexP: -1},
{Name: "XSAVEC", Extension: "XSAVEC", Mode: 15, Opcode: []uint8{15, 199}, Modrm: true, Mod: -3, Reg: 4, Rm: -1, NoRepPrefix: true, No66Prefix: true, Rexw: -1, VexP: -1},
{Name: "XSAVEC64", Extension: "XSAVEC", Mode: 15, Opcode: []uint8{15, 199}, Modrm: true, Mod: -3, Reg: 4, Rm: -1, NoRepPrefix: true, No66Prefix: true, Rexw: 1, VexP: -1},
{Name: "CLFLUSHOPT", Extension: "CLFLUSHOPT", Mode: 15, Opcode: []uint8{15, 174}, Prefix: []uint8{102}, Modrm: true, Mod: -3, Reg: 7, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "RDSEED", Extension: "RDSEED", Mode: 15, Opcode: []uint8{15, 199}, Modrm: true, Mod: 3, Reg: 7, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "RDFSBASE", Extension: "RDWRFSGS", Mode: 1, Opcode: []uint8{15, 174}, Prefix: []uint8{243}, Modrm: true, Mod: 3, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "RDGSBASE", Extension: "RDWRFSGS", Mode: 1, Opcode: []uint8{15, 174}, Prefix: []uint8{243}, Modrm: true, Mod: 3, Reg: 1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "WRFSBASE", Extension: "RDWRFSGS", Mode: 1, Opcode: []uint8{15, 174}, Prefix: []uint8{243}, Modrm: true, Mod: 3, Reg: 2, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "WRGSBASE", Extension: "RDWRFSGS", Mode: 1, Opcode: []uint8{15, 174}, Prefix: []uint8{243}, Modrm: true, Mod: 3, Reg: 3, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "CLAC", Extension: "SMAP", Mode: 15, Priv: true, Opcode: []uint8{15, 1}, Modrm: true, Mod: 3, Reg: 1, Rm: 2, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "STAC", Extension: "SMAP", Mode: 15, Priv: true, Opcode: []uint8{15, 1}, Modrm: true, Mod: 3, Reg: 1, Rm: 3, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "ENCLU", Extension: "SGX", Mode: 15, Opcode: []uint8{15, 1}, Modrm: true, Mod: 3, Reg: 2, Rm: 7, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "ENCLS", Extension: "SGX", Mode: 15, Priv: true, Opcode: []uint8{15, 1}, Modrm: true, Mod: 3, Reg: 1, Rm: 7, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "RDPID", Extension: "RDPID", Mode: 14, Opcode: []uint8{15, 199}, Prefix: []uint8{243}, Modrm: true, Mod: 3, Reg: 7, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "RDPID", Extension: "RDPID", Mode: 1, Opcode: []uint8{15, 199}, Prefix: []uint8{243}, Modrm: true, Mod: 3, Reg: 7, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PTWRITE", Extension: "PT", Mode: 15, Opcode: []uint8{15, 174}, Prefix: []uint8{243}, Modrm: true, Mod: -1, Reg: 4, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "MOVDIR64B", Extension: "MOVDIR", Mode: 14, Opcode: []uint8{15, 56, 248}, Prefix: []uint8{102}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "MOVDIR64B", Extension: "MOVDIR", Mode: 1, Opcode: []uint8{15, 56, 248}, Prefix: []uint8{102}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "MOVDIRI", Extension: "MOVDIR", Mode: 15, Opcode: []uint8{15, 56, 249}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, Rexw: -1, VexP: -1},
{Name: "MOVDIRI", Extension: "MOVDIR", Mode: 1, Opcode: []uint8{15, 56, 249}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, NoRepPrefix: true, No66Prefix: true, Rexw: 1, VexP: -1},
{Name: "TPAUSE", Extension: "WAITPKG", Mode: 15, Opcode: []uint8{15, 174}, Prefix: []uint8{102}, Modrm: true, Mod: 3, Reg: 6, Rm: -1, NoRepPrefix: true, Rexw: -1, VexP: -1},
{Name: "TPAUSE", Extension: "WAITPKG", Mode: 1, Opcode: []uint8{15, 174}, Prefix: []uint8{102}, Modrm: true, Mod: 3, Reg: 6, Rm: -1, NoRepPrefix: true, Rexw: 1, VexP: -1},
{Name: "UMONITOR", Extension: "WAITPKG", Mode: 15, Opcode: []uint8{15, 174}, Prefix: []uint8{243}, Modrm: true, Mod: 3, Reg: 6, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "UMWAIT", Extension: "WAITPKG", Mode: 15, Opcode: []uint8{15, 174}, Prefix: []uint8{242}, Modrm: true, Mod: 3, Reg: 6, Rm: -1, NoRepPrefix: true, Rexw: -1, VexP: -1},
{Name: "UMWAIT", Extension: "WAITPKG", Mode: 1, Opcode: []uint8{15, 174}, Prefix: []uint8{242}, Modrm: true, Mod: 3, Reg: 6, Rm: -1, NoRepPrefix: true, Rexw: 1, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 28}, Prefix: []uint8{242}, Modrm: true, Mod: -3, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 28}, Prefix: []uint8{243}, Modrm: true, Mod: -3, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 28}, Prefix: []uint8{102}, Modrm: true, Mod: -3, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 28}, Modrm: true, Mod: -3, Reg: 1, Rm: -1, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 28}, Modrm: true, Mod: -3, Reg: 2, Rm: -1, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 28}, Modrm: true, Mod: -3, Reg: 3, Rm: -1, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 28}, Modrm: true, Mod: -3, Reg: 4, Rm: -1, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 28}, Modrm: true, Mod: -3, Reg: 5, Rm: -1, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 28}, Modrm: true, Mod: -3, Reg: 6, Rm: -1, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 28}, Modrm: true, Mod: -3, Reg: 7, Rm: -1, VexP: -1},
{Name: "NOP", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 28}, Modrm: true, Mod: -3, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "CLDEMOTE", Extension: "CLDEMOTE", Mode: 15, Opcode: []uint8{15, 28}, Modrm: true, Mod: -3, Rm: -1, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "ENCLV", Extension: "SGX_ENCLV", Mode: 15, Opcode: []uint8{15, 1}, Modrm: true, Mod: 3, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "VADDPD", Extension: "AVX", Mode: 3, Opcode: []uint8{88}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VADDPD", Extension: "AVX", Mode: 3, Opcode: []uint8{88}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VADDPS", Extension: "AVX", Mode: 3, Opcode: []uint8{88}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1},
{Name: "VADDPS", Extension: "AVX", Mode: 3, Opcode: []uint8{88}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1},
{Name: "VADDSD", Extension: "AVX", Mode: 3, Opcode: []uint8{88}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexP: 3},
{Name: "VADDSS", Extension: "AVX", Mode: 3, Opcode: []uint8{88}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexP: 2},
{Name: "VADDSUBPD", Extension: "AVX", Mode: 3, Opcode: []uint8{208}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VADDSUBPD", Extension: "AVX", Mode: 3, Opcode: []uint8{208}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VADDSUBPS", Extension: "AVX", Mode: 3, Opcode: []uint8{208}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 3},
{Name: "VADDSUBPS", Extension: "AVX", Mode: 3, Opcode: []uint8{208}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 3},
{Name: "VANDPD", Extension: "AVX", Mode: 3, Opcode: []uint8{84}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VANDPD", Extension: "AVX", Mode: 3, Opcode: []uint8{84}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VANDPS", Extension: "AVX", Mode: 3, Opcode: []uint8{84}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1},
{Name: "VANDPS", Extension: "AVX", Mode: 3, Opcode: []uint8{84}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1},
{Name: "VANDNPD", Extension: "AVX", Mode: 3, Opcode: []uint8{85}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VANDNPD", Extension: "AVX", Mode: 3, Opcode: []uint8{85}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VANDNPS", Extension: "AVX", Mode: 3, Opcode: []uint8{85}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1},
{Name: "VANDNPS", Extension: "AVX", Mode: 3, Opcode: []uint8{85}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1},
{Name: "VBLENDPD", Extension: "AVX", Mode: 3, Opcode: []uint8{13}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 3, VexL: -1, VexP: 1},
{Name: "VBLENDPD", Extension: "AVX", Mode: 3, Opcode: []uint8{13}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 3, VexL: 1, VexP: 1},
{Name: "VBLENDPS", Extension: "AVX", Mode: 3, Opcode: []uint8{12}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 3, VexL: -1, VexP: 1},
{Name: "VBLENDPS", Extension: "AVX", Mode: 3, Opcode: []uint8{12}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 3, VexL: 1, VexP: 1},
{Name: "VCMPPD", Extension: "AVX", Mode: 3, Opcode: []uint8{194}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VCMPPD", Extension: "AVX", Mode: 3, Opcode: []uint8{194}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VCMPPS", Extension: "AVX", Mode: 3, Opcode: []uint8{194}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 1, VexL: -1},
{Name: "VCMPPS", Extension: "AVX", Mode: 3, Opcode: []uint8{194}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 1, VexL: 1},
{Name: "VCMPSD", Extension: "AVX", Mode: 3, Opcode: []uint8{194}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 1, VexP: 3},
{Name: "VCMPSS", Extension: "AVX", Mode: 3, Opcode: []uint8{194}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 1, VexP: 2},
{Name: "VCOMISD", Extension: "AVX", Mode: 3, Opcode: []uint8{47}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexNoR: true, VexP: 1},
{Name: "VCOMISS", Extension: "AVX", Mode: 3, Opcode: []uint8{47}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexNoR: true},
{Name: "VCVTDQ2PD", Extension: "AVX", Mode: 3, Opcode: []uint8{230}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true, VexP: 2},
{Name: "VCVTDQ2PD", Extension: "AVX", Mode: 3, Opcode: []uint8{230}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexNoR: true, VexP: 2},
{Name: "VCVTDQ2PS", Extension: "AVX", Mode: 3, Opcode: []uint8{91}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true},
{Name: "VCVTDQ2PS", Extension: "AVX", Mode: 3, Opcode: []uint8{91}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexNoR: true},
{Name: "VCVTPD2DQ", Extension: "AVX", Mode: 3, Opcode: []uint8{230}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true, VexP: 3},
{Name: "VCVTPD2DQ", Extension: "AVX", Mode: 3, Opcode: []uint8{230}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexNoR: true, VexP: 3},
{Name: "VCVTTPD2DQ", Extension: "AVX", Mode: 3, Opcode: []uint8{230}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VCVTTPD2DQ", Extension: "AVX", Mode: 3, Opcode: []uint8{230}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VCVTPD2PS", Extension: "AVX", Mode: 3, Opcode: []uint8{90}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VCVTPD2PS", Extension: "AVX", Mode: 3, Opcode: []uint8{90}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VCVTPS2DQ", Extension: "AVX", Mode: 3, Opcode: []uint8{91}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VCVTPS2DQ", Extension: "AVX", Mode: 3, Opcode: []uint8{91}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VCVTTPS2DQ", Extension: "AVX", Mode: 3, Opcode: []uint8{91}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true, VexP: 2},
{Name: "VCVTTPS2DQ", Extension: "AVX", Mode: 3, Opcode: []uint8{91}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexNoR: true, VexP: 2},
{Name: "VCVTPS2PD", Extension: "AVX", Mode: 3, Opcode: []uint8{90}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true},
{Name: "VCVTPS2PD", Extension: "AVX", Mode: 3, Opcode: []uint8{90}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexNoR: true},
{Name: "VCVTSD2SI", Extension: "AVX", Mode: 2, Opcode: []uint8{45}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexNoR: true, VexP: 3},
{Name: "VCVTSD2SI", Extension: "AVX", Mode: 1, Opcode: []uint8{45}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 1, VexNoR: true, VexP: 3},
{Name: "VCVTSD2SI", Extension: "AVX", Mode: 1, Opcode: []uint8{45}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 1, VexNoR: true, VexP: 3},
{Name: "VCVTTSD2SI", Extension: "AVX", Mode: 2, Opcode: []uint8{44}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexNoR: true, VexP: 3},
{Name: "VCVTTSD2SI", Extension: "AVX", Mode: 1, Opcode: []uint8{44}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 1, VexNoR: true, VexP: 3},
{Name: "VCVTTSD2SI", Extension: "AVX", Mode: 1, Opcode: []uint8{44}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 1, VexNoR: true, VexP: 3},
{Name: "VCVTSS2SI", Extension: "AVX", Mode: 2, Opcode: []uint8{45}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexNoR: true, VexP: 2},
{Name: "VCVTSS2SI", Extension: "AVX", Mode: 1, Opcode: []uint8{45}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 1, VexNoR: true, VexP: 2},
{Name: "VCVTSS2SI", Extension: "AVX", Mode: 1, Opcode: []uint8{45}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 1, VexNoR: true, VexP: 2},
{Name: "VCVTTSS2SI", Extension: "AVX", Mode: 2, Opcode: []uint8{44}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexNoR: true, VexP: 2},
{Name: "VCVTTSS2SI", Extension: "AVX", Mode: 1, Opcode: []uint8{44}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 1, VexNoR: true, VexP: 2},
{Name: "VCVTTSS2SI", Extension: "AVX", Mode: 1, Opcode: []uint8{44}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 1, VexNoR: true, VexP: 2},
{Name: "VCVTSD2SS", Extension: "AVX", Mode: 3, Opcode: []uint8{90}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexP: 3},
{Name: "VCVTSI2SD", Extension: "AVX", Mode: 2, Opcode: []uint8{42}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexP: 3},
{Name: "VCVTSI2SD", Extension: "AVX", Mode: 1, Opcode: []uint8{42}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 1, VexP: 3},
{Name: "VCVTSI2SD", Extension: "AVX", Mode: 1, Opcode: []uint8{42}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 1, VexP: 3},
{Name: "VCVTSI2SS", Extension: "AVX", Mode: 2, Opcode: []uint8{42}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexP: 2},
{Name: "VCVTSI2SS", Extension: "AVX", Mode: 1, Opcode: []uint8{42}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 1, VexP: 2},
{Name: "VCVTSI2SS", Extension: "AVX", Mode: 1, Opcode: []uint8{42}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 1, VexP: 2},
{Name: "VCVTSS2SD", Extension: "AVX", Mode: 3, Opcode: []uint8{90}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexP: 2},
{Name: "VDIVPD", Extension: "AVX", Mode: 3, Opcode: []uint8{94}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VDIVPD", Extension: "AVX", Mode: 3, Opcode: []uint8{94}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VDIVPS", Extension: "AVX", Mode: 3, Opcode: []uint8{94}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1},
{Name: "VDIVPS", Extension: "AVX", Mode: 3, Opcode: []uint8{94}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1},
{Name: "VDIVSD", Extension: "AVX", Mode: 3, Opcode: []uint8{94}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexP: 3},
{Name: "VDIVSS", Extension: "AVX", Mode: 3, Opcode: []uint8{94}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexP: 2},
{Name: "VEXTRACTF128", Extension: "AVX", Mode: 3, Opcode: []uint8{25}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VDPPD", Extension: "AVX", Mode: 3, Opcode: []uint8{65}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 3, VexL: -1, VexP: 1},
{Name: "VDPPS", Extension: "AVX", Mode: 3, Opcode: []uint8{64}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 3, VexL: -1, VexP: 1},
{Name: "VDPPS", Extension: "AVX", Mode: 3, Opcode: []uint8{64}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 3, VexL: 1, VexP: 1},
{Name: "VEXTRACTPS", Extension: "AVX", Mode: 3, Opcode: []uint8{23}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 3, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VZEROALL", Extension: "AVX", Mode: 3, Opcode: []uint8{119}, Mod: -100, Reg: -100, Rm: -100, Vex: 196, VexMap: 1, VexL: 1, VexNoR: true},
{Name: "VZEROUPPER", Extension: "AVX", Mode: 3, Opcode: []uint8{119}, Mod: -100, Reg: -100, Rm: -100, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true},
{Name: "VHADDPD", Extension: "AVX", Mode: 3, Opcode: []uint8{124}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VHADDPD", Extension: "AVX", Mode: 3, Opcode: []uint8{124}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VHADDPS", Extension: "AVX", Mode: 3, Opcode: []uint8{124}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 3},
{Name: "VHADDPS", Extension: "AVX", Mode: 3, Opcode: []uint8{124}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 3},
{Name: "VHSUBPD", Extension: "AVX", Mode: 3, Opcode: []uint8{125}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VHSUBPD", Extension: "AVX", Mode: 3, Opcode: []uint8{125}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VHSUBPS", Extension: "AVX", Mode: 3, Opcode: []uint8{125}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 3},
{Name: "VHSUBPS", Extension: "AVX", Mode: 3, Opcode: []uint8{125}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 3},
{Name: "VPERMILPD", Extension: "AVX", Mode: 3, Opcode: []uint8{13}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VPERMILPD", Extension: "AVX", Mode: 3, Opcode: []uint8{13}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VPERMILPD", Extension: "AVX", Mode: 3, Opcode: []uint8{5}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VPERMILPD", Extension: "AVX", Mode: 3, Opcode: []uint8{5}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VPERMILPS", Extension: "AVX", Mode: 3, Opcode: []uint8{12}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VPERMILPS", Extension: "AVX", Mode: 3, Opcode: []uint8{12}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VPERMILPS", Extension: "AVX", Mode: 3, Opcode: []uint8{4}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VPERMILPS", Extension: "AVX", Mode: 3, Opcode: []uint8{4}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VPERM2F128", Extension: "AVX", Mode: 3, Opcode: []uint8{6}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: 1, VexP: 1},
{Name: "VBROADCASTSS", Extension: "AVX", Mode: 3, Opcode: []uint8{24}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VBROADCASTSS", Extension: "AVX", Mode: 3, Opcode: []uint8{24}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VBROADCASTSD", Extension: "AVX", Mode: 3, Opcode: []uint8{25}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VBROADCASTF128", Extension: "AVX", Mode: 3, Opcode: []uint8{26}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VINSERTF128", Extension: "AVX", Mode: 3, Opcode: []uint8{24}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: 1, VexP: 1},
{Name: "VINSERTPS", Extension: "AVX", Mode: 3, Opcode: []uint8{33}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 3, VexL: -1, VexP: 1},
{Name: "VLDDQU", Extension: "AVX", Mode: 3, Opcode: []uint8{240}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true, VexP: 3},
{Name: "VLDDQU", Extension: "AVX", Mode: 3, Opcode: []uint8{240}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexNoR: true, VexP: 3},
{Name: "VMASKMOVPS", Extension: "AVX", Mode: 3, Opcode: []uint8{44}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VMASKMOVPS", Extension: "AVX", Mode: 3, Opcode: []uint8{44}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VMASKMOVPS", Extension: "AVX", Mode: 3, Opcode: []uint8{46}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VMASKMOVPS", Extension: "AVX", Mode: 3, Opcode: []uint8{46}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VMASKMOVPD", Extension: "AVX", Mode: 3, Opcode: []uint8{45}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VMASKMOVPD", Extension: "AVX", Mode: 3, Opcode: []uint8{45}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VMASKMOVPD", Extension: "AVX", Mode: 3, Opcode: []uint8{47}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VMASKMOVPD", Extension: "AVX", Mode: 3, Opcode: []uint8{47}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VPTEST", Extension: "AVX", Mode: 3, Opcode: []uint8{23}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VPTEST", Extension: "AVX", Mode: 3, Opcode: []uint8{23}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VTESTPS", Extension: "AVX", Mode: 3, Opcode: []uint8{14}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VTESTPS", Extension: "AVX", Mode: 3, Opcode: []uint8{14}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VTESTPD", Extension: "AVX", Mode: 3, Opcode: []uint8{15}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VTESTPD", Extension: "AVX", Mode: 3, Opcode: []uint8{15}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VMAXPD", Extension: "AVX", Mode: 3, Opcode: []uint8{95}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VMAXPD", Extension: "AVX", Mode: 3, Opcode: []uint8{95}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VMAXPS", Extension: "AVX", Mode: 3, Opcode: []uint8{95}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1},
{Name: "VMAXPS", Extension: "AVX", Mode: 3, Opcode: []uint8{95}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1},
{Name: "VMAXSD", Extension: "AVX", Mode: 3, Opcode: []uint8{95}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexP: 3},
{Name: "VMAXSS", Extension: "AVX", Mode: 3, Opcode: []uint8{95}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexP: 2},
{Name: "VMINPD", Extension: "AVX", Mode: 3, Opcode: []uint8{93}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VMINPD", Extension: "AVX", Mode: 3, Opcode: []uint8{93}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VMINPS", Extension: "AVX", Mode: 3, Opcode: []uint8{93}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1},
{Name: "VMINPS", Extension: "AVX", Mode: 3, Opcode: []uint8{93}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1},
{Name: "VMINSD", Extension: "AVX", Mode: 3, Opcode: []uint8{93}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexP: 3},
{Name: "VMINSS", Extension: "AVX", Mode: 3, Opcode: []uint8{93}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexP: 2},
{Name: "VMOVAPD", Extension: "AVX", Mode: 3, Opcode: []uint8{40}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VMOVAPD", Extension: "AVX", Mode: 3, Opcode: []uint8{41}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VMOVAPD", Extension: "AVX", Mode: 3, Opcode: []uint8{40}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VMOVAPD", Extension: "AVX", Mode: 3, Opcode: []uint8{41}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VMOVAPS", Extension: "AVX", Mode: 3, Opcode: []uint8{40}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true},
{Name: "VMOVAPS", Extension: "AVX", Mode: 3, Opcode: []uint8{41}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true},
{Name: "VMOVAPS", Extension: "AVX", Mode: 3, Opcode: []uint8{40}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexNoR: true},
{Name: "VMOVAPS", Extension: "AVX", Mode: 3, Opcode: []uint8{41}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexNoR: true},
{Name: "VMOVD", Extension: "AVX", Mode: 2, Opcode: []uint8{110}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VMOVD", Extension: "AVX", Mode: 2, Opcode: []uint8{126}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VMOVD", Extension: "AVX", Mode: 1, Opcode: []uint8{110}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VMOVD", Extension: "AVX", Mode: 1, Opcode: []uint8{126}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VMOVQ", Extension: "AVX", Mode: 1, Opcode: []uint8{110}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VMOVQ", Extension: "AVX", Mode: 1, Opcode: []uint8{126}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VMOVQ", Extension: "AVX", Mode: 3, Opcode: []uint8{126}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true, VexP: 2},
{Name: "VMOVQ", Extension: "AVX", Mode: 3, Opcode: []uint8{214}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VMOVDDUP", Extension: "AVX", Mode: 3, Opcode: []uint8{18}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true, VexP: 3},
{Name: "VMOVDDUP", Extension: "AVX", Mode: 3, Opcode: []uint8{18}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexNoR: true, VexP: 3},
{Name: "VMOVDQA", Extension: "AVX", Mode: 3, Opcode: []uint8{111}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VMOVDQA", Extension: "AVX", Mode: 3, Opcode: []uint8{127}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VMOVDQA", Extension: "AVX", Mode: 3, Opcode: []uint8{111}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VMOVDQA", Extension: "AVX", Mode: 3, Opcode: []uint8{127}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VMOVDQU", Extension: "AVX", Mode: 3, Opcode: []uint8{111}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true, VexP: 2},
{Name: "VMOVDQU", Extension: "AVX", Mode: 3, Opcode: []uint8{111}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexNoR: true, VexP: 2},
{Name: "VMOVDQU", Extension: "AVX", Mode: 3, Opcode: []uint8{127}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true, VexP: 2},
{Name: "VMOVDQU", Extension: "AVX", Mode: 3, Opcode: []uint8{127}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexNoR: true, VexP: 2},
{Name: "VMOVSHDUP", Extension: "AVX", Mode: 3, Opcode: []uint8{22}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true, VexP: 2},
{Name: "VMOVSHDUP", Extension: "AVX", Mode: 3, Opcode: []uint8{22}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexNoR: true, VexP: 2},
{Name: "VMOVSLDUP", Extension: "AVX", Mode: 3, Opcode: []uint8{18}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true, VexP: 2},
{Name: "VMOVSLDUP", Extension: "AVX", Mode: 3, Opcode: []uint8{18}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexNoR: true, VexP: 2},
{Name: "VPOR", Extension: "AVX", Mode: 3, Opcode: []uint8{235}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPAND", Extension: "AVX", Mode: 3, Opcode: []uint8{219}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPANDN", Extension: "AVX", Mode: 3, Opcode: []uint8{223}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPXOR", Extension: "AVX", Mode: 3, Opcode: []uint8{239}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPABSB", Extension: "AVX", Mode: 3, Opcode: []uint8{28}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VPABSW", Extension: "AVX", Mode: 3, Opcode: []uint8{29}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VPABSD", Extension: "AVX", Mode: 3, Opcode: []uint8{30}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VPHMINPOSUW", Extension: "AVX", Mode: 3, Opcode: []uint8{65}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VPSHUFD", Extension: "AVX", Mode: 3, Opcode: []uint8{112}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VPSHUFHW", Extension: "AVX", Mode: 3, Opcode: []uint8{112}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true, VexP: 2},
{Name: "VPSHUFLW", Extension: "AVX", Mode: 3, Opcode: []uint8{112}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true, VexP: 3},
{Name: "VPACKSSWB", Extension: "AVX", Mode: 3, Opcode: []uint8{99}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPACKSSDW", Extension: "AVX", Mode: 3, Opcode: []uint8{107}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPACKUSWB", Extension: "AVX", Mode: 3, Opcode: []uint8{103}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPACKUSDW", Extension: "AVX", Mode: 3, Opcode: []uint8{43}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VPSLLW", Extension: "AVX", Mode: 3, Opcode: []uint8{241}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPSLLD", Extension: "AVX", Mode: 3, Opcode: []uint8{242}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPSLLQ", Extension: "AVX", Mode: 3, Opcode: []uint8{243}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPSRLW", Extension: "AVX", Mode: 3, Opcode: []uint8{209}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPSRLD", Extension: "AVX", Mode: 3, Opcode: []uint8{210}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPSRLQ", Extension: "AVX", Mode: 3, Opcode: []uint8{211}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPSRAW", Extension: "AVX", Mode: 3, Opcode: []uint8{225}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPSRAD", Extension: "AVX", Mode: 3, Opcode: []uint8{226}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPADDB", Extension: "AVX", Mode: 3, Opcode: []uint8{252}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPADDW", Extension: "AVX", Mode: 3, Opcode: []uint8{253}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPADDD", Extension: "AVX", Mode: 3, Opcode: []uint8{254}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPADDQ", Extension: "AVX", Mode: 3, Opcode: []uint8{212}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPADDSB", Extension: "AVX", Mode: 3, Opcode: []uint8{236}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPADDSW", Extension: "AVX", Mode: 3, Opcode: []uint8{237}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPADDUSB", Extension: "AVX", Mode: 3, Opcode: []uint8{220}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPADDUSW", Extension: "AVX", Mode: 3, Opcode: []uint8{221}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPAVGB", Extension: "AVX", Mode: 3, Opcode: []uint8{224}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPAVGW", Extension: "AVX", Mode: 3, Opcode: []uint8{227}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPCMPEQB", Extension: "AVX", Mode: 3, Opcode: []uint8{116}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPCMPEQW", Extension: "AVX", Mode: 3, Opcode: []uint8{117}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPCMPEQD", Extension: "AVX", Mode: 3, Opcode: []uint8{118}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPCMPEQQ", Extension: "AVX", Mode: 3, Opcode: []uint8{41}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VPCMPGTB", Extension: "AVX", Mode: 3, Opcode: []uint8{100}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPCMPGTW", Extension: "AVX", Mode: 3, Opcode: []uint8{101}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPCMPGTD", Extension: "AVX", Mode: 3, Opcode: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPCMPGTQ", Extension: "AVX", Mode: 3, Opcode: []uint8{55}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VPHADDW", Extension: "AVX", Mode: 3, Opcode: []uint8{1}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VPHADDD", Extension: "AVX", Mode: 3, Opcode: []uint8{2}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VPHADDSW", Extension: "AVX", Mode: 3, Opcode: []uint8{3}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VPHSUBW", Extension: "AVX", Mode: 3, Opcode: []uint8{5}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VPHSUBD", Extension: "AVX", Mode: 3, Opcode: []uint8{6}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VPHSUBSW", Extension: "AVX", Mode: 3, Opcode: []uint8{7}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VPMULHUW", Extension: "AVX", Mode: 3, Opcode: []uint8{228}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPMULHRSW", Extension: "AVX", Mode: 3, Opcode: []uint8{11}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VPMULHW", Extension: "AVX", Mode: 3, Opcode: []uint8{229}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPMULLW", Extension: "AVX", Mode: 3, Opcode: []uint8{213}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPMULLD", Extension: "AVX", Mode: 3, Opcode: []uint8{64}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VPMULUDQ", Extension: "AVX", Mode: 3, Opcode: []uint8{244}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPMULDQ", Extension: "AVX", Mode: 3, Opcode: []uint8{40}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VPSADBW", Extension: "AVX", Mode: 3, Opcode: []uint8{246}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPSHUFB", Extension: "AVX", Mode: 3, Opcode: []uint8{0}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VPSIGNB", Extension: "AVX", Mode: 3, Opcode: []uint8{8}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VPSIGNW", Extension: "AVX", Mode: 3, Opcode: []uint8{9}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VPSIGND", Extension: "AVX", Mode: 3, Opcode: []uint8{10}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VPSUBSB", Extension: "AVX", Mode: 3, Opcode: []uint8{232}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPSUBSW", Extension: "AVX", Mode: 3, Opcode: []uint8{233}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPSUBUSB", Extension: "AVX", Mode: 3, Opcode: []uint8{216}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPSUBUSW", Extension: "AVX", Mode: 3, Opcode: []uint8{217}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPSUBB", Extension: "AVX", Mode: 3, Opcode: []uint8{248}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPSUBW", Extension: "AVX", Mode: 3, Opcode: []uint8{249}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPSUBD", Extension: "AVX", Mode: 3, Opcode: []uint8{250}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPSUBQ", Extension: "AVX", Mode: 3, Opcode: []uint8{251}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPUNPCKHBW", Extension: "AVX", Mode: 3, Opcode: []uint8{104}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPUNPCKHWD", Extension: "AVX", Mode: 3, Opcode: []uint8{105}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPUNPCKHDQ", Extension: "AVX", Mode: 3, Opcode: []uint8{106}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPUNPCKHQDQ", Extension: "AVX", Mode: 3, Opcode: []uint8{109}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPUNPCKLBW", Extension: "AVX", Mode: 3, Opcode: []uint8{96}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPUNPCKLWD", Extension: "AVX", Mode: 3, Opcode: []uint8{97}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPUNPCKLDQ", Extension: "AVX", Mode: 3, Opcode: []uint8{98}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPUNPCKLQDQ", Extension: "AVX", Mode: 3, Opcode: []uint8{108}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPSRLDQ", Extension: "AVX", Mode: 3, Opcode: []uint8{115}, Modrm: true, Mod: 3, Reg: 3, Rm: -1, Imm: 1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPSLLDQ", Extension: "AVX", Mode: 3, Opcode: []uint8{115}, Modrm: true, Mod: 3, Reg: 7, Rm: -1, Imm: 1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VMOVLHPS", Extension: "AVX", Mode: 3, Opcode: []uint8{22}, Modrm: true, Mod: 3, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1},
{Name: "VMOVHLPS", Extension: "AVX", Mode: 3, Opcode: []uint8{18}, Modrm: true, Mod: 3, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1},
{Name: "VPALIGNR", Extension: "AVX", Mode: 3, Opcode: []uint8{15}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 3, VexL: -1, VexP: 1},
{Name: "VPBLENDW", Extension: "AVX", Mode: 3, Opcode: []uint8{14}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 3, VexL: -1, VexP: 1},
{Name: "VROUNDPD", Extension: "AVX", Mode: 3, Opcode: []uint8{9}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 3, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VROUNDPD", Extension: "AVX", Mode: 3, Opcode: []uint8{9}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 3, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VROUNDPS", Extension: "AVX", Mode: 3, Opcode: []uint8{8}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 3, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VROUNDPS", Extension: "AVX", Mode: 3, Opcode: []uint8{8}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 3, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VROUNDSD", Extension: "AVX", Mode: 3, Opcode: []uint8{11}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 3, VexP: 1},
{Name: "VROUNDSS", Extension: "AVX", Mode: 3, Opcode: []uint8{10}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 3, VexP: 1},
{Name: "VSHUFPD", Extension: "AVX", Mode: 3, Opcode: []uint8{198}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VSHUFPD", Extension: "AVX", Mode: 3, Opcode: []uint8{198}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VSHUFPS", Extension: "AVX", Mode: 3, Opcode: []uint8{198}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 1, VexL: -1},
{Name: "VSHUFPS", Extension: "AVX", Mode: 3, Opcode: []uint8{198}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 1, VexL: 1},
{Name: "VRCPPS", Extension: "AVX", Mode: 3, Opcode: []uint8{83}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true},
{Name: "VRCPPS", Extension: "AVX", Mode: 3, Opcode: []uint8{83}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexNoR: true},
{Name: "VRCPSS", Extension: "AVX", Mode: 3, Opcode: []uint8{83}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexP: 2},
{Name: "VRSQRTPS", Extension: "AVX", Mode: 3, Opcode: []uint8{82}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true},
{Name: "VRSQRTPS", Extension: "AVX", Mode: 3, Opcode: []uint8{82}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexNoR: true},
{Name: "VRSQRTSS", Extension: "AVX", Mode: 3, Opcode: []uint8{82}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexP: 2},
{Name: "VSQRTPD", Extension: "AVX", Mode: 3, Opcode: []uint8{81}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VSQRTPD", Extension: "AVX", Mode: 3, Opcode: []uint8{81}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VSQRTPS", Extension: "AVX", Mode: 3, Opcode: []uint8{81}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true},
{Name: "VSQRTPS", Extension: "AVX", Mode: 3, Opcode: []uint8{81}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexNoR: true},
{Name: "VSQRTSD", Extension: "AVX", Mode: 3, Opcode: []uint8{81}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexP: 3},
{Name: "VSQRTSS", Extension: "AVX", Mode: 3, Opcode: []uint8{81}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexP: 2},
{Name: "VUNPCKHPD", Extension: "AVX", Mode: 3, Opcode: []uint8{21}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VUNPCKHPD", Extension: "AVX", Mode: 3, Opcode: []uint8{21}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VUNPCKHPS", Extension: "AVX", Mode: 3, Opcode: []uint8{21}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1},
{Name: "VUNPCKHPS", Extension: "AVX", Mode: 3, Opcode: []uint8{21}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1},
{Name: "VSUBPD", Extension: "AVX", Mode: 3, Opcode: []uint8{92}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VSUBPD", Extension: "AVX", Mode: 3, Opcode: []uint8{92}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VSUBPS", Extension: "AVX", Mode: 3, Opcode: []uint8{92}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1},
{Name: "VSUBPS", Extension: "AVX", Mode: 3, Opcode: []uint8{92}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1},
{Name: "VSUBSD", Extension: "AVX", Mode: 3, Opcode: []uint8{92}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexP: 3},
{Name: "VSUBSS", Extension: "AVX", Mode: 3, Opcode: []uint8{92}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexP: 2},
{Name: "VMULPD", Extension: "AVX", Mode: 3, Opcode: []uint8{89}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VMULPD", Extension: "AVX", Mode: 3, Opcode: []uint8{89}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VMULPS", Extension: "AVX", Mode: 3, Opcode: []uint8{89}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1},
{Name: "VMULPS", Extension: "AVX", Mode: 3, Opcode: []uint8{89}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1},
{Name: "VMULSD", Extension: "AVX", Mode: 3, Opcode: []uint8{89}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexP: 3},
{Name: "VMULSS", Extension: "AVX", Mode: 3, Opcode: []uint8{89}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexP: 2},
{Name: "VORPD", Extension: "AVX", Mode: 3, Opcode: []uint8{86}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VORPD", Extension: "AVX", Mode: 3, Opcode: []uint8{86}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VORPS", Extension: "AVX", Mode: 3, Opcode: []uint8{86}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1},
{Name: "VORPS", Extension: "AVX", Mode: 3, Opcode: []uint8{86}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1},
{Name: "VPMAXSB", Extension: "AVX", Mode: 3, Opcode: []uint8{60}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VPMAXSW", Extension: "AVX", Mode: 3, Opcode: []uint8{238}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPMAXSD", Extension: "AVX", Mode: 3, Opcode: []uint8{61}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VPMAXUB", Extension: "AVX", Mode: 3, Opcode: []uint8{222}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPMAXUW", Extension: "AVX", Mode: 3, Opcode: []uint8{62}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VPMAXUD", Extension: "AVX", Mode: 3, Opcode: []uint8{63}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VPMINSB", Extension: "AVX", Mode: 3, Opcode: []uint8{56}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VPMINSW", Extension: "AVX", Mode: 3, Opcode: []uint8{234}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPMINSD", Extension: "AVX", Mode: 3, Opcode: []uint8{57}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VPMINUB", Extension: "AVX", Mode: 3, Opcode: []uint8{218}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPMINUW", Extension: "AVX", Mode: 3, Opcode: []uint8{58}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VPMINUD", Extension: "AVX", Mode: 3, Opcode: []uint8{59}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VPMADDWD", Extension: "AVX", Mode: 3, Opcode: []uint8{245}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPMADDUBSW", Extension: "AVX", Mode: 3, Opcode: []uint8{4}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VMPSADBW", Extension: "AVX", Mode: 3, Opcode: []uint8{66}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 3, VexL: -1, VexP: 1},
{Name: "VPSLLW", Extension: "AVX", Mode: 3, Opcode: []uint8{113}, Modrm: true, Mod: 3, Reg: 6, Rm: -1, Imm: 1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPSLLD", Extension: "AVX", Mode: 3, Opcode: []uint8{114}, Modrm: true, Mod: 3, Reg: 6, Rm: -1, Imm: 1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPSLLQ", Extension: "AVX", Mode: 3, Opcode: []uint8{115}, Modrm: true, Mod: 3, Reg: 6, Rm: -1, Imm: 1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPSRAW", Extension: "AVX", Mode: 3, Opcode: []uint8{113}, Modrm: true, Mod: 3, Reg: 4, Rm: -1, Imm: 1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPSRAD", Extension: "AVX", Mode: 3, Opcode: []uint8{114}, Modrm: true, Mod: 3, Reg: 4, Rm: -1, Imm: 1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPSRLW", Extension: "AVX", Mode: 3, Opcode: []uint8{113}, Modrm: true, Mod: 3, Reg: 2, Rm: -1, Imm: 1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPSRLD", Extension: "AVX", Mode: 3, Opcode: []uint8{114}, Modrm: true, Mod: 3, Reg: 2, Rm: -1, Imm: 1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPSRLQ", Extension: "AVX", Mode: 3, Opcode: []uint8{115}, Modrm: true, Mod: 3, Reg: 2, Rm: -1, Imm: 1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VUCOMISD", Extension: "AVX", Mode: 3, Opcode: []uint8{46}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexNoR: true, VexP: 1},
{Name: "VUCOMISS", Extension: "AVX", Mode: 3, Opcode: []uint8{46}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexNoR: true},
{Name: "VUNPCKLPD", Extension: "AVX", Mode: 3, Opcode: []uint8{20}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VUNPCKLPD", Extension: "AVX", Mode: 3, Opcode: []uint8{20}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VUNPCKLPS", Extension: "AVX", Mode: 3, Opcode: []uint8{20}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1},
{Name: "VUNPCKLPS", Extension: "AVX", Mode: 3, Opcode: []uint8{20}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1},
{Name: "VXORPD", Extension: "AVX", Mode: 3, Opcode: []uint8{87}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VXORPD", Extension: "AVX", Mode: 3, Opcode: []uint8{87}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VXORPS", Extension: "AVX", Mode: 3, Opcode: []uint8{87}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1},
{Name: "VXORPS", Extension: "AVX", Mode: 3, Opcode: []uint8{87}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1},
{Name: "VMOVSS", Extension: "AVX", Mode: 3, Opcode: []uint8{16}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexNoR: true, VexP: 2},
{Name: "VMOVSS", Extension: "AVX", Mode: 3, Opcode: []uint8{16}, Modrm: true, Mod: 3, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexP: 2},
{Name: "VMOVSS", Extension: "AVX", Mode: 3, Opcode: []uint8{17}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexNoR: true, VexP: 2},
{Name: "VMOVSS", Extension: "AVX", Mode: 3, Opcode: []uint8{17}, Modrm: true, Mod: 3, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexP: 2},
{Name: "VMOVSD", Extension: "AVX", Mode: 3, Opcode: []uint8{16}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexNoR: true, VexP: 3},
{Name: "VMOVSD", Extension: "AVX", Mode: 3, Opcode: []uint8{16}, Modrm: true, Mod: 3, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexP: 3},
{Name: "VMOVSD", Extension: "AVX", Mode: 3, Opcode: []uint8{17}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexNoR: true, VexP: 3},
{Name: "VMOVSD", Extension: "AVX", Mode: 3, Opcode: []uint8{17}, Modrm: true, Mod: 3, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexP: 3},
{Name: "VMOVUPD", Extension: "AVX", Mode: 3, Opcode: []uint8{16}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VMOVUPD", Extension: "AVX", Mode: 3, Opcode: []uint8{17}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VMOVUPD", Extension: "AVX", Mode: 3, Opcode: []uint8{16}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VMOVUPD", Extension: "AVX", Mode: 3, Opcode: []uint8{17}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VMOVUPS", Extension: "AVX", Mode: 3, Opcode: []uint8{16}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true},
{Name: "VMOVUPS", Extension: "AVX", Mode: 3, Opcode: []uint8{17}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true},
{Name: "VMOVUPS", Extension: "AVX", Mode: 3, Opcode: []uint8{16}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexNoR: true},
{Name: "VMOVUPS", Extension: "AVX", Mode: 3, Opcode: []uint8{17}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexNoR: true},
{Name: "VMOVLPD", Extension: "AVX", Mode: 3, Opcode: []uint8{18}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VMOVLPD", Extension: "AVX", Mode: 3, Opcode: []uint8{19}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VMOVLPS", Extension: "AVX", Mode: 3, Opcode: []uint8{18}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1},
{Name: "VMOVLPS", Extension: "AVX", Mode: 3, Opcode: []uint8{19}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true},
{Name: "VMOVHPD", Extension: "AVX", Mode: 3, Opcode: []uint8{22}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VMOVHPD", Extension: "AVX", Mode: 3, Opcode: []uint8{23}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VMOVHPS", Extension: "AVX", Mode: 3, Opcode: []uint8{22}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1},
{Name: "VMOVHPS", Extension: "AVX", Mode: 3, Opcode: []uint8{23}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true},
{Name: "VMOVMSKPD", Extension: "AVX", Mode: 3, Opcode: []uint8{80}, Modrm: true, Mod: 3, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VMOVMSKPD", Extension: "AVX", Mode: 3, Opcode: []uint8{80}, Modrm: true, Mod: 3, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VMOVMSKPS", Extension: "AVX", Mode: 3, Opcode: []uint8{80}, Modrm: true, Mod: 3, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true},
{Name: "VMOVMSKPS", Extension: "AVX", Mode: 3, Opcode: []uint8{80}, Modrm: true, Mod: 3, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexNoR: true},
{Name: "VPMOVMSKB", Extension: "AVX", Mode: 3, Opcode: []uint8{215}, Modrm: true, Mod: 3, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VPMOVSXBW", Extension: "AVX", Mode: 3, Opcode: []uint8{32}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VPMOVSXBD", Extension: "AVX", Mode: 3, Opcode: []uint8{33}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VPMOVSXBQ", Extension: "AVX", Mode: 3, Opcode: []uint8{34}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VPMOVSXWD", Extension: "AVX", Mode: 3, Opcode: []uint8{35}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VPMOVSXWQ", Extension: "AVX", Mode: 3, Opcode: []uint8{36}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VPMOVSXDQ", Extension: "AVX", Mode: 3, Opcode: []uint8{37}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VPMOVZXBW", Extension: "AVX", Mode: 3, Opcode: []uint8{48}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VPMOVZXBD", Extension: "AVX", Mode: 3, Opcode: []uint8{49}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VPMOVZXBQ", Extension: "AVX", Mode: 3, Opcode: []uint8{50}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VPMOVZXWD", Extension: "AVX", Mode: 3, Opcode: []uint8{51}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VPMOVZXWQ", Extension: "AVX", Mode: 3, Opcode: []uint8{52}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VPMOVZXDQ", Extension: "AVX", Mode: 3, Opcode: []uint8{53}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VPEXTRB", Extension: "AVX", Mode: 3, Opcode: []uint8{20}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 3, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VPEXTRW", Extension: "AVX", Mode: 3, Opcode: []uint8{21}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 3, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VPEXTRW", Extension: "AVX", Mode: 3, Opcode: []uint8{197}, Modrm: true, Mod: 3, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VPEXTRQ", Extension: "AVX", Mode: 1, Opcode: []uint8{22}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: 1, Vex: 196, VexMap: 3, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VPEXTRD", Extension: "AVX", Mode: 1, Opcode: []uint8{22}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VPEXTRD", Extension: "AVX", Mode: 2, Opcode: []uint8{22}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 3, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VPINSRB", Extension: "AVX", Mode: 3, Opcode: []uint8{32}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 3, VexL: -1, VexP: 1},
{Name: "VPINSRW", Extension: "AVX", Mode: 3, Opcode: []uint8{196}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 1, VexL: -1, VexP: 1},
{Name: "VPINSRD", Extension: "AVX", Mode: 1, Opcode: []uint8{34}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: -1, VexP: 1},
{Name: "VPINSRD", Extension: "AVX", Mode: 2, Opcode: []uint8{34}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 3, VexL: -1, VexP: 1},
{Name: "VPINSRQ", Extension: "AVX", Mode: 1, Opcode: []uint8{34}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: 1, Vex: 196, VexMap: 3, VexL: -1, VexP: 1},
{Name: "VPCMPESTRI", Extension: "AVX", Mode: 2, Opcode: []uint8{97}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 3, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VPCMPESTRI", Extension: "AVX", Mode: 1, Opcode: []uint8{97}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 3, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VPCMPISTRI", Extension: "AVX", Mode: 2, Opcode: []uint8{99}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 3, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VPCMPISTRI", Extension: "AVX", Mode: 1, Opcode: []uint8{99}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 3, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VPCMPESTRM", Extension: "AVX", Mode: 2, Opcode: []uint8{96}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 3, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VPCMPESTRM", Extension: "AVX", Mode: 1, Opcode: []uint8{96}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 3, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VPCMPISTRM", Extension: "AVX", Mode: 3, Opcode: []uint8{98}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 3, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VMASKMOVDQU", Extension: "AVX", Mode: 3, Opcode: []uint8{247}, Modrm: true, Mod: 3, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VLDMXCSR", Extension: "AVX", Mode: 3, Opcode: []uint8{174}, Modrm: true, Mod: -3, Reg: 2, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true},
{Name: "VSTMXCSR", Extension: "AVX", Mode: 3, Opcode: []uint8{174}, Modrm: true, Mod: -3, Reg: 3, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true},
{Name: "VPBLENDVB", Extension: "AVX", Mode: 3, Opcode: []uint8{76}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: -1, VexP: 1},
{Name: "VBLENDVPD", Extension: "AVX", Mode: 3, Opcode: []uint8{75}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: -1, VexP: 1},
{Name: "VBLENDVPD", Extension: "AVX", Mode: 3, Opcode: []uint8{75}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: 1, VexP: 1},
{Name: "VBLENDVPS", Extension: "AVX", Mode: 3, Opcode: []uint8{74}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: -1, VexP: 1},
{Name: "VBLENDVPS", Extension: "AVX", Mode: 3, Opcode: []uint8{74}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: 1, VexP: 1},
{Name: "VMOVNTDQA", Extension: "AVX", Mode: 3, Opcode: []uint8{42}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VMOVNTDQ", Extension: "AVX", Mode: 3, Opcode: []uint8{231}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VMOVNTPD", Extension: "AVX", Mode: 3, Opcode: []uint8{43}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VMOVNTPS", Extension: "AVX", Mode: 3, Opcode: []uint8{43}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: -1, VexNoR: true},
{Name: "VMOVNTDQ", Extension: "AVX", Mode: 3, Opcode: []uint8{231}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VMOVNTPD", Extension: "AVX", Mode: 3, Opcode: []uint8{43}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VMOVNTPS", Extension: "AVX", Mode: 3, Opcode: []uint8{43}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexNoR: true},
{Name: "VAESKEYGENASSIST", Extension: "AVXAES", Mode: 3, Opcode: []uint8{223}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 3, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VAESENC", Extension: "AVXAES", Mode: 3, Opcode: []uint8{220}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VAESENCLAST", Extension: "AVXAES", Mode: 3, Opcode: []uint8{221}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VAESDEC", Extension: "AVXAES", Mode: 3, Opcode: []uint8{222}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VAESDECLAST", Extension: "AVXAES", Mode: 3, Opcode: []uint8{223}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VAESIMC", Extension: "AVXAES", Mode: 3, Opcode: []uint8{219}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VPCLMULQDQ", Extension: "AVX", Mode: 3, Opcode: []uint8{68}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 3, VexL: -1, VexP: 1},
{Name: "VCVTPH2PS", Extension: "F16C", Mode: 3, Opcode: []uint8{19}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VCVTPH2PS", Extension: "F16C", Mode: 3, Opcode: []uint8{19}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VCVTPS2PH", Extension: "F16C", Mode: 3, Opcode: []uint8{29}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VCVTPS2PH", Extension: "F16C", Mode: 3, Opcode: []uint8{29}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VFMADD132PD", Extension: "FMA", Mode: 3, Opcode: []uint8{152}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VFMADD132PD", Extension: "FMA", Mode: 3, Opcode: []uint8{152}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VFMADD132PS", Extension: "FMA", Mode: 3, Opcode: []uint8{152}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VFMADD132PS", Extension: "FMA", Mode: 3, Opcode: []uint8{152}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VFMADD132SD", Extension: "FMA", Mode: 3, Opcode: []uint8{153}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexP: 1},
{Name: "VFMADD132SS", Extension: "FMA", Mode: 3, Opcode: []uint8{153}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexP: 1},
{Name: "VFMADD213PD", Extension: "FMA", Mode: 3, Opcode: []uint8{168}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VFMADD213PD", Extension: "FMA", Mode: 3, Opcode: []uint8{168}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VFMADD213PS", Extension: "FMA", Mode: 3, Opcode: []uint8{168}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VFMADD213PS", Extension: "FMA", Mode: 3, Opcode: []uint8{168}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VFMADD213SD", Extension: "FMA", Mode: 3, Opcode: []uint8{169}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexP: 1},
{Name: "VFMADD213SS", Extension: "FMA", Mode: 3, Opcode: []uint8{169}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexP: 1},
{Name: "VFMADD231PD", Extension: "FMA", Mode: 3, Opcode: []uint8{184}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VFMADD231PD", Extension: "FMA", Mode: 3, Opcode: []uint8{184}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VFMADD231PS", Extension: "FMA", Mode: 3, Opcode: []uint8{184}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VFMADD231PS", Extension: "FMA", Mode: 3, Opcode: []uint8{184}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VFMADD231SD", Extension: "FMA", Mode: 3, Opcode: []uint8{185}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexP: 1},
{Name: "VFMADD231SS", Extension: "FMA", Mode: 3, Opcode: []uint8{185}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexP: 1},
{Name: "VFMADDSUB132PD", Extension: "FMA", Mode: 3, Opcode: []uint8{150}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VFMADDSUB132PD", Extension: "FMA", Mode: 3, Opcode: []uint8{150}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VFMADDSUB213PD", Extension: "FMA", Mode: 3, Opcode: []uint8{166}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VFMADDSUB213PD", Extension: "FMA", Mode: 3, Opcode: []uint8{166}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VFMADDSUB231PD", Extension: "FMA", Mode: 3, Opcode: []uint8{182}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VFMADDSUB231PD", Extension: "FMA", Mode: 3, Opcode: []uint8{182}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VFMADDSUB132PS", Extension: "FMA", Mode: 3, Opcode: []uint8{150}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VFMADDSUB132PS", Extension: "FMA", Mode: 3, Opcode: []uint8{150}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VFMADDSUB213PS", Extension: "FMA", Mode: 3, Opcode: []uint8{166}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VFMADDSUB213PS", Extension: "FMA", Mode: 3, Opcode: []uint8{166}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VFMADDSUB231PS", Extension: "FMA", Mode: 3, Opcode: []uint8{182}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VFMADDSUB231PS", Extension: "FMA", Mode: 3, Opcode: []uint8{182}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VFMSUBADD132PD", Extension: "FMA", Mode: 3, Opcode: []uint8{151}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VFMSUBADD132PD", Extension: "FMA", Mode: 3, Opcode: []uint8{151}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VFMSUBADD213PD", Extension: "FMA", Mode: 3, Opcode: []uint8{167}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VFMSUBADD213PD", Extension: "FMA", Mode: 3, Opcode: []uint8{167}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VFMSUBADD231PD", Extension: "FMA", Mode: 3, Opcode: []uint8{183}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VFMSUBADD231PD", Extension: "FMA", Mode: 3, Opcode: []uint8{183}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VFMSUBADD132PS", Extension: "FMA", Mode: 3, Opcode: []uint8{151}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VFMSUBADD132PS", Extension: "FMA", Mode: 3, Opcode: []uint8{151}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VFMSUBADD213PS", Extension: "FMA", Mode: 3, Opcode: []uint8{167}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VFMSUBADD213PS", Extension: "FMA", Mode: 3, Opcode: []uint8{167}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VFMSUBADD231PS", Extension: "FMA", Mode: 3, Opcode: []uint8{183}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VFMSUBADD231PS", Extension: "FMA", Mode: 3, Opcode: []uint8{183}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VFMSUB132PD", Extension: "FMA", Mode: 3, Opcode: []uint8{154}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VFMSUB132PD", Extension: "FMA", Mode: 3, Opcode: []uint8{154}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VFMSUB132PS", Extension: "FMA", Mode: 3, Opcode: []uint8{154}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VFMSUB132PS", Extension: "FMA", Mode: 3, Opcode: []uint8{154}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VFMSUB132SD", Extension: "FMA", Mode: 3, Opcode: []uint8{155}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexP: 1},
{Name: "VFMSUB132SS", Extension: "FMA", Mode: 3, Opcode: []uint8{155}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexP: 1},
{Name: "VFMSUB213PD", Extension: "FMA", Mode: 3, Opcode: []uint8{170}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VFMSUB213PD", Extension: "FMA", Mode: 3, Opcode: []uint8{170}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VFMSUB213PS", Extension: "FMA", Mode: 3, Opcode: []uint8{170}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VFMSUB213PS", Extension: "FMA", Mode: 3, Opcode: []uint8{170}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VFMSUB213SD", Extension: "FMA", Mode: 3, Opcode: []uint8{171}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexP: 1},
{Name: "VFMSUB213SS", Extension: "FMA", Mode: 3, Opcode: []uint8{171}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexP: 1},
{Name: "VFMSUB231PD", Extension: "FMA", Mode: 3, Opcode: []uint8{186}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VFMSUB231PD", Extension: "FMA", Mode: 3, Opcode: []uint8{186}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VFMSUB231PS", Extension: "FMA", Mode: 3, Opcode: []uint8{186}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VFMSUB231PS", Extension: "FMA", Mode: 3, Opcode: []uint8{186}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VFMSUB231SD", Extension: "FMA", Mode: 3, Opcode: []uint8{187}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexP: 1},
{Name: "VFMSUB231SS", Extension: "FMA", Mode: 3, Opcode: []uint8{187}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexP: 1},
{Name: "VFNMADD132PD", Extension: "FMA", Mode: 3, Opcode: []uint8{156}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VFNMADD132PD", Extension: "FMA", Mode: 3, Opcode: []uint8{156}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VFNMADD132PS", Extension: "FMA", Mode: 3, Opcode: []uint8{156}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VFNMADD132PS", Extension: "FMA", Mode: 3, Opcode: []uint8{156}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VFNMADD132SD", Extension: "FMA", Mode: 3, Opcode: []uint8{157}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexP: 1},
{Name: "VFNMADD132SS", Extension: "FMA", Mode: 3, Opcode: []uint8{157}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexP: 1},
{Name: "VFNMADD213PD", Extension: "FMA", Mode: 3, Opcode: []uint8{172}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VFNMADD213PD", Extension: "FMA", Mode: 3, Opcode: []uint8{172}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VFNMADD213PS", Extension: "FMA", Mode: 3, Opcode: []uint8{172}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VFNMADD213PS", Extension: "FMA", Mode: 3, Opcode: []uint8{172}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VFNMADD213SD", Extension: "FMA", Mode: 3, Opcode: []uint8{173}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexP: 1},
{Name: "VFNMADD213SS", Extension: "FMA", Mode: 3, Opcode: []uint8{173}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexP: 1},
{Name: "VFNMADD231PD", Extension: "FMA", Mode: 3, Opcode: []uint8{188}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VFNMADD231PD", Extension: "FMA", Mode: 3, Opcode: []uint8{188}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VFNMADD231PS", Extension: "FMA", Mode: 3, Opcode: []uint8{188}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VFNMADD231PS", Extension: "FMA", Mode: 3, Opcode: []uint8{188}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VFNMADD231SD", Extension: "FMA", Mode: 3, Opcode: []uint8{189}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexP: 1},
{Name: "VFNMADD231SS", Extension: "FMA", Mode: 3, Opcode: []uint8{189}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexP: 1},
{Name: "VFNMSUB132PD", Extension: "FMA", Mode: 3, Opcode: []uint8{158}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VFNMSUB132PD", Extension: "FMA", Mode: 3, Opcode: []uint8{158}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VFNMSUB132PS", Extension: "FMA", Mode: 3, Opcode: []uint8{158}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VFNMSUB132PS", Extension: "FMA", Mode: 3, Opcode: []uint8{158}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VFNMSUB132SD", Extension: "FMA", Mode: 3, Opcode: []uint8{159}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexP: 1},
{Name: "VFNMSUB132SS", Extension: "FMA", Mode: 3, Opcode: []uint8{159}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexP: 1},
{Name: "VFNMSUB213PD", Extension: "FMA", Mode: 3, Opcode: []uint8{174}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VFNMSUB213PD", Extension: "FMA", Mode: 3, Opcode: []uint8{174}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VFNMSUB213PS", Extension: "FMA", Mode: 3, Opcode: []uint8{174}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VFNMSUB213PS", Extension: "FMA", Mode: 3, Opcode: []uint8{174}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VFNMSUB213SD", Extension: "FMA", Mode: 3, Opcode: []uint8{175}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexP: 1},
{Name: "VFNMSUB213SS", Extension: "FMA", Mode: 3, Opcode: []uint8{175}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexP: 1},
{Name: "VFNMSUB231PD", Extension: "FMA", Mode: 3, Opcode: []uint8{190}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VFNMSUB231PD", Extension: "FMA", Mode: 3, Opcode: []uint8{190}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VFNMSUB231PS", Extension: "FMA", Mode: 3, Opcode: []uint8{190}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VFNMSUB231PS", Extension: "FMA", Mode: 3, Opcode: []uint8{190}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VFNMSUB231SD", Extension: "FMA", Mode: 3, Opcode: []uint8{191}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexP: 1},
{Name: "VFNMSUB231SS", Extension: "FMA", Mode: 3, Opcode: []uint8{191}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexP: 1},
{Name: "VGATHERDPD", Extension: "AVX2GATHER", Mode: 3, Opcode: []uint8{146}, Modrm: true, Mod: -3, Reg: -1, Rm: 4, Rexw: 1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1, Avx2Gather: true},
{Name: "VGATHERDPD", Extension: "AVX2GATHER", Mode: 3, Opcode: []uint8{146}, Modrm: true, Mod: -3, Reg: -1, Rm: 4, Rexw: 1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1, Avx2Gather: true},
{Name: "VGATHERDPS", Extension: "AVX2GATHER", Mode: 3, Opcode: []uint8{146}, Modrm: true, Mod: -3, Reg: -1, Rm: 4, Rexw: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1, Avx2Gather: true},
{Name: "VGATHERDPS", Extension: "AVX2GATHER", Mode: 3, Opcode: []uint8{146}, Modrm: true, Mod: -3, Reg: -1, Rm: 4, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1, Avx2Gather: true},
{Name: "VGATHERQPD", Extension: "AVX2GATHER", Mode: 3, Opcode: []uint8{147}, Modrm: true, Mod: -3, Reg: -1, Rm: 4, Rexw: 1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1, Avx2Gather: true},
{Name: "VGATHERQPD", Extension: "AVX2GATHER", Mode: 3, Opcode: []uint8{147}, Modrm: true, Mod: -3, Reg: -1, Rm: 4, Rexw: 1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1, Avx2Gather: true},
{Name: "VGATHERQPS", Extension: "AVX2GATHER", Mode: 3, Opcode: []uint8{147}, Modrm: true, Mod: -3, Reg: -1, Rm: 4, Rexw: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1, Avx2Gather: true},
{Name: "VGATHERQPS", Extension: "AVX2GATHER", Mode: 3, Opcode: []uint8{147}, Modrm: true, Mod: -3, Reg: -1, Rm: 4, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1, Avx2Gather: true},
{Name: "VPGATHERDQ", Extension: "AVX2GATHER", Mode: 3, Opcode: []uint8{144}, Modrm: true, Mod: -3, Reg: -1, Rm: 4, Rexw: 1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1, Avx2Gather: true},
{Name: "VPGATHERDQ", Extension: "AVX2GATHER", Mode: 3, Opcode: []uint8{144}, Modrm: true, Mod: -3, Reg: -1, Rm: 4, Rexw: 1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1, Avx2Gather: true},
{Name: "VPGATHERDD", Extension: "AVX2GATHER", Mode: 3, Opcode: []uint8{144}, Modrm: true, Mod: -3, Reg: -1, Rm: 4, Rexw: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1, Avx2Gather: true},
{Name: "VPGATHERDD", Extension: "AVX2GATHER", Mode: 3, Opcode: []uint8{144}, Modrm: true, Mod: -3, Reg: -1, Rm: 4, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1, Avx2Gather: true},
{Name: "VPGATHERQQ", Extension: "AVX2GATHER", Mode: 3, Opcode: []uint8{145}, Modrm: true, Mod: -3, Reg: -1, Rm: 4, Rexw: 1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1, Avx2Gather: true},
{Name: "VPGATHERQQ", Extension: "AVX2GATHER", Mode: 3, Opcode: []uint8{145}, Modrm: true, Mod: -3, Reg: -1, Rm: 4, Rexw: 1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1, Avx2Gather: true},
{Name: "VPGATHERQD", Extension: "AVX2GATHER", Mode: 3, Opcode: []uint8{145}, Modrm: true, Mod: -3, Reg: -1, Rm: 4, Rexw: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1, Avx2Gather: true},
{Name: "VPGATHERQD", Extension: "AVX2GATHER", Mode: 3, Opcode: []uint8{145}, Modrm: true, Mod: -3, Reg: -1, Rm: 4, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1, Avx2Gather: true},
{Name: "VPABSB", Extension: "AVX2", Mode: 3, Opcode: []uint8{28}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VPABSW", Extension: "AVX2", Mode: 3, Opcode: []uint8{29}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VPABSD", Extension: "AVX2", Mode: 3, Opcode: []uint8{30}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VPACKSSWB", Extension: "AVX2", Mode: 3, Opcode: []uint8{99}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPACKSSDW", Extension: "AVX2", Mode: 3, Opcode: []uint8{107}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPACKUSWB", Extension: "AVX2", Mode: 3, Opcode: []uint8{103}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPACKUSDW", Extension: "AVX2", Mode: 3, Opcode: []uint8{43}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VPSLLW", Extension: "AVX2", Mode: 3, Opcode: []uint8{241}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPSLLD", Extension: "AVX2", Mode: 3, Opcode: []uint8{242}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPSLLQ", Extension: "AVX2", Mode: 3, Opcode: []uint8{243}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPSRLW", Extension: "AVX2", Mode: 3, Opcode: []uint8{209}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPSRLD", Extension: "AVX2", Mode: 3, Opcode: []uint8{210}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPSRLQ", Extension: "AVX2", Mode: 3, Opcode: []uint8{211}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPSRAW", Extension: "AVX2", Mode: 3, Opcode: []uint8{225}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPSRAD", Extension: "AVX2", Mode: 3, Opcode: []uint8{226}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPADDB", Extension: "AVX2", Mode: 3, Opcode: []uint8{252}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPADDW", Extension: "AVX2", Mode: 3, Opcode: []uint8{253}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPADDD", Extension: "AVX2", Mode: 3, Opcode: []uint8{254}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPADDQ", Extension: "AVX2", Mode: 3, Opcode: []uint8{212}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPADDSB", Extension: "AVX2", Mode: 3, Opcode: []uint8{236}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPADDSW", Extension: "AVX2", Mode: 3, Opcode: []uint8{237}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPADDUSB", Extension: "AVX2", Mode: 3, Opcode: []uint8{220}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPADDUSW", Extension: "AVX2", Mode: 3, Opcode: []uint8{221}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPAVGB", Extension: "AVX2", Mode: 3, Opcode: []uint8{224}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPAVGW", Extension: "AVX2", Mode: 3, Opcode: []uint8{227}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPCMPEQB", Extension: "AVX2", Mode: 3, Opcode: []uint8{116}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPCMPEQW", Extension: "AVX2", Mode: 3, Opcode: []uint8{117}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPCMPEQD", Extension: "AVX2", Mode: 3, Opcode: []uint8{118}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPCMPEQQ", Extension: "AVX2", Mode: 3, Opcode: []uint8{41}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VPCMPGTB", Extension: "AVX2", Mode: 3, Opcode: []uint8{100}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPCMPGTW", Extension: "AVX2", Mode: 3, Opcode: []uint8{101}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPCMPGTD", Extension: "AVX2", Mode: 3, Opcode: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPCMPGTQ", Extension: "AVX2", Mode: 3, Opcode: []uint8{55}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VPHADDW", Extension: "AVX2", Mode: 3, Opcode: []uint8{1}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VPHADDD", Extension: "AVX2", Mode: 3, Opcode: []uint8{2}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VPHADDSW", Extension: "AVX2", Mode: 3, Opcode: []uint8{3}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VPHSUBW", Extension: "AVX2", Mode: 3, Opcode: []uint8{5}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VPHSUBD", Extension: "AVX2", Mode: 3, Opcode: []uint8{6}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VPHSUBSW", Extension: "AVX2", Mode: 3, Opcode: []uint8{7}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VPMADDWD", Extension: "AVX2", Mode: 3, Opcode: []uint8{245}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPMADDUBSW", Extension: "AVX2", Mode: 3, Opcode: []uint8{4}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VPMAXSB", Extension: "AVX2", Mode: 3, Opcode: []uint8{60}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VPMAXSW", Extension: "AVX2", Mode: 3, Opcode: []uint8{238}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPMAXSD", Extension: "AVX2", Mode: 3, Opcode: []uint8{61}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VPMAXUB", Extension: "AVX2", Mode: 3, Opcode: []uint8{222}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPMAXUW", Extension: "AVX2", Mode: 3, Opcode: []uint8{62}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VPMAXUD", Extension: "AVX2", Mode: 3, Opcode: []uint8{63}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VPMINSB", Extension: "AVX2", Mode: 3, Opcode: []uint8{56}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VPMINSW", Extension: "AVX2", Mode: 3, Opcode: []uint8{234}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPMINSD", Extension: "AVX2", Mode: 3, Opcode: []uint8{57}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VPMINUB", Extension: "AVX2", Mode: 3, Opcode: []uint8{218}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPMINUW", Extension: "AVX2", Mode: 3, Opcode: []uint8{58}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VPMINUD", Extension: "AVX2", Mode: 3, Opcode: []uint8{59}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VPMULHUW", Extension: "AVX2", Mode: 3, Opcode: []uint8{228}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPMULHRSW", Extension: "AVX2", Mode: 3, Opcode: []uint8{11}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VPMULHW", Extension: "AVX2", Mode: 3, Opcode: []uint8{229}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPMULLW", Extension: "AVX2", Mode: 3, Opcode: []uint8{213}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPMULLD", Extension: "AVX2", Mode: 3, Opcode: []uint8{64}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VPMULUDQ", Extension: "AVX2", Mode: 3, Opcode: []uint8{244}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPMULDQ", Extension: "AVX2", Mode: 3, Opcode: []uint8{40}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VPSADBW", Extension: "AVX2", Mode: 3, Opcode: []uint8{246}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPSHUFB", Extension: "AVX2", Mode: 3, Opcode: []uint8{0}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VPSIGNB", Extension: "AVX2", Mode: 3, Opcode: []uint8{8}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VPSIGNW", Extension: "AVX2", Mode: 3, Opcode: []uint8{9}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VPSIGND", Extension: "AVX2", Mode: 3, Opcode: []uint8{10}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VPSUBSB", Extension: "AVX2", Mode: 3, Opcode: []uint8{232}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPSUBSW", Extension: "AVX2", Mode: 3, Opcode: []uint8{233}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPSUBUSB", Extension: "AVX2", Mode: 3, Opcode: []uint8{216}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPSUBUSW", Extension: "AVX2", Mode: 3, Opcode: []uint8{217}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPSUBB", Extension: "AVX2", Mode: 3, Opcode: []uint8{248}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPSUBW", Extension: "AVX2", Mode: 3, Opcode: []uint8{249}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPSUBD", Extension: "AVX2", Mode: 3, Opcode: []uint8{250}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPSUBQ", Extension: "AVX2", Mode: 3, Opcode: []uint8{251}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPUNPCKHBW", Extension: "AVX2", Mode: 3, Opcode: []uint8{104}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPUNPCKHWD", Extension: "AVX2", Mode: 3, Opcode: []uint8{105}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPUNPCKHDQ", Extension: "AVX2", Mode: 3, Opcode: []uint8{106}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPUNPCKHQDQ", Extension: "AVX2", Mode: 3, Opcode: []uint8{109}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPUNPCKLBW", Extension: "AVX2", Mode: 3, Opcode: []uint8{96}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPUNPCKLWD", Extension: "AVX2", Mode: 3, Opcode: []uint8{97}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPUNPCKLDQ", Extension: "AVX2", Mode: 3, Opcode: []uint8{98}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPUNPCKLQDQ", Extension: "AVX2", Mode: 3, Opcode: []uint8{108}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPALIGNR", Extension: "AVX2", Mode: 3, Opcode: []uint8{15}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 3, VexL: 1, VexP: 1},
{Name: "VPBLENDW", Extension: "AVX2", Mode: 3, Opcode: []uint8{14}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 3, VexL: 1, VexP: 1},
{Name: "VMPSADBW", Extension: "AVX2", Mode: 3, Opcode: []uint8{66}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 3, VexL: 1, VexP: 1},
{Name: "VPOR", Extension: "AVX2", Mode: 3, Opcode: []uint8{235}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPAND", Extension: "AVX2", Mode: 3, Opcode: []uint8{219}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPANDN", Extension: "AVX2", Mode: 3, Opcode: []uint8{223}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPXOR", Extension: "AVX2", Mode: 3, Opcode: []uint8{239}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPBLENDVB", Extension: "AVX2", Mode: 3, Opcode: []uint8{76}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: 1, VexP: 1},
{Name: "VPMOVMSKB", Extension: "AVX2", Mode: 3, Opcode: []uint8{215}, Modrm: true, Mod: 3, Reg: -1, Rm: -1, Vex: 196, VexMap: 1, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VPSHUFD", Extension: "AVX2", Mode: 3, Opcode: []uint8{112}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 1, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VPSHUFHW", Extension: "AVX2", Mode: 3, Opcode: []uint8{112}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 1, VexL: 1, VexNoR: true, VexP: 2},
{Name: "VPSHUFLW", Extension: "AVX2", Mode: 3, Opcode: []uint8{112}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 1, VexL: 1, VexNoR: true, VexP: 3},
{Name: "VPSRLDQ", Extension: "AVX2", Mode: 3, Opcode: []uint8{115}, Modrm: true, Mod: 3, Reg: 3, Rm: -1, Imm: 1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPSLLDQ", Extension: "AVX2", Mode: 3, Opcode: []uint8{115}, Modrm: true, Mod: 3, Reg: 7, Rm: -1, Imm: 1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPSLLW", Extension: "AVX2", Mode: 3, Opcode: []uint8{113}, Modrm: true, Mod: 3, Reg: 6, Rm: -1, Imm: 1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPSLLD", Extension: "AVX2", Mode: 3, Opcode: []uint8{114}, Modrm: true, Mod: 3, Reg: 6, Rm: -1, Imm: 1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPSLLQ", Extension: "AVX2", Mode: 3, Opcode: []uint8{115}, Modrm: true, Mod: 3, Reg: 6, Rm: -1, Imm: 1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPSRAW", Extension: "AVX2", Mode: 3, Opcode: []uint8{113}, Modrm: true, Mod: 3, Reg: 4, Rm: -1, Imm: 1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPSRAD", Extension: "AVX2", Mode: 3, Opcode: []uint8{114}, Modrm: true, Mod: 3, Reg: 4, Rm: -1, Imm: 1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPSRLW", Extension: "AVX2", Mode: 3, Opcode: []uint8{113}, Modrm: true, Mod: 3, Reg: 2, Rm: -1, Imm: 1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPSRLD", Extension: "AVX2", Mode: 3, Opcode: []uint8{114}, Modrm: true, Mod: 3, Reg: 2, Rm: -1, Imm: 1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPSRLQ", Extension: "AVX2", Mode: 3, Opcode: []uint8{115}, Modrm: true, Mod: 3, Reg: 2, Rm: -1, Imm: 1, Vex: 196, VexMap: 1, VexL: 1, VexP: 1},
{Name: "VPMOVSXBW", Extension: "AVX2", Mode: 3, Opcode: []uint8{32}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VPMOVSXBD", Extension: "AVX2", Mode: 3, Opcode: []uint8{33}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VPMOVSXBQ", Extension: "AVX2", Mode: 3, Opcode: []uint8{34}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VPMOVSXWD", Extension: "AVX2", Mode: 3, Opcode: []uint8{35}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VPMOVSXWQ", Extension: "AVX2", Mode: 3, Opcode: []uint8{36}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VPMOVSXDQ", Extension: "AVX2", Mode: 3, Opcode: []uint8{37}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VPMOVZXBW", Extension: "AVX2", Mode: 3, Opcode: []uint8{48}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VPMOVZXBD", Extension: "AVX2", Mode: 3, Opcode: []uint8{49}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VPMOVZXBQ", Extension: "AVX2", Mode: 3, Opcode: []uint8{50}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VPMOVZXWD", Extension: "AVX2", Mode: 3, Opcode: []uint8{51}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VPMOVZXWQ", Extension: "AVX2", Mode: 3, Opcode: []uint8{52}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VPMOVZXDQ", Extension: "AVX2", Mode: 3, Opcode: []uint8{53}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VINSERTI128", Extension: "AVX2", Mode: 3, Opcode: []uint8{56}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: 1, VexP: 1},
{Name: "VEXTRACTI128", Extension: "AVX2", Mode: 3, Opcode: []uint8{57}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VPMASKMOVD", Extension: "AVX2", Mode: 3, Opcode: []uint8{140}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VPMASKMOVD", Extension: "AVX2", Mode: 3, Opcode: []uint8{140}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VPMASKMOVQ", Extension: "AVX2", Mode: 3, Opcode: []uint8{140}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VPMASKMOVQ", Extension: "AVX2", Mode: 3, Opcode: []uint8{140}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VPMASKMOVD", Extension: "AVX2", Mode: 3, Opcode: []uint8{142}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VPMASKMOVD", Extension: "AVX2", Mode: 3, Opcode: []uint8{142}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VPMASKMOVQ", Extension: "AVX2", Mode: 3, Opcode: []uint8{142}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VPMASKMOVQ", Extension: "AVX2", Mode: 3, Opcode: []uint8{142}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VPERM2I128", Extension: "AVX2", Mode: 3, Opcode: []uint8{70}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: 1, VexP: 1},
{Name: "VPERMQ", Extension: "AVX2", Mode: 3, Opcode: []uint8{0}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: 1, Vex: 196, VexMap: 3, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VPERMPD", Extension: "AVX2", Mode: 3, Opcode: []uint8{1}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: 1, Vex: 196, VexMap: 3, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VPERMD", Extension: "AVX2", Mode: 3, Opcode: []uint8{54}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VPERMPS", Extension: "AVX2", Mode: 3, Opcode: []uint8{22}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VPBLENDD", Extension: "AVX2", Mode: 3, Opcode: []uint8{2}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: -1, VexP: 1},
{Name: "VPBLENDD", Extension: "AVX2", Mode: 3, Opcode: []uint8{2}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: 1, VexP: 1},
{Name: "VPBROADCASTB", Extension: "AVX2", Mode: 3, Opcode: []uint8{120}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VPBROADCASTB", Extension: "AVX2", Mode: 3, Opcode: []uint8{120}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VPBROADCASTW", Extension: "AVX2", Mode: 3, Opcode: []uint8{121}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VPBROADCASTW", Extension: "AVX2", Mode: 3, Opcode: []uint8{121}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VPBROADCASTD", Extension: "AVX2", Mode: 3, Opcode: []uint8{88}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VPBROADCASTD", Extension: "AVX2", Mode: 3, Opcode: []uint8{88}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VPBROADCASTQ", Extension: "AVX2", Mode: 3, Opcode: []uint8{89}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VPBROADCASTQ", Extension: "AVX2", Mode: 3, Opcode: []uint8{89}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VBROADCASTSS", Extension: "AVX2", Mode: 3, Opcode: []uint8{24}, Modrm: true, Mod: 3, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1, VexNoR: true, VexP: 1},
{Name: "VBROADCASTSS", Extension: "AVX2", Mode: 3, Opcode: []uint8{24}, Modrm: true, Mod: 3, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VBROADCASTSD", Extension: "AVX2", Mode: 3, Opcode: []uint8{25}, Modrm: true, Mod: 3, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VBROADCASTI128", Extension: "AVX2", Mode: 3, Opcode: []uint8{90}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: 1, VexNoR: true, VexP: 1},
{Name: "VPSLLVD", Extension: "AVX2", Mode: 3, Opcode: []uint8{71}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VPSLLVD", Extension: "AVX2", Mode: 3, Opcode: []uint8{71}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VPSLLVQ", Extension: "AVX2", Mode: 3, Opcode: []uint8{71}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VPSLLVQ", Extension: "AVX2", Mode: 3, Opcode: []uint8{71}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VPSRLVD", Extension: "AVX2", Mode: 3, Opcode: []uint8{69}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VPSRLVD", Extension: "AVX2", Mode: 3, Opcode: []uint8{69}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VPSRLVQ", Extension: "AVX2", Mode: 3, Opcode: []uint8{69}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VPSRLVQ", Extension: "AVX2", Mode: 3, Opcode: []uint8{69}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VPSRAVD", Extension: "AVX2", Mode: 3, Opcode: []uint8{70}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VPSRAVD", Extension: "AVX2", Mode: 3, Opcode: []uint8{70}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VMOVNTDQA", Extension: "AVX2", Mode: 3, Opcode: []uint8{42}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: 1, VexNoR: true, VexP: 1},
{Name: "PDEP", Extension: "BMI2", Mode: 2, Opcode: []uint8{245}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 3},
{Name: "PDEP", Extension: "BMI2", Mode: 1, Opcode: []uint8{245}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 3},
{Name: "PDEP", Extension: "BMI2", Mode: 1, Opcode: []uint8{245}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: -1, VexP: 3},
{Name: "PEXT", Extension: "BMI2", Mode: 2, Opcode: []uint8{245}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 2},
{Name: "PEXT", Extension: "BMI2", Mode: 1, Opcode: []uint8{245}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 2},
{Name: "PEXT", Extension: "BMI2", Mode: 1, Opcode: []uint8{245}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: -1, VexP: 2},
{Name: "ANDN", Extension: "BMI1", Mode: 2, Opcode: []uint8{242}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1},
{Name: "ANDN", Extension: "BMI1", Mode: 1, Opcode: []uint8{242}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1},
{Name: "ANDN", Extension: "BMI1", Mode: 1, Opcode: []uint8{242}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: -1},
{Name: "BLSR", Extension: "BMI1", Mode: 2, Opcode: []uint8{243}, Modrm: true, Mod: -1, Reg: 1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1},
{Name: "BLSR", Extension: "BMI1", Mode: 1, Opcode: []uint8{243}, Modrm: true, Mod: -1, Reg: 1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1},
{Name: "BLSR", Extension: "BMI1", Mode: 1, Opcode: []uint8{243}, Modrm: true, Mod: -1, Reg: 1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: -1},
{Name: "BLSMSK", Extension: "BMI1", Mode: 2, Opcode: []uint8{243}, Modrm: true, Mod: -1, Reg: 2, Rm: -1, Vex: 196, VexMap: 2, VexL: -1},
{Name: "BLSMSK", Extension: "BMI1", Mode: 1, Opcode: []uint8{243}, Modrm: true, Mod: -1, Reg: 2, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1},
{Name: "BLSMSK", Extension: "BMI1", Mode: 1, Opcode: []uint8{243}, Modrm: true, Mod: -1, Reg: 2, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: -1},
{Name: "BLSI", Extension: "BMI1", Mode: 2, Opcode: []uint8{243}, Modrm: true, Mod: -1, Reg: 3, Rm: -1, Vex: 196, VexMap: 2, VexL: -1},
{Name: "BLSI", Extension: "BMI1", Mode: 1, Opcode: []uint8{243}, Modrm: true, Mod: -1, Reg: 3, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1},
{Name: "BLSI", Extension: "BMI1", Mode: 1, Opcode: []uint8{243}, Modrm: true, Mod: -1, Reg: 3, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: -1},
{Name: "BZHI", Extension: "BMI2", Mode: 2, Opcode: []uint8{245}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1},
{Name: "BZHI", Extension: "BMI2", Mode: 1, Opcode: []uint8{245}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1},
{Name: "BZHI", Extension: "BMI2", Mode: 1, Opcode: []uint8{245}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: -1},
{Name: "BEXTR", Extension: "BMI1", Mode: 2, Opcode: []uint8{247}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1},
{Name: "BEXTR", Extension: "BMI1", Mode: 1, Opcode: []uint8{247}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1},
{Name: "BEXTR", Extension: "BMI1", Mode: 1, Opcode: []uint8{247}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: -1},
{Name: "SHLX", Extension: "BMI2", Mode: 2, Opcode: []uint8{247}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "SHLX", Extension: "BMI2", Mode: 1, Opcode: []uint8{247}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "SHLX", Extension: "BMI2", Mode: 1, Opcode: []uint8{247}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "SARX", Extension: "BMI2", Mode: 2, Opcode: []uint8{247}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 2},
{Name: "SARX", Extension: "BMI2", Mode: 1, Opcode: []uint8{247}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 2},
{Name: "SARX", Extension: "BMI2", Mode: 1, Opcode: []uint8{247}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: -1, VexP: 2},
{Name: "SHRX", Extension: "BMI2", Mode: 2, Opcode: []uint8{247}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 3},
{Name: "SHRX", Extension: "BMI2", Mode: 1, Opcode: []uint8{247}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 3},
{Name: "SHRX", Extension: "BMI2", Mode: 1, Opcode: []uint8{247}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: -1, VexP: 3},
{Name: "MULX", Extension: "BMI2", Mode: 2, Opcode: []uint8{246}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 3},
{Name: "MULX", Extension: "BMI2", Mode: 1, Opcode: []uint8{246}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 3},
{Name: "MULX", Extension: "BMI2", Mode: 1, Opcode: []uint8{246}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: 1, Vex: 196, VexMap: 2, VexL: -1, VexP: 3},
{Name: "RORX", Extension: "BMI2", Mode: 2, Opcode: []uint8{240}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 3, VexL: -1, VexNoR: true, VexP: 3},
{Name: "RORX", Extension: "BMI2", Mode: 1, Opcode: []uint8{240}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: -1, Vex: 196, VexMap: 3, VexL: -1, VexNoR: true, VexP: 3},
{Name: "RORX", Extension: "BMI2", Mode: 1, Opcode: []uint8{240}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: 1, Vex: 196, VexMap: 3, VexL: -1, VexNoR: true, VexP: 3},
{Name: "TZCNT", Extension: "BMI1", Mode: 3, Opcode: []uint8{15, 188}, Prefix: []uint8{243}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "BSF", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 188}, Prefix: []uint8{243}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "VMFUNC", Extension: "VMFUNC", Mode: 15, Opcode: []uint8{15, 1}, Modrm: true, Mod: 3, Reg: 2, Rm: 4, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "INVPCID", Extension: "INVPCID", Mode: 1, Priv: true, Opcode: []uint8{15, 56, 130}, Prefix: []uint8{102}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "INVPCID", Extension: "INVPCID", Mode: 14, Priv: true, Opcode: []uint8{15, 56, 130}, Prefix: []uint8{102}, Modrm: true, Mod: -3, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "LZCNT", Extension: "LZCNT", Mode: 15, Opcode: []uint8{15, 189}, Prefix: []uint8{243}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "BSR", Extension: "BASE", Mode: 15, Opcode: []uint8{15, 189}, Prefix: []uint8{243}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "XBEGIN", Extension: "RTM", Mode: 15, Opcode: []uint8{199}, Modrm: true, Mod: 3, Reg: 7, Imm: -1, VexP: -1},
{Name: "XEND", Extension: "RTM", Mode: 15, Opcode: []uint8{15, 1}, Modrm: true, Mod: 3, Reg: 2, Rm: 5, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "XABORT", Extension: "RTM", Mode: 15, Opcode: []uint8{198}, Modrm: true, Mod: 3, Reg: 7, Imm: 1, VexP: -1},
{Name: "XTEST", Extension: "RTM", Mode: 15, Opcode: []uint8{15, 1}, Modrm: true, Mod: 3, Reg: 2, Rm: 6, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "ADCX", Extension: "ADOX_ADCX", Mode: 15, Opcode: []uint8{15, 56, 246}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, Rexw: -1, VexP: -1},
{Name: "ADCX", Extension: "ADOX_ADCX", Mode: 15, Opcode: []uint8{15, 56, 246}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, Rexw: 1, VexP: -1},
{Name: "ADOX", Extension: "ADOX_ADCX", Mode: 15, Opcode: []uint8{15, 56, 246}, Prefix: []uint8{243}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, Rexw: -1, VexP: -1},
{Name: "ADOX", Extension: "ADOX_ADCX", Mode: 15, Opcode: []uint8{15, 56, 246}, Prefix: []uint8{243}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, Rexw: 1, VexP: -1},
{Name: "RDPKRU", Extension: "PKU", Mode: 15, Opcode: []uint8{15, 1}, Modrm: true, Mod: 3, Reg: 5, Rm: 6, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "WRPKRU", Extension: "PKU", Mode: 15, Opcode: []uint8{15, 1}, Modrm: true, Mod: 3, Reg: 5, Rm: 7, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "CLWB", Extension: "CLWB", Mode: 15, Opcode: []uint8{15, 174}, Prefix: []uint8{102}, Modrm: true, Mod: -3, Reg: 6, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "PREFETCHWT1", Extension: "PREFETCHWT1", Mode: 15, Opcode: []uint8{15, 13}, Modrm: true, Mod: -3, Reg: 2, Rm: -1, VexP: -1},
{Name: "WBNOINVD", Extension: "WBNOINVD", Mode: 15, Priv: true, Opcode: []uint8{15, 9}, Prefix: []uint8{243}, Mod: -100, Reg: -100, Rm: -100, NoRepPrefix: true, VexP: -1},
{Name: "PCONFIG", Extension: "PCONFIG", Mode: 15, Priv: true, Opcode: []uint8{15, 1}, Modrm: true, Mod: 3, Rm: 5, NoRepPrefix: true, No66Prefix: true, VexP: -1},
{Name: "GF2P8AFFINEINVQB", Extension: "GFNI", Mode: 15, Opcode: []uint8{15, 58, 207}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, NoRepPrefix: true, VexP: -1},
{Name: "GF2P8AFFINEQB", Extension: "GFNI", Mode: 15, Opcode: []uint8{15, 58, 206}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, NoRepPrefix: true, VexP: -1},
{Name: "GF2P8MULB", Extension: "GFNI", Mode: 15, Opcode: []uint8{15, 56, 207}, Prefix: []uint8{102}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, NoRepPrefix: true, VexP: -1},
{Name: "VGF2P8AFFINEINVQB", Extension: "GFNI", Mode: 15, Opcode: []uint8{207}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: 1, Vex: 196, VexMap: 3, VexL: -1, VexP: 1},
{Name: "VGF2P8AFFINEINVQB", Extension: "GFNI", Mode: 15, Opcode: []uint8{207}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: 1, Vex: 196, VexMap: 3, VexL: 1, VexP: 1},
{Name: "VGF2P8AFFINEQB", Extension: "GFNI", Mode: 15, Opcode: []uint8{206}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: 1, Vex: 196, VexMap: 3, VexL: -1, VexP: 1},
{Name: "VGF2P8AFFINEQB", Extension: "GFNI", Mode: 15, Opcode: []uint8{206}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Rexw: 1, Vex: 196, VexMap: 3, VexL: 1, VexP: 1},
{Name: "VGF2P8MULB", Extension: "GFNI", Mode: 15, Opcode: []uint8{207}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: -1, VexP: 1},
{Name: "VGF2P8MULB", Extension: "GFNI", Mode: 15, Opcode: []uint8{207}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Rexw: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VAESDEC", Extension: "VAES", Mode: 15, Opcode: []uint8{222}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VAESDECLAST", Extension: "VAES", Mode: 15, Opcode: []uint8{223}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VAESENC", Extension: "VAES", Mode: 15, Opcode: []uint8{220}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VAESENCLAST", Extension: "VAES", Mode: 15, Opcode: []uint8{221}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Vex: 196, VexMap: 2, VexL: 1, VexP: 1},
{Name: "VPCLMULQDQ", Extension: "VPCLMULQDQ", Mode: 15, Opcode: []uint8{68}, Modrm: true, Mod: -1, Reg: -1, Rm: -1, Imm: 1, Vex: 196, VexMap: 3, VexL: 1, VexP: 1},
}
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package x86
import (
"math/rand"
"github.com/google/syzkaller/pkg/ifuzz/iset"
)
var pseudo = []*Insn{
{
Name: "PSEUDO_RDMSR",
Mode: 1<<iset.ModeLast - 1,
Priv: true,
Pseudo: true,
generator: func(cfg *iset.Config, r *rand.Rand) []byte {
gen := makeGen(cfg, r)
msr := msrs[r.Intn(len(msrs))]
gen.mov32(regECX, msr)
gen.byte(0x0f, 0x32) // rdmsr
return gen.text
},
},
{
Name: "PSEUDO_WRMSR",
Mode: 1<<iset.ModeLast - 1,
Priv: true,
Pseudo: true,
generator: func(cfg *iset.Config, r *rand.Rand) []byte {
gen := makeGen(cfg, r)
msr := msrs[r.Intn(len(msrs))]
v := iset.GenerateInt(cfg, r, 8)
gen.mov32(regECX, msr)
gen.mov32(regEAX, uint32(v>>0))
gen.mov32(regEDX, uint32(v>>32))
gen.byte(0x0f, 0x30) // wrmsr
return gen.text
},
},
{
Name: "PSEUDO_PCI_READ",
Mode: 1<<iset.ModeLast - 1,
Priv: true,
Pseudo: true,
generator: func(cfg *iset.Config, r *rand.Rand) []byte {
gen := makeGen(cfg, r)
addr, port, size := pciAddrPort(r)
gen.out32(0xcf8, addr)
gen.in(port, size)
return gen.text
},
},
{
Name: "PSEUDO_PCI_WRITE",
Mode: 1<<iset.ModeLast - 1,
Priv: true,
Pseudo: true,
generator: func(cfg *iset.Config, r *rand.Rand) []byte {
gen := makeGen(cfg, r)
addr, port, size := pciAddrPort(r)
val := iset.GenerateInt(cfg, r, 4)
gen.out32(0xcf8, addr)
gen.out(port, uint32(val), size)
return gen.text
},
},
{
Name: "PSEUDO_PORT_READ",
Mode: 1<<iset.ModeLast - 1,
Priv: true,
Pseudo: true,
generator: func(cfg *iset.Config, r *rand.Rand) []byte {
gen := makeGen(cfg, r)
port := ports[r.Intn(len(ports))]
gen.in(port, r.Intn(3))
return gen.text
},
},
{
Name: "PSEUDO_PORT_WRITE",
Mode: 1<<iset.ModeLast - 1,
Priv: true,
Pseudo: true,
generator: func(cfg *iset.Config, r *rand.Rand) []byte {
gen := makeGen(cfg, r)
port := ports[r.Intn(len(ports))]
val := iset.GenerateInt(cfg, r, 4)
gen.out(port, uint32(val), r.Intn(3))
return gen.text
},
},
{
Name: "PSEUDO_XOR_CR",
Mode: 1<<iset.ModeLast - 1,
Priv: true,
Pseudo: true,
generator: func(cfg *iset.Config, r *rand.Rand) []byte {
gen := makeGen(cfg, r)
cr := controlRegisters[r.Intn(len(controlRegisters))]
var v uint32
if cr == 8 {
v = uint32(r.Intn(15) + 1)
} else {
bit := controlRegistersBits[cr][r.Intn(len(controlRegistersBits[cr]))]
v = 1 << bit
}
gen.readCR(cr)
gen.xor32(regEAX, v)
gen.writeCR(cr)
return gen.text
},
},
{
Name: "PSEUDO_XOR_EFER",
Mode: 1<<iset.ModeLast - 1,
Priv: true,
Pseudo: true,
generator: func(cfg *iset.Config, r *rand.Rand) []byte {
gen := makeGen(cfg, r)
gen.mov32(regECX, eferMSR)
gen.byte(0x0f, 0x32) // rdmsr
bit := eferBits[r.Intn(len(eferBits))]
gen.xor32(regEAX, 1<<bit)
gen.byte(0x0f, 0x30) // wrmsr
return gen.text
},
},
{
Name: "PSEUDO_SET_BREAK",
Mode: 1<<iset.ModeLast - 1,
Priv: true,
Pseudo: true,
generator: func(cfg *iset.Config, r *rand.Rand) []byte {
gen := makeGen(cfg, r)
br := uint8(r.Intn(4))
loc := uint32(r.Intn(4))
typ := uint32(r.Intn(16))
addr := iset.GenerateInt(cfg, r, 8)
if cfg.Mode == iset.ModeLong64 {
gen.mov64(regRAX, addr)
} else {
gen.mov32(regEAX, uint32(addr))
}
gen.writeDR(br)
gen.readDR(7)
gen.xor32(regEAX, loc<<(br*2)|typ<<(16+br*4))
gen.writeDR(7)
return gen.text
},
},
{
Name: "PSEUDO_LOAD_SEG",
Mode: 1<<iset.ModeLast - 1,
Priv: true,
Pseudo: true,
generator: func(cfg *iset.Config, r *rand.Rand) []byte {
gen := makeGen(cfg, r)
sel := randSelector(r)
if cfg.Mode == iset.ModeReal16 {
sel = uint16(iset.GenerateInt(cfg, r, 8)) >> 4
}
reg := uint8(r.Intn(6))
gen.mov16(regAX, sel)
gen.byte(0x8e, 0xc0|(reg<<3)) // MOV %ax, %seg
return gen.text
},
},
{
Name: "PSEUDO_FAR_JMP",
Mode: 1<<iset.ModeLong64 | 1<<iset.ModeProt32 | 1<<iset.ModeProt16,
Priv: true,
Pseudo: true,
generator: func(cfg *iset.Config, r *rand.Rand) []byte {
gen := makeGen(cfg, r)
sel := randSelector(r)
off := iset.GenerateInt(cfg, r, 4)
if cfg.Mode == iset.ModeLong64 {
gen.mov32toSPaddr(uint32(sel), 0)
gen.mov32toSPaddr(uint32(off), 2)
if r.Intn(2) == 0 {
gen.byte(0xff, 0x2c, 0x24) // ljmp (%rsp)
} else {
gen.byte(0xff, 0x1c, 0x24) // lcall (%rsp)
}
} else {
if r.Intn(2) == 0 {
gen.byte(0xea) // ljmp $imm16, $imm16/32
} else {
gen.byte(0x9a) // lcall $imm16, $imm16/32
}
if cfg.Mode == iset.ModeProt16 {
gen.imm16(uint16(off))
} else {
gen.imm32(uint32(off))
}
gen.imm16(sel)
}
return gen.text
},
},
{
Name: "PSEUDO_LTR_LLDT",
Mode: 1<<iset.ModeLong64 | 1<<iset.ModeProt32 | 1<<iset.ModeProt16,
Priv: true,
Pseudo: true,
generator: func(cfg *iset.Config, r *rand.Rand) []byte {
gen := makeGen(cfg, r)
sel := randSelector(r)
gen.mov16(regAX, sel)
if r.Intn(2) == 0 {
gen.byte(0x0f, 0x00, 0xd8) // ltr %ax
} else {
gen.byte(0x0f, 0x00, 0xd0) // lldt %ax
}
return gen.text
},
},
{
Name: "PSEUDO_LGIDT",
Mode: 1<<iset.ModeLong64 | 1<<iset.ModeProt32 | 1<<iset.ModeProt16,
Priv: true,
Pseudo: true,
generator: func(cfg *iset.Config, r *rand.Rand) []byte {
gen := makeGen(cfg, r)
limit := uint32(iset.GenerateInt(cfg, r, 2))
base := uint32(iset.GenerateInt(cfg, r, 4))
gen.mov32toSPaddr(limit, 0)
gen.mov32toSPaddr(base, 2)
gen.mov32toSPaddr(0, 6)
gen.addr32()
if r.Intn(2) == 0 {
gen.byte(0x0f, 0x01, 0x14, 0x24) // lgdt (%rsp)
} else {
gen.byte(0x0f, 0x01, 0x1c, 0x24) // lidt (%rsp)
}
return gen.text
},
},
{
Name: "PSEUDO_HYPERCALL",
Mode: 1<<iset.ModeLong64 | 1<<iset.ModeProt32 | 1<<iset.ModeProt16,
Priv: true,
Pseudo: true,
generator: func(cfg *iset.Config, r *rand.Rand) []byte {
gen := makeGen(cfg, r)
switch r.Intn(2) {
case 0:
gen.mov32(regEAX, 1) // KVM_HC_VAPIC_POLL_IRQ
case 1:
gen.mov32(regEAX, 5) // KVM_HC_KICK_CPU
gen.mov32(regECX, uint32(iset.GenerateInt(cfg, r, 4))) // APIC ID
default:
panic("bad")
}
if r.Intn(2) == 0 {
gen.byte(0x0f, 0x01, 0xd9) // vmmcall
} else {
gen.byte(0x0f, 0x01, 0xc1) // vmcall
}
return gen.text
},
},
}
const (
regAL = iota
regAX
regEAX
regRAX
regCL
regCX
regECX
regRCX
regDL
regDX
regEDX
regRDX
)
type generator struct {
mode iset.Mode
r *rand.Rand
text []byte
}
func makeGen(cfg *iset.Config, r *rand.Rand) *generator {
return &generator{
mode: cfg.Mode,
r: r,
}
}
func (gen *generator) byte(v ...uint8) {
gen.text = append(gen.text, v...)
}
func (gen *generator) imm16(v uint16) {
gen.byte(byte(v>>0), byte(v>>8))
}
func (gen *generator) imm32(v uint32) {
gen.byte(byte(v>>0), byte(v>>8), byte(v>>16), byte(v>>24))
}
func (gen *generator) imm64(v uint64) {
gen.byte(byte(v>>0), byte(v>>8), byte(v>>16), byte(v>>24),
byte(v>>32), byte(v>>40), byte(v>>48), byte(v>>56))
}
func (gen *generator) operand16() {
switch gen.mode {
case iset.ModeLong64, iset.ModeProt32:
gen.byte(0x66)
case iset.ModeProt16, iset.ModeReal16:
default:
panic("bad mode")
}
}
func (gen *generator) operand32() {
switch gen.mode {
case iset.ModeLong64, iset.ModeProt32:
case iset.ModeProt16, iset.ModeReal16:
gen.byte(0x66)
default:
panic("bad mode")
}
}
func (gen *generator) addr32() {
switch gen.mode {
case iset.ModeLong64, iset.ModeProt32:
case iset.ModeProt16, iset.ModeReal16:
gen.byte(0x67)
default:
panic("bad mode")
}
}
func (gen *generator) mov8(reg int, v uint8) {
switch reg {
case regAL:
gen.byte(0xb0)
case regCL:
gen.byte(0xb1)
case regDL:
gen.byte(0xb2)
default:
panic("unknown register")
}
gen.byte(v)
}
func (gen *generator) mov16(reg int, v uint16) {
gen.operand16()
switch reg {
case regAX:
gen.byte(0xb8)
case regCX:
gen.byte(0xb9)
case regDX:
gen.byte(0xba)
default:
panic("unknown register")
}
gen.imm16(v)
}
func (gen *generator) mov32(reg int, v uint32) {
gen.operand32()
switch reg {
case regEAX:
gen.byte(0xb8)
case regECX:
gen.byte(0xb9)
case regEDX:
gen.byte(0xba)
default:
panic("unknown register")
}
gen.imm32(v)
}
func (gen *generator) mov64(reg int, v uint64) {
if gen.mode != iset.ModeLong64 {
panic("bad mode")
}
gen.byte(0x48)
switch reg {
case regRAX:
gen.byte(0xb8)
case regRCX:
gen.byte(0xb9)
case regRDX:
gen.byte(0xba)
default:
panic("unknown register")
}
gen.imm64(v)
}
// movl $v, off(%rsp).
func (gen *generator) mov32toSPaddr(v uint32, off uint8) {
gen.addr32()
gen.operand32()
gen.byte(0xc7, 0x44, 0x24, off)
gen.imm32(v)
}
func (gen *generator) xor32(reg int, v uint32) {
gen.operand32()
switch reg {
case regEAX:
gen.byte(0x35)
default:
panic("unknown register")
}
gen.imm32(v)
}
func (gen *generator) readCR(cr uint8) {
if cr < 8 {
// MOV %crN, %eax/%rax
gen.byte(0x0f, 0x20, 0xc0|cr<<3)
} else if cr < 16 {
// MOV %crN, %eax/%rax
gen.byte(0x44, 0x0f, 0x20, 0xc0|(cr-8)<<3)
} else {
panic("bad cr")
}
}
func (gen *generator) writeCR(cr uint8) {
if cr < 8 {
// MOV %eax/%rax, %crN
gen.byte(0x0f, 0x22, 0xc0|cr<<3)
} else if cr < 16 {
// MOV %eax/%rax, %crN
gen.byte(0x44, 0x0f, 0x22, 0xc0|(cr-8)<<3)
} else {
panic("bad cr")
}
}
func (gen *generator) readDR(dr uint8) {
if dr >= 8 {
panic("bad dr")
}
// MOV %drN, %eax/%rax
gen.byte(0x0f, 0x21, 0xc0|dr<<3)
}
func (gen *generator) writeDR(dr uint8) {
if dr >= 8 {
panic("bad dr")
}
// MOV %eax/%rax, %drN
gen.byte(0x0f, 0x23, 0xc0|dr<<3)
}
func (gen *generator) in8(port uint16) {
gen.mov16(regDX, port)
gen.byte(0xec) // in %al, %dx
}
func (gen *generator) in16(port uint16) {
gen.mov16(regDX, port)
gen.operand16()
gen.byte(0xed) // in %ax, %dx
}
func (gen *generator) in32(port uint16) {
gen.mov16(regDX, port)
gen.operand32()
gen.byte(0xed) // in %eax, %dx
}
func (gen *generator) in(port uint16, size int) {
switch size {
case 0:
gen.in8(port)
case 1:
gen.in16(port)
case 2:
gen.in32(port)
default:
panic("bad size")
}
}
func (gen *generator) out8(port uint16, v uint8) {
gen.mov16(regDX, port)
gen.mov8(regAL, v)
gen.byte(0xee) // out %dx, %al
}
func (gen *generator) out16(port, v uint16) {
gen.mov16(regDX, port)
gen.mov16(regAX, v)
gen.operand16()
gen.byte(0xef) // out %dx, %ax
}
func (gen *generator) out32(port uint16, v uint32) {
gen.mov16(regDX, port)
gen.mov32(regEAX, v)
gen.operand32()
gen.byte(0xef) // out %dx, %eax
}
func (gen *generator) out(port uint16, v uint32, size int) {
switch size {
case 0:
gen.out8(port, uint8(v))
case 1:
gen.out16(port, uint16(v))
case 2:
gen.out32(port, v)
default:
panic("bad size")
}
}
func randSelector(r *rand.Rand) uint16 {
seg := uint16(r.Intn(40))
dpl := uint16(r.Intn(4))
ldt := uint16(r.Intn(2))
return seg<<3 | ldt<<2 | dpl
}
func pciAddrPort(r *rand.Rand) (addr uint32, port uint16, size int) {
bus := uint32(r.Intn(256))
dev := uint32(r.Intn(32))
fn := uint32(r.Intn(8))
reghi := uint32(r.Intn(16))
reglo := uint32(r.Intn(64)) << 2
port = 0xcfc
switch size = r.Intn(3); size {
case 0:
port += uint16(reglo & 3)
reglo += uint32(r.Intn(4))
case 1:
port += uint16(reglo & 2)
reglo += uint32(r.Intn(2) * 2)
case 2:
}
addr = 0x80000000 | reghi<<24 | bus<<16 | dev<<11 | fn<<8 | reglo
return
}
var controlRegisters = []uint8{0, 3, 4, 8}
var controlRegistersBits = map[uint8][]uint8{
0: {0, 1, 2, 3, 4, 5, 16, 18, 29, 30, 31},
3: {3, 5},
4: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 13, 14, 16, 17, 18, 20, 21, 22},
}
const eferMSR = 0xC0000080
var eferBits = []uint8{0, 8, 10, 11, 12, 13, 14, 15}
var ports = []uint16{
0x40, 0x41, 0x42, 0x43, // PIT
0x61, // speaker
0x20, 0x21, 0xa0, 0xa1, 0x4d0, 0x4d1, // 8259
}
// sys/kvm.txt also knows this list.
var msrs = []uint32{
0x0, 0x1, 0x10, 0x11, 0x12, 0x13, 0x17, 0x1b,
0x20, 0x21, 0x28, 0x29, 0x2a, 0x2c, 0x33, 0x34,
0x3a, 0x3b, 0x40, 0x60, 0x79, 0x88, 0x89, 0x8a,
0x8b, 0x9b, 0x9e, 0xc1, 0xc2, 0xcd, 0xce, 0xe2,
0xe7, 0xe8, 0xfe, 0x116, 0x118, 0x119, 0x11a, 0x11b,
0x11e, 0x174, 0x175, 0x176, 0x179, 0x17a, 0x17b, 0x180,
0x181, 0x182, 0x183, 0x184, 0x185, 0x186, 0x187, 0x188,
0x189, 0x18a, 0x198, 0x199, 0x19a, 0x19b, 0x19c, 0x19d,
0x1a0, 0x1a2, 0x1a6, 0x1a7, 0x1aa, 0x1ad, 0x1ae, 0x1af,
0x1b0, 0x1b1, 0x1b2, 0x1c8, 0x1c9, 0x1d9, 0x1db, 0x1dc,
0x1dd, 0x1de, 0x1e0, 0x1fc, 0x200, 0x201, 0x202, 0x203,
0x204, 0x205, 0x206, 0x207, 0x208, 0x209, 0x20a, 0x20b,
0x20c, 0x20d, 0x20e, 0x20f, 0x210, 0x211, 0x212, 0x213,
0x214, 0x215, 0x216, 0x217, 0x218, 0x219, 0x21a, 0x21b,
0x21c, 0x21d, 0x21e, 0x21f, 0x220, 0x221, 0x222, 0x223,
0x224, 0x225, 0x226, 0x227, 0x228, 0x229, 0x22a, 0x22b,
0x22c, 0x22d, 0x22e, 0x22f, 0x230, 0x231, 0x232, 0x233,
0x234, 0x235, 0x236, 0x237, 0x238, 0x239, 0x23a, 0x23b,
0x23c, 0x23d, 0x23e, 0x23f, 0x240, 0x241, 0x242, 0x243,
0x244, 0x245, 0x246, 0x247, 0x248, 0x249, 0x24a, 0x24b,
0x24c, 0x24d, 0x24e, 0x24f, 0x250, 0x251, 0x252, 0x253,
0x254, 0x255, 0x256, 0x257, 0x258, 0x259, 0x25a, 0x25b,
0x25c, 0x25d, 0x25e, 0x25f, 0x260, 0x261, 0x262, 0x263,
0x264, 0x265, 0x266, 0x267, 0x268, 0x269, 0x26a, 0x26b,
0x26c, 0x26d, 0x26e, 0x26f, 0x270, 0x271, 0x272, 0x273,
0x274, 0x275, 0x276, 0x277, 0x278, 0x279, 0x27a, 0x27b,
0x27c, 0x27d, 0x27e, 0x27f, 0x280, 0x281, 0x282, 0x283,
0x284, 0x285, 0x286, 0x287, 0x288, 0x289, 0x28a, 0x28b,
0x28c, 0x28d, 0x28e, 0x28f, 0x290, 0x291, 0x292, 0x293,
0x294, 0x295, 0x296, 0x297, 0x298, 0x299, 0x29a, 0x29b,
0x29c, 0x29d, 0x29e, 0x29f, 0x2a0, 0x2a1, 0x2a2, 0x2a3,
0x2a4, 0x2a5, 0x2a6, 0x2a7, 0x2a8, 0x2a9, 0x2aa, 0x2ab,
0x2ac, 0x2ad, 0x2ae, 0x2af, 0x2b0, 0x2b1, 0x2b2, 0x2b3,
0x2b4, 0x2b5, 0x2b6, 0x2b7, 0x2b8, 0x2b9, 0x2ba, 0x2bb,
0x2bc, 0x2bd, 0x2be, 0x2bf, 0x2c0, 0x2c1, 0x2c2, 0x2c3,
0x2c4, 0x2c5, 0x2c6, 0x2c7, 0x2c8, 0x2c9, 0x2ca, 0x2cb,
0x2cc, 0x2cd, 0x2ce, 0x2cf, 0x2d0, 0x2d1, 0x2d2, 0x2d3,
0x2d4, 0x2d5, 0x2d6, 0x2d7, 0x2d8, 0x2d9, 0x2da, 0x2db,
0x2dc, 0x2dd, 0x2de, 0x2df, 0x2e0, 0x2e1, 0x2e2, 0x2e3,
0x2e4, 0x2e5, 0x2e6, 0x2e7, 0x2e8, 0x2e9, 0x2ea, 0x2eb,
0x2ec, 0x2ed, 0x2ee, 0x2ef, 0x2f0, 0x2f1, 0x2f2, 0x2f3,
0x2f4, 0x2f5, 0x2f6, 0x2f7, 0x2f8, 0x2f9, 0x2fa, 0x2fb,
0x2fc, 0x2fd, 0x2fe, 0x2ff, 0x300, 0x301, 0x302, 0x303,
0x304, 0x305, 0x306, 0x307, 0x308, 0x309, 0x30a, 0x30b,
0x30c, 0x30d, 0x30e, 0x30f, 0x310, 0x311, 0x312, 0x313,
0x314, 0x315, 0x316, 0x317, 0x318, 0x319, 0x31a, 0x31b,
0x31c, 0x31d, 0x31e, 0x31f, 0x320, 0x321, 0x322, 0x323,
0x324, 0x325, 0x326, 0x327, 0x328, 0x329, 0x32a, 0x32b,
0x32c, 0x32d, 0x32e, 0x32f, 0x330, 0x331, 0x332, 0x333,
0x334, 0x335, 0x336, 0x337, 0x338, 0x339, 0x33a, 0x33b,
0x33c, 0x33d, 0x33e, 0x33f, 0x340, 0x341, 0x342, 0x343,
0x344, 0x345, 0x346, 0x347, 0x348, 0x349, 0x34a, 0x34b,
0x34c, 0x34d, 0x34e, 0x34f, 0x350, 0x351, 0x352, 0x353,
0x354, 0x355, 0x356, 0x357, 0x358, 0x359, 0x35a, 0x35b,
0x35c, 0x35d, 0x35e, 0x35f, 0x360, 0x361, 0x362, 0x363,
0x364, 0x365, 0x366, 0x367, 0x368, 0x369, 0x36a, 0x36b,
0x36c, 0x36d, 0x36e, 0x36f, 0x370, 0x371, 0x372, 0x373,
0x374, 0x375, 0x376, 0x377, 0x378, 0x379, 0x37a, 0x37b,
0x37c, 0x37d, 0x37e, 0x37f, 0x380, 0x381, 0x382, 0x383,
0x384, 0x385, 0x386, 0x387, 0x388, 0x389, 0x38a, 0x38b,
0x38c, 0x38d, 0x38e, 0x38f, 0x390, 0x391, 0x392, 0x393,
0x394, 0x395, 0x396, 0x397, 0x398, 0x399, 0x39a, 0x39b,
0x39c, 0x39d, 0x39e, 0x39f, 0x3a0, 0x3a1, 0x3a2, 0x3a3,
0x3a4, 0x3a5, 0x3a6, 0x3a7, 0x3a8, 0x3a9, 0x3aa, 0x3ab,
0x3ac, 0x3ad, 0x3ae, 0x3af, 0x3b0, 0x3b1, 0x3b2, 0x3b3,
0x3b4, 0x3b5, 0x3b6, 0x3b7, 0x3b8, 0x3b9, 0x3ba, 0x3bb,
0x3bc, 0x3bd, 0x3be, 0x3bf, 0x3c2, 0x3c3, 0x3c4, 0x3c5,
0x3f1, 0x3f2, 0x3f6, 0x3f7, 0x3f8, 0x3f9, 0x3fa, 0x3fc,
0x3fd, 0x3fe, 0x3ff, 0x400, 0x401, 0x402, 0x403, 0x404,
0x405, 0x406, 0x407, 0x408, 0x409, 0x40a, 0x40b, 0x40c,
0x40d, 0x40e, 0x40f, 0x410, 0x411, 0x412, 0x413, 0x480,
0x481, 0x482, 0x483, 0x484, 0x485, 0x486, 0x487, 0x488,
0x489, 0x48a, 0x48b, 0x48c, 0x48d, 0x48e, 0x48f, 0x490,
0x491, 0x4c1, 0x4d0, 0x560, 0x561, 0x570, 0x571, 0x572,
0x580, 0x581, 0x582, 0x583, 0x584, 0x585, 0x586, 0x587,
0x600, 0x606, 0x60a, 0x60b, 0x60c, 0x60d, 0x610, 0x611,
0x613, 0x614, 0x618, 0x619, 0x61b, 0x61c, 0x630, 0x631,
0x632, 0x633, 0x634, 0x635, 0x638, 0x639, 0x63a, 0x63b,
0x640, 0x641, 0x642, 0x648, 0x649, 0x64a, 0x64b, 0x64c,
0x64d, 0x64e, 0x64f, 0x658, 0x659, 0x65a, 0x65b, 0x660,
0x668, 0x669, 0x680, 0x690, 0x6b0, 0x6b1, 0x6c0, 0x6e0,
0x770, 0x771, 0x772, 0x773, 0x774, 0x777, 0x800, 0x801,
0x802, 0x803, 0x804, 0x805, 0x806, 0x807, 0x808, 0x809,
0x80a, 0x80b, 0x80c, 0x80d, 0x80e, 0x80f, 0x810, 0x811,
0x812, 0x813, 0x814, 0x815, 0x816, 0x817, 0x818, 0x819,
0x81a, 0x81b, 0x81c, 0x81d, 0x81e, 0x81f, 0x820, 0x821,
0x822, 0x823, 0x824, 0x825, 0x826, 0x827, 0x828, 0x829,
0x82a, 0x82b, 0x82c, 0x82d, 0x82e, 0x82f, 0x830, 0x831,
0x832, 0x833, 0x834, 0x835, 0x836, 0x837, 0x838, 0x839,
0x83a, 0x83b, 0x83c, 0x83d, 0x83e, 0x83f, 0x840, 0x841,
0x842, 0x843, 0x844, 0x845, 0x846, 0x847, 0x848, 0x849,
0x84a, 0x84b, 0x84c, 0x84d, 0x84e, 0x84f, 0x850, 0x851,
0x852, 0x853, 0x854, 0x855, 0x856, 0x857, 0x858, 0x859,
0x85a, 0x85b, 0x85c, 0x85d, 0x85e, 0x85f, 0x860, 0x861,
0x862, 0x863, 0x864, 0x865, 0x866, 0x867, 0x868, 0x869,
0x86a, 0x86b, 0x86c, 0x86d, 0x86e, 0x86f, 0x870, 0x871,
0x872, 0x873, 0x874, 0x875, 0x876, 0x877, 0x878, 0x879,
0x87a, 0x87b, 0x87c, 0x87d, 0x87e, 0x87f, 0x880, 0x881,
0x882, 0x883, 0x884, 0x885, 0x886, 0x887, 0x888, 0x889,
0x88a, 0x88b, 0x88c, 0x88d, 0x88e, 0x88f, 0x890, 0x891,
0x892, 0x893, 0x894, 0x895, 0x896, 0x897, 0x898, 0x899,
0x89a, 0x89b, 0x89c, 0x89d, 0x89e, 0x89f, 0x8a0, 0x8a1,
0x8a2, 0x8a3, 0x8a4, 0x8a5, 0x8a6, 0x8a7, 0x8a8, 0x8a9,
0x8aa, 0x8ab, 0x8ac, 0x8ad, 0x8ae, 0x8af, 0x8b0, 0x8b1,
0x8b2, 0x8b3, 0x8b4, 0x8b5, 0x8b6, 0x8b7, 0x8b8, 0x8b9,
0x8ba, 0x8bb, 0x8bc, 0x8bd, 0x8be, 0x8bf, 0x8c0, 0x8c1,
0x8c2, 0x8c3, 0x8c4, 0x8c5, 0x8c6, 0x8c7, 0x8c8, 0x8c9,
0x8ca, 0x8cb, 0x8cc, 0x8cd, 0x8ce, 0x8cf, 0x8d0, 0x8d1,
0x8d2, 0x8d3, 0x8d4, 0x8d5, 0x8d6, 0x8d7, 0x8d8, 0x8d9,
0x8da, 0x8db, 0x8dc, 0x8dd, 0x8de, 0x8df, 0x8e0, 0x8e1,
0x8e2, 0x8e3, 0x8e4, 0x8e5, 0x8e6, 0x8e7, 0x8e8, 0x8e9,
0x8ea, 0x8eb, 0x8ec, 0x8ed, 0x8ee, 0x8ef, 0x8f0, 0x8f1,
0x8f2, 0x8f3, 0x8f4, 0x8f5, 0x8f6, 0x8f7, 0x8f8, 0x8f9,
0x8fa, 0x8fb, 0x8fc, 0x8fd, 0x8fe, 0x8ff, 0x900, 0x901,
0x902, 0x903, 0x904, 0x905, 0x906, 0x907, 0x908, 0x909,
0x90a, 0x90b, 0x90c, 0x90d, 0x90e, 0x90f, 0x910, 0x911,
0x912, 0x913, 0x914, 0x915, 0x916, 0x917, 0x918, 0x919,
0x91a, 0x91b, 0x91c, 0x91d, 0x91e, 0x91f, 0x920, 0x921,
0x922, 0x923, 0x924, 0x925, 0x926, 0x927, 0x928, 0x929,
0x92a, 0x92b, 0x92c, 0x92d, 0x92e, 0x92f, 0x930, 0x931,
0x932, 0x933, 0x934, 0x935, 0x936, 0x937, 0x938, 0x939,
0x93a, 0x93b, 0x93c, 0x93d, 0x93e, 0x93f, 0x940, 0x941,
0x942, 0x943, 0x944, 0x945, 0x946, 0x947, 0x948, 0x949,
0x94a, 0x94b, 0x94c, 0x94d, 0x94e, 0x94f, 0x950, 0x951,
0x952, 0x953, 0x954, 0x955, 0x956, 0x957, 0x958, 0x959,
0x95a, 0x95b, 0x95c, 0x95d, 0x95e, 0x95f, 0x960, 0x961,
0x962, 0x963, 0x964, 0x965, 0x966, 0x967, 0x968, 0x969,
0x96a, 0x96b, 0x96c, 0x96d, 0x96e, 0x96f, 0x970, 0x971,
0x972, 0x973, 0x974, 0x975, 0x976, 0x977, 0x978, 0x979,
0x97a, 0x97b, 0x97c, 0x97d, 0x97e, 0x97f, 0x980, 0x981,
0x982, 0x983, 0x984, 0x985, 0x986, 0x987, 0x988, 0x989,
0x98a, 0x98b, 0x98c, 0x98d, 0x98e, 0x98f, 0x990, 0x991,
0x992, 0x993, 0x994, 0x995, 0x996, 0x997, 0x998, 0x999,
0x99a, 0x99b, 0x99c, 0x99d, 0x99e, 0x99f, 0x9a0, 0x9a1,
0x9a2, 0x9a3, 0x9a4, 0x9a5, 0x9a6, 0x9a7, 0x9a8, 0x9a9,
0x9aa, 0x9ab, 0x9ac, 0x9ad, 0x9ae, 0x9af, 0x9b0, 0x9b1,
0x9b2, 0x9b3, 0x9b4, 0x9b5, 0x9b6, 0x9b7, 0x9b8, 0x9b9,
0x9ba, 0x9bb, 0x9bc, 0x9bd, 0x9be, 0x9bf, 0x9c0, 0x9c1,
0x9c2, 0x9c3, 0x9c4, 0x9c5, 0x9c6, 0x9c7, 0x9c8, 0x9c9,
0x9ca, 0x9cb, 0x9cc, 0x9cd, 0x9ce, 0x9cf, 0x9d0, 0x9d1,
0x9d2, 0x9d3, 0x9d4, 0x9d5, 0x9d6, 0x9d7, 0x9d8, 0x9d9,
0x9da, 0x9db, 0x9dc, 0x9dd, 0x9de, 0x9df, 0x9e0, 0x9e1,
0x9e2, 0x9e3, 0x9e4, 0x9e5, 0x9e6, 0x9e7, 0x9e8, 0x9e9,
0x9ea, 0x9eb, 0x9ec, 0x9ed, 0x9ee, 0x9ef, 0x9f0, 0x9f1,
0x9f2, 0x9f3, 0x9f4, 0x9f5, 0x9f6, 0x9f7, 0x9f8, 0x9f9,
0x9fa, 0x9fb, 0x9fc, 0x9fd, 0x9fe, 0x9ff, 0xa00, 0xa01,
0xa02, 0xa03, 0xa04, 0xa05, 0xa06, 0xa07, 0xa08, 0xa09,
0xa0a, 0xa0b, 0xa0c, 0xa0d, 0xa0e, 0xa0f, 0xa10, 0xa11,
0xa12, 0xa13, 0xa14, 0xa15, 0xa16, 0xa17, 0xa18, 0xa19,
0xa1a, 0xa1b, 0xa1c, 0xa1d, 0xa1e, 0xa1f, 0xa20, 0xa21,
0xa22, 0xa23, 0xa24, 0xa25, 0xa26, 0xa27, 0xa28, 0xa29,
0xa2a, 0xa2b, 0xa2c, 0xa2d, 0xa2e, 0xa2f, 0xa30, 0xa31,
0xa32, 0xa33, 0xa34, 0xa35, 0xa36, 0xa37, 0xa38, 0xa39,
0xa3a, 0xa3b, 0xa3c, 0xa3d, 0xa3e, 0xa3f, 0xa40, 0xa41,
0xa42, 0xa43, 0xa44, 0xa45, 0xa46, 0xa47, 0xa48, 0xa49,
0xa4a, 0xa4b, 0xa4c, 0xa4d, 0xa4e, 0xa4f, 0xa50, 0xa51,
0xa52, 0xa53, 0xa54, 0xa55, 0xa56, 0xa57, 0xa58, 0xa59,
0xa5a, 0xa5b, 0xa5c, 0xa5d, 0xa5e, 0xa5f, 0xa60, 0xa61,
0xa62, 0xa63, 0xa64, 0xa65, 0xa66, 0xa67, 0xa68, 0xa69,
0xa6a, 0xa6b, 0xa6c, 0xa6d, 0xa6e, 0xa6f, 0xa70, 0xa71,
0xa72, 0xa73, 0xa74, 0xa75, 0xa76, 0xa77, 0xa78, 0xa79,
0xa7a, 0xa7b, 0xa7c, 0xa7d, 0xa7e, 0xa7f, 0xa80, 0xa81,
0xa82, 0xa83, 0xa84, 0xa85, 0xa86, 0xa87, 0xa88, 0xa89,
0xa8a, 0xa8b, 0xa8c, 0xa8d, 0xa8e, 0xa8f, 0xa90, 0xa91,
0xa92, 0xa93, 0xa94, 0xa95, 0xa96, 0xa97, 0xa98, 0xa99,
0xa9a, 0xa9b, 0xa9c, 0xa9d, 0xa9e, 0xa9f, 0xaa0, 0xaa1,
0xaa2, 0xaa3, 0xaa4, 0xaa5, 0xaa6, 0xaa7, 0xaa8, 0xaa9,
0xaaa, 0xaab, 0xaac, 0xaad, 0xaae, 0xaaf, 0xab0, 0xab1,
0xab2, 0xab3, 0xab4, 0xab5, 0xab6, 0xab7, 0xab8, 0xab9,
0xaba, 0xabb, 0xabc, 0xabd, 0xabe, 0xabf, 0xac0, 0xac1,
0xac2, 0xac3, 0xac4, 0xac5, 0xac6, 0xac7, 0xac8, 0xac9,
0xaca, 0xacb, 0xacc, 0xacd, 0xace, 0xacf, 0xad0, 0xad1,
0xad2, 0xad3, 0xad4, 0xad5, 0xad6, 0xad7, 0xad8, 0xad9,
0xada, 0xadb, 0xadc, 0xadd, 0xade, 0xadf, 0xae0, 0xae1,
0xae2, 0xae3, 0xae4, 0xae5, 0xae6, 0xae7, 0xae8, 0xae9,
0xaea, 0xaeb, 0xaec, 0xaed, 0xaee, 0xaef, 0xaf0, 0xaf1,
0xaf2, 0xaf3, 0xaf4, 0xaf5, 0xaf6, 0xaf7, 0xaf8, 0xaf9,
0xafa, 0xafb, 0xafc, 0xafd, 0xafe, 0xaff, 0xb00, 0xb01,
0xb02, 0xb03, 0xb04, 0xb05, 0xb06, 0xb07, 0xb08, 0xb09,
0xb0a, 0xb0b, 0xb0c, 0xb0d, 0xb0e, 0xb0f, 0xb10, 0xb11,
0xb12, 0xb13, 0xb14, 0xb15, 0xb16, 0xb17, 0xb18, 0xb19,
0xb1a, 0xb1b, 0xb1c, 0xb1d, 0xb1e, 0xb1f, 0xb20, 0xb21,
0xb22, 0xb23, 0xb24, 0xb25, 0xb26, 0xb27, 0xb28, 0xb29,
0xb2a, 0xb2b, 0xb2c, 0xb2d, 0xb2e, 0xb2f, 0xb30, 0xb31,
0xb32, 0xb33, 0xb34, 0xb35, 0xb36, 0xb37, 0xb38, 0xb39,
0xb3a, 0xb3b, 0xb3c, 0xb3d, 0xb3e, 0xb3f, 0xb40, 0xb41,
0xb42, 0xb43, 0xb44, 0xb45, 0xb46, 0xb47, 0xb48, 0xb49,
0xb4a, 0xb4b, 0xb4c, 0xb4d, 0xb4e, 0xb4f, 0xb50, 0xb51,
0xb52, 0xb53, 0xb54, 0xb55, 0xb56, 0xb57, 0xb58, 0xb59,
0xb5a, 0xb5b, 0xb5c, 0xb5d, 0xb5e, 0xb5f, 0xb60, 0xb61,
0xb62, 0xb63, 0xb64, 0xb65, 0xb66, 0xb67, 0xb68, 0xb69,
0xb6a, 0xb6b, 0xb6c, 0xb6d, 0xb6e, 0xb6f, 0xb70, 0xb71,
0xb72, 0xb73, 0xb74, 0xb75, 0xb76, 0xb77, 0xb78, 0xb79,
0xb7a, 0xb7b, 0xb7c, 0xb7d, 0xb7e, 0xb7f, 0xb80, 0xb81,
0xb82, 0xb83, 0xb84, 0xb85, 0xb86, 0xb87, 0xb88, 0xb89,
0xb8a, 0xb8b, 0xb8c, 0xb8d, 0xb8e, 0xb8f, 0xb90, 0xb91,
0xb92, 0xb93, 0xb94, 0xb95, 0xb96, 0xb97, 0xb98, 0xb99,
0xb9a, 0xb9b, 0xb9c, 0xb9d, 0xb9e, 0xb9f, 0xba0, 0xba1,
0xba2, 0xba3, 0xba4, 0xba5, 0xba6, 0xba7, 0xba8, 0xba9,
0xbaa, 0xbab, 0xbac, 0xbad, 0xbae, 0xbaf, 0xbb0, 0xbb1,
0xbb2, 0xbb3, 0xbb4, 0xbb5, 0xbb6, 0xbb7, 0xbb8, 0xbb9,
0xbba, 0xbbb, 0xbbc, 0xbbd, 0xbbe, 0xbbf, 0xbc0, 0xbc1,
0xbc2, 0xbc3, 0xbc4, 0xbc5, 0xbc6, 0xbc7, 0xbc8, 0xbc9,
0xbca, 0xbcb, 0xbcc, 0xbcd, 0xbce, 0xbcf, 0xbd0, 0xbd1,
0xbd2, 0xbd3, 0xbd4, 0xbd5, 0xbd6, 0xbd7, 0xbd8, 0xbd9,
0xbda, 0xbdb, 0xbdc, 0xbdd, 0xbde, 0xbdf, 0xbe0, 0xbe1,
0xbe2, 0xbe3, 0xbe4, 0xbe5, 0xbe6, 0xbe7, 0xbe8, 0xbe9,
0xbea, 0xbeb, 0xbec, 0xbed, 0xbee, 0xbef, 0xbf0, 0xbf1,
0xbf2, 0xbf3, 0xbf4, 0xbf5, 0xbf6, 0xbf7, 0xbf8, 0xbf9,
0xbfa, 0xbfb, 0xbfc, 0xbfd, 0xbfe, 0xbff, 0xd90, 0xda0,
0xdc0, 0xdc1, 0xdc2, 0xdc3, 0xdc4, 0xdc5, 0xdc6, 0xdc7,
0x40000000, 0x40000001, 0x40000002, 0x40000003, 0x40000010, 0x40000020, 0x40000022, 0x40000023,
0x40000070, 0x40000071, 0x40000072, 0x40000073, 0x40000080, 0x40000081, 0x40000082, 0x40000083,
0x40000084, 0x40000090, 0x40000091, 0x40000092, 0x40000093, 0x40000094, 0x40000095, 0x40000096,
0x40000097, 0x40000098, 0x40000099, 0x4000009a, 0x4000009b, 0x4000009c, 0x4000009d, 0x4000009e,
0x4000009f, 0x400000b0, 0x400000b1, 0x400000b2, 0x400000b3, 0x400000b4, 0x400000b5, 0x400000b6,
0x400000b7, 0x40000100, 0x40000101, 0x40000102, 0x40000103, 0x40000104, 0x40000105, 0x4b564d00,
0x4b564d01, 0x4b564d02, 0x4b564d03, 0x4b564d04, 0xc0000080, 0xc0000081, 0xc0000082, 0xc0000083,
0xc0000084, 0xc0000100, 0xc0000101, 0xc0000102, 0xc0000103, 0xc0000104, 0xc001001f, 0xc0010020,
0xc0010044, 0xc0010062, 0xc0010063, 0xc0010064, 0xc0010114, 0xc0010115, 0xc0010117, 0xc0010140,
0xc0010141, 0xc0011020, 0xc0011022, 0xc001102a, 0xc0011030, 0xc0011031, 0xc0011032, 0xc0011033,
0xc0011034, 0xc0011035, 0xc0011036, 0xc0011037, 0xc0011038, 0xc0011039, 0xc001103a, 0xc001103b,
0xc001103d,
}
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
//go:generate go run gen/gen.go gen/all-enc-instructions.txt generated/insns.go
// Package x86 allows to generate and mutate x86 machine code.
package x86
import (
"math/rand"
"github.com/google/syzkaller/pkg/ifuzz/iset"
)
type Insn struct {
Name string
Extension string
Mode iset.Mode // bitmask of compatible modes
Priv bool // CPL=0
Pseudo bool // pseudo instructions can consist of several real instructions
Opcode []byte
Prefix []byte
Suffix []byte
Modrm bool
Mod int8
Reg int8 // -6 - segment register, -8 - control register
Rm int8
Srm bool // register is embed in the first byte
NoSibDisp bool // no SIB/disp even if modrm says otherwise
Imm int8 // immediate size, -1 - immediate size, -2 - address size, -3 - operand size
Imm2 int8
NoRepPrefix bool
No66Prefix bool
Rexw int8 // 1 must be set, -1 must not be set
Mem32 bool // instruction always references 32-bit memory operand, 0x67 is illegal
Mem16 bool // instruction always references 16-bit memory operand
Vex byte
VexMap byte
VexL int8
VexNoR bool
VexP int8
Avx2Gather bool
generator func(cfg *iset.Config, r *rand.Rand) []byte // for pseudo instructions
}
type InsnSet struct {
modeInsns iset.ModeInsns
Insns []*Insn
}
func Register(insns []*Insn) {
if len(insns) == 0 {
panic("no instructions")
}
insnset := &InsnSet{
Insns: append(insns, pseudo...),
}
for _, insn := range insnset.Insns {
insnset.modeInsns.Add(insn)
}
iset.Arches[iset.ArchX86] = insnset
}
func (insnset *InsnSet) GetInsns(mode iset.Mode, typ iset.Type) []iset.Insn {
return insnset.modeInsns[mode][typ]
}
func (insn *Insn) Info() (string, iset.Mode, bool, bool) {
return insn.Name, insn.Mode, insn.Pseudo, insn.Priv
}
func generateArg(cfg *iset.Config, r *rand.Rand, size int) []byte {
v := iset.GenerateInt(cfg, r, size)
arg := make([]byte, size)
for i := 0; i < size; i++ {
arg[i] = byte(v)
v >>= 8
}
return arg
}
// Copyright 2022 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package image
import (
"bytes"
"compress/zlib"
"encoding/base64"
"fmt"
"io"
"sync/atomic"
)
var (
// Total amount of images in memory and consumed memory (in bytes).
// Currently maintained only by the optimized implementation.
// Cannot import stats package due to import cycles.
StatImages atomic.Int64
StatMemory atomic.Int64
)
func Compress(rawData []byte) []byte {
var buffer bytes.Buffer
zlibWriter := zlib.NewWriter(&buffer)
_, err := zlibWriter.Write(rawData)
if err != nil {
panic(fmt.Sprintf("could not compress with zlib: %v", err))
}
err = zlibWriter.Close()
if err != nil {
panic(fmt.Sprintf("could not finalize compression with zlib: %v", err))
}
return buffer.Bytes()
}
func MustDecompress(compressed []byte) (data []byte, dtor func()) {
if len(compressed) == 0 {
return nil, func() {}
}
return mustDecompress(compressed)
}
func DecompressCheck(compressed []byte) error {
return decompressWriter(io.Discard, compressed)
}
func decompressWriter(w io.Writer, compressed []byte) error {
if len(compressed) == 0 {
return nil
}
zlibReader, err := zlib.NewReader(bytes.NewReader(compressed))
if err != nil {
return fmt.Errorf("could not initialise zlib: %w", err)
}
if _, err := io.Copy(w, zlibReader); err != nil {
return fmt.Errorf("could not read data with zlib: %w", err)
}
return zlibReader.Close()
}
func DecodeB64(b64Data []byte) ([]byte, error) {
decoder := base64.NewDecoder(base64.StdEncoding, bytes.NewReader(b64Data))
rawData, err := io.ReadAll(decoder)
if err != nil {
return nil, fmt.Errorf("could not decode Base64: %w", err)
}
return rawData, nil
}
func EncodeB64(rawData []byte) []byte {
var buf bytes.Buffer
encoder := base64.NewEncoder(base64.StdEncoding, &buf)
_, err := encoder.Write(rawData)
if err != nil {
panic(fmt.Sprintf("could not encode Base64: %v", err))
}
err = encoder.Close()
if err != nil {
panic(fmt.Sprintf("could not finalize encoding to Base64: %v", err))
}
return buf.Bytes()
}
// Copyright 2022 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
//go:build !windows && !386 && !arm
package image
import (
"bytes"
"compress/zlib"
"fmt"
"io"
"sync"
"syscall"
"unsafe"
)
// Temporary scratch data used by the decompression procedure.
type decompressScratch struct {
r bytes.Reader
zr io.Reader
buf []byte
}
// This is just for memory consumption estimation, does not need to be precise.
const pageSize = 4 << 10
var decompressPool = sync.Pool{New: func() interface{} {
return &decompressScratch{
buf: make([]byte, pageSize),
}
}}
func mustDecompress(compressed []byte) (data []byte, dtor func()) {
// Optimized decompression procedure that is ~2x faster than a naive version
// and consumes significantly less memory and generates less garbage.
// Images tend to contain lots of 0s, especially the larger images.
// The main idea is that we mmap a buffer and then don't write 0s into it
// (since it already contains all 0s). As the result if a page is all 0s
// then we don't page it in and don't consume memory for it.
// Executor uses the same optimization during decompression.
scratch := decompressPool.Get().(*decompressScratch)
defer decompressPool.Put(scratch)
scratch.r.Reset(compressed)
if scratch.zr == nil {
zr, err := zlib.NewReader(&scratch.r)
if err != nil {
panic(err)
}
scratch.zr = zr
} else {
if err := scratch.zr.(zlib.Resetter).Reset(&scratch.r, nil); err != nil {
panic(err)
}
}
// We don't know the size of the uncompressed image.
// We could uncompress it into ioutil.Discard first, then allocate memory and uncompress second time
// (and it's still faster than the naive uncompress into bytes.Buffer!).
// But we know maximum size of images, so just mmap the max size.
// It's fast and unused part does not consume memory.
// Note: executor/common_zlib.h also knows this const.
const maxImageSize = 132 << 20
var err error
data, err = syscall.Mmap(-1, 0, maxImageSize, syscall.PROT_READ|syscall.PROT_WRITE,
syscall.MAP_ANON|syscall.MAP_PRIVATE)
if err != nil {
panic(err)
}
pages := 0
dtor = func() {
StatImages.Add(-1)
StatMemory.Add(int64(-pages * pageSize))
if err := syscall.Munmap(data[:maxImageSize]); err != nil {
panic(err)
}
}
pagedIn := 0
offset := 0
for {
n, err := scratch.zr.Read(scratch.buf)
if err != nil && err != io.EOF {
panic(err)
}
if n == 0 {
break
}
if offset+n > len(data) {
panic(fmt.Sprintf("bad image size: offset=%v n=%v data=%v", offset, n, len(data)))
}
// Copy word-at-a-time and avoid bounds checks in the loop,
// this is considerably faster than a naive byte loop.
// We already checked bounds above.
type word uint64
const wordSize = unsafe.Sizeof(word(0))
// Don't copy the last word b/c otherwise we calculate pointer outside of scratch.buf object
// on the last iteration. We don't use it, but unsafe rules prohibit even calculating
// such pointers. Alternatively we could add 8 unused bytes to scratch.buf, but it will
// play badly with memory allocator size classes (it will consume whole additional page,
// or whatever is the alignment for such large objects). We could also break from the middle
// of the loop before updating src/dst pointers, but it hurts codegen a lot (compilers like
// canonical loop forms).
hasData := false
words := uintptr(n-1) / wordSize
src := (*word)(unsafe.Pointer(&scratch.buf[0]))
dst := (*word)(unsafe.Pointer(&data[offset]))
for i := uintptr(0); i < words; i++ {
if *src != 0 {
*dst = *src
}
src = (*word)(unsafe.Pointer(uintptr(unsafe.Pointer(src)) + wordSize))
dst = (*word)(unsafe.Pointer(uintptr(unsafe.Pointer(dst)) + wordSize))
hasData = true
}
// Copy any remaining trailing bytes.
for i := words * wordSize; i < uintptr(n); i++ {
v := scratch.buf[i]
if v != 0 {
data[uintptr(offset)+i] = v
hasData = true
}
}
if hasData && offset >= pagedIn {
pagedIn = (offset + n + pageSize - 1) & ^(pageSize - 1)
pages++
}
offset += n
}
data = data[:offset]
StatImages.Add(1)
StatMemory.Add(int64(pages * pageSize))
return
}
// Copyright 2024 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package image
import (
"errors"
"fmt"
"io"
"os"
"os/exec"
"strconv"
"strings"
"sync"
"github.com/google/syzkaller/pkg/log"
"github.com/google/syzkaller/pkg/osutil"
)
// Fsck runs fsckCmd against a file system image provided in r. It returns the
// fsck logs, whether the file system is clean and an error in case fsck could
// not be run.
func Fsck(r io.Reader, fsckCmd string) ([]byte, bool, error) {
// Write the image to a temporary file.
tempFile, err := os.CreateTemp("", "*.img")
if err != nil {
return nil, false, fmt.Errorf("failed to create temporary file: %w", err)
}
defer os.Remove(tempFile.Name())
_, err = io.Copy(tempFile, r)
if err != nil {
return nil, false, fmt.Errorf("failed to write data to temporary file: %w", err)
}
if err := tempFile.Close(); err != nil {
return nil, false, fmt.Errorf("failed to close temporary file: %w", err)
}
osutil.SandboxChown(tempFile.Name())
// And run the provided fsck command on it.
fsck := append(strings.Fields(fsckCmd), tempFile.Name())
cmd := osutil.Command(fsck[0], fsck[1:]...)
if err := osutil.Sandbox(cmd, true, true); err != nil {
return nil, false, err
}
exitCode := 0
output, err := cmd.CombinedOutput()
if err != nil {
var exitError (*exec.ExitError)
ok := errors.As(err, &exitError)
if ok {
exitCode = exitError.ExitCode()
} else {
return nil, false, err
}
}
prefix := fsckCmd + " exited with status code " + strconv.Itoa(exitCode) + "\n"
return append([]byte(prefix), output...), exitCode == 0, nil
}
type FsckChecker struct {
mu sync.Mutex
exists map[string]bool
}
func (fc *FsckChecker) Exists(cmd string) bool {
fc.mu.Lock()
defer fc.mu.Unlock()
bin := strings.Fields(cmd)[0]
if ret, ok := fc.exists[bin]; ok {
return ret
}
if fc.exists == nil {
fc.exists = map[string]bool{}
}
_, err := exec.LookPath(bin)
found := err == nil
if !found {
log.Logf(0, "%s not found, images won't be checked", bin)
}
fc.exists[bin] = found
return found
}
// Copyright 2020 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package kconfig
import (
"bufio"
"bytes"
"fmt"
"os"
"regexp"
)
// ConfigFile represents a parsed .config file.
// It should not be modified directly, only by means of calling methods.
// The only exception is Config.Value which may be modified directly.
// Note: config names don't include CONFIG_ prefix, here and in other public interfaces,
// users of this package should never mention CONFIG_.
// Use Yes/Mod/No consts to check for/set config to particular values.
type ConfigFile struct {
Configs []*Config
Map map[string]*Config // duplicates Configs for convenience
comments []string
}
type Config struct {
Name string
Value string
comments []string
}
const (
Yes = "y"
Mod = "m"
No = "---===[[[is not set]]]===---" // to make it more obvious when some code writes it directly
prefix = "CONFIG_"
)
// Value returns config value, or No if it's not present at all.
func (cf *ConfigFile) Value(name string) string {
cfg := cf.Map[name]
if cfg == nil {
return No
}
return cfg.Value
}
// Set changes config value, or adds it if it's not yet present.
func (cf *ConfigFile) Set(name, val string) {
cfg := cf.Map[name]
if cfg == nil {
cfg = &Config{
Name: name,
Value: val,
}
cf.Map[name] = cfg
cf.Configs = append(cf.Configs, cfg)
}
cfg.Value = val
cfg.comments = append(cfg.comments, cf.comments...)
cf.comments = nil
}
// Unset sets config value to No, if it's present in the config.
func (cf *ConfigFile) Unset(name string) {
cfg := cf.Map[name]
if cfg == nil {
return
}
cfg.Value = No
}
func (cf *ConfigFile) ModToYes() {
for _, cfg := range cf.Configs {
if cfg.Value == Mod {
cfg.Value = Yes
}
}
}
func (cf *ConfigFile) ModToNo() {
for _, cfg := range cf.Configs {
if cfg.Value == Mod {
cfg.Value = No
}
}
}
func (cf *ConfigFile) Serialize() []byte {
buf := new(bytes.Buffer)
for _, cfg := range cf.Configs {
for _, comment := range cfg.comments {
fmt.Fprintf(buf, "%v\n", comment)
}
if cfg.Value == No {
fmt.Fprintf(buf, "# %v%v is not set\n", prefix, cfg.Name)
} else {
fmt.Fprintf(buf, "%v%v=%v\n", prefix, cfg.Name, cfg.Value)
}
}
for _, comment := range cf.comments {
fmt.Fprintf(buf, "%v\n", comment)
}
return buf.Bytes()
}
func ParseConfig(file string) (*ConfigFile, error) {
data, err := os.ReadFile(file)
if err != nil {
return nil, fmt.Errorf("failed to open .config file %v: %w", file, err)
}
return ParseConfigData(data, file)
}
func ParseConfigData(data []byte, file string) (*ConfigFile, error) {
cf := &ConfigFile{
Map: make(map[string]*Config),
}
s := bufio.NewScanner(bytes.NewReader(data))
for s.Scan() {
cf.parseLine(s.Text())
}
return cf, nil
}
func (cf *ConfigFile) Clone() *ConfigFile {
cf1 := &ConfigFile{
Map: make(map[string]*Config),
comments: cf.comments,
}
for _, cfg := range cf.Configs {
cfg1 := new(Config)
*cfg1 = *cfg
cf1.Configs = append(cf1.Configs, cfg1)
cf1.Map[cfg1.Name] = cfg1
}
return cf1
}
func (cf *ConfigFile) parseLine(text string) {
if match := reConfigY.FindStringSubmatch(text); match != nil {
cf.Set(match[1], match[2])
} else if match := reConfigN.FindStringSubmatch(text); match != nil {
cf.Set(match[1], No)
} else {
cf.comments = append(cf.comments, text)
}
}
var (
reConfigY = regexp.MustCompile(`^` + prefix + `([A-Za-z0-9_]+)=(y|m|(?:-?[0-9]+)|(?:0x[0-9a-fA-F]+)|(?:".*?"))$`)
reConfigN = regexp.MustCompile(`^# ` + prefix + `([A-Za-z0-9_]+) is not set$`)
)
// Copyright 2020 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package kconfig
import (
"fmt"
)
// expr represents an arbitrary kconfig expression used in "depends on", "visible if", "if", etc.
// Currently we can only extract dependent symbols from expressions.
type expr interface {
String() string
collectDeps(map[string]bool)
}
type exprShell struct {
cmd string
}
func (ex *exprShell) String() string {
return "$" + ex.cmd
}
func (ex *exprShell) collectDeps(deps map[string]bool) {
}
type exprNot struct {
ex expr
}
func (ex *exprNot) String() string {
return fmt.Sprintf("!(%v)", ex.ex)
}
func (ex *exprNot) collectDeps(deps map[string]bool) {
}
type exprIdent struct {
name string
}
func (ex *exprIdent) String() string {
return ex.name
}
func (ex *exprIdent) collectDeps(deps map[string]bool) {
deps[ex.name] = true
}
type exprString struct {
val string
}
func (ex *exprString) String() string {
return fmt.Sprintf("%q", ex.val)
}
func (ex *exprString) collectDeps(deps map[string]bool) {
}
type exprBin struct {
op binOp
lex expr
rex expr
}
type binOp int
const (
opNop binOp = iota
opAnd
opOr
opEq
opNe
opLt
opLe
opGt
opGe
)
func (op binOp) String() string {
switch op {
case opAnd:
return "&&"
case opOr:
return "||"
case opEq:
return "="
case opNe:
return "!="
case opLt:
return "<"
case opLe:
return "<="
case opGt:
return ">"
case opGe:
return ">="
default:
return fmt.Sprintf("???(%v)", int(op))
}
}
func (ex *exprBin) String() string {
return fmt.Sprintf("(%v %v %v)", ex.lex, ex.op, ex.rex)
}
func (ex *exprBin) collectDeps(deps map[string]bool) {
ex.lex.collectDeps(deps)
ex.rex.collectDeps(deps)
}
func exprAnd(lex, rex expr) expr {
if lex == nil {
return rex
}
if rex == nil {
return lex
}
return &exprBin{
op: opAnd,
lex: lex,
rex: rex,
}
}
// Recursive-descent parsing with strict precedence levels.
// See kconfig docs for reference:
// https://www.kernel.org/doc/html/latest/kbuild/kconfig-language.html#menu-dependencies
// The doc claims that all operators have different precedence levels,
// e.g. '<' has higher precedence than '>' rather than being left-associative with the same precedence.
// This is somewhat strange semantics and here it is implemented as simply being left-associative.
// For now it does not matter since we do not evaluate expressions.
func (p *parser) parseExpr() expr {
ex := p.parseExprAnd()
for p.TryConsume("||") {
ex = &exprBin{
op: opOr,
lex: ex,
rex: p.parseExprAnd(),
}
}
return ex
}
func (p *parser) parseExprAnd() expr {
ex := p.parseExprCmp()
for p.TryConsume("&&") {
ex = &exprBin{
op: opAnd,
lex: ex,
rex: p.parseExprCmp(),
}
}
return ex
}
func (p *parser) parseExprCmp() expr {
ex := p.parseExprTerm()
for {
op := opNop
switch {
case p.TryConsume("="):
op = opEq
case p.TryConsume("!="):
op = opNe
case p.TryConsume("<="):
op = opLe
case p.TryConsume(">="):
op = opGe
case p.TryConsume("<"):
op = opLt
case p.TryConsume(">"):
op = opGt
}
if op == opNop {
break
}
ex = &exprBin{
op: op,
lex: ex,
rex: p.parseExprTerm(),
}
}
return ex
}
func (p *parser) parseExprTerm() expr {
if p.TryConsume("$") {
return &exprShell{
cmd: p.Shell(),
}
}
if str, ok := p.TryQuotedString(); ok {
return &exprString{
val: str,
}
}
if p.TryConsume("!") {
return &exprNot{
ex: p.parseExprTerm(),
}
}
if p.TryConsume("(") {
ex := p.parseExpr()
p.MustConsume(")")
return ex
}
return &exprIdent{
name: p.Ident(),
}
}
// Copyright 2020 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package kconfig
import (
"github.com/google/syzkaller/sys/targets"
)
func FuzzParseKConfig(data []byte) int {
ParseData(targets.Get("linux", "amd64"), data, "kconfig")
return 0
}
func FuzzParseConfig(data []byte) int {
ParseConfigData(data, "config")
return 0
}
func FuzzParseExpr(data []byte) int {
p := newParser(data, "expr")
if !p.nextLine() {
return 0
}
p.parseExpr()
return 0
}
// Copyright 2020 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
// Package kconfig implements parsing of the Linux kernel Kconfig and .config files
// and provides some algorithms to work with these files. For Kconfig reference see:
// https://www.kernel.org/doc/html/latest/kbuild/kconfig-language.html
package kconfig
import (
"fmt"
"os"
"path/filepath"
"strings"
"sync"
"github.com/google/syzkaller/sys/targets"
)
// KConfig represents a parsed Kconfig file (including includes).
type KConfig struct {
Root *Menu // mainmenu
Configs map[string]*Menu // only config/menuconfig entries
}
// Menu represents a single hierarchical menu or config.
type Menu struct {
Kind MenuKind // config/menu/choice/etc
Type ConfigType // tristate/bool/string/etc
Name string // name without CONFIG_
Elems []*Menu // sub-elements for menus
Parent *Menu // parent menu, non-nil for everythign except for mainmenu
kconf *KConfig // back-link to the owning KConfig
prompts []prompt
defaults []defaultVal
dependsOn expr
visibleIf expr
deps map[string]bool
depsOnce sync.Once
selects []string
selectedBy []string // filled in in setSelectedBy()
}
type prompt struct {
text string
cond expr
}
type defaultVal struct {
val expr
cond expr
}
type (
MenuKind int
ConfigType int
)
const (
_ MenuKind = iota
MenuConfig
MenuGroup
MenuChoice
MenuComment
)
const (
_ ConfigType = iota
TypeBool
TypeTristate
TypeString
TypeInt
TypeHex
)
// DependsOn returns all transitive configs this config depends on.
func (m *Menu) DependsOn() map[string]bool {
m.depsOnce.Do(func() {
m.deps = make(map[string]bool)
if m.dependsOn != nil {
m.dependsOn.collectDeps(m.deps)
}
if m.visibleIf != nil {
m.visibleIf.collectDeps(m.deps)
}
var indirect []string
for cfg := range m.deps {
dep := m.kconf.Configs[cfg]
if dep == nil {
delete(m.deps, cfg)
continue
}
for cfg1 := range dep.DependsOn() {
indirect = append(indirect, cfg1)
}
}
for _, cfg := range indirect {
m.deps[cfg] = true
}
})
return m.deps
}
func (m *Menu) Prompt() string {
// TODO: check prompt conditions, some prompts may be not visible.
// If all prompts are not visible, then then menu if effectively disabled (at least for user).
for _, p := range m.prompts {
return p.text
}
return ""
}
type kconfigParser struct {
*parser
target *targets.Target
includes []*parser
stack []*Menu
cur *Menu
baseDir string
helpIdent int
}
func Parse(target *targets.Target, file string) (*KConfig, error) {
data, err := os.ReadFile(file)
if err != nil {
return nil, fmt.Errorf("failed to open Kconfig file %v: %w", file, err)
}
return ParseData(target, data, file)
}
func ParseData(target *targets.Target, data []byte, file string) (*KConfig, error) {
kp := &kconfigParser{
parser: newParser(data, file),
target: target,
baseDir: filepath.Dir(file),
}
kp.parseFile()
if kp.err != nil {
return nil, kp.err
}
if len(kp.stack) == 0 {
return nil, fmt.Errorf("no mainmenu in config")
}
root := kp.stack[0]
kconf := &KConfig{
Root: root,
Configs: make(map[string]*Menu),
}
kconf.walk(root, nil, nil)
kconf.setSelectedBy()
return kconf, nil
}
func (kconf *KConfig) walk(m *Menu, dependsOn, visibleIf expr) {
m.kconf = kconf
m.dependsOn = exprAnd(dependsOn, m.dependsOn)
m.visibleIf = exprAnd(visibleIf, m.visibleIf)
if m.Kind == MenuConfig {
kconf.Configs[m.Name] = m
}
for _, elem := range m.Elems {
kconf.walk(elem, m.dependsOn, m.visibleIf)
}
}
// NOTE: the function is ignoring the "if" part of select/imply.
func (kconf *KConfig) setSelectedBy() {
for name, cfg := range kconf.Configs {
for _, selectedName := range cfg.selects {
selected := kconf.Configs[selectedName]
if selected == nil {
continue
}
selected.selectedBy = append(selected.selectedBy, name)
}
}
}
// NOTE: the function is ignoring the "if" part of select/imply.
func (kconf *KConfig) SelectedBy(name string) map[string]bool {
ret := map[string]bool{}
toVisit := []string{name}
for len(toVisit) > 0 {
next := kconf.Configs[toVisit[len(toVisit)-1]]
toVisit = toVisit[:len(toVisit)-1]
if next == nil {
continue
}
for _, selectedBy := range next.selectedBy {
ret[selectedBy] = true
toVisit = append(toVisit, selectedBy)
}
}
return ret
}
func (kp *kconfigParser) parseFile() {
for kp.nextLine() {
kp.parseLine()
if kp.TryConsume("#") {
_ = kp.ConsumeLine()
}
}
kp.endCurrent()
}
func (kp *kconfigParser) parseLine() {
if kp.eol() {
return
}
if kp.helpIdent != 0 {
if kp.identLevel() >= kp.helpIdent {
_ = kp.ConsumeLine()
return
}
kp.helpIdent = 0
}
if kp.TryConsume("#") {
_ = kp.ConsumeLine()
return
}
if kp.TryConsume("$") {
_ = kp.Shell()
return
}
ident := kp.Ident()
if kp.TryConsume("=") || kp.TryConsume(":=") {
// Macro definition, see:
// https://www.kernel.org/doc/html/latest/kbuild/kconfig-macro-language.html
// We don't use this for anything now.
kp.ConsumeLine()
return
}
kp.parseMenu(ident)
}
func (kp *kconfigParser) parseMenu(cmd string) {
switch cmd {
case "source":
file, ok := kp.TryQuotedString()
if !ok {
file = kp.ConsumeLine()
}
kp.includeSource(file)
case "mainmenu":
kp.pushCurrent(&Menu{
Kind: MenuConfig,
prompts: []prompt{{text: kp.QuotedString()}},
})
case "comment":
kp.newCurrent(&Menu{
Kind: MenuComment,
prompts: []prompt{{text: kp.QuotedString()}},
})
case "menu":
kp.pushCurrent(&Menu{
Kind: MenuGroup,
prompts: []prompt{{text: kp.QuotedString()}},
})
case "if":
kp.pushCurrent(&Menu{
Kind: MenuGroup,
visibleIf: kp.parseExpr(),
})
case "choice":
kp.pushCurrent(&Menu{
Kind: MenuChoice,
})
case "endmenu", "endif", "endchoice":
kp.popCurrent()
case "config", "menuconfig":
kp.newCurrent(&Menu{
Kind: MenuConfig,
Name: kp.Ident(),
})
default:
kp.parseConfigType(cmd)
}
}
func (kp *kconfigParser) parseConfigType(typ string) {
cur := kp.current()
switch typ {
case "tristate":
cur.Type = TypeTristate
kp.tryParsePrompt()
case "def_tristate":
cur.Type = TypeTristate
kp.parseDefaultValue()
case "bool":
cur.Type = TypeBool
kp.tryParsePrompt()
case "def_bool":
cur.Type = TypeBool
kp.parseDefaultValue()
case "int":
cur.Type = TypeInt
kp.tryParsePrompt()
case "def_int":
cur.Type = TypeInt
kp.parseDefaultValue()
case "hex":
cur.Type = TypeHex
kp.tryParsePrompt()
case "def_hex":
cur.Type = TypeHex
kp.parseDefaultValue()
case "string":
cur.Type = TypeString
kp.tryParsePrompt()
case "def_string":
cur.Type = TypeString
kp.parseDefaultValue()
default:
kp.parseProperty(typ)
}
}
func (kp *kconfigParser) parseProperty(prop string) {
cur := kp.current()
switch prop {
case "prompt":
kp.tryParsePrompt()
case "depends":
kp.MustConsume("on")
cur.dependsOn = exprAnd(cur.dependsOn, kp.parseExpr())
case "visible":
kp.MustConsume("if")
cur.visibleIf = exprAnd(cur.visibleIf, kp.parseExpr())
case "select", "imply":
name := kp.Ident()
cur.selects = append(cur.selects, name)
if kp.TryConsume("if") {
_ = kp.parseExpr()
}
case "option":
// It can be 'option foo', or 'option bar="BAZ"'.
kp.ConsumeLine()
case "modules":
case "optional":
case "default":
kp.parseDefaultValue()
case "range":
_, _ = kp.parseExpr(), kp.parseExpr() // from, to
if kp.TryConsume("if") {
_ = kp.parseExpr()
}
case "help", "---help---":
// Help rules are tricky: end of help is identified by smaller indentation level
// as would be rendered on a terminal with 8-column tabs setup, minus empty lines.
for kp.nextLine() {
if kp.eol() {
continue
}
kp.helpIdent = kp.identLevel()
kp.ConsumeLine()
break
}
default:
kp.failf("unknown line")
}
}
func (kp *kconfigParser) includeSource(file string) {
kp.newCurrent(nil)
file = kp.expandString(file)
file = filepath.Join(kp.baseDir, file)
data, err := os.ReadFile(file)
if err != nil {
kp.failf("%v", err)
return
}
kp.includes = append(kp.includes, kp.parser)
kp.parser = newParser(data, file)
kp.parseFile()
err = kp.err
kp.parser = kp.includes[len(kp.includes)-1]
kp.includes = kp.includes[:len(kp.includes)-1]
if kp.err == nil {
kp.err = err
}
}
func (kp *kconfigParser) pushCurrent(m *Menu) {
kp.endCurrent()
kp.cur = m
kp.stack = append(kp.stack, m)
}
func (kp *kconfigParser) popCurrent() {
kp.endCurrent()
if len(kp.stack) < 2 {
kp.failf("unbalanced endmenu")
return
}
last := kp.stack[len(kp.stack)-1]
kp.stack = kp.stack[:len(kp.stack)-1]
top := kp.stack[len(kp.stack)-1]
last.Parent = top
top.Elems = append(top.Elems, last)
}
func (kp *kconfigParser) newCurrent(m *Menu) {
kp.endCurrent()
kp.cur = m
}
func (kp *kconfigParser) current() *Menu {
if kp.cur == nil {
kp.failf("config property outside of config")
return &Menu{}
}
return kp.cur
}
func (kp *kconfigParser) endCurrent() {
if kp.cur == nil {
return
}
if len(kp.stack) == 0 {
kp.failf("unbalanced endmenu")
return
}
top := kp.stack[len(kp.stack)-1]
if top != kp.cur {
kp.cur.Parent = top
top.Elems = append(top.Elems, kp.cur)
}
kp.cur = nil
}
func (kp *kconfigParser) tryParsePrompt() {
if str, ok := kp.TryQuotedString(); ok {
prompt := prompt{
text: str,
}
if kp.TryConsume("if") {
prompt.cond = kp.parseExpr()
}
kp.current().prompts = append(kp.current().prompts, prompt)
}
}
func (kp *kconfigParser) parseDefaultValue() {
def := defaultVal{val: kp.parseExpr()}
if kp.TryConsume("if") {
def.cond = kp.parseExpr()
}
kp.current().defaults = append(kp.current().defaults, def)
}
func (kp *kconfigParser) expandString(str string) string {
str = strings.ReplaceAll(str, "$(SRCARCH)", kp.target.KernelHeaderArch)
str = strings.ReplaceAll(str, "$SRCARCH", kp.target.KernelHeaderArch)
str = strings.ReplaceAll(str, "$(KCONFIG_EXT_PREFIX)", "")
str = strings.ReplaceAll(str, "$(MALI_KCONFIG_EXT_PREFIX)", "") // ChromeOS.
return str
}
// Copyright 2020 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package kconfig
import (
"fmt"
"sort"
"github.com/google/syzkaller/pkg/bisect/minimize"
"github.com/google/syzkaller/pkg/debugtracer"
)
// Minimize finds an equivalent with respect to the provided predicate, but smaller config.
// It accepts base (small) and full (large) config. It is assumed that the predicate returns true for the full config.
// It is also assumed that base and full are not just two completely arbitrary configs, but full it produced from base
// mostly by adding more configs. The minimization procedure thus consists of figuring out what set of configs that
// are present in full and are not present in base affect the predicate.
// If maxPredRuns is non-zero, minimization will stop after the specified number of runs.
func (kconf *KConfig) Minimize(base, full *ConfigFile, pred func(*ConfigFile) (bool, error),
maxSteps int, dt debugtracer.DebugTracer) (*ConfigFile, error) {
diff, other := kconf.missingLeafConfigs(base, full)
dt.Log("kconfig minimization: base=%v full=%v leaves diff=%v", len(base.Configs), len(full.Configs), len(diff))
diffToConfig := func(part []string) (*ConfigFile, []string) {
if len(part) == 0 {
// We're testing the baseline config only.
return base, nil
}
suspects := kconf.addDependencies(base, full, part)
candidate := base.Clone()
// Always move all non-tristate configs from full to base as we don't minimize them.
for _, cfg := range other {
candidate.Set(cfg.Name, cfg.Value)
}
for _, cfg := range suspects {
candidate.Set(cfg, Yes)
}
return candidate, suspects
}
var step int
minimizePred := func(diffs []string) (bool, error) {
step++
config, _ := diffToConfig(diffs)
dt.SaveFile(fmt.Sprintf("step_%d.config", step), config.Serialize())
return pred(config)
}
result, err := minimize.Slice(
minimize.Config[string]{
Pred: minimizePred,
MaxSteps: maxSteps,
Logf: dt.Log,
},
diff,
)
if err != nil {
return nil, err
}
config, suspects := diffToConfig(result)
if suspects != nil {
dt.Log("minimized to %d configs; suspects: %v", len(result), suspects)
kconf.writeSuspects(dt, suspects)
}
return config, nil
}
func (kconf *KConfig) missingConfigs(base, full *ConfigFile) (tristate []string, other []*Config) {
for _, cfg := range full.Configs {
if cfg.Value == Yes && base.Value(cfg.Name) == No {
tristate = append(tristate, cfg.Name)
} else if cfg.Value != No && cfg.Value != Yes && cfg.Value != Mod {
other = append(other, cfg)
}
}
sort.Strings(tristate)
return
}
// missingLeafConfigs returns the set of configs no other config depends upon.
func (kconf *KConfig) missingLeafConfigs(base, full *ConfigFile) ([]string, []*Config) {
diff, other := kconf.missingConfigs(base, full)
needed := map[string]bool{}
for _, config := range diff {
for _, needs := range kconf.addDependencies(base, full, []string{config}) {
if needs != config {
needed[needs] = true
}
}
}
var leaves []string
for _, key := range diff {
if !needed[key] {
leaves = append(leaves, key)
}
}
return leaves, other
}
func (kconf *KConfig) addDependencies(base, full *ConfigFile, configs []string) []string {
closure := make(map[string]bool)
for _, cfg := range configs {
closure[cfg] = true
if m := kconf.Configs[cfg]; m != nil {
for dep := range m.DependsOn() {
if full.Value(dep) != No && base.Value(dep) == No {
closure[dep] = true
}
}
}
}
var sorted []string
for cfg := range closure {
sorted = append(sorted, cfg)
}
sort.Strings(sorted)
return sorted
}
const CauseConfigFile = "cause.config"
func (kconf *KConfig) writeSuspects(dt debugtracer.DebugTracer, suspects []string) {
cf := &ConfigFile{
Map: make(map[string]*Config),
}
for _, cfg := range suspects {
cf.Set(cfg, Yes)
}
dt.SaveFile(CauseConfigFile, cf.Serialize())
}
// Copyright 2020 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package kconfig
import (
"bytes"
"fmt"
"strings"
)
// parser is a helper for parsing simple text protocols tailored for kconfig syntax.
type parser struct {
data []byte
file string
current string
col int
line int
err error
}
func newParser(data []byte, file string) *parser {
return &parser{
data: data,
file: file,
}
}
// nextLine resets the parser to the next line.
// Automatically concatenates lines split with \ at the end.
func (p *parser) nextLine() bool {
if !p.eol() {
p.failf("tailing data at the end of line")
return false
}
if p.err != nil || len(p.data) == 0 {
return false
}
p.col = 0
p.line++
p.current = p.readNextLine()
for p.current != "" && p.current[len(p.current)-1] == '\\' && len(p.data) != 0 {
p.current = p.current[:len(p.current)-1] + p.readNextLine()
p.line++
}
p.skipSpaces()
return true
}
func (p *parser) readNextLine() string {
line := ""
nextLine := bytes.IndexByte(p.data, '\n')
if nextLine != -1 {
line = string(p.data[:nextLine])
p.data = p.data[nextLine+1:]
} else {
line = string(p.data)
p.data = nil
}
return line
}
func (p *parser) skipSpaces() {
for p.col < len(p.current) && (p.current[p.col] == ' ' || p.current[p.col] == '\t') {
p.col++
}
}
func (p *parser) identLevel() int {
level := 0
for i := 0; i < p.col; i++ {
level++
if p.current[i] == '\t' {
level = (level + 7) & ^7
}
}
return level
}
func (p *parser) failf(msg string, args ...interface{}) {
if p.err == nil {
p.err = fmt.Errorf("%v:%v:%v: %v\n%v", p.file, p.line, p.col, fmt.Sprintf(msg, args...), p.current)
}
}
func (p *parser) eol() bool {
return p.col == len(p.current)
}
func (p *parser) char() byte {
if p.err != nil {
return 0
}
if p.eol() {
p.failf("unexpected end of line")
return 0
}
v := p.current[p.col]
p.col++
return v
}
func (p *parser) peek() byte {
if p.err != nil || p.eol() {
return 0
}
return p.current[p.col]
}
func (p *parser) ConsumeLine() string {
res := p.current[p.col:]
p.col = len(p.current)
return res
}
func (p *parser) TryConsume(what string) bool {
if !strings.HasPrefix(p.current[p.col:], what) {
return false
}
p.col += len(what)
p.skipSpaces()
return true
}
func (p *parser) MustConsume(what string) {
if !p.TryConsume(what) {
p.failf("expected %q", what)
}
}
func (p *parser) QuotedString() string {
var str []byte
quote := p.char()
if quote != '"' && quote != '\'' {
p.failf("expect quoted string")
}
for ch := p.char(); ch != quote; ch = p.char() {
if ch == 0 {
p.failf("unterminated quoted string")
break
}
if ch == '\\' {
ch = p.char()
switch ch {
case '\'', '"', '\\', 'n':
str = append(str, ch)
default:
p.failf("bad quoted character")
}
continue
}
str = append(str, ch)
if ch == '$' && p.peek() == '(' {
str = append(str, p.Shell()...)
}
}
p.skipSpaces()
return string(str)
}
func (p *parser) TryQuotedString() (string, bool) {
if ch := p.peek(); ch == '"' || ch == '\'' {
return p.QuotedString(), true
}
return "", false
}
func (p *parser) Ident() string {
var str []byte
for !p.eol() {
ch := p.peek()
if ch >= 'a' && ch <= 'z' ||
ch >= 'A' && ch <= 'Z' ||
ch >= '0' && ch <= '9' ||
ch == '_' || ch == '-' {
str = append(str, ch)
p.col++
continue
}
break
}
if len(str) == 0 {
p.failf("expected an identifier")
}
p.skipSpaces()
return string(str)
}
func (p *parser) Shell() string {
start := p.col
p.MustConsume("(")
for !p.eol() && p.peek() != ')' {
if p.peek() == '"' {
p.QuotedString()
} else if p.peek() == '(' {
p.Shell()
} else {
p.col++
}
}
if ch := p.char(); ch != ')' {
p.failf("shell expression is not terminated")
}
res := p.current[start:p.col]
p.skipSpaces()
return res
}
// Copyright 2016 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
// Package log provides functionality similar to standard log package with some extensions:
// - verbosity levels
// - global verbosity setting that can be used by multiple packages
// - ability to disable all output
// - ability to cache recent output in memory
package log
import (
"bytes"
"flag"
"fmt"
golog "log"
"strings"
"sync"
"sync/atomic"
"time"
)
var (
flagV = flag.Int("vv", 0, "verbosity")
mu sync.Mutex
cacheMem int
cacheMaxMem int
cachePos int
cacheEntries []string
cachingEnabled atomic.Bool
instanceName string
prependTime = true // for testing
)
// EnableLogCaching enables in memory caching of log output.
// Caches up to maxLines, but no more than maxMem bytes.
// Cached output can later be queried with CachedOutput.
func EnableLogCaching(maxLines, maxMem int) {
mu.Lock()
defer mu.Unlock()
if cacheEntries != nil {
Fatalf("log caching is already enabled")
}
if maxLines < 1 || maxMem < 1 {
panic("invalid maxLines/maxMem")
}
cacheMaxMem = maxMem
cacheEntries = make([]string, maxLines)
cachingEnabled.Store(true)
}
// Retrieves cached log output.
func CachedLogOutput() string {
mu.Lock()
defer mu.Unlock()
buf := new(bytes.Buffer)
for i := range cacheEntries {
pos := (cachePos + i) % len(cacheEntries)
if cacheEntries[pos] == "" {
continue
}
buf.WriteString(cacheEntries[pos])
buf.Write([]byte{'\n'})
}
return buf.String()
}
// If the name is set, it will be displayed for all logs.
func SetName(name string) {
instanceName = name
}
// V reports whether verbosity at the call site is at least the requested level.
// See https://pkg.go.dev/github.com/golang/glog#V for details.
func V(level int) bool {
return level <= *flagV
}
func Log(v int, msg string) {
Logf(v, "%v", msg)
}
func Logf(v int, msg string, args ...interface{}) {
writeMessage(v, "", msg, args...)
}
func Error(err error) {
Errorf("%v", err)
}
func Errorf(msg string, args ...interface{}) {
writeMessage(0, "ERROR", msg, args...)
}
func Fatal(err error) {
Fatalf("%v", err)
}
func Fatalf(msg string, args ...interface{}) {
golog.Fatal(message("FATAL", msg, args...))
}
func message(severity, msg string, args ...interface{}) string {
var sb strings.Builder
if severity != "" {
fmt.Fprintf(&sb, "[%s] ", severity)
}
if instanceName != "" {
fmt.Fprintf(&sb, "%s: ", instanceName)
}
fmt.Fprintf(&sb, msg, args...)
return sb.String()
}
func writeMessage(v int, severity, msg string, args ...interface{}) {
cache := v <= 1 && cachingEnabled.Load()
if !V(v) && !cache {
return
}
text := message(severity, msg, args...)
if V(v) {
golog.Print(text)
}
if !cache {
return
}
mu.Lock()
defer mu.Unlock()
cacheMem -= len(cacheEntries[cachePos])
if cacheMem < 0 {
panic("log cache size underflow")
}
timeStr := ""
if prependTime {
timeStr = time.Now().Format("2006/01/02 15:04:05 ")
}
cacheEntries[cachePos] = timeStr + text
cacheMem += len(cacheEntries[cachePos])
cachePos++
if cachePos == len(cacheEntries) {
cachePos = 0
}
for i := 0; i < len(cacheEntries)-1 && cacheMem > cacheMaxMem; i++ {
pos := (cachePos + i) % len(cacheEntries)
cacheMem -= len(cacheEntries[pos])
cacheEntries[pos] = ""
}
if cacheMem < 0 {
panic("log cache size underflow")
}
}
type VerboseWriter int
func (w VerboseWriter) Write(data []byte) (int, error) {
Logf(int(w), "%s", data)
return len(data), nil
}
// Copyright 2015 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package mgrconfig
import (
"bytes"
"fmt"
"os"
"path/filepath"
"regexp"
"runtime"
"strings"
"github.com/google/syzkaller/pkg/config"
"github.com/google/syzkaller/pkg/osutil"
"github.com/google/syzkaller/pkg/vminfo"
"github.com/google/syzkaller/prog"
_ "github.com/google/syzkaller/sys" // most mgrconfig users want targets too
"github.com/google/syzkaller/sys/targets"
)
// Derived config values that are handy to keep with the config, filled after reading user config.
type Derived struct {
Target *prog.Target
SysTarget *targets.Target
// Parsed Target:
TargetOS string
TargetArch string
TargetVMArch string
// Full paths to binaries we are going to use:
ExecprogBin string
ExecutorBin string
Syscalls []int
NoMutateCalls map[int]bool // Set of IDs of syscalls which should not be mutated.
Timeouts targets.Timeouts
// Special debugging/development mode specified by VM type "none".
// In this mode syz-manager does not start any VMs, but instead a user is supposed
// to start syz-executor process in a VM manually.
VMLess bool
LocalModules []*vminfo.KernelModule
}
func LoadData(data []byte) (*Config, error) {
cfg, err := LoadPartialData(data)
if err != nil {
return nil, err
}
if err := Complete(cfg); err != nil {
return nil, err
}
return cfg, nil
}
func LoadFile(filename string) (*Config, error) {
cfg, err := LoadPartialFile(filename)
if err != nil {
return nil, err
}
if err := Complete(cfg); err != nil {
return nil, err
}
return cfg, nil
}
func LoadPartialData(data []byte) (*Config, error) {
cfg := defaultValues()
if err := config.LoadData(data, cfg); err != nil {
return nil, err
}
if err := SetTargets(cfg); err != nil {
return nil, err
}
return cfg, nil
}
func LoadPartialFile(filename string) (*Config, error) {
cfg := defaultValues()
if err := config.LoadFile(filename, cfg); err != nil {
return nil, err
}
if err := SetTargets(cfg); err != nil {
return nil, err
}
return cfg, nil
}
func defaultValues() *Config {
return &Config{
SSHUser: "root",
Cover: true,
Reproduce: true,
Sandbox: "none",
RPC: ":0",
MaxCrashLogs: 100,
Procs: 6,
PreserveCorpus: true,
RunFsck: true,
Experimental: Experimental{
RemoteCover: true,
CoverEdges: true,
DescriptionsMode: manualDescriptions,
},
}
}
type DescriptionsMode int
const (
invalidDescriptions = iota
ManualDescriptions
AutoDescriptions
AnyDescriptions
)
const manualDescriptions = "manual"
var (
strToDescriptionsMode = map[string]DescriptionsMode{
manualDescriptions: ManualDescriptions,
"auto": AutoDescriptions,
"any": AnyDescriptions,
}
)
func SetTargets(cfg *Config) error {
var err error
cfg.TargetOS, cfg.TargetVMArch, cfg.TargetArch, err = splitTarget(cfg.RawTarget)
if err != nil {
return err
}
cfg.Target, err = prog.GetTarget(cfg.TargetOS, cfg.TargetArch)
if err != nil {
return err
}
cfg.SysTarget = targets.Get(cfg.TargetOS, cfg.TargetVMArch)
if cfg.SysTarget == nil {
return fmt.Errorf("unsupported OS/arch: %v/%v", cfg.TargetOS, cfg.TargetVMArch)
}
return nil
}
func Complete(cfg *Config) error {
if err := checkNonEmpty(
cfg.TargetOS, "target",
cfg.TargetVMArch, "target",
cfg.TargetArch, "target",
cfg.Workdir, "workdir",
cfg.Syzkaller, "syzkaller",
cfg.Type, "type",
cfg.SSHUser, "ssh_user",
); err != nil {
return err
}
cfg.Workdir = osutil.Abs(cfg.Workdir)
if cfg.WorkdirTemplate != "" {
cfg.WorkdirTemplate = osutil.Abs(cfg.WorkdirTemplate)
if _, err := os.ReadDir(cfg.WorkdirTemplate); err != nil {
return fmt.Errorf("failed to read workdir_template: %w", err)
}
}
if cfg.Image != "" {
if !osutil.IsExist(cfg.Image) {
return fmt.Errorf("bad config param image: can't find %v", cfg.Image)
}
cfg.Image = osutil.Abs(cfg.Image)
}
if err := cfg.completeBinaries(); err != nil {
return err
}
if cfg.Procs < 1 || cfg.Procs > prog.MaxPids {
return fmt.Errorf("bad config param procs: '%v', want [1, %v]", cfg.Procs, prog.MaxPids)
}
switch cfg.Sandbox {
case "none", "setuid", "namespace", "android":
default:
return fmt.Errorf("config param sandbox must contain one of none/setuid/namespace/android")
}
if err := cfg.checkSSHParams(); err != nil {
return err
}
cfg.CompleteKernelDirs()
if err := cfg.completeServices(); err != nil {
return nil
}
if cfg.FuzzingVMs < 0 {
return fmt.Errorf("fuzzing_vms cannot be less than 0")
}
var err error
cfg.Syscalls, err = ParseEnabledSyscalls(cfg.Target, cfg.EnabledSyscalls, cfg.DisabledSyscalls,
strToDescriptionsMode[cfg.Experimental.DescriptionsMode])
if err != nil {
return err
}
cfg.NoMutateCalls, err = ParseNoMutateSyscalls(cfg.Target, cfg.NoMutateSyscalls)
if err != nil {
return err
}
if err := cfg.completeFocusAreas(); err != nil {
return err
}
cfg.initTimeouts()
cfg.VMLess = cfg.Type == "none"
return nil
}
func (cfg *Config) completeServices() error {
if cfg.HubClient != "" {
if err := checkNonEmpty(
cfg.Name, "name",
cfg.HubAddr, "hub_addr",
); err != nil {
return err
}
}
if cfg.HubDomain != "" &&
!regexp.MustCompile(`^[a-zA-Z0-9-_.]{2,50}(/[a-zA-Z0-9-_.]{2,50})?$`).MatchString(cfg.HubDomain) {
return fmt.Errorf("bad value for hub_domain")
}
if cfg.DashboardClient != "" {
if err := checkNonEmpty(
cfg.Name, "name",
cfg.DashboardAddr, "dashboard_addr",
); err != nil {
return err
}
}
if !cfg.AssetStorage.IsEmpty() {
if cfg.DashboardClient == "" {
return fmt.Errorf("asset storage also requires dashboard client")
}
if err := cfg.AssetStorage.Validate(); err != nil {
return err
}
}
return nil
}
func (cfg *Config) initTimeouts() {
slowdown := 1
switch {
case cfg.Type == "qemu" && (runtime.GOARCH == cfg.SysTarget.Arch || runtime.GOARCH == cfg.SysTarget.VMArch):
// If TCG is enabled for QEMU, increase the slowdown.
if bytes.Contains(cfg.VM, []byte("-accel tcg")) {
slowdown = 10
}
case cfg.Type == "qemu" && runtime.GOARCH != cfg.SysTarget.Arch && runtime.GOARCH != cfg.SysTarget.VMArch:
// Assuming qemu emulation.
// Quick tests of mmap syscall on arm64 show ~9x slowdown.
slowdown = 10
case cfg.Type == targets.GVisor && cfg.Cover && strings.Contains(cfg.Name, "-race"):
// Go coverage+race has insane slowdown of ~350x. We can't afford such large value,
// but a smaller value should be enough to finish at least some syscalls.
// Note: the name check is a hack.
slowdown = 10
}
// Note: we could also consider heavy debug tools (KASAN/KMSAN/KCSAN/KMEMLEAK) if necessary.
cfg.Timeouts = cfg.SysTarget.Timeouts(slowdown)
}
func checkNonEmpty(fields ...string) error {
for i := 0; i < len(fields); i += 2 {
if fields[i] == "" {
return fmt.Errorf("config param %v is empty", fields[i+1])
}
}
return nil
}
func (cov *CovFilterCfg) Empty() bool {
return len(cov.Functions)+len(cov.Files)+len(cov.RawPCs) == 0
}
func (cfg *Config) CompleteKernelDirs() {
cfg.KernelObj = osutil.Abs(cfg.KernelObj)
if cfg.KernelSrc == "" {
cfg.KernelSrc = cfg.KernelObj // assume in-tree build by default
}
cfg.KernelSrc = osutil.Abs(cfg.KernelSrc)
if cfg.KernelBuildSrc == "" {
cfg.KernelBuildSrc = cfg.KernelSrc
}
cfg.KernelBuildSrc = osutil.Abs(cfg.KernelBuildSrc)
}
type KernelDirs struct {
Src string
Obj string
BuildSrc string
}
func (cfg *Config) KernelDirs() *KernelDirs {
return &KernelDirs{
Src: cfg.KernelSrc,
Obj: cfg.KernelObj,
BuildSrc: cfg.KernelBuildSrc,
}
}
func (cfg *Config) checkSSHParams() error {
if cfg.SSHKey == "" {
return nil
}
info, err := os.Stat(cfg.SSHKey)
if err != nil {
return err
}
if info.Mode()&0077 != 0 {
return fmt.Errorf("sshkey %v is unprotected, ssh will reject it, do chmod 0600", cfg.SSHKey)
}
cfg.SSHKey = osutil.Abs(cfg.SSHKey)
return nil
}
func (cfg *Config) completeBinaries() error {
cfg.Syzkaller = osutil.Abs(cfg.Syzkaller)
exe := cfg.SysTarget.ExeExtension
targetBin := func(name, arch string) string {
return filepath.Join(cfg.Syzkaller, "bin", cfg.TargetOS+"_"+arch, name+exe)
}
cfg.ExecprogBin = targetBin("syz-execprog", cfg.TargetVMArch)
cfg.ExecutorBin = targetBin("syz-executor", cfg.TargetArch)
if cfg.ExecprogBinOnTarget != "" {
cfg.SysTarget.ExecprogBin = cfg.ExecprogBinOnTarget
}
if cfg.ExecutorBinOnTarget != "" {
cfg.SysTarget.ExecutorBin = cfg.ExecutorBinOnTarget
}
if cfg.StraceBinOnTarget && cfg.StraceBin == "" {
cfg.StraceBin = "strace"
}
// If the target already provides binaries, we don't need to copy them.
if cfg.SysTarget.ExecprogBin != "" {
cfg.ExecprogBin = ""
}
if cfg.SysTarget.ExecutorBin != "" {
cfg.ExecutorBin = ""
}
if cfg.ExecprogBin != "" && !osutil.IsExist(cfg.ExecprogBin) {
return fmt.Errorf("bad config syzkaller param: can't find %v", cfg.ExecprogBin)
}
if cfg.ExecutorBin != "" && !osutil.IsExist(cfg.ExecutorBin) {
return fmt.Errorf("bad config syzkaller param: can't find %v", cfg.ExecutorBin)
}
if !cfg.StraceBinOnTarget && cfg.StraceBin != "" {
if !osutil.IsExist(cfg.StraceBin) {
return fmt.Errorf("bad config param strace_bin: can't find %v", cfg.StraceBin)
}
cfg.StraceBin = osutil.Abs(cfg.StraceBin)
}
return nil
}
func (cfg *Config) completeFocusAreas() error {
names := map[string]bool{}
seenEmptyFilter := false
for i, area := range cfg.Experimental.FocusAreas {
if area.Name != "" {
if names[area.Name] {
return fmt.Errorf("duplicate focus area name: %q", area.Name)
}
names[area.Name] = true
}
if area.Weight <= 0 {
return fmt.Errorf("focus area #%d: negative weight", i)
}
if area.Filter.Empty() {
if seenEmptyFilter {
return fmt.Errorf("there must be only one focus area with an empty filter")
}
seenEmptyFilter = true
}
}
if !cfg.CovFilter.Empty() {
if len(cfg.Experimental.FocusAreas) > 0 {
return fmt.Errorf("you cannot use both cov_filter and focus_areas")
}
cfg.Experimental.FocusAreas = []FocusArea{
{
Name: "filtered",
Filter: cfg.CovFilter,
Weight: 1.0,
},
}
cfg.CovFilter = CovFilterCfg{}
}
return nil
}
func splitTarget(target string) (string, string, string, error) {
if target == "" {
return "", "", "", fmt.Errorf("target is empty")
}
targetParts := strings.Split(target, "/")
if len(targetParts) != 2 && len(targetParts) != 3 {
return "", "", "", fmt.Errorf("bad config param target")
}
os := targetParts[0]
vmarch := targetParts[1]
arch := targetParts[1]
if len(targetParts) == 3 {
arch = targetParts[2]
}
return os, vmarch, arch, nil
}
func ParseEnabledSyscalls(target *prog.Target, enabled, disabled []string,
descriptionsMode DescriptionsMode) ([]int, error) {
if descriptionsMode == invalidDescriptions {
return nil, fmt.Errorf("config param descriptions_mode must contain one of auto/manual/any")
}
syscalls := make(map[int]bool)
if len(enabled) != 0 {
for _, c := range enabled {
n := 0
for _, call := range target.Syscalls {
if MatchSyscall(call.Name, c) {
syscalls[call.ID] = true
n++
}
}
if n == 0 {
return nil, fmt.Errorf("unknown enabled syscall: %v", c)
}
}
} else {
for _, call := range target.Syscalls {
syscalls[call.ID] = true
}
}
for call := range syscalls {
if target.Syscalls[call].Attrs.Disabled ||
descriptionsMode == ManualDescriptions && target.Syscalls[call].Attrs.Automatic ||
descriptionsMode == AutoDescriptions &&
!target.Syscalls[call].Attrs.Automatic && !target.Syscalls[call].Attrs.AutomaticHelper {
delete(syscalls, call)
}
}
for _, c := range disabled {
n := 0
for _, call := range target.Syscalls {
if MatchSyscall(call.Name, c) {
delete(syscalls, call.ID)
n++
}
}
if n == 0 {
return nil, fmt.Errorf("unknown disabled syscall: %v", c)
}
}
if len(syscalls) == 0 {
return nil, fmt.Errorf("all syscalls are disabled by disable_syscalls in config")
}
var arr []int
for id := range syscalls {
arr = append(arr, id)
}
return arr, nil
}
func ParseNoMutateSyscalls(target *prog.Target, syscalls []string) (map[int]bool, error) {
var result = make(map[int]bool)
for _, c := range syscalls {
n := 0
for _, call := range target.Syscalls {
if MatchSyscall(call.Name, c) {
result[call.ID] = true
n++
}
}
if n == 0 {
return nil, fmt.Errorf("unknown no_mutate syscall: %v", c)
}
}
return result, nil
}
func MatchSyscall(name, pattern string) bool {
if pattern == name || strings.HasPrefix(name, pattern+"$") {
return true
}
if len(pattern) > 1 && pattern[len(pattern)-1] == '*' &&
strings.HasPrefix(name, pattern[:len(pattern)-1]) {
return true
}
return false
}
// Copyright 2015 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package osutil
import (
"fmt"
"io"
"os"
"path/filepath"
)
// CopyFile atomically copies oldFile to newFile preserving permissions and modification time.
func CopyFile(oldFile, newFile string) error {
oldf, err := os.Open(oldFile)
if err != nil {
return err
}
defer oldf.Close()
stat, err := oldf.Stat()
if err != nil {
return err
}
tmpFile := newFile + ".tmp"
newf, err := os.OpenFile(tmpFile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, stat.Mode()&os.ModePerm)
if err != nil {
return err
}
defer newf.Close()
_, err = io.Copy(newf, oldf)
if err != nil {
return err
}
if err := newf.Close(); err != nil {
return err
}
if err := os.Chtimes(tmpFile, stat.ModTime(), stat.ModTime()); err != nil {
return err
}
return os.Rename(tmpFile, newFile)
}
// Rename is similar to os.Rename but handles cross-device renaming (by copying).
func Rename(oldFile, newFile string) error {
err := os.Rename(oldFile, newFile)
if err != nil {
// Can't use syscall.EXDEV because this is used in appengine app.
err = CopyFile(oldFile, newFile)
os.Remove(oldFile)
}
return err
}
// FillDirectory is used to fill in directory structure for tests.
func FillDirectory(dir string, fileContent map[string]string) error {
for path, content := range fileContent {
fullPath := filepath.Join(dir, path)
dirPath := filepath.Dir(fullPath)
if err := MkdirAll(dirPath); err != nil {
return fmt.Errorf("mkdir %q failed: %w", dirPath, err)
}
if err := WriteFile(fullPath, []byte(content)); err != nil {
return fmt.Errorf("write file failed: %w", err)
}
}
return nil
}
// WriteTempFile writes data to a temp file and returns its name.
func WriteTempFile(data []byte) (string, error) {
// Note: pkg/report knows about "syzkaller" prefix as it appears in crashes as process name.
f, err := os.CreateTemp("", "syzkaller")
if err != nil {
return "", fmt.Errorf("failed to create a temp file: %w", err)
}
if _, err := f.Write(data); err != nil {
f.Close()
os.Remove(f.Name())
return "", fmt.Errorf("failed to write a temp file: %w", err)
}
f.Close()
return f.Name(), nil
}
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package osutil
import (
"bytes"
"compress/gzip"
"context"
"encoding/json"
"errors"
"fmt"
"io"
"os"
"os/exec"
"path/filepath"
"strings"
"sync"
"syscall"
"time"
_ "unsafe" // required to use go:linkname
)
const (
DefaultDirPerm = 0755
DefaultFilePerm = 0644
DefaultExecPerm = 0755
)
// RunCmd runs "bin args..." in dir with timeout and returns its output.
func RunCmd(timeout time.Duration, dir, bin string, args ...string) ([]byte, error) {
cmd := Command(bin, args...)
cmd.Dir = dir
return Run(timeout, cmd)
}
// Run runs cmd with the specified timeout.
// Returns combined output. If the command fails, err includes output.
func Run(timeout time.Duration, cmd *exec.Cmd) ([]byte, error) {
output := new(bytes.Buffer)
if cmd.Stdout == nil {
cmd.Stdout = output
}
if cmd.Stderr == nil {
cmd.Stderr = output
}
setPdeathsig(cmd, true)
if err := cmd.Start(); err != nil {
return nil, fmt.Errorf("failed to start %v %+v: %w", cmd.Path, cmd.Args, err)
}
done := make(chan bool)
timedout := make(chan bool, 1)
timer := time.NewTimer(timeout)
go func() {
select {
case <-timer.C:
timedout <- true
killPgroup(cmd)
cmd.Process.Kill()
case <-done:
timedout <- false
timer.Stop()
}
}()
err := cmd.Wait()
close(done)
if err != nil {
text := fmt.Sprintf("failed to run %q: %v", cmd.Args, err)
if <-timedout {
text = fmt.Sprintf("timedout after %v %q", timeout, cmd.Args)
}
exitCode := cmd.ProcessState.ExitCode()
var exitErr *exec.ExitError
if errors.As(err, &exitErr) {
if status, ok := exitErr.Sys().(syscall.WaitStatus); ok {
exitCode = status.ExitStatus()
}
}
return output.Bytes(), &VerboseError{
Title: text,
Output: output.Bytes(),
ExitCode: exitCode,
}
}
return output.Bytes(), nil
}
// CommandContext is similar to os/exec.CommandContext, but also sets PDEATHSIG to SIGKILL on linux,
// i.e. the child will be killed immediately.
func CommandContext(ctx context.Context, bin string, args ...string) *exec.Cmd {
cmd := exec.CommandContext(ctx, bin, args...)
setPdeathsig(cmd, true)
return cmd
}
// Command is similar to os/exec.Command, but also sets PDEATHSIG to SIGKILL on linux,
// i.e. the child will be killed immediately.
func Command(bin string, args ...string) *exec.Cmd {
cmd := exec.Command(bin, args...)
setPdeathsig(cmd, true)
return cmd
}
// Command is similar to os/exec.Command, but also sets PDEATHSIG to SIGTERM on linux,
// i.e. the child has a chance to exit gracefully. This may be important when running
// e.g. syz-manager. If it is killed immediately, it can leak GCE instances.
func GraciousCommand(bin string, args ...string) *exec.Cmd {
cmd := exec.Command(bin, args...)
setPdeathsig(cmd, false)
return cmd
}
type VerboseError struct {
Title string
Output []byte
ExitCode int
}
func (err *VerboseError) Error() string {
if len(err.Output) == 0 {
return err.Title
}
return fmt.Sprintf("%v\n%s", err.Title, err.Output)
}
func PrependContext(ctx string, err error) error {
var verboseError *VerboseError
switch {
case errors.As(err, &verboseError):
verboseError.Title = fmt.Sprintf("%v: %v", ctx, verboseError.Title)
return verboseError
default:
return fmt.Errorf("%v: %w", ctx, err)
}
}
func IsDir(name string) bool {
fileInfo, err := os.Stat(name)
return err == nil && fileInfo.IsDir()
}
// IsExist returns true if the file name exists.
func IsExist(name string) bool {
_, err := os.Stat(name)
return err == nil
}
// FilesExist returns true if all files exist in dir.
// Files are assumed to be relative names in slash notation.
func FilesExist(dir string, files map[string]bool) bool {
for pattern, required := range files {
if !required {
continue
}
files, err := filepath.Glob(filepath.Join(dir, filepath.FromSlash(pattern)))
if err != nil || len(files) == 0 {
return false
}
}
return true
}
// CopyFiles copies files from srcDir to dstDir as atomically as possible.
// Files are assumed to be relative glob patterns in slash notation in srcDir.
// All other files in dstDir are removed.
func CopyFiles(srcDir, dstDir string, files map[string]bool) error {
// Linux does not support atomic dir replace, so we copy to tmp dir first.
// Then remove dst dir and rename tmp to dst (as atomic as can get on Linux).
tmpDir := dstDir + ".tmp"
if err := os.RemoveAll(tmpDir); err != nil {
return err
}
if err := MkdirAll(tmpDir); err != nil {
return err
}
if err := foreachPatternFile(srcDir, tmpDir, files, CopyFile); err != nil {
return err
}
if err := os.RemoveAll(dstDir); err != nil {
return err
}
return os.Rename(tmpDir, dstDir)
}
func foreachPatternFile(srcDir, dstDir string, files map[string]bool, fn func(src, dst string) error) error {
srcDir = filepath.Clean(srcDir)
dstDir = filepath.Clean(dstDir)
for pattern, required := range files {
files, err := filepath.Glob(filepath.Join(srcDir, filepath.FromSlash(pattern)))
if err != nil {
return err
}
if len(files) == 0 {
if !required {
continue
}
return fmt.Errorf("file %v does not exist", pattern)
}
for _, file := range files {
if !strings.HasPrefix(file, srcDir) {
return fmt.Errorf("file %q matched from %q in %q doesn't have src prefix", file, pattern, srcDir)
}
dst := filepath.Join(dstDir, strings.TrimPrefix(file, srcDir))
if err := MkdirAll(filepath.Dir(dst)); err != nil {
return err
}
if err := fn(file, dst); err != nil {
return err
}
}
}
return nil
}
func CopyDirRecursively(srcDir, dstDir string) error {
if err := MkdirAll(dstDir); err != nil {
return err
}
files, err := os.ReadDir(srcDir)
if err != nil {
return err
}
for _, file := range files {
src := filepath.Join(srcDir, file.Name())
dst := filepath.Join(dstDir, file.Name())
if file.IsDir() {
if err := CopyDirRecursively(src, dst); err != nil {
return err
}
continue
}
if err := CopyFile(src, dst); err != nil {
return err
}
}
return nil
}
// LinkFiles creates hard links for files from dstDir to srcDir.
// Files are assumed to be relative names in slash notation.
// All other files in dstDir are removed.
func LinkFiles(srcDir, dstDir string, files map[string]bool) error {
if err := os.RemoveAll(dstDir); err != nil {
return err
}
if err := MkdirAll(dstDir); err != nil {
return err
}
return foreachPatternFile(srcDir, dstDir, files, os.Link)
}
func MkdirAll(dir string) error {
return os.MkdirAll(dir, DefaultDirPerm)
}
func WriteFile(filename string, data []byte) error {
return os.WriteFile(filename, data, DefaultFilePerm)
}
// WriteFileAtomically writes data to file filename without exposing and empty/partially-written file.
// This is useful for writing generated source files. Exposing an empty file may break tools
// that run on source files in parallel.
func WriteFileAtomically(filename string, data []byte) error {
// We can't use os.CreateTemp b/c it may be on a different mount,
// and Rename can't move across mounts.
tmpFile := filename + ".tmp"
if err := WriteFile(tmpFile, data); err != nil {
return err
}
return os.Rename(tmpFile, filename)
}
func WriteJSON[T any](filename string, obj T) error {
jsonData, err := json.MarshalIndent(obj, "", "\t")
if err != nil {
return fmt.Errorf("failed to marshal: %w", err)
}
return WriteFile(filename, jsonData)
}
func WriteGzipStream(filename string, reader io.Reader) error {
f, err := os.Create(filename)
if err != nil {
return err
}
defer f.Close()
gz := gzip.NewWriter(f)
defer gz.Close()
_, err = io.Copy(gz, reader)
return err
}
func WriteExecFile(filename string, data []byte) error {
os.Remove(filename)
return os.WriteFile(filename, data, DefaultExecPerm)
}
// TempFile creates a unique temp filename.
// Note: the file already exists when the function returns.
func TempFile(prefix string) (string, error) {
f, err := os.CreateTemp("", prefix)
if err != nil {
return "", fmt.Errorf("failed to create temp file: %w", err)
}
f.Close()
return f.Name(), nil
}
// Return all files in a directory.
func ListDir(dir string) ([]string, error) {
f, err := os.Open(dir)
if err != nil {
return nil, err
}
defer f.Close()
return f.Readdirnames(-1)
}
var (
wd string
wdOnce sync.Once
)
func Abs(path string) string {
wdOnce.Do(func() {
var err error
wd, err = os.Getwd()
if err != nil {
panic(fmt.Sprintf("failed to get wd: %v", err))
}
})
if wd1, err := os.Getwd(); err == nil && wd1 != wd {
panic(fmt.Sprintf("wd changed: %q -> %q", wd, wd1))
}
if path == "" {
return path
}
if !filepath.IsAbs(path) {
path = filepath.Join(wd, path)
}
return filepath.Clean(path)
}
// CreationTime returns file creation time.
// May return zero time, if not known.
func CreationTime(fi os.FileInfo) time.Time {
return creationTime(fi)
}
// MonotonicNano returns monotonic time in nanoseconds from some unspecified point in time.
// Useful mostly to measure time intervals.
// This function should be used inside of tested VMs b/c time.Now may reject to use monotonic time
// if the fuzzer messes with system time (sets time past Y2157, see comments in time/time.go).
// This is a hacky way to use the private runtime function.
// If this ever breaks, we can either provide specializations for different Go versions
// using build tags, or fall back to time.Now.
//
//go:linkname MonotonicNano runtime.nanotime
func MonotonicNano() time.Duration
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package osutil
import (
"fmt"
"os"
"os/exec"
"path/filepath"
"strconv"
"strings"
"sync"
"syscall"
"time"
"golang.org/x/sys/unix"
)
func creationTime(fi os.FileInfo) time.Time {
st := fi.Sys().(*syscall.Stat_t)
return time.Unix(int64(st.Ctim.Sec), int64(st.Ctim.Nsec)) // nolint: unconvert
}
// RemoveAll is similar to os.RemoveAll, but can handle more cases.
func RemoveAll(dir string) error {
files, _ := os.ReadDir(dir)
for _, f := range files {
name := filepath.Join(dir, f.Name())
if f.IsDir() {
RemoveAll(name)
}
unix.Unmount(name, unix.MNT_FORCE)
}
if err := os.RemoveAll(dir); err != nil {
removeImmutable(dir)
return os.RemoveAll(dir)
}
return nil
}
func SystemMemorySize() uint64 {
var info syscall.Sysinfo_t
syscall.Sysinfo(&info)
return uint64(info.Totalram) // nolint:unconvert
}
func removeImmutable(fname string) error {
// Reset FS_XFLAG_IMMUTABLE/FS_XFLAG_APPEND.
fd, err := syscall.Open(fname, syscall.O_RDONLY, 0)
if err != nil {
return err
}
defer syscall.Close(fd)
return unix.IoctlSetPointerInt(fd, unix.FS_IOC_SETFLAGS, 0)
}
func Sandbox(cmd *exec.Cmd, user, net bool) error {
enabled, uid, gid, err := initSandbox()
if err != nil || !enabled {
return err
}
if cmd.SysProcAttr == nil {
cmd.SysProcAttr = new(syscall.SysProcAttr)
}
if net {
cmd.SysProcAttr.Cloneflags = syscall.CLONE_NEWNET | syscall.CLONE_NEWIPC |
syscall.CLONE_NEWNS | syscall.CLONE_NEWUTS | syscall.CLONE_NEWPID
}
if user {
cmd.SysProcAttr.Credential = &syscall.Credential{
Uid: uid,
Gid: gid,
}
}
return nil
}
func SandboxChown(file string) error {
enabled, uid, gid, err := initSandbox()
if err != nil || !enabled {
return err
}
return os.Chown(file, int(uid), int(gid))
}
var (
sandboxOnce sync.Once
sandboxEnabled = true
sandboxUsername = "syzkaller"
sandboxUID = ^uint32(0)
sandboxGID = ^uint32(0)
)
func initSandbox() (bool, uint32, uint32, error) {
sandboxOnce.Do(func() {
if syscall.Getuid() != 0 || os.Getenv("CI") != "" || os.Getenv("SYZ_DISABLE_SANDBOXING") == "yes" {
sandboxEnabled = false
return
}
uid, err := usernameToID("-u")
if err != nil {
return
}
gid, err := usernameToID("-g")
if err != nil {
return
}
sandboxUID = uid
sandboxGID = gid
})
if sandboxEnabled && sandboxUID == ^uint32(0) {
return false, 0, 0, fmt.Errorf("user %q is not found, can't sandbox command", sandboxUsername)
}
return sandboxEnabled, sandboxUID, sandboxGID, nil
}
func usernameToID(what string) (uint32, error) {
out, err := RunCmd(time.Minute, "", "id", what, sandboxUsername)
if err != nil {
return 0, err
}
str := strings.Trim(string(out), " \t\n")
id, err := strconv.ParseUint(str, 10, 32)
if err != nil {
return 0, err
}
return uint32(id), nil
}
func setPdeathsig(cmd *exec.Cmd, hardKill bool) {
if cmd.SysProcAttr == nil {
cmd.SysProcAttr = new(syscall.SysProcAttr)
}
if hardKill {
cmd.SysProcAttr.Pdeathsig = syscall.SIGKILL
} else {
cmd.SysProcAttr.Pdeathsig = syscall.SIGTERM
}
// We will kill the whole process group.
cmd.SysProcAttr.Setpgid = true
}
func killPgroup(cmd *exec.Cmd) {
syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL)
}
func prolongPipe(r, w *os.File) {
for sz := 128 << 10; sz <= 2<<20; sz *= 2 {
syscall.Syscall(syscall.SYS_FCNTL, w.Fd(), syscall.F_SETPIPE_SZ, uintptr(sz))
}
}
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
//go:build freebsd || netbsd || openbsd || linux || darwin
package osutil
import (
"fmt"
"io"
"os"
"os/signal"
"path/filepath"
"strconv"
"syscall"
)
// ProcessTempDir creates a new temp dir in where and returns its path and an unique index.
// It also cleans up old, unused temp dirs after dead processes.
func ProcessTempDir(where string) (string, error) {
lk := filepath.Join(where, "instance-lock")
lkf, err := syscall.Open(lk, syscall.O_RDWR|syscall.O_CREAT, DefaultFilePerm)
if err != nil {
return "", err
}
defer syscall.Close(lkf)
if err := syscall.Flock(lkf, syscall.LOCK_EX); err != nil {
return "", err
}
defer syscall.Flock(lkf, syscall.LOCK_UN)
for i := 0; i < 1e3; i++ {
path := filepath.Join(where, fmt.Sprintf("instance-%v", i))
pidfile := filepath.Join(path, ".pid")
err := os.Mkdir(path, DefaultDirPerm)
if os.IsExist(err) {
// Try to clean up.
if cleanupTempDir(path, pidfile) {
i--
}
continue
}
if err != nil {
return "", err
}
if err := WriteFile(pidfile, []byte(strconv.Itoa(syscall.Getpid()))); err != nil {
return "", err
}
return path, nil
}
return "", fmt.Errorf("too many live instances")
}
func cleanupTempDir(path, pidfile string) bool {
data, err := os.ReadFile(pidfile)
if err == nil && len(data) > 0 {
pid, err := strconv.Atoi(string(data))
if err == nil && pid > 1 {
if err := syscall.Kill(pid, 0); err == syscall.ESRCH {
if os.Remove(pidfile) == nil {
return os.RemoveAll(path) == nil
}
}
}
}
// If err != nil, assume that the pid file is not created yet.
return false
}
// HandleInterrupts closes shutdown chan on first SIGINT
// (expecting that the program will gracefully shutdown and exit)
// and terminates the process on third SIGINT.
func HandleInterrupts(shutdown chan struct{}) {
go func() {
c := make(chan os.Signal, 3)
signal.Notify(c, syscall.SIGINT, syscall.SIGTERM)
<-c
close(shutdown)
fmt.Fprint(os.Stderr, "SIGINT: shutting down...\n")
<-c
fmt.Fprint(os.Stderr, "SIGINT: shutting down harder...\n")
<-c
fmt.Fprint(os.Stderr, "SIGINT: terminating\n")
os.Exit(int(syscall.SIGINT))
}()
}
func LongPipe() (io.ReadCloser, io.WriteCloser, error) {
r, w, err := os.Pipe()
if err != nil {
return nil, nil, fmt.Errorf("failed to create pipe: %w", err)
}
prolongPipe(r, w)
return r, w, err
}
// Copyright 2025 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package osutil
import (
"archive/tar"
"compress/gzip"
"io"
"io/fs"
"os"
"path/filepath"
"strings"
)
func TarGzDirectory(dir string, writer io.Writer) error {
gzw := gzip.NewWriter(writer)
defer gzw.Close()
return tarDirectory(dir, gzw)
}
func tarDirectory(dir string, writer io.Writer) error {
tw := tar.NewWriter(writer)
defer tw.Close()
return filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error {
if err != nil || path == dir {
return err
}
typ := d.Type()
if !typ.IsDir() && !typ.IsRegular() {
// Only folders and regular files.
return nil
}
relPath, err := filepath.Rel(dir, path)
if err != nil {
return err
}
relPath = filepath.ToSlash(relPath)
info, err := d.Info()
if err != nil {
return err
}
header, err := tar.FileInfoHeader(info, "")
if err != nil {
return err
}
header.Name = relPath
if typ.IsDir() && !strings.HasSuffix(header.Name, "/") {
header.Name += "/"
}
if err := tw.WriteHeader(header); err != nil {
return err
}
if typ.IsDir() {
return nil
}
// Write the file content.
f, err := os.Open(path)
if err != nil {
return err
}
_, err = io.Copy(tw, f)
f.Close()
return err
})
}
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package report
import (
"bytes"
"fmt"
"path/filepath"
"regexp"
"strconv"
"strings"
"github.com/google/syzkaller/pkg/symbolizer"
)
type bsd struct {
*config
oopses []*oops
symbolizeRes []*regexp.Regexp
kernelObject string
symbols map[string][]symbolizer.Symbol
}
func ctorBSD(cfg *config, oopses []*oops, symbolizeRes []*regexp.Regexp) (reporterImpl, error) {
var symbols map[string][]symbolizer.Symbol
kernelObject := ""
if cfg.kernelDirs.Obj != "" {
kernelObject = filepath.Join(cfg.kernelDirs.Obj, cfg.target.KernelObject)
var err error
symbols, err = symbolizer.ReadTextSymbols(kernelObject)
if err != nil {
return nil, err
}
}
ctx := &bsd{
config: cfg,
oopses: oopses,
symbolizeRes: symbolizeRes,
kernelObject: kernelObject,
symbols: symbols,
}
return ctx, nil
}
func (ctx *bsd) ContainsCrash(output []byte) bool {
return containsCrash(output, ctx.oopses, ctx.ignores)
}
func (ctx *bsd) Parse(output []byte) *Report {
return simpleLineParser(output, ctx.oopses, nil, ctx.ignores)
}
func (ctx *bsd) Symbolize(rep *Report) error {
symb := symbolizer.Make(ctx.config.target)
defer symb.Close()
var symbolized []byte
prefix := rep.reportPrefixLen
for _, line := range bytes.SplitAfter(rep.Report, []byte("\n")) {
line := bytes.Clone(line)
newLine := ctx.symbolizeLine(symb.Symbolize, line)
if prefix > len(symbolized) {
prefix += len(newLine) - len(line)
}
symbolized = append(symbolized, newLine...)
}
rep.Report = symbolized
rep.reportPrefixLen = prefix
return nil
}
func (ctx *bsd) symbolizeLine(symbFunc func(string, ...uint64) ([]symbolizer.Frame, error),
line []byte) []byte {
var match []int
// Check whether the line corresponds to the any of the parts that require symbolization.
for _, re := range ctx.symbolizeRes {
match = re.FindSubmatchIndex(line)
if match != nil {
break
}
}
if match == nil {
return line
}
// First part of the matched regex contains the function name.
// Second part contains the offset.
fn := line[match[2]:match[3]]
off, err := strconv.ParseUint(string(line[match[4]:match[5]]), 16, 64)
if err != nil {
return line
}
// Get the symbol from the list of symbols generated using the kernel object and addr2line.
symb := ctx.symbols[string(fn)]
if len(symb) == 0 {
return line
}
fnStart := (0xffffffff << 32) | symb[0].Addr
// Retrieve the frames for the corresponding offset of the function.
frames, err := symbFunc(ctx.kernelObject, fnStart+off)
if err != nil || len(frames) == 0 {
return line
}
var symbolized []byte
// Go through each of the frames and add the corresponding file names and line numbers.
for _, frame := range frames {
file := frame.File
file = strings.TrimPrefix(file, ctx.kernelDirs.BuildSrc)
file = strings.TrimPrefix(file, "/")
info := fmt.Sprintf(" %v:%v", file, frame.Line)
modified := append([]byte{}, line...)
modified = replace(modified, match[5], match[5], []byte(info))
if frame.Inline {
// If frames are marked inline then show that in the report also.
end := match[5] + len(info)
modified = replace(modified, end, end, []byte(" [inline]"))
modified = replace(modified, match[5], match[5], []byte(" "+frame.Func))
}
symbolized = append(symbolized, modified...)
}
return symbolized
}
// Copyright 2023 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package crash
import "slices"
type Type string
const (
UnknownType = Type("")
// keep-sorted start
AtomicSleep = Type("ATOMIC_SLEEP")
Bug = Type("BUG")
DoS = Type("DoS")
Hang = Type("HANG")
KASANInvalidFree = Type("KASAN-INVALID-FREE")
KASANNullPtrDerefRead = Type("KASAN-NULL-POINTER-DEREFERENCE-READ")
KASANNullPtrDerefWrite = Type("KASAN-NULL-POINTER-DEREFERENCE-WRITE")
KASANRead = Type("KASAN-READ")
KASANUnknown = Type("KASAN-UNKNOWN")
KASANUseAfterFreeRead = Type("KASAN-USE-AFTER-FREE-READ")
KASANUseAfterFreeWrite = Type("KASAN-USE-AFTER-FREE-WRITE")
KASANWrite = Type("KASAN-WRITE")
KCSANAssert = Type("KCSAN-ASSERT")
KCSANDataRace = Type("KCSAN-DATARACE")
KCSANUnknown = Type("KCSAN-UNKNOWN")
KFENCEInvalidFree = Type("KFENCE-INVALID-FREE")
KFENCEMemoryCorruption = Type("KFENCE-MEMORY-CORRUPTION")
KFENCERead = Type("KFENCE-READ")
KFENCEUnknown = Type("KFENCE-UNKNOWN")
KFENCEUseAfterFreeRead = Type("KFENCE-USE-AFTER-FREE-READ")
KFENCEUseAfterFreeWrite = Type("KFENCE-USE-AFTER-FREE-WRITE")
KFENCEWrite = Type("KFENCE-WRITE")
KMSANInfoLeak = Type("KMSAN-INFO-LEAK")
KMSANUninitValue = Type("KMSAN-UNINIT-VALUE")
KMSANUnknown = Type("KMSAN-UNKNOWN")
KMSANUseAfterFreeRead = Type("KMSAN-USE-AFTER-FREE-READ")
LockdepBug = Type("LOCKDEP")
MemoryLeak = Type("LEAK")
MemorySafetyBUG = Type("MEMORY_SAFETY_BUG")
MemorySafetyUBSAN = Type("MEMORY_SAFETY_UBSAN")
NullPtrDerefBUG = Type("NULL-POINTER-DEREFERENCE")
RefcountWARNING = Type("REFCOUNT_WARNING")
UBSAN = Type("UBSAN")
Warning = Type("WARNING")
// keep-sorted end
LostConnection = Type("LOST_CONNECTION")
SyzFailure = Type("SYZ_FAILURE")
UnexpectedReboot = Type("REBOOT")
)
func (t Type) String() string {
if t == UnknownType {
return "UNKNOWN"
}
return string(t)
}
type TypeGroupPred func(Type) bool
func (t Type) IsKASAN() bool {
return slices.Contains([]Type{
KASANNullPtrDerefRead, KASANNullPtrDerefWrite, KASANRead, KASANWrite,
KASANUseAfterFreeRead, KASANUseAfterFreeWrite, KASANInvalidFree, KASANUnknown}, t)
}
func (t Type) IsKMSAN() bool {
return slices.Contains([]Type{
KMSANUninitValue, KMSANInfoLeak, KMSANUseAfterFreeRead, KMSANUnknown}, t)
}
func (t Type) IsKCSAN() bool {
return t == KCSANDataRace || t == KCSANAssert || t == KCSANUnknown
}
func (t Type) IsUBSAN() bool {
return t == UBSAN || t == MemorySafetyUBSAN
}
func (t Type) IsBUG() bool {
return slices.Contains([]Type{Bug, MemorySafetyBUG, NullPtrDerefBUG}, t)
}
func (t Type) IsWarning() bool {
return t == Warning || t == RefcountWARNING
}
func (t Type) IsBugOrWarning() bool {
return t.IsBUG() || t.IsWarning()
}
func (t Type) IsMemSafety() bool {
return t == MemorySafetyBUG || t == RefcountWARNING || t == MemorySafetyUBSAN
}
func (t Type) IsMemoryLeak() bool {
return t == MemoryLeak
}
func (t Type) IsLockingBug() bool {
return t.IsLockdep() || t.IsAtomicSleep()
}
func (t Type) IsDoS() bool {
return t == Bug || t == DoS
}
func (t Type) IsHang() bool {
return t == Hang
}
func (t Type) IsLockdep() bool {
return t == LockdepBug
}
func (t Type) IsAtomicSleep() bool {
return t == AtomicSleep
}
// Copyright 2021 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package report
import (
"regexp"
)
func ctorDarwin(cfg *config) (reporterImpl, []string, error) {
symbolizeRes := []*regexp.Regexp{}
ctx, err := ctorBSD(cfg, darwinOopses, symbolizeRes)
return ctx, nil, err
}
var darwinOopses = append([]*oops{
{
[]byte("panic(cpu "),
[]oopsFormat{
{
title: compile("panic\\(.+\\): (assertion failed: .*), file"),
fmt: "panic: %[1]v",
},
{
title: compile("panic\\(.+\\): Kernel trap at 0x[0-9a-f]+, (type .*), registers"),
fmt: "panic: Kernel trap %[1]v",
},
{
title: compile("panic\\(.+\\): \"in6p_route_copyout: wrong or corrupted route:"),
fmt: "panic: in6p_route_copyout: wrong or corrupted route",
},
{
title: compile("panic\\(.+\\): \"(zalloc:.+)\\([0-9]+ elements\\)( .*)\""),
fmt: "panic: %[1]v%[2]v",
},
{
title: compile("panic\\(.+\\): \"(.*)\""),
fmt: "panic: %[1]v",
},
{
title: compile("panic\\(.+\\): (.*)"),
fmt: "panic: %[1]v",
},
},
[]*regexp.Regexp{},
},
{
[]byte("Debugger: Unexpected kernel trap number:"),
[]oopsFormat{
{
title: compile("Debugger: (Unexpected kernel trap number: 0x[0-9a-f]+)"),
fmt: "debugger: %[1]v",
},
},
[]*regexp.Regexp{},
},
&groupGoRuntimeErrors,
}, commonOopses...)
// Copyright 2021 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package report
import (
"bufio"
"bytes"
"fmt"
"os"
"regexp"
"strconv"
"strings"
"time"
"github.com/google/syzkaller/pkg/osutil"
"github.com/google/syzkaller/sys/targets"
)
type DecompilerFlagMask uint64
// Extra flags that control the flow of decompilation.
const (
FlagForceArmThumbMode DecompilerFlagMask = 1 << iota
)
const objdumpCallTimeout = 10 * time.Second
type DecompiledOpcode struct {
Offset int
IsBad bool
Instruction string
FullDescription string
}
// Decompiles a byte array with opcodes into human-readable descriptions.
// Target must specify the environment from which the opcodes were taken.
func DecompileOpcodes(rawOpcodes []byte, flags DecompilerFlagMask, target *targets.Target) ([]DecompiledOpcode, error) {
args, err := objdumpBuildArgs(flags, target)
if err != nil {
return nil, err
}
outBytes, err := objdumpExecutor(rawOpcodes, args, target)
if err != nil {
return nil, err
}
list := objdumpParseOutput(outBytes)
if len(list) == 0 && len(rawOpcodes) > 0 {
return nil, fmt.Errorf("no instructions found while the total size is %v bytes", len(rawOpcodes))
}
return list, nil
}
func objdumpExecutor(rawOpcodes []byte, args []string, target *targets.Target) ([]byte, error) {
fileName, err := osutil.TempFile("syz-opcode-decompiler")
if err != nil {
return nil, fmt.Errorf("failed to create temp file: %w", err)
}
defer os.Remove(fileName)
err = osutil.WriteFile(fileName, rawOpcodes)
if err != nil {
return nil, fmt.Errorf("failed to write to temp file: %w", err)
}
return osutil.RunCmd(objdumpCallTimeout, "", target.Objdump, append(args, fileName)...)
}
// nolint: lll
var objdumpAsmLineRegexp = regexp.MustCompile(`\s+([a-fA-F0-9]+)\:\s+((?:[a-fA-F0-9]{2,8}\s*)*[a-fA-F0-9]{2,8})\s+(.*?)\s*$`)
func objdumpParseOutput(rawOutput []byte) []DecompiledOpcode {
ret := []DecompiledOpcode{}
for s := bufio.NewScanner(bytes.NewReader(rawOutput)); s.Scan(); {
result := objdumpAsmLineRegexp.FindStringSubmatch(string(s.Bytes()))
if result == nil {
continue
}
offset, err := strconv.ParseUint(result[1], 16, 64)
if err != nil {
continue
}
const objdumpBadInstruction = "(bad)"
ret = append(ret, DecompiledOpcode{
Offset: int(offset),
IsBad: result[3] == objdumpBadInstruction,
Instruction: result[3],
FullDescription: strings.TrimRight(result[0], " \t"),
})
}
return ret
}
func objdumpBuildArgs(flags DecompilerFlagMask, target *targets.Target) ([]string, error) {
// objdump won't be able to decompile a raw binary file unless we specify the exact
// architecture through the -m parameter.
ret := []string{"-b", "binary", "-D"}
switch target.Arch {
case targets.ARM64:
ret = append(ret, "-maarch64")
case targets.ARM:
ret = append(ret, "-marm")
if flags&FlagForceArmThumbMode != 0 {
ret = append(ret, "-M", "force-thumb")
}
case targets.I386:
ret = append(ret, "-mi386")
case targets.AMD64:
ret = append(ret, "-mi386", "-Mx86-64")
case targets.MIPS64LE:
ret = append(ret, "-mmips")
case targets.PPC64LE:
ret = append(ret, "-mppc")
case targets.S390x:
ret = append(ret, "-m", "s390:64-bit")
case targets.RiscV64:
ret = append(ret, "-mriscv")
default:
return nil, fmt.Errorf("cannot build objdump args for %#v", target.Arch)
}
return ret, nil
}
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package report
import (
"regexp"
)
type freebsd struct {
*config
}
func ctorFreebsd(cfg *config) (reporterImpl, []string, error) {
ctx := &freebsd{
config: cfg,
}
return ctx, nil, nil
}
func (ctx *freebsd) ContainsCrash(output []byte) bool {
return containsCrash(output, freebsdOopses, ctx.ignores)
}
func (ctx *freebsd) Parse(output []byte) *Report {
return simpleLineParser(output, freebsdOopses, freebsdStackParams, ctx.ignores)
}
func (ctx *freebsd) Symbolize(rep *Report) error {
return nil
}
var freebsdStackParams = &stackParams{}
// nolint: goconst
var freebsdOopses = append([]*oops{
{
[]byte("Fatal trap"),
[]oopsFormat{
{
title: compile("Fatal trap (.+?)\\n(?:.*\\n)+?" +
"KDB: stack backtrace:\\n" +
"(?:#[0-9]+ {{ADDR}} at (?:kdb_backtrace|vpanic|panic|trap_fatal|" +
"trap_pfault|trap|calltrap|m_copydata|__rw_wlock_hard)" +
"\\+{{ADDR}}\\n)*#[0-9]+ {{ADDR}} at {{FUNC}}{{ADDR}}"),
fmt: "Fatal trap %[1]v in %[2]v",
},
{
title: compile("(Fatal trap [0-9]+:.*) while in (?:user|kernel) mode\\n(?:.*\\n)+?" +
"KDB: stack backtrace:\\n" +
"(?:[a-zA-Z0-9_]+\\(\\) at [a-zA-Z0-9_]+\\+0x.*\\n)*" +
"--- trap 0x[0-9a-fA-F]+.* ---\\n" +
"([a-zA-Z0-9_]+)\\(\\) at [a-zA-Z0-9_]+\\+0x.*\\n"),
fmt: "%[1]v in %[2]v",
},
},
[]*regexp.Regexp{},
},
{
[]byte("panic:"),
[]oopsFormat{
{
title: compile("panic: ffs_write: type {{ADDR}} [0-9]+ \\([0-9]+,[0-9]+\\)"),
fmt: "panic: ffs_write: type ADDR X (Y,Z)",
},
{
title: compile("panic: ([a-zA-Z]+[a-zA-Z0-9_]*\\(\\)) of destroyed (mutex|rmlock|rwlock|sx) @ " +
"/.*/(sys/.*:[0-9]+)"),
fmt: "panic: %[1]v of destroyed %[2]v at %[3]v",
},
{
title: compile("panic: No chunks on the queues for sid [0-9]+\\.\\n"),
fmt: "panic: sctp: no chunks on the queues",
},
{
title: compile("panic: size_on_all_streams = [0-9]+ smaller than control length [0-9]+\\n"),
fmt: "panic: size_on_all_streams smaller than control length",
},
{
title: compile("panic: sbflush_internal: ccc [0-9]+ mb [0-9]+ mbcnt [0-9]+\\n"),
fmt: "panic: sbflush_internal: residual data",
},
{
title: compile("(panic: sx lock still held)\\n(?:.*\\n)+?" +
"KDB: stack backtrace:\\n" +
"(?:[a-zA-Z0-9_]+\\(\\) at [a-zA-Z0-9_]+\\+0x.*\\n)*" +
"sx_destroy\\(\\) at [a-zA-Z0-9_+/ ]+\\n" +
"([a-zA-Z0-9_]+)\\(\\) at [a-zA-Z0-9_+/ ]+\\+0x.*\\n"),
fmt: "%[1]v in %[2]v",
},
{
title: compile("panic: pfi_dynaddr_setup: dyn is 0x[0-9a-f]+\\n"),
fmt: "panic: pfi_dynaddr_setup: non-NULL dyn",
},
{
title: compile("(panic: ASan: Invalid access, [0-9]+-byte (?:read|write)) at {{ADDR}},.*\\n(?:.*\\n)+?" +
"KDB: stack backtrace:\\n" +
"(?:[a-zA-Z0-9_]+\\(\\) at [a-zA-Z0-9_]+\\+0x.*\\n)*" +
"__asan_.*\\(\\) at [a-zA-Z0-9_+/ ]+\\n" +
"([a-zA-Z0-9_]+)\\(\\) at [a-zA-Z0-9_+/ ]+\\+0x.*\\n"),
fmt: "%[1]v in %[2]v",
},
},
[]*regexp.Regexp{},
},
&groupGoRuntimeErrors,
}, commonOopses...)
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package report
import (
"bytes"
"fmt"
"path/filepath"
"regexp"
"strconv"
"strings"
"github.com/google/syzkaller/pkg/symbolizer"
"github.com/ianlancetaylor/demangle"
)
type fuchsia struct {
*config
obj string
}
var (
// Ignore these strings when detecting crashes.
fuchsiaIgnores = []*regexp.Regexp{
// Don't generate a crash report for a Rust panic, unless it causes a kernel panic.
regexp.MustCompile(`panic::`),
}
rustBacktrace = regexp.MustCompile(` (stack backtrace:)`)
starnixLinePrefix = regexp.MustCompile(`^\[\d+\.\d+\]`)
zirconRIP = regexp.MustCompile(` RIP: (0x[0-9a-f]+) `)
zirconBT = regexp.MustCompile(`^bt#[0-9]+: (0x[0-9a-f]+)`)
zirconReportEnd = []byte("Halted")
zirconAssertFailed = []byte("ASSERT FAILED at")
zirconLinePrefix = regexp.MustCompile(`^\[\d+\.\d+\] \d+\.\d+> `)
zirconUnrelated = []*regexp.Regexp{
regexp.MustCompile(`^$`),
regexp.MustCompile(`stopping other cpus`),
regexp.MustCompile(`^halting cpu`),
regexp.MustCompile(`^dso: `),
regexp.MustCompile(`^UPTIME: `),
regexp.MustCompile(`^BUILDID `),
regexp.MustCompile(`^Halting\.\.\.`),
}
)
func ctorFuchsia(cfg *config) (reporterImpl, []string, error) {
ctx := &fuchsia{
config: cfg,
}
ctx.ignores = append(ctx.ignores, fuchsiaIgnores...)
if ctx.kernelDirs.Obj != "" {
ctx.obj = filepath.Join(ctx.kernelDirs.Obj, ctx.target.KernelObject)
}
suppressions := []string{
"fatal exception: process /tmp/syz-executor", // OOM presumably
}
return ctx, suppressions, nil
}
func (ctx *fuchsia) ContainsCrash(output []byte) bool {
return containsCrash(output, fuchsiaOopses, ctx.ignores)
}
func (ctx *fuchsia) Parse(output []byte) *Report {
// We symbolize here because zircon output does not contain even function names.
symbolized := ctx.symbolize(output)
rep := simpleLineParser(symbolized, fuchsiaOopses, fuchsiaStackParams, ctx.ignores)
if rep == nil {
return nil
}
rep.Output = output
if report := ctx.shortenReport(rep.Report); len(report) != 0 {
rep.Report = report
}
if strings.HasPrefix(rep.Title, "starnix kernel panic") {
if report := ctx.shortenStarnixPanicReport(rep.Report, 5, 20); len(report) != 0 {
rep.Report = report
}
}
return rep
}
// Captures lines that match one of `starnixFramePatterns`, plus some surrounding lines that may
// or may not be interesting.
//
// Captures up to `maxUnrelatedLines` of consecutive lines that do not start with the usual starnix
// log prefix `starnixLinePrefix` before suppressing unrelated lines. These lines are often
// syzkaller log lines, but are sometimes continuations of newline-containing logs from starnix.
//
// Captures up to `maxUnmatchedLines` of consecutive starnix log lines that do not match one of
// `starnixFramePatterns` before ending the report. These lines (usually in relatively short groups)
// may separate portions of the stack trace.
func (ctx *fuchsia) shortenStarnixPanicReport(report []byte, maxUnrelatedLines, maxUnmatchedLines int) []byte {
out := new(bytes.Buffer)
unrelatedLines := 0
unmatchedLines := 0
for _, line := range lines(report) {
if matchesAny(line, starnixFramePatterns) {
unrelatedLines = 0
unmatchedLines = 0
} else if starnixLinePrefix.FindSubmatch(line) == nil {
unrelatedLines += 1
if unrelatedLines > maxUnrelatedLines {
continue
}
} else {
unmatchedLines += 1
}
out.Write(line)
out.WriteByte('\n')
if unmatchedLines == maxUnmatchedLines {
break
}
}
return append(bytes.TrimRight(out.Bytes(), "\n"), '\n')
}
func (ctx *fuchsia) shortenReport(report []byte) []byte {
out := new(bytes.Buffer)
for _, rawLine := range lines(report) {
line := zirconLinePrefix.ReplaceAll(rawLine, nil)
if matchesAny(line, zirconUnrelated) {
continue
}
if bytes.Contains(line, zirconReportEnd) {
break
}
out.Write(line)
out.WriteByte('\n')
}
return out.Bytes()
}
func (ctx *fuchsia) symbolize(output []byte) []byte {
symb := symbolizer.Make(ctx.config.target)
defer symb.Close()
out := new(bytes.Buffer)
lines := lines(output)
for i := 0; i < len(lines); i++ {
line := lines[i]
if bytes.Contains(line, zirconAssertFailed) && len(line) == 127 {
// This is super hacky: but zircon splits the most important information in long assert lines
// (and they are always long) into several lines in irreversible way. Try to restore full line.
line = append([]byte{}, line...)
if i+1 < len(lines) {
line = append(bytes.Clone(line), lines[i+1]...)
i++
}
}
if ctx.obj != "" {
if match := zirconRIP.FindSubmatchIndex(line); match != nil {
if ctx.processPC(out, symb, line, match, false) {
continue
}
} else if match := zirconBT.FindSubmatchIndex(line); match != nil {
if ctx.processPC(out, symb, line, match, true) {
continue
}
}
}
out.Write(line)
out.WriteByte('\n')
}
return out.Bytes()
}
func (ctx *fuchsia) processPC(out *bytes.Buffer, symb symbolizer.Symbolizer,
line []byte, match []int, call bool) bool {
prefix := line[match[0]:match[1]]
pcStart := match[2] - match[0]
pcEnd := match[3] - match[0]
pcStr := prefix[pcStart:pcEnd]
pc, err := strconv.ParseUint(string(pcStr), 0, 64)
if err != nil {
return false
}
shortPC := pc & 0xfffffff
pc = 0xffffffff80000000 | shortPC
if call {
pc--
}
frames, err := symb.Symbolize(ctx.obj, pc)
if err != nil || len(frames) == 0 {
return false
}
for _, frame := range frames {
file := ctx.trimFile(frame.File)
name := demangle.Filter(frame.Func, demangle.NoParams, demangle.NoTemplateParams)
if strings.Contains(name, "<lambda(") {
// Demangling produces super long (full) names for lambdas.
name = "lambda"
}
id := "[ inline ]"
if !frame.Inline {
id = fmt.Sprintf("0x%08x", shortPC)
}
start := replace(append([]byte{}, prefix...), pcStart, pcEnd, []byte(id))
fmt.Fprintf(out, "%s %v %v:%v\n", start, name, file, frame.Line)
}
return true
}
func (ctx *fuchsia) trimFile(file string) string {
const (
prefix1 = "zircon/kernel/"
prefix2 = "zircon/"
)
if pos := strings.LastIndex(file, prefix1); pos != -1 {
return file[pos+len(prefix1):]
}
if pos := strings.LastIndex(file, prefix2); pos != -1 {
return file[pos+len(prefix2):]
}
return file
}
func (ctx *fuchsia) Symbolize(rep *Report) error {
// We symbolize in Parse because zircon stacktraces don't contain even function names.
return nil
}
var zirconStartRes = []*regexp.Regexp{}
var zirconFramePatterns = []*regexp.Regexp{
compile(` RIP: 0x[0-9a-f]{8} +([a-zA-Z0-9_:~]+)`),
compile(` RIP: \[ inline \] +([a-zA-Z0-9_:~]+)`),
compile(`^bt#[0-9]+: 0x[0-9a-f]{8} +([a-zA-Z0-9_:~]+)`),
compile(`^bt#[0-9]+: \[ inline \] +([a-zA-Z0-9_:~]+)`),
}
var zirconSkipPatterns = []string{
"^platform_halt$",
"^exception_die$",
"^_panic$",
}
var starnixStartRes = []*regexp.Regexp{
rustBacktrace,
}
var starnixFramePatterns = []*regexp.Regexp{
compile(`\s*\[\[\[ELF module #0x[\da-f]+.*(BuildID=[\da-f]{16}) (0x[\da-f]+)\]\]\]`),
compile(`\[[\d.]+\]\[\d+\]\[\d+\]\[.*\]\s*\[\[\[ELF module #0x[\da-f]+.*(BuildID=[\da-f]{16}) (0x[\da-f]+)\]\]\]`),
compile(`\[[\d.]+\]\[\d+\]\[\d+\]\[.*\].*#\d+.*`),
compile(`\s*#\d.*(.+):([\d]+)[\s]+<(.*)>\+(0x[\da-f]+)`),
}
var starnixSkipPatterns = []string{}
var fuchsiaStackParams = &stackParams{
stackStartRes: append(zirconStartRes, starnixStartRes...),
frameRes: append(zirconFramePatterns, starnixFramePatterns...),
skipPatterns: append(zirconSkipPatterns, starnixSkipPatterns...),
}
var zirconOopses = []*oops{
{
[]byte("ZIRCON KERNEL PANIC"),
[]oopsFormat{
{
title: compile("ZIRCON KERNEL PANIC(?:.*\\n)+?.*ASSERT FAILED(?:.*\\n)+?.*bt#00:"),
fmt: "ASSERT FAILED in %[1]v",
stack: &stackFmt{
parts: []*regexp.Regexp{
parseStackTrace,
},
},
},
{
// Some debug asserts don't contain stack trace.
title: compile("ZIRCON KERNEL PANIC(?:.*\\n)+?.*ASSERT FAILED at \\(.+?\\): (.*)"),
fmt: "ASSERT FAILED: %[1]v",
noStackTrace: true,
},
{
title: compile("ZIRCON KERNEL PANIC(?:.*\\n)+?.*double fault, halting(?:.*\\n)+?.*bt#00:"),
fmt: "double fault in %[1]v",
stack: &stackFmt{
parts: []*regexp.Regexp{
parseStackTrace,
},
},
},
{
// Some double faults don't contain stack trace.
title: compile("ZIRCON KERNEL PANIC(?:.*\\n)+?.*double fault, halting"),
fmt: "double fault",
noStackTrace: true,
},
{
title: compile("ZIRCON KERNEL PANIC(?:.*\\n)+?.*Supervisor Page Fault exception, halting"),
fmt: "Supervisor Fault in %[1]v",
stack: &stackFmt{
parts: []*regexp.Regexp{
parseStackTrace,
},
},
},
{
title: compile("ZIRCON KERNEL PANIC(?:.*\\n)+?.*recursion in interrupt handler"),
fmt: "recursion in interrupt handler in %[1]v",
stack: &stackFmt{
parts: []*regexp.Regexp{
parseStackTrace,
},
},
},
{
title: compile("ZIRCON KERNEL PANIC(?:.*\\n)+?.*KVM internal error"),
fmt: "KVM internal error",
noStackTrace: true,
},
{
title: compile("ZIRCON KERNEL PANIC"),
fmt: "KERNEL PANIC in %[1]v",
stack: &stackFmt{
parts: []*regexp.Regexp{
parseStackTrace,
},
},
},
},
[]*regexp.Regexp{},
},
{
[]byte("recursion in interrupt handler"),
[]oopsFormat{
{
title: compile("recursion in interrupt handler(?:.*\\n)+?.*(?:bt#00:|RIP:)"),
fmt: "recursion in interrupt handler in %[1]v",
stack: &stackFmt{
parts: []*regexp.Regexp{
parseStackTrace,
},
},
},
{
title: compile("recursion in interrupt handler"),
fmt: "recursion in interrupt handler",
noStackTrace: true,
},
},
[]*regexp.Regexp{},
},
// We should detect just "stopping other cpus" as some kernel crash rather then as "lost connection",
// but if we add oops for "stopping other cpus", then it will interfere with other formats,
// because "stopping other cpus" usually goes after "ZIRCON KERNEL PANIC", but sometimes before. Mess.
// {
// []byte("stopping other cpus"),
// },
{
[]byte("welcome to Zircon"),
[]oopsFormat{
{
title: compile("welcome to Zircon"),
fmt: "unexpected kernel reboot",
noStackTrace: true,
},
},
[]*regexp.Regexp{},
},
{
[]byte("KVM internal error"),
[]oopsFormat{
{
title: compile("KVM internal error"),
fmt: "KVM internal error",
noStackTrace: true,
},
},
[]*regexp.Regexp{},
},
{
[]byte("<== fatal exception"),
[]oopsFormat{
{
title: compile("<== fatal exception"),
report: compile("<== fatal exception: process ([a-zA-Z0-9_/-]+)"),
fmt: "fatal exception in %[1]v",
noStackTrace: true,
},
},
[]*regexp.Regexp{
compile("<== fatal exception: process .+?syz.+?\\["),
},
},
}
var starnixOopses = []*oops{
{
[]byte("STARNIX KERNEL PANIC"),
[]oopsFormat{
{
title: compile("STARNIX KERNEL PANIC"),
report: compile("STARNIX KERNEL PANIC(?:.|\\n)*info=panicked at [./]*(.*):.*:.*:\\n(.*)\\n"),
fmt: "starnix kernel panic in %[1]v: %[2]v",
stack: &stackFmt{
parts: []*regexp.Regexp{
rustBacktrace,
parseStackTrace,
},
},
},
},
[]*regexp.Regexp{},
},
}
var fuchsiaOopses = append(append(append(zirconOopses, starnixOopses...), commonOopses...), &groupGoRuntimeErrors)
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package report
import (
"fmt"
"github.com/google/syzkaller/pkg/mgrconfig"
"github.com/google/syzkaller/sys/targets"
)
func Fuzz(data []byte) int {
res := 0
for os, reporter := range fuzzReporters {
typ := reporter.typ
containsCrash := reporter.ContainsCrash(data)
rep := reporter.Parse(data)
if containsCrash != (rep != nil) {
panic(fmt.Sprintf("%v: ContainsCrash and Parse disagree", typ))
}
if rep == nil {
continue
}
res = 1
reporter.Symbolize(rep)
if rep.Title == "" {
panic(fmt.Sprintf("%v: Title is empty", typ))
}
if len(rep.Report) == 0 {
panic(fmt.Sprintf("%v: len(Report) == 0", typ))
}
if len(rep.Output) == 0 {
panic(fmt.Sprintf("%v: len(Output) == 0", typ))
}
if os == targets.Fuchsia {
// Fuchsia has Start/End/SkipPos set incorrectly because it symbolizes before parsing.
continue
}
if rep.StartPos != 0 && rep.EndPos != 0 && rep.StartPos >= rep.EndPos {
panic(fmt.Sprintf("%v: bad StartPos\nStartPos=%v >= EndPos=%v",
typ, rep.StartPos, rep.EndPos))
}
if rep.EndPos > len(rep.Output) {
panic(fmt.Sprintf("%v: bad EndPos\nEndPos=%v > len(Output)=%v",
typ, rep.EndPos, len(rep.Output)))
}
if rep.SkipPos <= rep.StartPos || rep.SkipPos > rep.EndPos {
panic(fmt.Sprintf("%v: bad SkipPos\nSkipPos=%v: StartPos=%v EndPos=%v",
typ, rep.SkipPos, rep.StartPos, rep.EndPos))
}
// If we parse from StartPos, we must find the same report.
rep1 := reporter.ParseFrom(data, rep.StartPos)
if rep1 == nil || rep1.Title != rep.Title || rep1.StartPos != rep.StartPos {
title, startPos := "", -1
if rep1 != nil {
title, startPos = rep1.Title, rep1.StartPos
}
panic(fmt.Sprintf("%v: did not find the same reports at StartPos\n"+
"StartPos=%v/%v\nTitle0=%q\nTitle1=%q",
typ, rep.StartPos, startPos, rep.Title, title))
}
}
return res
}
var fuzzReporters = func() map[string]*Reporter {
reporters := make(map[string]*Reporter)
for os := range ctors {
if os == targets.Windows {
continue
}
target := targets.Get(os, targets.AMD64)
if target == nil {
continue
}
cfg := &mgrconfig.Config{
Derived: mgrconfig.Derived{
SysTarget: target,
TargetOS: os,
TargetArch: targets.AMD64,
},
}
reporter, err := NewReporter(cfg)
if err != nil {
panic(err)
}
if _, ok := reporter.impl.(*stub); ok {
continue
}
reporters[os] = reporter
}
return reporters
}()
// Copyright 2018 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package report
import (
"bytes"
"regexp"
)
type gvisor struct {
*config
}
func ctorGvisor(cfg *config) (reporterImpl, []string, error) {
ctx := &gvisor{
config: cfg,
}
suppressions := []string{
"panic: ptrace sysemu failed: no such process", // OOM kill
`panic: ptrace (s|g)et fpregs.* failed: no such process`, // OOM kill
`panic: ptrace (s|g)et regs.* failed: no such process`, // OOM kill
"panic: error initializing first thread: resource temporarily unavailable", // PID exhaustion
"panic: unable to activate mm: creating stub process: resource temporarily unavailable", // PID exhaustion
"panic: executor failed: pthread_create failed", // PID exhaustion
"panic: failed to start executor binary",
"panic: error mapping run data: error mapping runData: cannot allocate memory",
"race: limit on 8128 simultaneously alive goroutines is exceeded, dying",
"ERROR: ThreadSanitizer", // Go race failing due to OOM.
"FATAL: ThreadSanitizer",
"ThreadSanitizer: clock allocator overflow \\(65536\\*1024\\). Dying.",
}
return ctx, suppressions, nil
}
func (ctx *gvisor) ContainsCrash(output []byte) bool {
return containsCrash(output, gvisorOopses, ctx.ignores)
}
func (ctx *gvisor) Parse(output []byte) *Report {
rep := simpleLineParser(output, gvisorOopses, nil, ctx.ignores)
if rep == nil {
return nil
}
rep.Title = replaceTable(gvisorTitleReplacement, rep.Title)
rep.Report = ctx.shortenReport(rep.Report)
return rep
}
func (ctx *gvisor) shortenReport(report []byte) []byte {
// gvisor panics include stacks of all goroutines.
// This output is too lengthy for report and not very useful.
// So we always take 5 lines from report and then cut it at the next empty line.
// The intention is to capture panic header and traceback of the first goroutine.
pos := 0
for i := 0; i < 5; i++ {
pos1 := bytes.IndexByte(report[pos:], '\n')
if pos1 == -1 {
return report
}
pos += pos1 + 1
}
end := bytes.Index(report[pos:], []byte{'\n', '\n'})
if end == -1 {
return report
}
if bytes.Contains(report, []byte("WARNING: DATA RACE")) {
// For data races extract both stacks.
end2 := bytes.Index(report[pos+end+2:], []byte{'\n', '\n'})
if end2 != -1 {
end += end2 + 2
}
}
return report[:pos+end+1]
}
func (ctx *gvisor) Symbolize(rep *Report) error {
return nil
}
var gvisorTitleReplacement = []replacement{
{
regexp.MustCompile(`container ".*"`),
"container NAME",
},
{
regexp.MustCompile(`sandbox ".*"`),
"sandbox NAME",
},
{
regexp.MustCompile(`(pid|PID) [0-9]+`),
"pid X",
},
}
var gvisorOopses = append([]*oops{
{
[]byte("Panic:"),
[]oopsFormat{
{
title: compile("Panic:(.*)"),
fmt: "Panic:%[1]v",
noStackTrace: true,
},
},
[]*regexp.Regexp{},
},
{
[]byte("SIGSEGV:"),
[]oopsFormat{
{
title: compile("SIGSEGV:(.*)"),
fmt: "SIGSEGV:%[1]v",
noStackTrace: true,
},
},
[]*regexp.Regexp{},
},
{
[]byte("SIGBUS:"),
[]oopsFormat{
{
title: compile("SIGBUS:(.*)"),
fmt: "SIGBUS:%[1]v",
noStackTrace: true,
},
},
[]*regexp.Regexp{},
},
{
[]byte("FATAL ERROR:"),
[]oopsFormat{
{
title: compile("FATAL ERROR:(.*)"),
fmt: "FATAL ERROR:%[1]v",
noStackTrace: true,
},
},
[]*regexp.Regexp{},
},
{
[]byte("WARNING: DATA RACE"),
[]oopsFormat{
{
title: compile("WARNING: DATA RACE"),
report: compile("WARNING: DATA RACE\n(?:.*\n)*? (?:[a-zA-Z0-9./_-]+/)([a-zA-Z0-9.()*_]+)\\(\\)\n"),
fmt: "DATA RACE in %[1]v",
noStackTrace: true,
},
},
[]*regexp.Regexp{},
},
{
[]byte("Invalid request partialResult"),
[]oopsFormat{
{
title: compile("Invalid request partialResult"),
report: compile("Invalid request partialResult .* for (.*) operation"),
fmt: "Invalid request partialResult in %[1]v",
noStackTrace: true,
},
},
[]*regexp.Regexp{},
},
{
[]byte("fatal error:"),
[]oopsFormat{
{
title: compile("fatal error:(.*)"),
fmt: "fatal error:%[1]v",
noStackTrace: true,
},
},
[]*regexp.Regexp{},
},
}, commonOopses...)
// Copyright 2025 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package report
import (
"github.com/google/syzkaller/pkg/report/crash"
)
// impactOrder represent an ordering of bug impact severity. The earlier
// entries are considered more severe.
var impactOrder = []crash.Type{
// Highest Priority (Direct Memory Corruption - Write)
crash.KASANUseAfterFreeWrite,
crash.KASANWrite,
// High Priority (Memory Corruption)
crash.KASANInvalidFree,
crash.KFENCEInvalidFree,
crash.KFENCEMemoryCorruption,
crash.KASANUseAfterFreeRead,
crash.KMSANUseAfterFreeRead,
crash.KASANRead,
crash.KFENCERead,
crash.MemorySafetyUBSAN, // array-index-out-of-bounds, at least Read.
crash.KCSANAssert,
crash.RefcountWARNING, // we had a few UAFs in the past
crash.KASANNullPtrDerefWrite,
crash.KASANNullPtrDerefRead,
crash.NullPtrDerefBUG,
// Medium Priority (Infoleaks, Uninitialized Memory, Corruptions)
crash.KMSANInfoLeak,
crash.MemorySafetyBUG,
crash.KMSANUninitValue,
// Medium Priority (Concurrency and Severe Instability)
crash.KCSANDataRace,
crash.AtomicSleep, // high potential for system-wide deadlocks
crash.LockdepBug, // indicates potential deadlocks and hangs
// Lower-Medium Priority (Denial of Service and General Bugs)
crash.MemoryLeak, // a form of DoS
crash.DoS,
crash.Hang,
// Unknown types shouldn't be mentioned here. If bug goes to Unknown it means we need better parsing/processing.
// You can find them at the end of the scored list on the bug enumeration pages.
// crash.KMSANUnknown
// crash.KASANUnknown
// crash.KCSANUnknown
}
// TitlesToImpact converts a bug title(s) to an impact score.
// If several titles provided, it returns the highest score.
// A higher score indicates a more severe impact.
// -1 means unknown.
func TitlesToImpact(title string, otherTitles ...string) int {
maxImpact := -1
for _, t := range append([]string{title}, otherTitles...) {
typ := TitleToCrashType(t)
for i, t := range impactOrder {
if typ == t {
maxImpact = max(maxImpact, len(impactOrder)-i)
}
}
}
return maxImpact
}
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package report
import (
"bytes"
"fmt"
"path/filepath"
"regexp"
"strconv"
"strings"
"time"
"github.com/google/syzkaller/pkg/cover/backend"
"github.com/google/syzkaller/pkg/osutil"
"github.com/google/syzkaller/pkg/report/crash"
"github.com/google/syzkaller/pkg/symbolizer"
"github.com/google/syzkaller/pkg/vcs"
"github.com/google/syzkaller/sys/targets"
"github.com/ianlancetaylor/demangle"
)
type linux struct {
*config
vmlinux string
symbols map[string]map[string][]symbolizer.Symbol
consoleOutputRe *regexp.Regexp
taskContext *regexp.Regexp
cpuContext *regexp.Regexp
questionableFrame *regexp.Regexp
guiltyFileIgnores []*regexp.Regexp
guiltyLineIgnore *regexp.Regexp
reportStartIgnores []*regexp.Regexp
infoMessagesWithStack [][]byte
eoi []byte
symbolizerCache symbolizer.Cache
}
func ctorLinux(cfg *config) (reporterImpl, []string, error) {
symbols := make(map[string]map[string][]symbolizer.Symbol)
vmlinux := ""
if cfg.kernelDirs.Obj != "" {
vmlinux = filepath.Join(cfg.kernelDirs.Obj, cfg.target.KernelObject)
var err error
symbols[""], err = symbolizer.ReadTextSymbols(vmlinux)
if err != nil {
return nil, nil, err
}
for _, mod := range cfg.kernelModules {
if mod.Name == "" {
continue
}
ss, err := symbolizer.ReadTextSymbols(mod.Path)
if err != nil {
continue
}
symbols[mod.Name] = ss
}
}
ctx := &linux{
config: cfg,
vmlinux: vmlinux,
symbols: symbols,
}
// nolint: lll
ctx.consoleOutputRe = regexp.MustCompile(`^(?:\*\* [0-9]+ printk messages dropped \*\* )?(?:.* login: )?(?:\<[0-9]+\>)?\[ *[0-9]+\.[0-9]+\](\[ *(?:C|T)[0-9]+\])? `)
ctx.taskContext = regexp.MustCompile(`\[ *T[0-9]+\]`)
ctx.cpuContext = regexp.MustCompile(`\[ *C[0-9]+\]`)
ctx.questionableFrame = regexp.MustCompile(`(\[\<[0-9a-f]+\>\])? \? `)
ctx.eoi = []byte("<EOI>")
ctx.guiltyFileIgnores = []*regexp.Regexp{
regexp.MustCompile(`.*\.h`),
regexp.MustCompile(`^lib/.*`),
regexp.MustCompile(`^virt/lib/.*`),
regexp.MustCompile(`^mm/kasan/.*`),
regexp.MustCompile(`^mm/kmsan/.*`),
regexp.MustCompile(`^kernel/kcov.c`),
regexp.MustCompile(`^mm/sl.b.c`),
regexp.MustCompile(`^mm/filemap.c`),
regexp.MustCompile(`^mm/folio-compat.c`),
regexp.MustCompile(`^mm/truncate.c`),
regexp.MustCompile(`^mm/memory.c`),
regexp.MustCompile(`^mm/percpu.*`),
regexp.MustCompile(`^mm/vmalloc.c`),
regexp.MustCompile(`^mm/page_alloc.c`),
regexp.MustCompile(`^mm/mempool.c`),
regexp.MustCompile(`^mm/util.c`),
regexp.MustCompile(`^kernel/rcu/.*`),
regexp.MustCompile(`^arch/.*/kernel/traps.c`),
regexp.MustCompile(`^arch/.*/kernel/unwind.*.c`),
regexp.MustCompile(`^arch/.*/mm/fault.c`),
regexp.MustCompile(`^arch/.*/mm/physaddr.c`),
regexp.MustCompile(`^arch/.*/kernel/stacktrace.c`),
regexp.MustCompile(`^arch/.*/kernel/apic/apic.c`),
regexp.MustCompile(`^arch/arm64/kernel/entry.*.c`),
regexp.MustCompile(`^arch/arm64/kernel/process\.c`),
regexp.MustCompile(`^kernel/locking/.*`),
regexp.MustCompile(`^kernel/panic.c`),
regexp.MustCompile(`^kernel/printk/printk.*.c`),
regexp.MustCompile(`^kernel/softirq.c`),
regexp.MustCompile(`^kernel/kthread.c`),
regexp.MustCompile(`^kernel/sched/.*.c`),
regexp.MustCompile(`^kernel/stacktrace.c`),
regexp.MustCompile(`^kernel/time/timer.c`),
regexp.MustCompile(`^kernel/workqueue.c`),
regexp.MustCompile(`^net/core/dev.c`),
regexp.MustCompile(`^net/core/sock.c`),
regexp.MustCompile(`^net/core/skbuff.c`),
regexp.MustCompile(`^fs/proc/generic.c`),
regexp.MustCompile(`^trusty/`), // Trusty sources are not in linux kernel tree.
regexp.MustCompile(`^drivers/usb/core/urb.c`), // WARNING in urb.c usually means a bug in a driver
// Crashes in these files are almost always caused by the calling code.
regexp.MustCompile(`^arch/.*/lib/crc.*`),
}
ctx.guiltyLineIgnore = regexp.MustCompile(`(hardirqs|softirqs)\s+last\s+(enabled|disabled)|^Register r\d+ information`)
// These pattern do _not_ start a new report, i.e. can be in a middle of another report.
ctx.reportStartIgnores = []*regexp.Regexp{
compile(`invalid opcode: 0000`),
compile(`Kernel panic - not syncing`),
compile(`unregister_netdevice: waiting for`),
// Double fault can happen during handling of paging faults
// if memory is badly corrupted. Also it usually happens
// synchronously, which means that maybe the report is not corrupted.
// But of course it can come from another CPU as well.
compile(`PANIC: double fault`),
compile(`Internal error:`),
}
// These pattern math kernel reports which are not bugs in itself but contain stack traces.
// If we see them in the middle of another report, we know that the report is potentially corrupted.
ctx.infoMessagesWithStack = [][]byte{
[]byte("vmalloc: allocation failure:"),
[]byte("FAULT_INJECTION: forcing a failure"),
[]byte("FAULT_FLAG_ALLOW_RETRY missing"),
}
suppressions := []string{
"panic: failed to start executor binary",
"panic: executor failed: pthread_create failed",
"panic: failed to create temp dir",
"fatal error: unexpected signal during runtime execution", // presubmably OOM turned into SIGBUS
"signal SIGBUS: bus error", // presubmably OOM turned into SIGBUS
"SYZFAIL: SIGBUS",
"Out of memory: Kill process .* \\(syz-executor\\)",
"Out of memory: Kill process .* \\(sshd\\)",
"Killed process .* \\(syz-executor\\)",
"Killed process .* \\(sshd\\)",
"lowmemorykiller: Killing 'syz-executor'",
"lowmemorykiller: Killing 'sshd'",
"INIT: PANIC: segmentation violation!",
"\\*\\*\\* stack smashing detected \\*\\*\\*: terminated",
}
return ctx, suppressions, nil
}
const contextConsole = "console"
func (ctx *linux) ContainsCrash(output []byte) bool {
return containsCrash(output, linuxOopses, ctx.ignores)
}
func (ctx *linux) Parse(output []byte) *Report {
oops, startPos, context := ctx.findFirstOops(output)
if oops == nil {
return nil
}
for questionable := false; ; questionable = true {
rep := &Report{
Output: output,
StartPos: startPos,
}
endPos, reportEnd, report, prefix := ctx.findReport(output, oops, startPos, context, questionable)
rep.EndPos = endPos
title, corrupted, altTitles, format := extractDescription(report[:reportEnd], oops, linuxStackParams)
if title == "" {
prefix = nil
report = output[rep.StartPos:rep.EndPos]
title, corrupted, altTitles, format = extractDescription(report, oops, linuxStackParams)
if title == "" {
panic(fmt.Sprintf("non matching oops for %q context=%q in:\n%s\n",
oops.header, context, report))
}
}
rep.Title = title
rep.AltTitles = altTitles
rep.Corrupted = corrupted != ""
rep.CorruptedReason = corrupted
for _, line := range prefix {
rep.Report = append(rep.Report, line...)
rep.Report = append(rep.Report, '\n')
}
rep.reportPrefixLen = len(rep.Report)
rep.Report = append(rep.Report, report...)
rep.Type = TitleToCrashType(rep.Title)
setExecutorInfo(rep)
if !rep.Corrupted {
rep.Corrupted, rep.CorruptedReason = isCorrupted(title, report, format)
}
if rep.CorruptedReason == corruptedNoFrames && context != contextConsole && !questionable {
// We used to look at questionable frame with the following incentive:
// """
// Some crash reports have all frames questionable.
// So if we get a corrupted report because there are no frames,
// try again now looking at questionable frames.
// Only do this if we have a real context (CONFIG_PRINTK_CALLER=y),
// to be on the safer side. Without context it's too easy to use
// a stray frame from a wrong context.
// """
// Most likely reports without proper stack traces were caused by a bug
// in the unwinder and are now fixed in 187b96db5ca7 "x86/unwind/orc:
// Fix unwind_get_return_address_ptr() for inactive tasks".
// Disable trying to use questionable frames for now.
useQuestionableFrames := false
if useQuestionableFrames {
continue
}
}
return rep
}
}
func (ctx *linux) findFirstOops(output []byte) (oops *oops, startPos int, context string) {
for pos, next := 0, 0; pos < len(output); pos = next + 1 {
next = bytes.IndexByte(output[pos:], '\n')
if next != -1 {
next += pos
} else {
next = len(output)
}
line := output[pos:next]
for _, oops1 := range linuxOopses {
if matchOops(line, oops1, ctx.ignores) {
oops = oops1
startPos = pos
context = ctx.extractContext(line)
return
}
}
}
return
}
// This method decides if the report prefix is already long enough to be cut on "Kernel panic - not
// syncing: panic_on_kmsan set ...".
func (ctx *linux) reportMinLines(oopsLine []byte) int {
if bytes.Contains(oopsLine, []byte("BUG: KMSAN:")) {
// KMSAN reports do not have the "Call trace" and some of the other lines which are
// present e.g. in KASAN reports. So we use a lower threshold for them.
return 16
}
return 22
}
// Yes, it is complex, but all state and logic are tightly coupled. It's unclear how to simplify it.
// nolint: gocyclo, gocognit
func (ctx *linux) findReport(output []byte, oops *oops, startPos int, context string, useQuestionable bool) (
endPos, reportEnd int, report []byte, prefix [][]byte) {
// Prepend 5 lines preceding start of the report,
// they can contain additional info related to the report.
maxPrefix := 5
if ctx.taskContext.MatchString(context) {
// If we have CONFIG_PRINTK_CALLER, we collect more b/c it comes from the same task.
maxPrefix = 50
}
secondReportPos := 0
textLines := 0
skipText, cpuTraceback := false, false
oopsLine := []byte{}
for pos, next := 0, 0; pos < len(output); pos = next + 1 {
next = bytes.IndexByte(output[pos:], '\n')
if next != -1 {
next += pos
} else {
next = len(output)
}
line := output[pos:next]
context1 := ctx.extractContext(line)
stripped, questionable := ctx.stripLinePrefix(line, context1, useQuestionable)
if pos < startPos {
if context1 == context && len(stripped) != 0 && !questionable {
prefix = append(prefix, append([]byte{}, stripped...))
if len(prefix) > maxPrefix {
prefix = prefix[1:]
}
}
continue
}
isOopsLine := pos == startPos
if isOopsLine {
oopsLine = line
}
for _, oops1 := range linuxOopses {
if !matchOops(line, oops1, ctx.ignores) {
if !isOopsLine && secondReportPos == 0 {
for _, pattern := range ctx.infoMessagesWithStack {
if bytes.Contains(line, pattern) {
secondReportPos = pos
break
}
}
}
continue
}
endPos = next
if !isOopsLine && secondReportPos == 0 {
if !matchesAny(line, ctx.reportStartIgnores) {
secondReportPos = pos
}
}
}
if !isOopsLine && (questionable ||
context1 != context && (!cpuTraceback || !ctx.cpuContext.MatchString(context1))) {
continue
}
textLines++
skipLine := skipText
if bytes.Contains(line, []byte("Disabling lock debugging due to kernel taint")) {
skipLine = true
} else if bytes.Contains(line, []byte("Sending NMI from CPU")) {
// If we are doing traceback of all CPUs, then we also need to preserve output
// from other CPUs regardless of what is the current context.
// Otherwise we will throw traceback away because it does not match the oops context.
cpuTraceback = true
} else if (bytes.Contains(line, []byte("Kernel panic - not syncing")) ||
bytes.Contains(line, []byte("WARNING: possible circular locking dependency detected"))) &&
textLines > ctx.reportMinLines(oopsLine) {
// If panic_on_warn set, then we frequently have 2 stacks:
// one for the actual report (or maybe even more than one),
// and then one for panic caused by panic_on_warn. This makes
// reports unnecessary long and the panic (current) stack
// is always present in the actual report. So we strip the
// panic message. However, we check that we have enough lines
// before the panic, because sometimes we have, for example,
// a single WARNING line without a stack and then the panic
// with the stack.
// Oops messages frequently induce possible deadlock reports
// because oops reporting introduces unexpected locking chains.
// So if we have enough of the actual oops, strip the deadlock message.
skipText = true
skipLine = true
}
if !isOopsLine && skipLine {
continue
}
report = append(report, stripped...)
report = append(report, '\n')
if secondReportPos == 0 || context != "" && context != contextConsole {
reportEnd = len(report)
}
}
return
}
func (ctx *linux) stripLinePrefix(line []byte, context string, useQuestionable bool) ([]byte, bool) {
if context == "" {
return line, false
}
start := bytes.Index(line, []byte("] "))
line = line[start+2:]
if !bytes.Contains(line, ctx.eoi) {
// x86_64 prefix.
if ctx.questionableFrame.Match(line) {
pos := bytes.Index(line, []byte(" ? "))
return line[pos+2:], !useQuestionable
}
// PowerPC suffix.
if bytes.HasSuffix(line, []byte(" (unreliable)")) {
return line[:len(line)-13], !useQuestionable
}
}
return line, false
}
func (ctx *linux) extractContext(line []byte) string {
match := ctx.consoleOutputRe.FindSubmatchIndex(line)
if match == nil {
return ""
}
if match[2] == -1 {
return contextConsole
}
return string(line[match[2]:match[3]])
}
func (ctx *linux) Symbolize(rep *Report) error {
var symbFunc symbFuncCb
if ctx.vmlinux != "" {
symb := symbolizer.Make(ctx.config.target)
defer symb.Close()
symbFunc = func(bin string, pc uint64) ([]symbolizer.Frame, error) {
return ctx.symbolizerCache.Symbolize(symb.Symbolize, bin, pc)
}
}
if err := ctx.symbolize(rep, symbFunc); err != nil {
return err
}
rep.Report = ctx.decompileOpcodes(rep.Report, rep)
// Skip getting maintainers for Android fuzzing since the kernel source
// directory structure is different.
if ctx.config.vmType == "cuttlefish" || ctx.config.vmType == "proxyapp" {
return nil
}
// We still do this even if we did not symbolize,
// because tests pass in already symbolized input.
rep.GuiltyFile = ctx.extractGuiltyFile(rep)
if rep.GuiltyFile != "" {
maintainers, err := ctx.getMaintainers(rep.GuiltyFile)
if err != nil {
return err
}
rep.Recipients = maintainers
}
return nil
}
type symbFuncCb = func(string, uint64) ([]symbolizer.Frame, error)
func (ctx *linux) symbolize(rep *Report, symbFunc symbFuncCb) error {
var symbolized []byte
prefix := rep.reportPrefixLen
for _, line := range bytes.SplitAfter(rep.Report, []byte("\n")) {
var newLine []byte
parsed, ok := parseLinuxBacktraceLine(line)
if ok {
lines := []linuxBacktraceLine{parsed}
if symbFunc != nil {
lines = symbolizeLine(symbFunc, ctx, parsed)
}
for _, line := range lines {
line.Name = demangle.Filter(line.Name, demangle.NoParams)
newLine = append(newLine, line.Assemble()...)
}
} else {
newLine = line
}
if prefix > len(symbolized) {
prefix += len(newLine) - len(line)
}
symbolized = append(symbolized, newLine...)
}
oldReport := rep.Report
rep.Report = symbolized
oldPrefixLen := rep.reportPrefixLen
rep.reportPrefixLen = prefix
if len(rep.Report) > 0 && rep.reportPrefixLen > len(rep.Report) {
panic(fmt.Sprintf("invalid reportPrefixLen after symbolize: prefix %d -> %d,"+
"report len: %d -> %d, old report: %q",
oldPrefixLen, rep.reportPrefixLen, len(oldReport), len(rep.Report), oldReport,
))
}
return nil
}
type linuxBacktraceLine struct {
// Fields and corresponding indices in the indices array.
Name string // 2:3
Offset uint64 // 4:5
Size uint64 // 6:7
// ... 8:9 is a ModName + its enclosing parentheses.
ModName string // 10:11
BuildID string // 12:13
IsRipFrame bool
// These fields are to be set externally.
Inline bool
FileLine string
// These fields are not to be modified outside of the type's methods.
raw []byte
indices []int
}
func parseLinuxBacktraceLine(line []byte) (info linuxBacktraceLine, ok bool) {
match := linuxSymbolizeRe.FindSubmatchIndex(line)
if match == nil {
return
}
info.raw = line
info.indices = match
info.Name = string(line[match[2]:match[3]])
var err error
info.Offset, err = strconv.ParseUint(string(line[match[4]:match[5]]), 16, 64)
if err != nil {
return
}
info.Size, err = strconv.ParseUint(string(line[match[6]:match[7]]), 16, 64)
if err != nil {
return
}
if match[10] != -1 && match[11] != -1 {
info.ModName = string(line[match[10]:match[11]])
}
if match[12] != -1 && match[13] != -1 {
info.BuildID = string(line[match[12]:match[13]])
}
info.IsRipFrame = linuxRipFrame.Match(line)
return info, true
}
// Note that Assemble() ignores changes to Offset and Size (no reason as these are not updated anywhere).
func (line linuxBacktraceLine) Assemble() []byte {
match := line.indices
modified := append([]byte{}, line.raw...)
if line.BuildID != "" {
modified = replace(modified, match[8], match[9], []byte(" ["+line.ModName+"]"))
}
if line.FileLine != "" {
modified = replace(modified, match[7], match[7], []byte(line.FileLine))
}
if line.Inline {
end := match[7] + len(line.FileLine)
modified = replace(modified, end, end, []byte(" [inline]"))
modified = replace(modified, match[2], match[7], []byte(line.Name))
} else {
modified = replace(modified, match[2], match[3], []byte(line.Name))
}
return modified
}
func symbolizeLine(symbFunc func(bin string, pc uint64) ([]symbolizer.Frame, error), ctx *linux,
parsed linuxBacktraceLine) []linuxBacktraceLine {
symb := ctx.symbols[parsed.ModName][parsed.Name]
if len(symb) == 0 {
return []linuxBacktraceLine{parsed}
}
var funcStart uint64
for _, s := range symb {
if funcStart == 0 || int(parsed.Size) == s.Size {
funcStart = s.Addr
}
}
pc := funcStart + parsed.Offset
if !parsed.IsRipFrame {
// Usually we have return PCs, so we need to look at the previous instruction.
// But RIP lines contain the exact faulting PC.
pc--
}
var bin string
for _, mod := range ctx.config.kernelModules {
if mod.Name == parsed.ModName {
bin = mod.Path
break
}
}
frames, err := symbFunc(bin, pc)
if err != nil || len(frames) == 0 {
return []linuxBacktraceLine{parsed}
}
var ret []linuxBacktraceLine
for _, frame := range frames {
path, _ := backend.CleanPath(frame.File, &ctx.kernelDirs, nil)
copy := parsed
copy.FileLine = fmt.Sprintf(" %v:%v", path, frame.Line)
if frame.Inline {
copy.Inline = true
copy.Name = frame.Func
}
ret = append(ret, copy)
}
return ret
}
type parsedOpcodes struct {
rawBytes []byte
decompileFlags DecompilerFlagMask
offset int
}
type decompiledOpcodes struct {
opcodes []DecompiledOpcode
trappingOpcodeIdx int
leftBytesCut int
}
// processOpcodes converts a string representation of opcodes used by the Linux kernel into
// a sequence of the machine instructions, that surround the one that crashed the kernel.
// If the input does not start on a boundary of an instruction, it is attempted to adjust the
// strting position.
// The method returns an error if it did not manage to correctly decompile the opcodes or
// of the decompiled code is not of interest to the reader (e.g. it is a user-space code).
func (ctx *linux) processOpcodes(codeSlice string) (*decompiledOpcodes, error) {
parsed, err := ctx.parseOpcodes(codeSlice)
if err != nil {
return nil, err
}
decompiled, err := ctx.decompileWithOffset(parsed)
if err != nil {
return nil, err
}
if linuxSkipTrapInstrRe.MatchString(decompiled.opcodes[decompiled.trappingOpcodeIdx].Instruction) {
// For some reports (like WARNINGs) the trapping instruction is an intentionally
// invalid instruction. Decompilation of such code only allows to see the
// mechanism, through which the kernel implements such assertions and does not
// aid in finding the real issue.
return nil, fmt.Errorf("these opcodes are not of interest")
}
return decompiled, nil
}
func (ctx *linux) decompileWithOffset(parsed parsedOpcodes) (*decompiledOpcodes, error) {
// It is not guaranteed that the fragment of opcodes starts exactly at the boundary
// of a machine instruction. In order to simplify debugging process, we are trying
// to find the right starting position.
//
// We iterate over a fixed number of left boundaries. The exact number of iterations
// should strike a balance between the potential usefulness and the extra time needed
// to invoke the decompiler.
const opcodeAdjustmentLimit = 8
var bestResult *decompiledOpcodes
for leftCut := 0; leftCut <= parsed.offset && leftCut < opcodeAdjustmentLimit; leftCut++ {
newBytes := parsed.rawBytes[leftCut:]
newOffset := parsed.offset - leftCut
instructions, err := DecompileOpcodes(newBytes, parsed.decompileFlags, ctx.target)
if err != nil {
return nil, err
}
// We only want to return the response, where there exists a decoded instruction that
// perfectly aligns with the trapping instruction offset.
// At the same time, we'll do out best to find a code listing that does not contain
// unrecognized (bad) instuctions - this serves as an indicator of a valid result.
hasBad := false
trappingIdx := -1
for idx, instruction := range instructions {
if instruction.Offset == newOffset {
trappingIdx = idx
}
if instruction.Offset >= newOffset {
// Do not take into account instructions after the target offset. Once
// decompiler begins to find the right boundary, we cannot improve them.
break
}
hasBad = hasBad || instruction.IsBad
}
if trappingIdx < 0 {
continue
}
if !hasBad || bestResult == nil {
bestResult = &decompiledOpcodes{
opcodes: instructions,
trappingOpcodeIdx: trappingIdx,
leftBytesCut: leftCut,
}
if !hasBad {
// The best offset is already found.
break
}
}
}
if bestResult == nil {
return nil, fmt.Errorf("unable to align decompiled code and the trapping instruction offset")
}
return bestResult, nil
}
func (ctx *linux) parseOpcodes(codeSlice string) (parsedOpcodes, error) {
width := 0
bytes := []byte{}
trapOffset := -1
for _, part := range strings.Split(strings.TrimSpace(codeSlice), " ") {
if part == "" || len(part)%2 != 0 {
return parsedOpcodes{}, fmt.Errorf("invalid opcodes string %#v", part)
}
// Check if this is a marker of a trapping instruction.
if part[0] == '(' || part[0] == '<' {
if trapOffset >= 0 {
return parsedOpcodes{}, fmt.Errorf("invalid opcodes string: multiple trap intructions")
}
trapOffset = len(bytes)
if len(part) < 3 {
return parsedOpcodes{}, fmt.Errorf("invalid opcodes string: invalid trap opcode")
}
part = part[1 : len(part)-1]
}
if width == 0 {
width = len(part) / 2
}
number, err := strconv.ParseUint(part, 16, 64)
if err != nil {
return parsedOpcodes{}, fmt.Errorf("invalid opcodes string: failed to parse %#v", part)
}
extraBytes := make([]byte, width)
switch len(extraBytes) {
case 1:
extraBytes[0] = byte(number)
case 2:
ctx.target.HostEndian.PutUint16(extraBytes, uint16(number))
case 4:
ctx.target.HostEndian.PutUint32(extraBytes, uint32(number))
case 8:
ctx.target.HostEndian.PutUint64(extraBytes, number)
default:
return parsedOpcodes{}, fmt.Errorf("invalid opcodes string: invalid width %v", width)
}
bytes = append(bytes, extraBytes...)
}
if trapOffset < 0 {
return parsedOpcodes{}, fmt.Errorf("invalid opcodes string: no trapping instructions")
}
var flags DecompilerFlagMask
if ctx.target.Arch == targets.ARM && width == 2 {
flags |= FlagForceArmThumbMode
}
return parsedOpcodes{
rawBytes: bytes,
decompileFlags: flags,
offset: trapOffset,
}, nil
}
// decompileOpcodes detects the most meaningful "Code: " lines from the report, decompiles
// them and appends a human-readable listing to the end of the report.
func (ctx *linux) decompileOpcodes(text []byte, report *Report) []byte {
if report.Type == crash.Hang {
// Even though Hang reports do contain the Code: section, there's no point in
// decompiling that. So just return the text.
return text
}
// Iterate over all "Code: " lines and pick the first that could be decompiled
// that might be of interest to the user.
var decompiled *decompiledOpcodes
lines := lines(text)
for i, line := range lines {
var prevLine []byte
if i > 0 {
prevLine = lines[i-1]
}
// We want to avoid decompiling code from user-space as it is not of big interest during
// debugging kernel problems.
// For now this check only works for x86/amd64, but Linux on other architectures supported
// by syzkaller does not seem to include user-space code in its oops messages.
if linuxUserSegmentRe.Match(prevLine) {
continue
}
match := linuxCodeRe.FindSubmatch(line)
if match == nil {
continue
}
decompiledLine, err := ctx.processOpcodes(string(match[1]))
if err != nil {
continue
}
decompiled = decompiledLine
break
}
if decompiled == nil {
return text
}
skipInfo := ""
if decompiled.leftBytesCut > 0 {
skipInfo = fmt.Sprintf(", %v bytes skipped", decompiled.leftBytesCut)
}
// The decompiled instructions are intentionally put to the bottom of the report instead
// being inlined below the corresponding "Code:" line. The intent is to continue to keep
// the most important information at the top of the report, so that it is visible from
// the syzbot dashboard without scrolling.
headLine := fmt.Sprintf("----------------\nCode disassembly (best guess)%v:\n", skipInfo)
text = append(text, headLine...)
for idx, opcode := range decompiled.opcodes {
line := opcode.FullDescription
if idx == decompiled.trappingOpcodeIdx {
line = fmt.Sprintf("*%s <-- trapping instruction\n", line[1:])
} else {
line += "\n"
}
text = append(text, line...)
}
return text
}
func (ctx *linux) extractGuiltyFile(rep *Report) string {
return ctx.extractGuiltyFileRaw(rep.Title, rep.Report[rep.reportPrefixLen:])
}
func (ctx *linux) extractGuiltyFileRaw(title string, report []byte) string {
if strings.HasPrefix(title, "INFO: rcu detected stall") {
// Special case for rcu stalls.
// There are too many frames that we want to skip before actual guilty frames,
// we would need to ignore too many files and that would be fragile.
// So instead we try to extract guilty file starting from the known
// interrupt entry point first.
for _, interruptEnd := range []string{"apic_timer_interrupt+0x",
"el1h_64_irq+0x", "Exception stack"} {
if pos := bytes.Index(report, []byte(interruptEnd)); pos != -1 {
if file := ctx.extractGuiltyFileImpl(report[pos:]); file != "" {
return file
}
}
}
}
return ctx.extractGuiltyFileImpl(report)
}
func (ctx *linux) extractGuiltyFileImpl(report []byte) string {
// Extract the first possible guilty file.
guilty := ""
var line []byte
lines := lines(report)
for len(lines) > 0 {
line, lines = lines[0], lines[1:]
match := filenameRe.FindSubmatch(line)
if match == nil {
continue
}
file := match[1]
if guilty == "" {
// Avoid producing no guilty file at all, otherwise we mail the report to nobody.
// It's unclear if it's better to return the first one or the last one.
// So far the only test we have has only one file anyway.
guilty = string(file)
}
if matchesAny(file, ctx.guiltyFileIgnores) || ctx.guiltyLineIgnore.Match(line) {
continue
}
guilty = filepath.Clean(string(file))
break
}
// Search for deeper filepaths in the stack trace below the first possible guilty file.
deepestPath := filepath.Dir(guilty)
for len(lines) > 0 {
line, lines = lines[0], lines[1:]
match := filenameRe.FindSubmatch(line)
if match == nil {
continue
}
file := match[1]
if matchesAny(file, ctx.guiltyFileIgnores) || ctx.guiltyLineIgnore.Match(line) {
continue
}
clean := filepath.Clean(string(file))
// Check if the new path has *both* the same directory prefix *and* a deeper suffix.
if strings.HasPrefix(clean, deepestPath) {
suffix := strings.TrimPrefix(clean, deepestPath)
if deeperPathRe.Match([]byte(suffix)) {
guilty = clean
deepestPath = filepath.Dir(guilty)
}
}
}
return guilty
}
func (ctx *linux) getMaintainers(file string) (vcs.Recipients, error) {
if ctx.kernelDirs.Src == "" {
return nil, nil
}
return GetLinuxMaintainers(ctx.kernelDirs.Src, file)
}
func GetLinuxMaintainers(kernelSrc, file string) (vcs.Recipients, error) {
mtrs, err := getMaintainersImpl(kernelSrc, file, false)
if err != nil {
return nil, err
}
if len(mtrs) <= 1 {
mtrs, err = getMaintainersImpl(kernelSrc, file, true)
if err != nil {
return nil, err
}
}
return mtrs, nil
}
func getMaintainersImpl(kernelSrc, file string, blame bool) (vcs.Recipients, error) {
// See #1441 re --git-min-percent.
args := []string{"--git-min-percent=15"}
if blame {
args = append(args, "--git-blame")
}
args = append(args, "-f", file)
script := filepath.FromSlash("scripts/get_maintainer.pl")
output, err := osutil.RunCmd(time.Minute, kernelSrc, script, args...)
if err != nil {
return nil, err
}
return vcs.ParseMaintainersLinux(output), nil
}
func isCorrupted(title string, report []byte, format oopsFormat) (bool, string) {
// Check for common title corruptions.
for _, re := range linuxCorruptedTitles {
if re.MatchString(title) {
return true, "title matches corrupted regexp"
}
}
// If the report hasn't matched any of the oops titles, don't mark it as corrupted.
if format.title == nil {
return false, ""
}
if format.noStackTrace {
return false, ""
}
// When a report contains 'Call Trace', 'backtrace', 'Allocated' or 'Freed' keywords,
// it must also contain at least a single stack frame after each of them.
hasStackTrace := false
for _, key := range linuxStackParams.stackStartRes {
match := key.FindSubmatchIndex(report)
if match == nil {
continue
}
frames := lines(report[match[0]:])
if len(frames) < 4 {
return true, "call trace is missed"
}
corrupted := true
frames = frames[1:]
// Check that at least one of the next few lines contains a frame.
outer:
for i := 0; i < 15 && i < len(frames); i++ {
for _, key1 := range linuxStackParams.stackStartRes {
// Next stack trace starts.
if key1.Match(frames[i]) {
break outer
}
}
if bytes.Contains(frames[i], []byte("(stack is not available)")) ||
matchesAny(frames[i], linuxStackParams.frameRes) {
hasStackTrace = true
corrupted = false
break
}
}
if corrupted {
return true, "no frames in a stack trace"
}
}
if !hasStackTrace {
return true, "no stack trace in report"
}
return false, ""
}
var syzLinuxCommRe = regexp.MustCompile(` Comm: syz\.(\d+)\.(\d+) `)
func setExecutorInfo(rep *Report) {
match := syzLinuxCommRe.FindSubmatch(rep.Report)
if match == nil {
return
}
info := &ExecutorInfo{}
var err error
info.ProcID, err = strconv.Atoi(string(match[1]))
if err != nil {
return
}
info.ExecID, err = strconv.Atoi(string(match[2]))
if err != nil {
return
}
rep.Executor = info
}
func linuxStallFrameExtractor(frames []string) (string, int) {
// During rcu stalls and cpu lockups kernel loops in some part of code,
// usually across several functions. When the stall is detected, traceback
// points to a random stack within the looping code. We generally take
// the top function in the stack (with few exceptions) as the bug identity.
// As the result stalls with the same root would produce multiple reports
// in different functions, which is bad.
// Instead we identify a representative function deeper in the stack.
// For most syscalls it can be the syscall entry function (e.g. SyS_timer_create).
// However, for highly discriminated functions syscalls like ioctl/read/write/connect
// we take the previous function (e.g. for connect the one that points to exact
// protocol, or for ioctl the one that is related to the device).
prev, prevIdx := frames[0], 0
for i, frame := range frames {
if matchesAny([]byte(frame), linuxStallAnchorFrames) {
if strings.Contains(frame, "smp_call_function") {
// In this case we want this function rather than the previous one
// (there can be several variations on the next one).
prev = "smp_call_function"
prevIdx = i
}
return prev, prevIdx
}
prev, prevIdx = frame, i
}
return "", -1
}
func linuxHangTaskFrameExtractor(frames []string) (string, int) {
// The problem with task hung reports is that they manifest at random victim stacks,
// rather at the root cause stack. E.g. if there is something wrong with RCU subsystem,
// we are getting hangs all over the kernel on all synchronize_* calls.
// So before resotring to the common logic of skipping some common frames,
// we look for 2 common buckets: hangs on synchronize_rcu and hangs on rtnl_lock
// and group these together.
const synchronizeRCU = "synchronize_rcu"
anchorFrames := map[string]string{
"rtnl_lock": "",
"synchronize_rcu": synchronizeRCU,
"synchronize_srcu": synchronizeRCU,
"synchronize_net": synchronizeRCU,
"synchronize_sched": synchronizeRCU,
}
for i, frame := range frames {
for anchor, replacement := range anchorFrames {
if strings.Contains(frame, anchor) {
if replacement != "" {
frame = replacement
}
return frame, i
}
}
}
skip := []string{"sched", "_lock", "_slowlock", "down", "rwsem", "completion", "kthread",
"wait", "synchronize", "context_switch", "__switch_to", "cancel_delayed_work",
"rcu_barrier"}
nextFrame:
for i, frame := range frames {
for _, ignore := range skip {
if strings.Contains(frame, ignore) {
continue nextFrame
}
}
return frame, i
}
return "", -1
}
var linuxStallAnchorFrames = []*regexp.Regexp{
// Various generic functions that dispatch work.
// We also include some of their callers, so that if some names change
// we don't skip whole stacks and proceed parsing the next one.
compile("process_one_work"), // workqueue callback
compile("do_syscall_"), // syscall entry
compile("do_fast_syscall_"), // syscall entry
compile("sysenter_dispatch"), // syscall entry
compile("tracesys_phase2"), // syscall entry
compile("el0_svc_handler"), // syscall entry
compile("invoke_syscall"), // syscall entry
compile("ret_fast_syscall"), // arm syscall entry
compile("netif_receive_skb"), // net receive entry point
compile("do_softirq"),
compile("call_timer_fn"),
compile("_run_timers"),
compile("run_timer_softirq"),
compile("hrtimer_run"),
compile("run_ksoftirqd"),
compile("smpboot_thread_fn"),
compile("^kthread$"),
compile("start_secondary"),
compile("cpu_startup_entry"),
compile("ret_from_fork"),
// Important discriminated syscalls (file_operations callbacks, etc):
compile("vfs_write"),
compile("vfs_read"),
compile("vfs_iter_read"),
compile("vfs_iter_write"),
compile("do_iter_read"),
compile("do_iter_write"),
compile("call_read_iter"),
compile("call_write_iter"),
compile("new_sync_read"),
compile("new_sync_write"),
compile("vfs_ioctl"),
compile("ksys_ioctl"), // vfs_ioctl may be inlined
compile("compat_ioctl"),
compile("compat_sys_ioctl"),
compile("blkdev_driver_ioctl"),
compile("blkdev_ioctl"),
compile("^call_read_iter"),
compile("^call_write_iter"),
compile("do_iter_readv_writev"),
compile("^call_mmap"),
compile("mmap_region"),
compile("do_mmap"),
compile("do_dentry_open"),
compile("vfs_open"),
// Socket operations:
compile("^sock_sendmsg"),
compile("^sock_recvmsg"),
compile("^sock_release"),
compile("^__sock_release"),
compile("^setsockopt$"),
compile("kernel_setsockopt"),
compile("sock_common_setsockopt"),
compile("^listen$"),
compile("kernel_listen"),
compile("sk_common_release"),
compile("^sock_mmap"),
compile("^accept$"),
compile("kernel_accept"),
compile("^sock_do_ioctl"),
compile("^sock_ioctl"),
compile("^compat_sock_ioctl"),
compile("^nfnetlink_rcv_msg"),
compile("^rtnetlink_rcv_msg"),
compile("^netlink_dump"),
compile("^(sys_)?(socketpair|connect|ioctl)"),
// Page fault entry points:
compile("__do_fault"),
compile("do_page_fault"),
compile("^page_fault$"),
// exit_to_usermode_loop callbacks:
compile("__fput"),
compile("task_work_run"),
compile("exit_to_usermode"),
compile("smp_call_function"),
compile("tasklet_action"),
compile("tasklet_hi_action"),
}
// nolint: lll
var (
linuxSymbolizeRe = regexp.MustCompile(`(?:\[\<(?:(?:0x)?[0-9a-f]+)\>\])?[ \t]+\(?(?:[0-9]+:)?([a-zA-Z0-9_.]+)\+0x([0-9a-f]+)/0x([0-9a-f]+)( ?\[([a-zA-Z0-9_.]+)( .*)?\])?\)?`)
linuxRipFrame = compile(`(?:IP|NIP|pc |PC is at):? (?:(?:[0-9]+:)?(?:{{PC}} +){0,2}{{FUNC}}|(?:[0-9]+:)?0x[0-9a-f]+|(?:[0-9]+:)?{{PC}} +\[< *\(null\)>\] +\(null\)|[0-9]+: +\(null\))`)
linuxCallTrace = compile(`(?:Call (?:T|t)race:)|(?:Backtrace:)`)
linuxCodeRe = regexp.MustCompile(`(?m)^\s*Code\:\s+((?:[A-Fa-f0-9\(\)\<\>]{2,8}\s*)*)\s*$`)
linuxSkipTrapInstrRe = regexp.MustCompile(`^ud2|brk\s+#0x800$`)
linuxUserSegmentRe = regexp.MustCompile(`^RIP:\s+0033:`)
)
var linuxCorruptedTitles = []*regexp.Regexp{
// Sometimes timestamps get merged into the middle of report description.
regexp.MustCompile(`\[ *[0-9]+\.[0-9]+\]`),
}
var linuxStackParams = &stackParams{
stackStartRes: []*regexp.Regexp{
regexp.MustCompile(`Call (?:T|t)race`),
regexp.MustCompile(`Allocated:`),
regexp.MustCompile(`Allocated by task [0-9]+:`),
regexp.MustCompile(`Freed:`),
regexp.MustCompile(`Freed by task [0-9]+:`),
// Match 'backtrace:', but exclude 'stack backtrace:'
regexp.MustCompile(`[^k] backtrace:`),
regexp.MustCompile(`Backtrace:`),
regexp.MustCompile(`Uninit was stored to memory at`),
},
frameRes: []*regexp.Regexp{
compile("^ *(?:{{PC}} ){0,2}{{FUNC}}"),
// Arm is totally different.
// Extract both current and next frames. This is needed for the top
// frame which is present only in LR register which we don't parse.
compile(`^ *{{PC}} \(([a-zA-Z0-9_.]+)\) from {{PC}} \({{FUNC}}`),
},
skipPatterns: []string{
"__sanitizer",
"__asan",
"kasan",
"hwasan",
"__msan",
"kmsan",
"kcsan_setup_watchpoint",
"check_memory_region",
"check_heap_object",
"check_object",
"read_word_at_a_time",
"(read|write)_once_.*nocheck",
"print_address_description",
"panic",
"invalid_op",
"report_bug",
"fixup_bug",
"print_report",
"print_usage_bug",
"do_error",
"invalid_op",
`_trap$|do_trap`,
"show_stack",
"dump_stack",
"walk_stack",
"dump_backtrace",
"warn_slowpath",
"warn_alloc",
"warn_bogus",
"__warn",
"alloc_page",
"k?v?(?:m|z|c)alloc",
"krealloc",
"kmem_cache",
"allocate_slab",
"__alloc_frozen_pages_noprof",
"folio_(?:alloc|unlock)",
"filemap_alloc_folio",
"__filemap_get_folio",
"find_or_create_page",
"do_read_cache_folio",
"read_cache_page",
"pagecache_get_page",
"grab_cache_page_write_begin",
"slab_",
"debug_object",
"timer_is_static_object",
"work_is_static_object",
"__might_fault",
"print_unlock",
"imbalance_bug",
"lockdep",
"bh_enable",
"bh_disable",
"perf_trace",
"lock_acquire",
"lock_release",
"lock_class",
"mark_lock",
"(reacquire|mark)_held_locks",
"raw_spin_rq",
"spin_lock",
"spin_trylock",
"spin_unlock",
"read_lock",
"read_trylock",
"write_lock",
"write_trylock",
"read_unlock",
"write_unlock",
"^down$",
"down_read",
"down_write",
"down_read_trylock",
"down_write_trylock",
"down_trylock",
"up_read",
"up_write",
"^mutex_",
"^__mutex_",
"^rt_mutex_",
"owner_on_cpu",
"osq_lock",
"osq_unlock",
"atomic(64)?_(dec|inc|read|set|or|xor|and|add|sub|fetch|xchg|cmpxchg|try)",
"(set|clear|change|test)_bit",
"__wake_up",
"^refcount_",
"^kref_",
"ref_tracker",
"seqprop_assert",
"memcpy",
"memcmp",
"memset",
"memchr",
"memmove",
"memdup",
"strcmp",
"strncmp",
"strcpy",
"strlcpy",
"strncpy",
"strscpy",
"strlen",
"strstr",
"strnstr",
"strnlen",
"strchr",
"strdup",
"strndup",
"copy_to_user",
"copy_from_user",
"copy_to_iter",
"copy_from_iter",
"copy_page_to_iter",
"copy_page_from_iter",
"copy_folio_to_iter",
"^copyin$",
"^copyout$",
"put_user",
"get_user",
"might_fault",
"might_sleep",
"list_add",
"list_del",
"list_replace",
"list_move",
"list_splice",
"^rb_",
"^__rb_",
"_indirect_thunk_", // retpolines
"string",
"pointer",
"snprintf",
"scnprintf",
"kasprintf",
"kvasprintf",
"printk",
"va_format",
"dev_info",
"dev_notice",
"dev_warn",
"dev_err",
"dev_alert",
"dev_crit",
"dev_emerg",
"program_check_exception",
"program_check_common",
"del_timer",
"flush_work",
"__cancel_work_timer",
"cancel_work_sync",
"try_to_grab_pending",
"flush_workqueue",
"drain_workqueue",
"destroy_workqueue",
"queue_work",
"finish_wait",
"kthread_stop",
"kobject_",
"add_uevent_var",
"get_device_parent",
"device_add",
"device_del",
"device_unregister",
"device_destroy",
"device_release",
"devres_release_all",
"hwrng_unregister",
"i2c_del_adapter",
"__unregister_client",
"device_for_each_child",
"rollback_registered",
"unregister_netdev",
"sysfs_remove",
"device_remove_file",
"tty_unregister_device",
"dummy_urb_enqueue",
"usb_kill_urb",
"usb_kill_anchored_urbs",
"usb_control_msg",
"usb_hcd_submit_urb",
"usb_submit_urb",
"^complete$",
"wait_for_completion",
"^kv?free$",
"kfree_skb",
"readb$",
"readw$",
"readl$",
"readq$",
"writeb$",
"writew$",
"writel$",
"writeq$",
"logic_in",
"logic_out",
"^crc\\d+",
"crc_itu_t",
"__might_resched",
"assertfail",
"^iput$",
"^iput_final$",
"^ihold$",
"hex_dump_to_buffer",
"print_hex_dump",
"^klist_",
"(trace|lockdep)_(hard|soft)irq",
"^(un)?lock_page",
"stack_trace_consume_entry",
"arch_stack_walk",
"stack_trace_save",
"insert_work",
"__queue_delayed_work",
"queue_delayed_work_on",
"ida_free",
// arm64 translation exception handling path.
"do_(kernel|translation)_fault",
"do_mem_abort",
"el1_abort",
"el1h_64_sync(?:_handler)?",
"print_tainted",
"xas_(?:start|load|find)",
"find_lock_entries",
"truncate_inode_pages_range",
"__phys_addr",
"__fortify_report",
"cleanup_srcu_struct",
"rhashtable_lookup",
"extract_(user|iter)_to_sg",
"drop_nlink",
"^get_taint$",
"^put_device$",
"lock_timer_base",
"__timer_delete_sync",
"sk_stop_timer_sync",
"__mod_timer",
},
corruptedLines: []*regexp.Regexp{
// Fault injection stacks are frequently intermixed with crash reports.
// Note: the actual symbol can have all kinds of weird suffixes like ".isra.7", ".cold" or ".isra.56.cold.74".
compile(`^( \[\<?(?:0x)?[0-9a-f]+\>?\])? should_fail(slab)?(\.[a-z0-9.]+)?\+0x`),
},
stripFramePrefixes: []string{
"SYSC_",
"SyS_",
"sys_",
"__x64_",
"__ia32_",
"__arm64_",
"____sys_",
"___sys_",
"__sys_",
"__se_",
"__se_sys_",
"__do_sys_",
"compat_SYSC_",
"compat_SyS_",
"ksys_",
},
}
func warningStackFmt(skip ...string) *stackFmt {
return &stackFmt{
// In newer kernels WARNING traps and actual stack starts after invalid_op frame,
// older kernels just print stack.
parts: []*regexp.Regexp{
// x86_64 warning stack starts with "RIP:" line,
// while powerpc64 starts with "--- interrupt:".
compile("(?:" + linuxRipFrame.String() + "|--- interrupt: [0-9]+ at {{FUNC}})"),
parseStackTrace,
},
parts2: []*regexp.Regexp{
linuxCallTrace,
parseStackTrace,
},
skip: skip,
}
}
// nolint: lll
var linuxOopses = append([]*oops{
{
[]byte("BUG:"),
[]oopsFormat{
{
title: compile("BUG: KASAN:"),
report: compile("BUG: KASAN: ([a-z\\-]+) in {{FUNC}}(?:.*\\n)+?.*(Read|Write) (?:of size|at addr) (?:[0-9a-f]+)"),
fmt: "KASAN: %[1]v %[3]v in %[4]v",
alt: []string{"bad-access in %[4]v"},
stack: &stackFmt{
parts: []*regexp.Regexp{
compile("BUG: KASAN: (?:[a-z\\-]+) in {{FUNC}}"),
linuxCallTrace,
parseStackTrace,
},
// These frames are present in KASAN_HW_TAGS reports.
skip: []string{"kernel_fault", "tag_check", "mem_abort", "^el1_", "^el1h_"},
},
},
{
title: compile("BUG: KASAN:"),
report: compile("BUG: KASAN: (?:double-free or invalid-free|double-free|invalid-free) in {{FUNC}}"),
fmt: "KASAN: invalid-free in %[2]v",
alt: []string{"invalid-free in %[2]v"},
stack: &stackFmt{
parts: []*regexp.Regexp{
compile("BUG: KASAN: (?:double-free or invalid-free|double-free|invalid-free) in {{FUNC}}"),
linuxCallTrace,
parseStackTrace,
},
skip: []string{"slab_", "kfree", "vunmap", "vfree"},
},
},
{
title: compile("BUG: KASAN: ([a-z\\-]+) on address(?:.*\\n)+?.*(Read|Write) of size ([0-9]+)"),
fmt: "KASAN: %[1]v %[2]v",
},
{
title: compile("BUG: KASAN: (.*)"),
fmt: "KASAN: %[1]v",
corrupted: true,
},
{
title: compile("BUG: KMSAN: kernel-usb-infoleak"),
report: compile("BUG: KMSAN: kernel-usb-infoleak in {{FUNC}}"),
fmt: "KMSAN: kernel-usb-infoleak in %[2]v",
alt: []string{"KMSAN origin in %[3]v"},
stack: &stackFmt{
parts: []*regexp.Regexp{
parseStackTrace,
compile("(Local variable .* created at:|Uninit was created at:)"),
parseStackTrace,
},
skip: []string{"alloc_skb", "usb_submit_urb", "usb_start_wait_urb", "usb_bulk_msg", "usb_interrupt_msg", "usb_control_msg"},
},
noStackTrace: true,
},
{
title: compile("BUG: KMSAN:"),
report: compile("BUG: KMSAN: ([a-z\\-]+) in {{FUNC}}"),
fmt: "KMSAN: %[1]v in %[3]v",
alt: []string{
"bad-access in %[3]v",
},
stack: &stackFmt{
parts: []*regexp.Regexp{
parseStackTrace,
compile("(Local variable .* created at:|Uninit was created at:)"),
parseStackTrace,
},
skip: []string{"alloc_skb", "netlink_ack", "netlink_rcv_skb"},
},
noStackTrace: true,
},
{
title: compile("BUG: KCSAN: data-race"),
report: compile("BUG: KCSAN: (.*)"),
fmt: "KCSAN: %[1]v",
noStackTrace: true,
},
{
title: compile("BUG: KCSAN:"),
report: compile("BUG: KCSAN: (.*)"),
fmt: "KCSAN: %[1]v",
noStackTrace: true,
},
{
title: compile("BUG: KFENCE: (use-after-free|out-of-bounds) (read|write) in {{FUNC}}"),
fmt: "KFENCE: %[1]v %[2]v in %[4]v",
alt: []string{"bad-access in %[4]v"},
stack: &stackFmt{
parts: []*regexp.Regexp{
compile("BUG: KFENCE: (?:[a-z\\- ]+) in {{FUNC}}"),
parseStackTrace,
},
},
},
{
title: compile("BUG: KFENCE: invalid free in {{FUNC}}"),
fmt: "KFENCE: invalid free in %[2]v",
alt: []string{"invalid-free in %[2]v"},
noStackTrace: true,
stack: &stackFmt{
parts: []*regexp.Regexp{
compile("BUG: KFENCE: (?:[a-z\\- ]+) in {{FUNC}}"),
parseStackTrace,
},
},
},
{
title: compile("BUG: KFENCE: invalid (read|write) in {{FUNC}}"),
fmt: "KFENCE: invalid %[1]v in %[3]v",
alt: []string{"bad-access in %[3]v"},
stack: &stackFmt{
parts: []*regexp.Regexp{
compile("BUG: KFENCE: (?:[a-z\\- ]+) in {{FUNC}}"),
parseStackTrace,
},
},
},
{
title: compile("BUG: KFENCE: memory corruption in {{FUNC}}"),
fmt: "KFENCE: memory corruption in %[2]v",
noStackTrace: true,
stack: &stackFmt{
parts: []*regexp.Regexp{
compile("BUG: KFENCE: (?:[a-z\\- ]+) in {{FUNC}}"),
parseStackTrace,
},
},
},
{
title: compile("BUG: (?:unable to handle kernel paging request|unable to handle page fault for address|Unable to handle kernel data access)"),
fmt: "BUG: unable to handle kernel paging request in %[1]v",
alt: []string{"bad-access in %[1]v"},
stack: &stackFmt{
parts: []*regexp.Regexp{
linuxRipFrame,
linuxCallTrace,
parseStackTrace,
},
},
},
{
title: compile("BUG: (?:unable to handle kernel NULL pointer dereference|kernel NULL pointer dereference|Kernel NULL pointer dereference)"),
fmt: "BUG: unable to handle kernel NULL pointer dereference in %[1]v",
alt: []string{"bad-access in %[1]v"},
stack: &stackFmt{
parts: []*regexp.Regexp{
linuxRipFrame,
linuxCallTrace,
parseStackTrace,
},
},
},
{
// Sometimes with such BUG failures, the second part of the header doesn't get printed
// or gets corrupted, because kernel prints it as two separate printk() calls.
title: compile("BUG: (?:unable to handle kernel|Unable to handle kernel)"),
fmt: "BUG: unable to handle kernel",
corrupted: true,
},
{
title: compile("BUG: (spinlock|rwlock) (lockup suspected|already unlocked|recursion" +
"|cpu recursion|bad magic|wrong owner|wrong CPU|trylock failure on UP)"),
fmt: "BUG: %[1]v %[2]v in %[3]v",
stack: &stackFmt{
parts: []*regexp.Regexp{
linuxCallTrace,
parseStackTrace,
},
skip: []string{"spin_", "_lock", "_unlock"},
},
},
{
title: compile("BUG: soft lockup"),
fmt: "BUG: soft lockup in %[1]v",
alt: []string{"stall in %[1]v"},
stack: &stackFmt{
parts: []*regexp.Regexp{
linuxRipFrame,
linuxCallTrace,
parseStackTrace,
},
extractor: linuxStallFrameExtractor,
},
},
{
title: compile("BUG: .*still has locks held!"),
report: compile("BUG: .*still has locks held!(?:.*\\n)+?.*{{PC}} +{{FUNC}}"),
fmt: "BUG: still has locks held in %[1]v",
},
{
title: compile("BUG: scheduling while atomic"),
fmt: "BUG: scheduling while atomic in %[1]v",
stack: &stackFmt{
parts: []*regexp.Regexp{
linuxCallTrace,
parseStackTrace,
},
skip: []string{"schedule"},
},
},
{
title: compile("BUG: lock held when returning to user space"),
report: compile("BUG: lock held when returning to user space(?:.*\\n)+?.*leaving the kernel with locks still held(?:.*\\n)+?.*at: (?:{{PC}} +)?{{FUNC}}"),
fmt: "BUG: lock held when returning to user space in %[1]v",
noStackTrace: true,
},
{
title: compile("BUG: bad unlock balance detected!"),
fmt: "BUG: bad unlock balance in %[1]v",
stack: &stackFmt{
parts: []*regexp.Regexp{
compile("{{PC}} +{{FUNC}}"),
linuxCallTrace,
parseStackTrace,
},
},
},
{
title: compile("BUG: held lock freed!"),
report: compile("BUG: held lock freed!(?:.*\\n)+?.*{{PC}} +{{FUNC}}"),
fmt: "BUG: held lock freed in %[1]v",
},
{
title: compile("BUG: Bad rss-counter state"),
fmt: "BUG: Bad rss-counter state",
noStackTrace: true,
},
{
title: compile("BUG: non-zero nr_ptes on freeing mm"),
fmt: "BUG: non-zero nr_ptes on freeing mm",
noStackTrace: true,
},
{
title: compile("BUG: non-zero nr_pmds on freeing mm"),
fmt: "BUG: non-zero nr_pmds on freeing mm",
noStackTrace: true,
},
{
// Kernel includes filesystem type and block device name into the message.
// We used to include them, but block devices are plain harmful (loop0/1/2),
// and filesystem type also leads to duplicates. So now we exclude them.
title: compile("BUG: Dentry .* still in use"),
report: compile("BUG: Dentry .* still in use \\([0-9]+\\) \\[(unmount) of ([^\\]]+)\\]"),
fmt: "BUG: Dentry still in use in %[1]v",
alt: []string{"BUG: Dentry still in use [%[1]v of %[2]v]"},
},
{
title: compile("BUG: Bad page (state|cache)"),
fmt: "BUG: Bad page %[1]v in %[2]v",
stack: &stackFmt{
// TODO: on arm64, for some reason we don't see the page origin backtrace.
// We see the stack trace where the bug was detected, but we consider it to be
// not sufficient to reliably group crashes.
// So Bad page reports on arm64 for now will end up marked as corrupted.
parts: []*regexp.Regexp{
compile(`page last allocated`),
parseStackTrace,
},
skip: []string{"(free|put|get|update|release)_page",
"free_unref", "^_*folio", "truncate_inode_pages",
"page_frag_free", "alloc", "vmap", "page_owner"},
},
},
{
title: compile("BUG: Bad page map"),
fmt: "BUG: Bad page map",
},
{
title: compile("BUG: workqueue lockup"),
fmt: "BUG: workqueue lockup",
noStackTrace: true,
},
{
title: compile("BUG: sleeping function called from invalid context at (.*)"),
fmt: "BUG: sleeping function called from invalid context in %[2]v",
stack: &stackFmt{
parts: []*regexp.Regexp{
linuxCallTrace,
parseStackTrace,
},
},
},
{
title: compile("BUG: using ([a-z_]+)\\(\\) in preemptible"),
fmt: "BUG: using %[1]v() in preemptible code in %[2]v",
stack: &stackFmt{
parts: []*regexp.Regexp{
linuxCallTrace,
parseStackTrace,
},
skip: []string{"dump_stack", "preemption", "preempt", "debug_",
"processor_id", "this_cpu"},
},
},
{
title: compile("BUG: workqueue leaked lock or atomic"),
report: compile("BUG: workqueue leaked lock or atomic(?:.*\\n)+?" +
".*last function: ([a-zA-Z0-9_]+)\\n"),
fmt: "BUG: workqueue leaked lock or atomic in %[1]v",
noStackTrace: true,
},
{
title: compile("BUG: memory leak"),
fmt: "memory leak in %[1]v",
stack: &stackFmt{
parts: []*regexp.Regexp{
compile("backtrace:"),
parseStackTrace,
},
skip: []string{"kmemleak", "mmap", "kmem", "slab", "alloc", "create_object",
"idr_get", "list_lru_init", "kasprintf", "kvasprintf",
"pcpu_create", "strdup", "strndup", "memdup"},
},
},
{
title: compile("BUG: .*stack guard page was hit at"),
fmt: "BUG: stack guard page was hit in %[1]v",
alt: []string{"stack-overflow in %[1]v"},
stack: &stackFmt{
parts: []*regexp.Regexp{
linuxRipFrame,
linuxCallTrace,
parseStackTrace,
},
extractor: linuxStallFrameExtractor,
},
},
{
title: compile("BUG: Invalid wait context"),
// Somehow amd64 and arm/arm64 report this bug completely differently.
// This is arm/arm64 format, but we match amd64 title to not duplicate bug reports.
fmt: "WARNING: locking bug in %[1]v",
stack: &stackFmt{
parts: []*regexp.Regexp{
linuxCallTrace,
parseStackTrace,
},
skip: []string{"lock_sock", "release_sock"},
},
},
{
title: compile(`BUG:[[:space:]]*(?:\n|$)`),
fmt: "BUG: corrupted",
corrupted: true,
},
},
[]*regexp.Regexp{
// CONFIG_DEBUG_OBJECTS output.
compile("ODEBUG:"),
// Android prints this sometimes during boot.
compile("Boot_DEBUG:"),
compile("xlog_status:"),
// Android ART debug output.
compile("DEBUG:"),
// pkg/host output in debug mode.
compile("BUG: no syscalls can create resource"),
},
},
{
[]byte("WARNING:"),
[]oopsFormat{
{
title: compile("WARNING: .*lib/debugobjects\\.c.* (?:debug_print|debug_check)"),
fmt: "WARNING: ODEBUG bug in %[1]v",
// Skip all users of ODEBUG as well.
stack: warningStackFmt("debug_", "rcu", "hrtimer_", "timer_",
"work_", "percpu_", "vunmap",
"vfree", "__free_", "debug_check", "kobject_"),
},
{
title: compile("WARNING: .*mm/usercopy\\.c.* usercopy_warn"),
fmt: "WARNING: bad usercopy in %[1]v",
stack: warningStackFmt("usercopy", "__check"),
},
{
title: compile("WARNING: .*lib/kobject\\.c.* kobject_"),
fmt: "WARNING: kobject bug in %[1]v",
stack: warningStackFmt("kobject_"),
},
{
title: compile("WARNING: .*fs/proc/generic\\.c.* proc_register"),
fmt: "WARNING: proc registration bug in %[1]v",
stack: warningStackFmt("proc_"),
},
{
title: compile("WARNING: .*lib/refcount\\.c.* refcount_"),
fmt: "WARNING: refcount bug in %[1]v",
stack: warningStackFmt("refcount", "kobject_"),
},
{
title: compile("WARNING: .*kernel/locking/lockdep\\.c.*lock_"),
fmt: "WARNING: locking bug in %[1]v",
stack: warningStackFmt("lock_sock", "release_sock"),
},
{
title: compile("WARNING: .*still has locks held!"),
report: compile("WARNING: .*still has locks held!(?:.*\\n)+?.*at: {{FUNC}}"),
fmt: "WARNING: still has locks held in %[1]v",
},
{
title: compile("WARNING: Nested lock was not taken"),
fmt: "WARNING: nested lock was not taken in %[1]v",
stack: warningStackFmt(),
},
{
title: compile("WARNING: lock held when returning to user space"),
report: compile("WARNING: lock held when returning to user space(?:.*\\n)+?.*leaving the kernel with locks still held(?:.*\\n)+?.*at: (?:{{PC}} +)?{{FUNC}}"),
fmt: "WARNING: lock held when returning to user space in %[1]v",
noStackTrace: true,
},
{
title: compile("WARNING: .*mm/.*\\.c.* k?.?malloc"),
fmt: "WARNING: kmalloc bug in %[1]v",
stack: warningStackFmt("kmalloc", "krealloc", "slab", "kmem"),
},
{
title: compile("WARNING: .*mm/vmalloc.c.*__vmalloc_node"),
fmt: "WARNING: zero-size vmalloc in %[1]v",
stack: warningStackFmt(),
},
{
title: compile("WARNING: .* usb_submit_urb"),
fmt: "WARNING in %[1]v/usb_submit_urb",
stack: warningStackFmt("usb_submit_urb", "usb_start_wait_urb", "usb_bulk_msg", "usb_interrupt_msg", "usb_control_msg"),
},
{
title: compile("WARNING: .* at {{SRC}} {{FUNC}}"),
fmt: "WARNING in %[3]v",
stack: warningStackFmt(),
},
{
title: compile("WARNING: {{SRC}} at {{FUNC}}"),
fmt: "WARNING in %[3]v",
stack: warningStackFmt(),
},
{
title: compile("WARNING: possible circular locking dependency detected"),
report: compile("WARNING: possible circular locking dependency detected(?:.*\\n)+?.*is trying to acquire lock"),
fmt: "possible deadlock in %[1]v",
stack: &stackFmt{
parts: []*regexp.Regexp{
compile("at: (?:{{PC}} +)?{{FUNC}}"),
compile("at: (?:{{PC}} +)?{{FUNC}}"),
parseStackTrace,
},
// These workqueue functions take locks associated with work items.
// All deadlocks observed in these functions are
// work-item-subsystem-related.
skip: []string{"process_one_work", "flush_workqueue",
"drain_workqueue", "destroy_workqueue"},
},
},
{
title: compile("WARNING: possible irq lock inversion dependency detected"),
report: compile("WARNING: possible irq lock inversion dependency detected(?:.*\\n)+?.*just changed the state of lock(?:.*\\n)+?.*at: (?:{{PC}} +)?{{FUNC}}"),
fmt: "possible deadlock in %[1]v",
},
{
title: compile("WARNING: .*-safe -> .*-unsafe lock order detected"),
fmt: "possible deadlock in %[1]v",
stack: &stackFmt{
parts: []*regexp.Regexp{
compile("which became (?:.*) at:"),
parseStackTrace,
},
},
},
{
title: compile("WARNING: possible recursive locking detected"),
report: compile("WARNING: possible recursive locking detected(?:.*\\n)+?.*is trying to acquire lock(?:.*\\n)+?.*at: (?:{{PC}} +)?{{FUNC}}"),
fmt: "possible deadlock in %[1]v",
},
{
title: compile("WARNING: inconsistent lock state"),
report: compile("WARNING: inconsistent lock state(?:.*\\n)+?.*takes(?:.*\\n)+?.*at: (?:{{PC}} +)?{{FUNC}}"),
fmt: "inconsistent lock state in %[2]v",
stack: &stackFmt{
parts: []*regexp.Regexp{
linuxCallTrace,
parseStackTrace,
},
},
},
{
title: compile("WARNING: suspicious RCU usage"),
report: compile("WARNING: suspicious RCU usage(?:.*\n)+?.*?{{SRC}}"),
fmt: "WARNING: suspicious RCU usage in %[2]v",
stack: &stackFmt{
parts: []*regexp.Regexp{
linuxCallTrace,
parseStackTrace,
},
skip: []string{"rcu", "kmem", "slab"},
},
},
{
title: compile("WARNING: kernel stack regs at [0-9a-f]+ in [^ ]* has bad '([^']+)' value"),
fmt: "WARNING: kernel stack regs has bad '%[1]v' value",
noStackTrace: true,
},
{
title: compile("WARNING: kernel stack frame pointer at [0-9a-f]+ in [^ ]* has bad value"),
fmt: "WARNING: kernel stack frame pointer has bad value",
noStackTrace: true,
},
{
title: compile("WARNING: bad unlock balance detected!"),
fmt: "WARNING: bad unlock balance in %[1]v",
stack: &stackFmt{
parts: []*regexp.Regexp{
compile("{{PC}} +{{FUNC}}"),
linuxCallTrace,
parseStackTrace,
},
},
},
{
title: compile("WARNING: held lock freed!"),
report: compile("WARNING: held lock freed!(?:.*\\n)+?.*at:(?: {{PC}})? +{{FUNC}}"),
fmt: "WARNING: held lock freed in %[1]v",
},
{
title: compile("WARNING: kernel stack regs .* has bad 'bp' value"),
fmt: "WARNING: kernel stack regs has bad value",
noStackTrace: true,
},
{
title: compile("WARNING: kernel stack frame pointer .* has bad value"),
fmt: "WARNING: kernel stack regs has bad value",
noStackTrace: true,
},
{
title: compile(`WARNING:[[:space:]]*(?:\n|$)`),
fmt: "WARNING: corrupted",
corrupted: true,
},
},
[]*regexp.Regexp{
compile("WARNING: /etc/ssh/moduli does not exist, using fixed modulus"), // printed by sshd
compile("WARNING: workqueue cpumask: online intersect > possible intersect"),
compile("WARNING: [Tt]he mand mount option"),
compile("WARNING: Unsupported flag value\\(s\\) of 0x%x in DT_FLAGS_1"), // printed when glibc is dumped
compile("WARNING: Unprivileged eBPF is enabled with eIBRS"),
compile(`WARNING: fbcon: Driver '(.*)' missed to adjust virtual screen size (\((?:\d+)x(?:\d+) vs\. (?:\d+)x(?:\d+)\))`),
compile(`WARNING: See https.* for mitigation options.`),
compile(`WARNING: kernel not compiled with CPU_SRSO`),
compile(`EXT4-[Ff][Ss](?: \(.*\))?:`), // printed in __ext4_msg
compile(`(?i)warning: .* uses (deprecated v2 capabilities|wireless extensions)`),
compile(`XFS \(\w+\): WARNING`),
},
},
{
[]byte("INFO:"),
[]oopsFormat{
{
title: compile("INFO: possible circular locking dependency detected"),
report: compile("INFO: possible circular locking dependency detected \\](?:.*\\n)+?.*is trying to acquire lock(?:.*\\n)+?.*at: {{PC}} +{{FUNC}}"),
fmt: "possible deadlock in %[1]v",
},
{
title: compile("INFO: possible irq lock inversion dependency detected"),
report: compile("INFO: possible irq lock inversion dependency detected \\](?:.*\\n)+?.*just changed the state of lock(?:.*\\n)+?.*at: {{PC}} +{{FUNC}}"),
fmt: "possible deadlock in %[1]v",
},
{
title: compile("INFO: SOFTIRQ-safe -> SOFTIRQ-unsafe lock order detected"),
report: compile("INFO: SOFTIRQ-safe -> SOFTIRQ-unsafe lock order detected \\](?:.*\\n)+?.*is trying to acquire(?:.*\\n)+?.*at: {{PC}} +{{FUNC}}"),
fmt: "possible deadlock in %[1]v",
},
{
title: compile("INFO: possible recursive locking detected"),
report: compile("INFO: possible recursive locking detected \\](?:.*\\n)+?.*is trying to acquire lock(?:.*\\n)+?.*at: {{PC}} +{{FUNC}}"),
fmt: "possible deadlock in %[1]v",
},
{
title: compile("INFO: inconsistent lock state"),
report: compile("INFO: inconsistent lock state \\](?:.*\\n)+?.*takes(?:.*\\n)+?.*at: {{PC}} +{{FUNC}}"),
fmt: "inconsistent lock state in %[1]v",
},
{
title: compile("INFO: rcu_(?:preempt|sched|bh) (?:self-)?detected(?: expedited)? stall"),
fmt: "INFO: rcu detected stall in %[1]v",
alt: []string{"stall in %[1]v"},
stack: &stackFmt{
parts: []*regexp.Regexp{
compile("apic_timer_interrupt"),
linuxRipFrame,
parseStackTrace,
},
parts2: []*regexp.Regexp{
compile("(?:apic_timer_interrupt|Exception stack|el1h_64_irq)"),
parseStackTrace,
},
skip: []string{"apic_timer_interrupt", "rcu"},
extractor: linuxStallFrameExtractor,
},
},
{
title: compile("INFO: trying to register non-static key"),
fmt: "INFO: trying to register non-static key in %[1]v",
stack: &stackFmt{
parts: []*regexp.Regexp{
linuxCallTrace,
parseStackTrace,
},
skip: []string{"stack", "lock", "IRQ"},
},
},
{
title: compile("INFO: suspicious RCU usage"),
report: compile("INFO: suspicious RCU usage(?:.*\n)+?.*?{{SRC}}"),
fmt: "INFO: suspicious RCU usage in %[2]v",
stack: &stackFmt{
parts: []*regexp.Regexp{
linuxCallTrace,
parseStackTrace,
},
skip: []string{"rcu", "kmem", "slab"},
},
},
{
title: compile("INFO: task .* blocked for more than [0-9]+ seconds"),
fmt: "INFO: task hung in %[1]v",
alt: []string{"hang in %[1]v"},
stack: &stackFmt{
parts: []*regexp.Regexp{
linuxCallTrace,
parseStackTrace,
},
extractor: linuxHangTaskFrameExtractor,
},
},
{
title: compile("INFO: task .* can't die for more than .* seconds"),
fmt: "INFO: task can't die in %[1]v",
alt: []string{"hang in %[1]v"},
stack: &stackFmt{
parts: []*regexp.Regexp{
linuxCallTrace,
parseStackTrace,
},
skip: []string{"schedule"},
},
},
{
// This gets captured for corrupted old-style KASAN reports.
title: compile("INFO: (Freed|Allocated) in (.*)"),
fmt: "INFO: %[1]v in %[2]v",
corrupted: true,
},
{
title: compile(`INFO:[[:space:]]*(?:\n|$)`),
fmt: "INFO: corrupted",
corrupted: true,
},
},
[]*regexp.Regexp{
compile("INFO: lockdep is turned off"),
compile("INFO: Stall ended before state dump start"),
compile("INFO: NMI handler"),
compile("INFO: recovery required on readonly filesystem"),
compile("(handler|interrupt).*took too long"),
compile("INFO: sys_.* is not present in /proc/kallsyms"), // pkg/host output in debug mode
compile("INFO: no syscalls can create resource"), // pkg/host output in debug mode
compile("rmt_storage:INFO:"), // Android prints this.
compile("_INFO:"), // To filter out "INVALID BTF_INFO:NUM".
},
},
{
[]byte("Unable to handle kernel"),
[]oopsFormat{
{
title: compile("Unable to handle kernel (paging request|NULL pointer dereference|access to user memory)"),
fmt: "BUG: unable to handle kernel %[1]v in %[2]v",
alt: []string{"bad-access in %[2]v"},
stack: &stackFmt{
parts: []*regexp.Regexp{
linuxRipFrame,
linuxCallTrace,
parseStackTrace,
},
},
},
},
[]*regexp.Regexp{},
},
{
[]byte("general protection fault"),
[]oopsFormat{
{
title: compile("general protection fault.*:"),
fmt: "general protection fault in %[1]v",
alt: []string{"bad-access in %[1]v"},
stack: &stackFmt{
parts: []*regexp.Regexp{
linuxRipFrame,
linuxCallTrace,
parseStackTrace,
},
},
},
},
[]*regexp.Regexp{
compile(`general protection fault .* error:\d+ in `),
},
},
{
[]byte("stack segment: "),
[]oopsFormat{
{
title: compile("stack segment: "),
fmt: "stack segment fault in %[1]v",
stack: &stackFmt{
parts: []*regexp.Regexp{
linuxRipFrame,
linuxCallTrace,
parseStackTrace,
},
},
},
},
[]*regexp.Regexp{},
},
{
[]byte("Kernel panic"),
[]oopsFormat{
// Note: for stack corruption reports kernel may fail
// to print function symbol name and/or unwind stack.
{
title: compile("Kernel panic - not syncing: stack-protector:"),
report: compile("Kernel panic - not syncing: stack-protector: Kernel stack is corrupted in: {{FUNC}}"),
fmt: "kernel panic: stack is corrupted in %[1]v",
noStackTrace: true,
},
{
title: compile("Kernel panic - not syncing: stack-protector:"),
report: compile("Kernel panic - not syncing: stack-protector: Kernel stack is corrupted in: [a-f0-9]+"),
fmt: "kernel panic: stack is corrupted in %[1]v",
stack: &stackFmt{
parts: []*regexp.Regexp{
linuxCallTrace,
parseStackTrace,
},
skip: []string{"stack_chk"},
},
},
{
title: compile("Kernel panic - not syncing: corrupted stack end"),
report: compile("Kernel panic - not syncing: corrupted stack end detected inside scheduler"),
fmt: "kernel panic: corrupted stack end in %[1]v",
alt: []string{"stack-overflow in %[1]v"},
stack: &stackFmt{
parts: []*regexp.Regexp{
linuxCallTrace,
parseStackTrace,
},
skip: []string{"schedule", "retint_kernel"},
extractor: linuxStallFrameExtractor,
},
},
{
title: compile("Kernel panic - not syncing: kernel stack overflow"),
fmt: "kernel stack overflow in %[1]v",
alt: []string{"stack-overflow in %[1]v"},
stack: &stackFmt{
parts: []*regexp.Regexp{
linuxCallTrace,
parseStackTrace,
},
skip: []string{"bad_stack"},
extractor: linuxStallFrameExtractor,
},
},
{
title: compile("Kernel panic - not syncing: Attempted to kill init!"),
fmt: "kernel panic: Attempted to kill init!",
},
{
title: compile("Kernel panic - not syncing: Couldn't open N_TTY ldisc for [^ ]+ --- error -[0-9]+"),
fmt: "kernel panic: Couldn't open N_TTY ldisc",
},
{
// 'kernel panic: Fatal exception' is usually printed after BUG,
// so if we captured it as a report description, that means the
// report got truncated and we missed the actual BUG header.
title: compile("Kernel panic - not syncing: Fatal exception"),
fmt: "kernel panic: Fatal exception",
corrupted: true,
},
{
// Same, but for WARNINGs and KASAN reports.
title: compile("Kernel panic - not syncing: panic_on_warn set"),
fmt: "kernel panic: panic_on_warn set",
corrupted: true,
},
{
// Same, but for task hung reports.
title: compile("Kernel panic - not syncing: hung_task: blocked tasks"),
fmt: "kernel panic: hung_task: blocked tasks",
corrupted: true,
},
{
title: compile("Kernel panic - not syncing: (.*)"),
fmt: "kernel panic: %[1]v",
},
},
[]*regexp.Regexp{},
},
{
[]byte("PANIC: double fault"),
[]oopsFormat{
{
title: compile("PANIC: double fault"),
fmt: "PANIC: double fault in %[1]v",
stack: &stackFmt{
parts: []*regexp.Regexp{
linuxRipFrame,
},
},
},
},
[]*regexp.Regexp{},
},
{
[]byte("rust_kernel: panicked"),
[]oopsFormat{
{
title: compile("rust_kernel: panicked"),
report: compile("rust_kernel: panicked at [^\n]*?\n(.+?)\n"),
fmt: "%[1]v in %[2]v",
stack: &stackFmt{
parts: []*regexp.Regexp{
linuxCallTrace,
parseStackTrace,
},
skip: []string{
regexp.QuoteMeta(`__rustc::rust_begin_unwind`),
},
},
},
},
[]*regexp.Regexp{},
},
{
[]byte("kernel BUG"),
[]oopsFormat{
{
title: compile("kernel BUG at mm/usercopy.c"),
fmt: "BUG: bad usercopy in %[1]v",
stack: &stackFmt{
parts: []*regexp.Regexp{
linuxCallTrace,
parseStackTrace,
},
skip: []string{"usercopy", "__check"},
},
},
{
title: compile("kernel BUG at lib/list_debug.c"),
fmt: "BUG: corrupted list in %[1]v",
alt: []string{"bad-access in %[1]v"}, // also sometimes due to memory corruption/race
stack: &stackFmt{
parts: []*regexp.Regexp{
linuxCallTrace,
parseStackTrace,
},
},
},
{
title: compile("kernel BUG at (.*)"),
fmt: "kernel BUG in %[2]v",
stack: &stackFmt{
parts: []*regexp.Regexp{
linuxRipFrame,
linuxCallTrace,
parseStackTrace,
},
// Lots of skb wrappers contain BUG_ON, but the bug is almost always in the caller.
skip: []string{"^skb_"},
},
},
},
[]*regexp.Regexp{},
},
{
[]byte("Kernel BUG"),
[]oopsFormat{
{
title: compile("Kernel BUG (.*)"),
fmt: "kernel BUG %[1]v",
},
},
[]*regexp.Regexp{},
},
{
[]byte("BUG kmalloc-"),
[]oopsFormat{
{
title: compile("BUG kmalloc-.*: Object already free"),
fmt: "BUG: Object already free",
},
},
[]*regexp.Regexp{},
},
{
[]byte("divide error:"),
[]oopsFormat{
{
title: compile("divide error: "),
fmt: "divide error in %[1]v",
stack: &stackFmt{
parts: []*regexp.Regexp{
linuxRipFrame,
},
},
},
},
[]*regexp.Regexp{},
},
{
// A misspelling of the above introduced in 9d06c4027f21 ("x86/entry: Convert Divide Error to IDTENTRY").
[]byte("divide_error:"),
[]oopsFormat{
{
title: compile("divide_error: "),
fmt: "divide error in %[1]v",
stack: &stackFmt{
parts: []*regexp.Regexp{
linuxRipFrame,
},
},
},
},
[]*regexp.Regexp{},
},
{
[]byte("invalid opcode:"),
[]oopsFormat{
{
title: compile("invalid opcode: "),
fmt: "invalid opcode in %[1]v",
stack: &stackFmt{
parts: []*regexp.Regexp{
linuxRipFrame,
},
},
},
},
[]*regexp.Regexp{},
},
{
[]byte("UBSAN:"),
[]oopsFormat{
{
title: compile("UBSAN:"),
report: compile("UBSAN: Undefined behaviour in"),
fmt: "UBSAN: undefined-behaviour in %[1]v",
stack: &stackFmt{
parts: []*regexp.Regexp{
linuxCallTrace,
parseStackTrace,
},
skip: []string{"ubsan", "overflow"},
},
},
{
title: compile("UBSAN: array-index-out-of-bounds in"),
fmt: "UBSAN: array-index-out-of-bounds in %[1]v",
alt: []string{"bad-access in %[1]v"},
stack: &stackFmt{
parts: []*regexp.Regexp{
linuxCallTrace,
parseStackTrace,
},
skip: []string{"ubsan", "overflow"},
},
},
{
title: compile("UBSAN:"),
report: compile("UBSAN: (.*?) in"),
fmt: "UBSAN: %[1]v in %[2]v",
stack: &stackFmt{
parts: []*regexp.Regexp{
linuxCallTrace,
parseStackTrace,
},
skip: []string{"ubsan", "overflow"},
},
},
},
[]*regexp.Regexp{},
},
{
[]byte("Booting the kernel."),
[]oopsFormat{
{
title: compile("^Booting the kernel"),
fmt: "unexpected kernel reboot",
noStackTrace: true,
},
},
[]*regexp.Regexp{
// These may appear on the same line when the fuzzer reads from the console the existing
// boot message and then pass it as mount option, kernel then prints it back
// as an invalid mount option and we detect false reboot.
compile("Parsing ELF|Decompressing Linux|Unknown parameter '"),
},
},
{
[]byte("unregister_netdevice: waiting for"),
[]oopsFormat{
{
title: compile("unregister_netdevice: waiting for (?:.*) to become free"),
fmt: "unregister_netdevice: waiting for DEV to become free",
noStackTrace: true,
},
},
[]*regexp.Regexp{},
},
{
// Custom vfs error printed by older versions of the kernel, see #3621.
[]byte("VFS: Close: file count is 0"),
[]oopsFormat{
{
title: compile("VFS: Close: file count is 0"),
fmt: "VFS: Close: file count is zero (use-after-free)",
noStackTrace: true,
},
},
[]*regexp.Regexp{},
},
{
// Custom vfs error printed by older versions of the kernel, see #3621.
[]byte("VFS: Busy inodes after unmount"),
[]oopsFormat{
{
title: compile("VFS: Busy inodes after unmount"),
fmt: "VFS: Busy inodes after unmount (use-after-free)",
noStackTrace: true,
},
},
[]*regexp.Regexp{},
},
{
[]byte("Internal error:"),
[]oopsFormat{
{
title: compile("Internal error:"),
fmt: "Internal error in %[1]v",
// arm64 shows some crashes as "Internal error: synchronous external abort",
// while arm shows the same crash as "Unable to handle kernel paging request",
// so we need to merge them.
alt: []string{"bad-access in %[1]v"},
stack: &stackFmt{
parts: []*regexp.Regexp{
linuxRipFrame,
linuxCallTrace,
parseStackTrace,
},
},
},
},
[]*regexp.Regexp{},
},
{
[]byte("Unhandled fault:"),
[]oopsFormat{
{
title: compile("Unhandled fault:"),
fmt: "Unhandled fault in %[1]v",
// x86_64 shows NULL derefs as "general protection fault",
// while arm shows the same crash as "Unhandled fault: page domain fault".
alt: []string{"bad-access in %[1]v"},
stack: &stackFmt{
parts: []*regexp.Regexp{
linuxRipFrame,
linuxCallTrace,
parseStackTrace,
},
},
},
},
[]*regexp.Regexp{},
},
{
[]byte("Alignment trap:"),
[]oopsFormat{
{
title: compile("Alignment trap:"),
fmt: "Alignment trap in %[1]v",
stack: &stackFmt{
parts: []*regexp.Regexp{
linuxRipFrame,
linuxCallTrace,
parseStackTrace,
},
},
},
},
[]*regexp.Regexp{},
},
{
[]byte("trusty: panic"),
[]oopsFormat{
{
title: compile("trusty: panic.* ASSERT FAILED"),
report: compile("trusty: panic \\(.*?\\):(?: DEBUG)? ASSERT FAILED at \\(.*?\\): (.+)"),
fmt: "trusty: ASSERT FAILED: %[1]v",
noStackTrace: true,
},
{
title: compile("trusty: panic.* ASSERT FAILED.*: *(.*)"),
fmt: "trusty: ASSERT FAILED: %[1]v",
corrupted: true,
},
{
title: compile("trusty: panic"),
report: compile("trusty: panic \\(.*?\\): (.+)"),
fmt: "trusty: panic: %[1]v",
noStackTrace: true,
},
},
[]*regexp.Regexp{},
},
&groupGoRuntimeErrors,
}, commonOopses...)
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package report
import (
"regexp"
)
func ctorNetbsd(cfg *config) (reporterImpl, []string, error) {
symbolizeRes := []*regexp.Regexp{
// stack
regexp.MustCompile(` at netbsd:([A-Za-z0-9_]+)\+0x([0-9a-f]+)`),
// witness
regexp.MustCompile(`#[0-9]+ +([A-Za-z0-9_]+)\+0x([0-9a-f]+)`),
}
cfg.ignores = append(cfg.ignores, regexp.MustCompile("event_init: unable to initialize")) // postfix output
ctx, err := ctorBSD(cfg, netbsdOopses, symbolizeRes)
return ctx, nil, err
}
// nolint: lll
var netbsdOopses = append([]*oops{
{
[]byte("fault in supervisor mode"),
[]oopsFormat{
{
title: compile("fatal (page|protection|integer divide) fault in supervisor mode"),
report: compile(`fatal (page|protection|integer divide) fault in supervisor mode(?:.*\n)+?.*Stopped in.*netbsd:([^\\+]+)`),
fmt: "%[1]v fault in %[2]v",
},
},
[]*regexp.Regexp{},
},
{
[]byte("panic: "),
[]oopsFormat{
{
title: compile("panic: kernel diagnostic assertion"),
report: compile(`panic: kernel diagnostic assertion "(.*?)"`),
fmt: "assert failed: %[1]v",
},
{
title: compile("panic: lock error"),
report: compile(`panic: lock error:(?:.*\n)+?.*?Begin traceback.*?\n(?:.*(?:panic|printf|lockdebug|abort|mutex).*\n)*.*?\](.*?)\(`),
fmt: "lock error in %[1]v",
},
{
title: compile("ASan: Unauthorized Access"),
report: compile(`ASan: Unauthorized Access (?:.*\n)+(?:kasan|__asan).*\n(.*)\(`),
fmt: "ASan: Unauthorized Access in %[1]v",
},
{
title: compile("MSan: Uninitialized"),
report: compile(`MSan: Uninitialized (?:.*\n)+(?:kmsan|__msan).*\n(.*)\(`),
fmt: "MSan: Uninitialized Memory in %[1]v",
},
{
title: compile("UBSan: Undefined Behavior"),
report: compile(`UBSan: Undefined Behavior (?:.*\n)+(?:Handle|__ubsan).*\n(.*)\(`),
fmt: "UBSan: Undefined Behavior in %[1]v",
},
},
[]*regexp.Regexp{
compile(`ddb\.onpanic:`),
},
},
{
[]byte("UBSan:"),
[]oopsFormat{
{
title: compile("UBSan:"),
fmt: "UBSan: Undefined behavior",
},
},
[]*regexp.Regexp{},
},
&groupGoRuntimeErrors,
}, commonOopses...)
// Copyright 2018 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package report
import (
"regexp"
)
func ctorOpenbsd(cfg *config) (reporterImpl, []string, error) {
symbolizeRes := []*regexp.Regexp{
// stack
regexp.MustCompile(` at ([A-Za-z0-9_]+)\+0x([0-9a-f]+)`),
// witness
regexp.MustCompile(`#[0-9]+ +([A-Za-z0-9_]+)\+0x([0-9a-f]+)`),
}
ctx, err := ctorBSD(cfg, openbsdOopses, symbolizeRes)
if err != nil {
return nil, nil, err
}
suppressions := []string{
"panic: vop_generic_badop",
"witness: lock order reversal:\\n(.*\\n)*.*[0-9stnd]+ 0x[0-9a-f]+ inode(.*\\n)*.*lock order .* first seen at",
"panic:.*send disconnect: Broken pipe",
}
return ctx, suppressions, nil
}
var openbsdOopses = append([]*oops{
{
[]byte("cleaned vnode"),
[]oopsFormat{
{
title: compile("cleaned vnode: "),
fmt: "panic: cleaned vnode isn't",
},
},
[]*regexp.Regexp{},
},
{
[]byte("panic:"),
[]oopsFormat{
{
title: compile(`\nddb\{\d+\}> show panic(?Us:.*)[*]cpu\d+: ([^\n]+)(?Us:.*)\nddb\{\d+\}> trace`),
fmt: "panic: %[1]v",
},
{
title: compile("panic: kernel diagnostic assertion (.+) failed: file \".*/([^\"]+)"),
fmt: "assert %[1]v failed in %[2]v",
},
{
title: compile("panic: Data modified on freelist: .* previous type ([^ ]+)"),
fmt: "malloc: free list modified: %[1]v",
},
{
title: compile("panic: pool_cache_item_magic_check: ([^ ]+) cpu free list modified"),
fmt: "pool: cpu free list modified: %[1]v",
},
{
title: compile("panic: pool_do_put: ([^:]+): double pool_put"),
fmt: "pool: double put: %[1]v",
},
{
title: compile("panic: pool_do_get: ([^:]+) free list modified"),
fmt: "pool: free list modified: %[1]v",
},
{
title: compile("panic: pool_p_free: ([^:]+) free list modified"),
fmt: "pool: free list modified: %[1]v",
},
{
title: compile("panic: timeout_add: to_ticks \\(.+\\) < 0"),
fmt: "panic: timeout_add: to_ticks < 0",
},
{
title: compile("panic: attempt to execute user address {{ADDR}} in supervisor mode"),
fmt: "panic: attempt to execute user address",
},
{
title: compile("panic: unhandled af"),
fmt: "panic: unhandled af",
},
{
title: compile("panic: (kqueue|knote).* ([a-z]+ .*)"),
fmt: "kqueue: %[2]v",
},
{
title: compile("panic: receive ([0-9][a-z]*):"),
fmt: "soreceive %[1]v",
},
},
[]*regexp.Regexp{},
},
{
[]byte("lock order reversal:"),
[]oopsFormat{
{
title: compile("lock order reversal:\\n(?:.*\\n)*lock order data .* missing"),
fmt: "witness: reversal: lock order data missing",
},
{
title: compile("lock order reversal:\\n+.*1st {{ADDR}} ([^\\ ]+).*\\n.*2nd {{ADDR}} ([^\\ ]+)"),
fmt: "witness: reversal: %[1]v %[2]v",
},
},
[]*regexp.Regexp{},
},
{
[]byte("witness:"),
[]oopsFormat{
{
title: compile("witness: thread {{ADDR}} exiting with the following locks held:"),
fmt: "witness: thread exiting with locks held",
},
{
title: compile("witness: userret: returning with the following locks held:(.*\\n)+?.*sys_([a-z0-9_]+)\\+"),
fmt: "witness: userret: %[2]v",
},
{
title: compile("(witness: .*)"),
fmt: "%[1]v",
},
},
[]*regexp.Regexp{},
},
{
[]byte("uvm_fault("),
[]oopsFormat{
{
title: compile("uvm_fault\\((?:.*\\n)+?.*Stopped at[ ]+{{ADDR}}"),
report: compile("uvm_fault\\((?:.*\\n)+?.*end trace frame"),
fmt: "uvm_fault",
},
{
title: compile("uvm_fault\\((?:.*\\n)+?.*Stopped at[ ]+([^\\+]+)"),
report: compile("uvm_fault(?:.*\\n)+?.*Stopped at[ ]+([^\\+]+)(?:.*\\n)+?.*end trace frame"),
fmt: "uvm_fault: %[1]v",
},
{
title: compile("uvm_fault\\("),
fmt: "uvm_fault",
corrupted: true,
},
},
[]*regexp.Regexp{},
},
{
[]byte("kernel:"),
[]oopsFormat{
{
title: compile("kernel: page fault trap, code=0.*\\nStopped at[ ]+([^\\+]+)"),
fmt: "uvm_fault: %[1]v",
},
{
title: compile("kernel: protection fault trap, code=0.*\\nStopped at[ ]+([^\\+]+)"),
fmt: "protection_fault: %[1]v",
},
},
[]*regexp.Regexp{
compile("reorder_kernel"),
},
},
&groupGoRuntimeErrors,
}, commonOopses...)
// Copyright 2016 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
// Package report contains functions that process kernel output,
// detect/extract crash messages, symbolize them, etc.
package report
import (
"bytes"
"fmt"
"regexp"
"strings"
"github.com/google/syzkaller/pkg/cover/backend"
"github.com/google/syzkaller/pkg/mgrconfig"
"github.com/google/syzkaller/pkg/report/crash"
"github.com/google/syzkaller/pkg/vcs"
"github.com/google/syzkaller/pkg/vminfo"
"github.com/google/syzkaller/sys/targets"
"github.com/ianlancetaylor/demangle"
)
type reporterImpl interface {
// ContainsCrash searches kernel console output for oops messages.
ContainsCrash(output []byte) bool
// Parse extracts information about oops from console output.
// Returns nil if no oops found.
Parse(output []byte) *Report
// Symbolize symbolizes rep.Report and fills in Maintainers.
Symbolize(rep *Report) error
}
type Reporter struct {
typ string
impl reporterImpl
suppressions []*regexp.Regexp
interests []*regexp.Regexp
}
type Report struct {
// Title contains a representative description of the first oops.
Title string
// Alternative titles, used for better deduplication.
// If two crashes have a non-empty intersection of Title/AltTitles, they are considered the same bug.
AltTitles []string
// Bug type (e.g. hang, memory leak, etc).
Type crash.Type
// The indicative function name.
Frame string
// Report contains whole oops text.
Report []byte
// Output contains whole raw console output as passed to Reporter.Parse.
Output []byte
// StartPos/EndPos denote region of output with oops message(s).
StartPos int
EndPos int
// SkipPos is position in output where parsing for the next report should start.
SkipPos int
// Suppressed indicates whether the report should not be reported to user.
Suppressed bool
// Corrupted indicates whether the report is truncated of corrupted in some other way.
Corrupted bool
// CorruptedReason contains reason why the report is marked as corrupted.
CorruptedReason string
// Recipients is a list of RecipientInfo with Email, Display Name, and type.
Recipients vcs.Recipients
// GuiltyFile is the source file that we think is to blame for the crash (filled in by Symbolize).
GuiltyFile string
// Arbitrary information about the test VM, may be attached to the report by users of the package.
MachineInfo []byte
// If the crash happened in the context of the syz-executor process, Executor will hold more info.
Executor *ExecutorInfo
// reportPrefixLen is length of additional prefix lines that we added before actual crash report.
reportPrefixLen int
// symbolized is set if the report is symbolized.
symbolized bool
}
type ExecutorInfo struct {
ProcID int // ID of the syz-executor proc mentioned in the crash report.
ExecID int // The program the syz-executor was executing.
}
func (rep *Report) String() string {
return fmt.Sprintf("crash: %v\n%s", rep.Title, rep.Report)
}
// NewReporter creates reporter for the specified OS/Type.
func NewReporter(cfg *mgrconfig.Config) (*Reporter, error) {
var localModules []*vminfo.KernelModule
if cfg.KernelObj != "" {
var err error
localModules, err = backend.DiscoverModules(cfg.SysTarget, cfg.KernelObj, cfg.ModuleObj)
if err != nil {
return nil, err
}
cfg.LocalModules = localModules
}
typ := cfg.TargetOS
if cfg.Type == targets.GVisor || cfg.Type == targets.Starnix {
typ = cfg.Type
}
ctor := ctors[typ]
if ctor == nil {
return nil, fmt.Errorf("unknown OS: %v", typ)
}
ignores, err := compileRegexps(cfg.Ignores)
if err != nil {
return nil, err
}
interests, err := compileRegexps(cfg.Interests)
if err != nil {
return nil, err
}
config := &config{
target: cfg.SysTarget,
vmType: cfg.Type,
kernelDirs: *cfg.KernelDirs(),
ignores: ignores,
kernelModules: localModules,
}
rep, suppressions, err := ctor(config)
if err != nil {
return nil, err
}
suppressions = append(suppressions, []string{
// Go runtime OOM messages:
"fatal error: runtime: out of memory",
"fatal error: runtime: cannot allocate memory",
"fatal error: out of memory",
"fatal error: newosproc",
// Panic with ENOMEM err:
"panic: .*cannot allocate memory",
}...)
suppressions = append(suppressions, cfg.Suppressions...)
supps, err := compileRegexps(suppressions)
if err != nil {
return nil, err
}
reporter := &Reporter{
typ: typ,
impl: rep,
suppressions: supps,
interests: interests,
}
return reporter, nil
}
const (
corruptedNoFrames = "extracted no frames"
)
var ctors = map[string]fn{
targets.Linux: ctorLinux,
targets.Starnix: ctorFuchsia,
targets.GVisor: ctorGvisor,
targets.FreeBSD: ctorFreebsd,
targets.Darwin: ctorDarwin,
targets.NetBSD: ctorNetbsd,
targets.OpenBSD: ctorOpenbsd,
targets.Fuchsia: ctorFuchsia,
targets.Windows: ctorStub,
}
type config struct {
target *targets.Target
vmType string
kernelDirs mgrconfig.KernelDirs
ignores []*regexp.Regexp
kernelModules []*vminfo.KernelModule
}
type fn func(cfg *config) (reporterImpl, []string, error)
func compileRegexps(list []string) ([]*regexp.Regexp, error) {
compiled := make([]*regexp.Regexp, len(list))
for i, str := range list {
re, err := regexp.Compile(str)
if err != nil {
return nil, fmt.Errorf("failed to compile %q: %w", str, err)
}
compiled[i] = re
}
return compiled, nil
}
func (reporter *Reporter) Parse(output []byte) *Report {
return reporter.ParseFrom(output, 0)
}
func (reporter *Reporter) ParseFrom(output []byte, minReportPos int) *Report {
rep := reporter.impl.Parse(output[minReportPos:])
if rep == nil {
return nil
}
rep.Output = output
rep.StartPos += minReportPos
rep.EndPos += minReportPos
rep.Title = sanitizeTitle(replaceTable(dynamicTitleReplacement, rep.Title))
for i, title := range rep.AltTitles {
rep.AltTitles[i] = sanitizeTitle(replaceTable(dynamicTitleReplacement, title))
}
rep.Suppressed = matchesAny(rep.Output, reporter.suppressions)
if bytes.Contains(rep.Output, gceConsoleHangup) {
rep.Corrupted = true
}
if match := reportFrameRe.FindStringSubmatch(rep.Title); match != nil {
rep.Frame = match[1]
}
rep.SkipPos = len(output)
if pos := bytes.IndexByte(rep.Output[rep.StartPos:], '\n'); pos != -1 {
rep.SkipPos = rep.StartPos + pos
}
// This generally should not happen.
// But openbsd does some hacks with /r/n which may lead to off-by-one EndPos.
rep.EndPos = max(rep.EndPos, rep.SkipPos)
return rep
}
func (reporter *Reporter) ContainsCrash(output []byte) bool {
return reporter.impl.ContainsCrash(output)
}
func (reporter *Reporter) Symbolize(rep *Report) error {
if rep.symbolized {
panic("Symbolize is called twice")
}
rep.symbolized = true
if err := reporter.impl.Symbolize(rep); err != nil {
return err
}
if !reporter.isInteresting(rep) {
rep.Suppressed = true
}
return nil
}
func (reporter *Reporter) isInteresting(rep *Report) bool {
if len(reporter.interests) == 0 {
return true
}
if matchesAnyString(rep.Title, reporter.interests) ||
matchesAnyString(rep.GuiltyFile, reporter.interests) {
return true
}
for _, title := range rep.AltTitles {
if matchesAnyString(title, reporter.interests) {
return true
}
}
for _, recipient := range rep.Recipients {
if matchesAnyString(recipient.Address.Address, reporter.interests) {
return true
}
}
return false
}
// There are cases when we need to extract a guilty file, but have no ability to do it the
// proper way -- parse and symbolize the raw console output log. One of such cases is
// the syz-fillreports tool, which only has access to the already symbolized logs.
// ReportToGuiltyFile does its best to extract the data.
func (reporter *Reporter) ReportToGuiltyFile(title string, report []byte) string {
ii, ok := reporter.impl.(interface {
extractGuiltyFileRaw(title string, report []byte) string
})
if !ok {
return ""
}
return ii.extractGuiltyFileRaw(title, report)
}
func IsSuppressed(reporter *Reporter, output []byte) bool {
return matchesAny(output, reporter.suppressions) ||
bytes.Contains(output, gceConsoleHangup)
}
// ParseAll returns all successive reports in output.
func ParseAll(reporter *Reporter, output []byte) (reports []*Report) {
skipPos := 0
for {
rep := reporter.ParseFrom(output, skipPos)
if rep == nil {
return
}
reports = append(reports, rep)
skipPos = rep.SkipPos
}
}
// GCE console connection sometimes fails with this message.
// The message frequently happens right after a kernel panic.
// So if we see it in output where we recognized a crash, we mark the report as corrupted
// because the crash message is usually truncated (maybe we don't even have the title line).
// If we see it in no output/lost connection reports then we mark them as suppressed instead
// because the crash itself may have been caused by the console connection error.
var gceConsoleHangup = []byte("serialport: VM disconnected.")
type replacement struct {
match *regexp.Regexp
replacement string
}
func replaceTable(replacements []replacement, str string) string {
for _, repl := range replacements {
for stop := false; !stop; {
newStr := repl.match.ReplaceAllString(str, repl.replacement)
stop = newStr == str
str = newStr
}
}
return str
}
var dynamicTitleReplacement = []replacement{
{
// Executor PIDs are not interesting.
regexp.MustCompile(`syz-executor\.?[0-9]+((/|:)[0-9]+)?`),
"syz-executor",
},
{
// Executor process IDs are dynamic and are not interesting.
regexp.MustCompile(`syzkaller[0-9]+((/|:)[0-9]+)?`),
"syzkaller",
},
{
// Replace that everything looks like an address with "ADDR",
// addresses in descriptions can't be good regardless of the oops regexps.
regexp.MustCompile(`([^a-zA-Z0-9])(?:0x)?[0-9a-f]{6,}`),
"${1}ADDR",
},
{
// Replace IP addresses.
regexp.MustCompile(`([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})`),
"IP",
},
{
// Replace that everything looks like a file line number with "LINE".
regexp.MustCompile(`(\.\w+)(:[0-9]+)+`),
"${1}:LINE",
},
{
// Replace all raw references to runctions (e.g. "ip6_fragment+0x1052/0x2d80")
// with just function name ("ip6_fragment"). Offsets and sizes are not stable.
regexp.MustCompile(`([a-zA-Z][a-zA-Z0-9_.]+)\+0x[0-9a-z]+/0x[0-9a-z]+`),
"${1}",
},
{
// CPU numbers are not interesting.
regexp.MustCompile(`CPU#[0-9]+`),
"CPU",
},
{
// Replace with "NUM" everything that looks like a decimal number and has not
// been replaced yet. It might require multiple replacement executions as the
// matching substrings may overlap (e.g. "0,1,2").
regexp.MustCompile(`(\W)(\d+)(\W|$)`),
"${1}NUM${3}",
},
{
// Some decimal numbers can be a part of a function name,
// we need to preserve them (e.g. cfg80211* or nl802154*).
// However, if the number is too long, it's probably something else.
regexp.MustCompile(`(\d+){7,}`),
"NUM",
},
}
func sanitizeTitle(title string) string {
const maxTitleLen = 120 // Corrupted/intermixed lines can be very long.
res := make([]byte, 0, len(title))
prev := byte(' ')
for i := 0; i < len(title) && i < maxTitleLen; i++ {
ch := title[i]
switch {
case ch == '\t':
ch = ' '
case ch < 0x20 || ch >= 0x7f:
continue
}
if ch == ' ' && prev == ' ' {
continue
}
res = append(res, ch)
prev = ch
}
return strings.TrimSpace(string(res))
}
type oops struct {
header []byte
formats []oopsFormat
suppressions []*regexp.Regexp
}
type oopsFormat struct {
title *regexp.Regexp
// If title is matched but report is not, the report is considered corrupted.
report *regexp.Regexp
// Format string to create report title.
// Strings captured by title (or by report if present) are passed as input.
// If stack is not nil, extracted function name is passed as an additional last argument.
fmt string
// Alternative titles used for better crash deduplication.
// Format is the same as for fmt.
alt []string
// If not nil, a function name is extracted from the report and passed to fmt.
// If not nil but frame extraction fails, the report is considered corrupted.
stack *stackFmt
// Disable stack report corruption checking as it would expect one of stackStartRes to be
// present, but this format does not comply with that.
noStackTrace bool
corrupted bool
}
type stackFmt struct {
// parts describe how guilty stack frame must be extracted from the report.
// parts are matched consecutively potentially capturing frames.
// parts can be of 3 types:
// - non-capturing regexp, matched against report and advances current position
// - capturing regexp, same as above, but also yields a frame
// - special value parseStackTrace means that a stack trace must be parsed
// starting from current position
parts []*regexp.Regexp
// If parts2 is present it is tried when parts matching fails.
parts2 []*regexp.Regexp
// Skip these functions in stack traces (matched as substring).
skip []string
// Custom frame extractor (optional).
// Accepts set of all frames, returns guilty frame and corruption reason.
extractor frameExtractor
}
type frameExtractor func(frames []string) (string, int)
var parseStackTrace *regexp.Regexp
func compile(re string) *regexp.Regexp {
re = strings.ReplaceAll(re, "{{ADDR}}", "0x[0-9a-f]+")
re = strings.ReplaceAll(re, "{{PC}}", "\\[\\<?(?:0x)?[0-9a-f]+\\>?\\]")
re = strings.ReplaceAll(re, "{{FUNC}}", "([a-zA-Z0-9_]+)(?:\\.|\\+)")
re = strings.ReplaceAll(re, "{{SRC}}", "([a-zA-Z0-9-_/.]+\\.[a-z]+:[0-9]+)")
return regexp.MustCompile(re)
}
func containsCrash(output []byte, oopses []*oops, ignores []*regexp.Regexp) bool {
for pos := 0; pos < len(output); {
next := bytes.IndexByte(output[pos:], '\n')
if next != -1 {
next += pos
} else {
next = len(output)
}
for _, oops := range oopses {
if matchOops(output[pos:next], oops, ignores) {
return true
}
}
pos = next + 1
}
return false
}
func matchOops(line []byte, oops *oops, ignores []*regexp.Regexp) bool {
match := bytes.Index(line, oops.header)
if match == -1 {
return false
}
if matchesAny(line, oops.suppressions) {
return false
}
if matchesAny(line, ignores) {
return false
}
return true
}
func extractDescription(output []byte, oops *oops, params *stackParams) (
desc, corrupted string, altTitles []string, format oopsFormat) {
startPos := len(output)
matchedTitle := false
for _, f := range oops.formats {
match := f.title.FindSubmatchIndex(output)
if match == nil || match[0] > startPos {
continue
}
if match[0] == startPos && desc != "" {
continue
}
if match[0] < startPos {
desc = ""
format = oopsFormat{}
startPos = match[0]
}
matchedTitle = true
if f.report != nil {
match = f.report.FindSubmatchIndex(output)
if match == nil {
continue
}
}
var argPrefix []any
for i := 2; i < len(match); i += 2 {
argPrefix = append(argPrefix, string(output[match[i]:match[i+1]]))
}
var frames []extractedFrame
corrupted = ""
if f.stack != nil {
var ok bool
frames, ok = extractStackFrame(params, f.stack, output[match[0]:])
if !ok {
corrupted = corruptedNoFrames
}
}
args := canonicalArgs(argPrefix, frames)
desc = fmt.Sprintf(f.fmt, args...)
for _, alt := range f.alt {
altTitles = append(altTitles, fmt.Sprintf(alt, args...))
}
// Also consider partially stripped prefixes - these will help us
// better deduplicate the reports.
argSequences := partiallyStrippedArgs(argPrefix, frames, params)
for _, args := range argSequences {
altTitle := fmt.Sprintf(f.fmt, args...)
if altTitle != desc {
altTitles = append(altTitles, altTitle)
}
for _, alt := range f.alt {
altTitles = append(altTitles, fmt.Sprintf(alt, args...))
}
}
altTitles = uniqueStrings(altTitles)
format = f
}
if desc == "" {
// If we are here and matchedTitle is set, it means that we've matched
// a title of an oops but not full report regexp or stack trace,
// which means the report was corrupted.
if matchedTitle {
corrupted = "matched title but not report regexp"
}
pos := bytes.Index(output, oops.header)
if pos == -1 {
return
}
end := bytes.IndexByte(output[pos:], '\n')
if end == -1 {
end = len(output)
} else {
end += pos
}
desc = string(output[pos:end])
}
if corrupted == "" && format.corrupted {
corrupted = "report format is marked as corrupted"
}
return
}
type stackParams struct {
// stackStartRes matches start of stack traces.
stackStartRes []*regexp.Regexp
// frameRes match different formats of lines containing kernel frames (capture function name).
frameRes []*regexp.Regexp
// skipPatterns match functions that must be unconditionally skipped.
skipPatterns []string
// If we looked at any lines that match corruptedLines during report analysis,
// then the report is marked as corrupted.
corruptedLines []*regexp.Regexp
// Prefixes that need to be removed from frames.
// E.g. syscall prefixes as different arches have different prefixes.
stripFramePrefixes []string
}
func (sp *stackParams) stripFrames(frames []string) []string {
var ret []string
for _, origFrame := range frames {
// Pick the shortest one.
frame := origFrame
for _, prefix := range sp.stripFramePrefixes {
newFrame := strings.TrimPrefix(origFrame, prefix)
if len(newFrame) < len(frame) {
frame = newFrame
}
}
ret = append(ret, frame)
}
return ret
}
type extractedFrame struct {
canonical string
raw string
}
func extractStackFrame(params *stackParams, stack *stackFmt, output []byte) ([]extractedFrame, bool) {
skip := append([]string{}, params.skipPatterns...)
skip = append(skip, stack.skip...)
var skipRe *regexp.Regexp
if len(skip) != 0 {
skipRe = regexp.MustCompile(strings.Join(skip, "|"))
}
extractor := func(rawFrames []string) extractedFrame {
if len(rawFrames) == 0 {
return extractedFrame{}
}
stripped := params.stripFrames(rawFrames)
if stack.extractor == nil {
return extractedFrame{stripped[0], rawFrames[0]}
}
frame, idx := stack.extractor(stripped)
if frame != "" {
return extractedFrame{frame, rawFrames[idx]}
}
return extractedFrame{}
}
frames, ok := extractStackFrameImpl(params, output, skipRe, stack.parts, extractor)
if ok || len(stack.parts2) == 0 {
return frames, ok
}
return extractStackFrameImpl(params, output, skipRe, stack.parts2, extractor)
}
func lines(text []byte) [][]byte {
return bytes.Split(text, []byte("\n"))
}
func extractStackFrameImpl(params *stackParams, output []byte, skipRe *regexp.Regexp,
parts []*regexp.Regexp, extractor func([]string) extractedFrame) ([]extractedFrame, bool) {
lines := lines(output)
var rawFrames []string
var results []extractedFrame
ok := true
numStackTraces := 0
nextPart:
for partIdx := 0; ; partIdx++ {
if partIdx == len(parts) || parts[partIdx] == parseStackTrace && numStackTraces > 0 {
keyFrame := extractor(rawFrames)
if keyFrame.canonical == "" {
keyFrame, ok = extractedFrame{"corrupted", "corrupted"}, false
}
results = append(results, keyFrame)
rawFrames = nil
}
if partIdx == len(parts) {
break
}
part := parts[partIdx]
if part == parseStackTrace {
numStackTraces++
var ln []byte
for len(lines) > 0 {
ln, lines = lines[0], lines[1:]
if matchesAny(ln, params.corruptedLines) {
ok = false
continue nextPart
}
if matchesAny(ln, params.stackStartRes) {
continue nextPart
}
if partIdx != len(parts)-1 {
match := parts[partIdx+1].FindSubmatch(ln)
if match != nil {
rawFrames = appendStackFrame(rawFrames, match, skipRe)
partIdx++
continue nextPart
}
}
var match [][]byte
for _, re := range params.frameRes {
match = re.FindSubmatch(ln)
if match != nil {
break
}
}
rawFrames = appendStackFrame(rawFrames, match, skipRe)
}
} else {
var ln []byte
for len(lines) > 0 {
ln, lines = lines[0], lines[1:]
if matchesAny(ln, params.corruptedLines) {
ok = false
continue nextPart
}
match := part.FindSubmatch(ln)
if match == nil {
continue
}
rawFrames = appendStackFrame(rawFrames, match, skipRe)
break
}
}
}
return results, ok
}
func appendStackFrame(frames []string, match [][]byte, skipRe *regexp.Regexp) []string {
if len(match) < 2 {
return frames
}
for _, frame := range match[1:] {
if frame == nil {
continue
}
frame := demangle.Filter(string(frame), demangle.NoParams)
if skipRe == nil || !skipRe.MatchString(frame) {
frames = append(frames, frame)
}
}
return frames
}
func canonicalArgs(prefix []any, frames []extractedFrame) []any {
ret := append([]any{}, prefix...)
for _, frame := range frames {
ret = append(ret, frame.canonical)
}
return ret
}
func partiallyStrippedArgs(prefix []any, frames []extractedFrame, params *stackParams) [][]any {
if params == nil {
return nil
}
ret := [][]any{}
for i := 0; i <= len(params.stripFramePrefixes); i++ {
var list []any
add := true
// Also include the raw frames.
stripPrefix := ""
if i > 0 {
stripPrefix, add = params.stripFramePrefixes[i-1], false
}
for _, frame := range frames {
trimmed := strings.TrimPrefix(frame.raw, stripPrefix)
if trimmed != frame.raw {
add = true
}
list = append(list, trimmed)
}
if add {
list = append(append([]any{}, prefix...), list...)
ret = append(ret, list)
}
}
return ret
}
func uniqueStrings(source []string) []string {
dup := map[string]struct{}{}
var ret []string
for _, item := range source {
if _, ok := dup[item]; ok {
continue
}
dup[item] = struct{}{}
ret = append(ret, item)
}
return ret
}
func simpleLineParser(output []byte, oopses []*oops, params *stackParams, ignores []*regexp.Regexp) *Report {
rep := &Report{
Output: output,
}
var oops *oops
for pos := 0; pos < len(output); {
next := bytes.IndexByte(output[pos:], '\n')
if next != -1 {
next += pos
} else {
next = len(output)
}
line := output[pos:next]
for _, oops1 := range oopses {
if matchOops(line, oops1, ignores) {
oops = oops1
rep.StartPos = pos
rep.EndPos = next
break
}
}
if oops != nil {
break
}
pos = next + 1
}
if oops == nil {
return nil
}
title, corrupted, altTitles, _ := extractDescription(output[rep.StartPos:], oops, params)
rep.Title = title
rep.AltTitles = altTitles
rep.Report = output[rep.StartPos:]
rep.Corrupted = corrupted != ""
rep.CorruptedReason = corrupted
rep.Type = TitleToCrashType(rep.Title)
return rep
}
func matchesAny(line []byte, res []*regexp.Regexp) bool {
for _, re := range res {
if re.Match(line) {
return true
}
}
return false
}
func matchesAnyString(str string, res []*regexp.Regexp) bool {
for _, re := range res {
if re.MatchString(str) {
return true
}
}
return false
}
// replace replaces [start:end] in where with what, inplace.
func replace(where []byte, start, end int, what []byte) []byte {
if len(what) >= end-start {
where = append(where, what[end-start:]...)
copy(where[start+len(what):], where[end:])
copy(where[start:], what)
} else {
copy(where[start+len(what):], where[end:])
where = where[:len(where)-(end-start-len(what))]
copy(where[start:], what)
}
return where
}
// Truncate leaves up to `begin` bytes at the beginning of log and
// up to `end` bytes at the end of the log.
func Truncate(log []byte, begin, end int) []byte {
if begin+end >= len(log) {
return log
}
var b bytes.Buffer
b.Write(log[:begin])
if begin > 0 {
b.WriteString("\n\n")
}
fmt.Fprintf(&b, "<<cut %d bytes out>>",
len(log)-begin-end,
)
if end > 0 {
b.WriteString("\n\n")
}
b.Write(log[len(log)-end:])
return b.Bytes()
}
var (
filenameRe = regexp.MustCompile(`([a-zA-Z0-9_\-\./]*[a-zA-Z0-9_\-]+\.(c|h)):[0-9]+`)
reportFrameRe = regexp.MustCompile(`.* in ((?:<[a-zA-Z0-9_: ]+>)?[a-zA-Z0-9_:]+)`)
// Matches a slash followed by at least one directory nesting before .c/.h file.
deeperPathRe = regexp.MustCompile(`^/[a-zA-Z0-9_\-\./]+/[a-zA-Z0-9_\-]+\.(c|h)$`)
)
// These are produced by syzkaller itself.
// But also catches crashes in Go programs in gvisor/fuchsia.
var commonOopses = []*oops{
{
// Errors produced by executor's fail function.
[]byte("SYZFAIL:"),
[]oopsFormat{
{
title: compile("SYZFAIL:(.*)"),
fmt: "SYZFAIL:%[1]v",
noStackTrace: true,
},
},
[]*regexp.Regexp{},
},
{
// Errors produced by log.Fatal functions.
[]byte("SYZFATAL:"),
[]oopsFormat{
{
title: compile("SYZFATAL:(.*)()"),
alt: []string{"SYZFATAL%[2]s"},
fmt: "SYZFATAL:%[1]v",
noStackTrace: true,
},
},
[]*regexp.Regexp{},
},
{
[]byte("panic:"),
[]oopsFormat{
{
// This is gvisor-specific, but we need to handle it here since we handle "panic:" here.
title: compile("panic: Sentry detected .* stuck task"),
fmt: "panic: Sentry detected stuck tasks",
noStackTrace: true,
},
{
title: compile("panic:(.*)"),
fmt: "panic:%[1]v",
noStackTrace: true,
},
},
[]*regexp.Regexp{
// This can match some kernel functions (skb_panic, skb_over_panic).
compile("_panic:"),
// Android prints this sometimes during boot.
compile("xlog_status:"),
compile(`ddb\.onpanic:`),
compile(`evtlog_status:`),
},
},
}
var groupGoRuntimeErrors = oops{
[]byte("fatal error:"),
[]oopsFormat{
{
title: compile("fatal error:"),
fmt: "go runtime error",
noStackTrace: true,
},
},
[]*regexp.Regexp{
compile("ALSA"),
compile("fatal error: cannot create timer"),
},
}
func TitleToCrashType(title string) crash.Type {
for _, t := range titleToType {
for _, prefix := range t.includePrefixes {
if strings.HasPrefix(title, prefix) {
return t.crashType
}
}
}
return crash.UnknownType
}
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package report
type stub struct {
*config
}
func ctorStub(cfg *config) (reporterImpl, []string, error) {
ctx := &stub{
config: cfg,
}
return ctx, nil, nil
}
func (ctx *stub) ContainsCrash(output []byte) bool {
panic("not implemented")
}
func (ctx *stub) Parse(output []byte) *Report {
panic("not implemented")
}
func (ctx *stub) Symbolize(rep *Report) error {
panic("not implemented")
}
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package serializer
import (
"reflect"
"strings"
"fmt"
"io"
)
// Write writes Go-syntax representation of v into w.
// This is similar to fmt.Fprintf(w, "%#v", v), but properly handles pointers,
// does not write package names before types, omits struct fields with default values,
// omits type names where possible, etc. On the other hand, it currently does not
// support all types (e.g. channels and maps).
func Write(ww io.Writer, i interface{}) {
w := writer{ww}
v := reflect.ValueOf(i)
if v.Kind() == reflect.Slice && (v.IsNil() || v.Len() == 0) {
w.typ(v.Type())
w.string("(nil)")
return
}
w.do(v, false)
}
func WriteString(i interface{}) string {
var sb strings.Builder
Write(&sb, i)
return sb.String()
}
type writer struct {
w io.Writer
}
func (w *writer) do(v reflect.Value, sliceElem bool) {
switch v.Kind() {
case reflect.Ptr:
w.doPtr(v, sliceElem)
case reflect.Interface:
w.doInterface(v)
case reflect.Slice:
w.doSlice(v)
case reflect.Struct:
w.doStruct(v, sliceElem)
case reflect.Bool:
if v.Bool() {
w.string("true")
} else {
w.string("false")
}
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
fmt.Fprintf(w.w, "%v", v.Int())
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
fmt.Fprintf(w.w, "%v", v.Uint())
case reflect.String:
fmt.Fprintf(w.w, "%q", v.String())
case reflect.Func:
if !v.IsNil() {
panic("no way to serialize funcs")
}
fmt.Fprintf(w.w, "nil")
default:
panic(fmt.Sprintf("unsupported type: %#v", v.Type().String()))
}
}
func (w *writer) doPtr(v reflect.Value, sliceElem bool) {
if v.IsNil() {
w.string("nil")
return
}
if !sliceElem {
w.byte('&')
}
if v.Elem().Kind() != reflect.Struct {
panic(fmt.Sprintf("only pointers to structs are supported, got %v",
v.Type().Name()))
}
w.do(v.Elem(), sliceElem)
}
func (w *writer) doInterface(v reflect.Value) {
if v.IsNil() {
w.string("nil")
return
}
elem := v.Elem()
// Handling of user types that has underlying primitive types. Consider:
// type T int
// var obj interface{} = T(42)
// T has kind reflect.Int. But if we serialize obj as just "42", it will be turned into plain int.
// Detect this case and serialize obj as "T(42)".
if (elem.Kind() == reflect.Bool || elem.Kind() == reflect.String ||
elem.Type().ConvertibleTo(reflect.TypeOf(0))) &&
strings.Contains(elem.Type().String(), ".") {
w.string(elem.Type().Name())
w.byte('(')
w.do(elem, false)
w.byte(')')
return
}
w.do(elem, false)
}
func (w *writer) doSlice(v reflect.Value) {
if v.IsNil() || v.Len() == 0 {
w.string("nil")
return
}
w.typ(v.Type())
sub := v.Type().Elem().Kind()
if sub == reflect.Ptr || sub == reflect.Interface || sub == reflect.Struct {
// Elem per-line.
w.string("{\n")
for i := 0; i < v.Len(); i++ {
w.do(v.Index(i), true)
w.string(",\n")
}
w.byte('}')
return
}
// All on one line.
w.byte('{')
for i := 0; i < v.Len(); i++ {
if i > 0 {
w.byte(',')
}
w.do(v.Index(i), true)
}
w.byte('}')
}
func (w *writer) doStruct(v reflect.Value, sliceElem bool) {
if !sliceElem {
w.string(v.Type().Name())
}
w.byte('{')
fieldNames := false
for i := 0; i < v.NumField(); i++ {
f := v.Field(i)
if isDefaultValue(f) || !f.CanSet() {
fieldNames = true
break
}
}
needComma := false
for i := 0; i < v.NumField(); i++ {
f := v.Field(i)
if fieldNames && (isDefaultValue(f) || !f.CanSet()) {
continue
}
if needComma {
w.byte(',')
}
if fieldNames {
w.string(v.Type().Field(i).Name)
w.byte(':')
}
w.do(f, false)
needComma = true
}
w.byte('}')
}
func (w *writer) typ(t reflect.Type) {
switch t.Kind() {
case reflect.Ptr:
w.byte('*')
w.typ(t.Elem())
case reflect.Slice:
w.string("[]")
w.typ(t.Elem())
default:
w.string(t.Name())
}
}
func (w *writer) string(v string) {
io.WriteString(w.w, v)
}
func (w *writer) byte(v byte) {
if bw, ok := w.w.(io.ByteWriter); ok {
bw.WriteByte(v)
} else {
w.w.Write([]byte{v})
}
}
func isDefaultValue(v reflect.Value) bool {
switch v.Kind() {
case reflect.Ptr:
return v.IsNil()
case reflect.Interface:
return v.IsNil()
case reflect.Slice:
return v.IsNil() || v.Len() == 0
case reflect.Struct:
for i := 0; i < v.NumField(); i++ {
if !isDefaultValue(v.Field(i)) {
return false
}
}
return true
case reflect.Bool:
return !v.Bool()
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return v.Int() == 0
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return v.Uint() == 0
case reflect.String:
return v.String() == ""
case reflect.Func:
return false
default:
return false
}
}
// Copyright 2024 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package stat
import (
"sync"
"time"
)
type AverageParameter interface {
time.Duration
}
type AverageValue[T AverageParameter] struct {
mu sync.Mutex
total int64
avg T
}
func (av *AverageValue[T]) Value() T {
av.mu.Lock()
defer av.mu.Unlock()
return av.avg
}
func (av *AverageValue[T]) Save(val T) {
av.mu.Lock()
defer av.mu.Unlock()
av.total++
av.avg += (val - av.avg) / T(av.total)
}
// Copyright 2024 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package stat
import (
"fmt"
"reflect"
"sort"
"strconv"
"sync"
"sync/atomic"
"time"
"github.com/VividCortex/gohistogram"
"github.com/prometheus/client_golang/prometheus"
)
// This file provides prometheus/streamz style metrics (Val type) for instrumenting code for monitoring.
// It also provides a registry for such metrics (set type) and a global default registry.
//
// Simple uses of metrics:
//
// statFoo := stat.New("metric name", "metric description")
// statFoo.Add(1)
//
// stat.New("metric name", "metric description", LenOf(mySlice, rwMutex))
//
// Metric visualization code uses Collect/RenderGraphs functions to obtain values of all registered metrics.
type UI struct {
Name string
Desc string
Link string
Level Level
Value string
V int
}
func New(name, desc string, opts ...any) *Val {
return global.New(name, desc, opts...)
}
func Collect(level Level) []UI {
return global.Collect(level)
}
func RenderGraphs() []UIGraph {
return global.RenderGraphs()
}
var global = newSet(256, true)
type set struct {
mu sync.Mutex
vals map[string]*Val
graphs map[string]*graph
nextOrder atomic.Uint64
totalTicks int
historySize int
historyTicks int
historyPos int
historyScale int
}
type graph struct {
level Level
stacked bool
lines map[string]*line
}
type line struct {
name string
desc string
order uint64
rate bool
data []float64
hist []*gohistogram.NumericHistogram
}
const (
tickPeriod = time.Second
histogramBuckets = 255
)
func newSet(histSize int, tick bool) *set {
s := &set{
vals: make(map[string]*Val),
historySize: histSize,
historyScale: 1,
graphs: make(map[string]*graph),
}
if tick {
go func() {
for range time.NewTicker(tickPeriod).C {
s.tick()
}
}()
}
return s
}
func (s *set) Collect(level Level) []UI {
s.mu.Lock()
defer s.mu.Unlock()
period := time.Duration(s.totalTicks) * tickPeriod
if period == 0 {
period = tickPeriod
}
var res []UI
for _, v := range s.vals {
if v.level < level {
continue
}
val := v.Val()
res = append(res, UI{
Name: v.name,
Desc: v.desc,
Link: v.link,
Level: v.level,
Value: v.fmt(val, period),
V: val,
})
}
sort.Slice(res, func(i, j int) bool {
if res[i].Level != res[j].Level {
return res[i].Level > res[j].Level
}
return res[i].Name < res[j].Name
})
return res
}
// Additional options for Val metrics.
// Level controls if the metric should be printed to console in periodic heartbeat logs,
// or showed on the simple web interface, or showed in the expert interface only.
type Level int
const (
All Level = iota
Simple
Console
)
// Link adds a hyperlink to metric name.
type Link string
// Prometheus exports the metric to Prometheus under the given name.
type Prometheus string
// Rate says to collect/visualize metric rate per unit of time rather then total value.
type Rate struct{}
// Distribution says to collect/visualize histogram of individual sample distributions.
type Distribution struct{}
// Graph allows to combine multiple related metrics on a single graph.
type Graph string
// StackedGraph is like Graph, but shows metrics on a stacked graph.
type StackedGraph string
// NoGraph says to not visualize the metric as a graph.
const NoGraph Graph = ""
// LenOf reads the metric value from the given slice/map/chan.
func LenOf(containerPtr any, mu *sync.RWMutex) func() int {
v := reflect.ValueOf(containerPtr)
_ = v.Elem().Len() // panics if container is not slice/map/chan
return func() int {
mu.RLock()
defer mu.RUnlock()
return v.Elem().Len()
}
}
func FormatMB(v int, period time.Duration) string {
const KB, MB = 1 << 10, 1 << 20
return fmt.Sprintf("%v MB (%v kb/sec)", (v+MB/2)/MB, (v+KB/2)/KB/int(period/time.Second))
}
// Addittionally a custom 'func() int' can be passed to read the metric value from the function.
// and 'func(int, time.Duration) string' can be passed for custom formatting of the metric value.
func (s *set) New(name, desc string, opts ...any) *Val {
v := &Val{
name: name,
desc: desc,
graph: name,
order: s.nextOrder.Add(1),
fmt: func(v int, period time.Duration) string { return strconv.Itoa(v) },
}
stacked := false
for _, o := range opts {
switch opt := o.(type) {
case Level:
v.level = opt
case Link:
v.link = string(opt)
case Graph:
v.graph = string(opt)
case StackedGraph:
v.graph = string(opt)
stacked = true
case Rate:
v.rate = true
v.fmt = formatRate
case Distribution:
v.hist = true
case func() int:
v.ext = opt
case func(int, time.Duration) string:
v.fmt = opt
case Prometheus:
// Prometheus Instrumentation https://prometheus.io/docs/guides/go-application.
prometheus.Register(prometheus.NewGaugeFunc(prometheus.GaugeOpts{
Name: string(opt),
Help: desc,
},
func() float64 { return float64(v.Val()) },
))
default:
panic(fmt.Sprintf("unknown stats option %#v", o))
}
}
s.mu.Lock()
defer s.mu.Unlock()
s.vals[name] = v
if v.graph != "" {
if s.graphs[v.graph] == nil {
s.graphs[v.graph] = &graph{
lines: make(map[string]*line),
}
}
s.graphs[v.graph].level = max(s.graphs[v.graph].level, v.level)
s.graphs[v.graph].stacked = stacked
}
return v
}
type Val struct {
name string
desc string
link string
graph string
level Level
order uint64
val atomic.Uint64
ext func() int
fmt func(int, time.Duration) string
rate bool
hist bool
prev int
histMu sync.Mutex
histVal *gohistogram.NumericHistogram
}
func (v *Val) Add(val int) {
if v.ext != nil {
panic(fmt.Sprintf("stat %v is in external mode", v.name))
}
if v.hist {
v.histMu.Lock()
if v.histVal == nil {
v.histVal = gohistogram.NewHistogram(histogramBuckets)
}
v.histVal.Add(float64(val))
v.histMu.Unlock()
return
}
v.val.Add(uint64(val))
}
func (v *Val) Val() int {
if v.ext != nil {
return v.ext()
}
if v.hist {
v.histMu.Lock()
defer v.histMu.Unlock()
if v.histVal == nil {
return 0
}
return int(v.histVal.Mean())
}
return int(v.val.Load())
}
func formatRate(v int, period time.Duration) string {
secs := int(period.Seconds())
if x := v / secs; x >= 10 {
return fmt.Sprintf("%v (%v/sec)", v, x)
}
if x := v * 60 / secs; x >= 10 {
return fmt.Sprintf("%v (%v/min)", v, x)
}
x := v * 60 * 60 / secs
return fmt.Sprintf("%v (%v/hour)", v, x)
}
func (s *set) tick() {
s.mu.Lock()
defer s.mu.Unlock()
if s.historyPos == s.historySize {
s.compress()
}
s.totalTicks++
s.historyTicks++
for _, v := range s.vals {
if v.graph == "" {
continue
}
graph := s.graphs[v.graph]
ln := graph.lines[v.name]
if ln == nil {
ln = &line{
name: v.name,
desc: v.desc,
order: v.order,
rate: v.rate,
}
if v.hist {
ln.hist = make([]*gohistogram.NumericHistogram, s.historySize)
} else {
ln.data = make([]float64, s.historySize)
}
graph.lines[v.name] = ln
}
if v.hist {
if s.historyTicks == s.historyScale {
v.histMu.Lock()
ln.hist[s.historyPos] = v.histVal
v.histVal = nil
v.histMu.Unlock()
}
} else {
val := v.Val()
pv := &ln.data[s.historyPos]
if v.rate {
*pv += float64(val-v.prev) / float64(s.historyScale)
v.prev = val
} else {
*pv = max(*pv, float64(val))
}
}
}
if s.historyTicks != s.historyScale {
return
}
s.historyTicks = 0
s.historyPos++
}
func (s *set) compress() {
half := s.historySize / 2
s.historyPos = half
s.historyScale *= 2
for _, graph := range s.graphs {
for _, line := range graph.lines {
for i := 0; i < half; i++ {
if line.hist != nil {
h1, h2 := line.hist[2*i], line.hist[2*i+1]
line.hist[2*i], line.hist[2*i+1] = nil, nil
line.hist[i] = h1
if h1 == nil {
line.hist[i] = h2
}
} else {
v1, v2 := line.data[2*i], line.data[2*i+1]
line.data[2*i], line.data[2*i+1] = 0, 0
if line.rate {
line.data[i] = (v1 + v2) / 2
} else {
line.data[i] = v1
if v2 > v1 {
line.data[i] = v2
}
}
}
}
}
}
}
type UIGraph struct {
ID int
Title string
Stacked bool
Level Level
Lines []string
Points []UIPoint
}
type UIPoint struct {
X int
Y []float64
}
func (s *set) RenderGraphs() []UIGraph {
s.mu.Lock()
defer s.mu.Unlock()
var graphs []UIGraph
tick := s.historyScale * int(tickPeriod.Seconds())
for title, graph := range s.graphs {
if len(graph.lines) == 0 {
continue
}
var lines []*line
for _, ln := range graph.lines {
lines = append(lines, ln)
}
sort.Slice(lines, func(i, j int) bool {
return lines[i].order < lines[j].order
})
g := UIGraph{
ID: len(graphs),
Title: title,
Stacked: graph.stacked,
Level: graph.level,
Points: make([]UIPoint, s.historyPos),
}
for i := 0; i < s.historyPos; i++ {
g.Points[i].X = i * tick
}
for _, ln := range lines {
if ln.hist == nil {
g.Lines = append(g.Lines, ln.name+": "+ln.desc)
for i := 0; i < s.historyPos; i++ {
g.Points[i].Y = append(g.Points[i].Y, ln.data[i])
}
} else {
for _, percent := range []int{10, 50, 90} {
g.Lines = append(g.Lines, fmt.Sprintf("%v%%", percent))
for i := 0; i < s.historyPos; i++ {
v := 0.0
if ln.hist[i] != nil {
v = ln.hist[i].Quantile(float64(percent) / 100)
}
g.Points[i].Y = append(g.Points[i].Y, v)
}
}
}
}
graphs = append(graphs, g)
}
sort.Slice(graphs, func(i, j int) bool {
if graphs[i].Level != graphs[j].Level {
return graphs[i].Level > graphs[j].Level
}
return graphs[i].Title < graphs[j].Title
})
return graphs
}
// Copyright 2016 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
// TODO: strip " (discriminator N)", "constprop", "isra" from function names.
package symbolizer
import (
"bufio"
"fmt"
"io"
"os/exec"
"strconv"
"strings"
"github.com/google/syzkaller/pkg/osutil"
"github.com/google/syzkaller/sys/targets"
)
type addr2Line struct {
target *targets.Target
subprocs map[string]*subprocess
interner Interner
}
type subprocess struct {
cmd *exec.Cmd
stdin io.Closer
stdout io.Closer
input *bufio.Writer
scanner *bufio.Scanner
}
func (s *addr2Line) Symbolize(bin string, pcs ...uint64) ([]Frame, error) {
sub, err := s.getSubprocess(bin)
if err != nil {
return nil, err
}
return symbolize(&s.interner, sub.input, sub.scanner, pcs)
}
func (s *addr2Line) Close() {
for _, sub := range s.subprocs {
sub.stdin.Close()
sub.stdout.Close()
sub.cmd.Process.Kill()
sub.cmd.Wait()
}
}
func (s *addr2Line) getSubprocess(bin string) (*subprocess, error) {
if sub := s.subprocs[bin]; sub != nil {
return sub, nil
}
addr2line, err := s.target.Addr2Line()
if err != nil {
return nil, err
}
cmd := osutil.Command(addr2line, "-afi", "-e", bin)
stdin, err := cmd.StdinPipe()
if err != nil {
return nil, err
}
stdout, err := cmd.StdoutPipe()
if err != nil {
stdin.Close()
return nil, err
}
if err := cmd.Start(); err != nil {
stdin.Close()
stdout.Close()
return nil, err
}
sub := &subprocess{
cmd: cmd,
stdin: stdin,
stdout: stdout,
input: bufio.NewWriter(stdin),
scanner: bufio.NewScanner(stdout),
}
if s.subprocs == nil {
s.subprocs = make(map[string]*subprocess)
}
s.subprocs[bin] = sub
return sub, nil
}
func symbolize(interner *Interner, input *bufio.Writer, scanner *bufio.Scanner, pcs []uint64) ([]Frame, error) {
var frames []Frame
done := make(chan error, 1)
go func() {
var err error
defer func() {
done <- err
}()
if !scanner.Scan() {
if err = scanner.Err(); err == nil {
err = io.EOF
}
return
}
for range pcs {
var frames1 []Frame
frames1, err = parse(interner, scanner)
if err != nil {
return
}
frames = append(frames, frames1...)
}
for i := 0; i < 2; i++ {
scanner.Scan()
}
}()
for _, pc := range pcs {
if _, err := fmt.Fprintf(input, "0x%x\n", pc); err != nil {
return nil, err
}
}
// Write an invalid PC so that parse doesn't block reading input.
// We read out result for this PC at the end of the function.
if _, err := fmt.Fprintf(input, "0xffffffffffffffff\n"); err != nil {
return nil, err
}
input.Flush()
if err := <-done; err != nil {
return nil, err
}
return frames, nil
}
func parse(interner *Interner, s *bufio.Scanner) ([]Frame, error) {
pc, err := strconv.ParseUint(s.Text(), 0, 64)
if err != nil {
return nil, fmt.Errorf("failed to parse pc '%v' in addr2line output: %w", s.Text(), err)
}
var frames []Frame
for s.Scan() {
ln := s.Text()
if len(ln) > 3 && ln[0] == '0' && ln[1] == 'x' {
break
}
fn := ln
if !s.Scan() {
err := s.Err()
if err == nil {
err = io.EOF
}
return nil, fmt.Errorf("failed to read file:line from addr2line: %w", err)
}
ln = s.Text()
colon := strings.LastIndexByte(ln, ':')
if colon == -1 {
return nil, fmt.Errorf("failed to parse file:line in addr2line output: %v", ln)
}
lineEnd := colon + 1
for lineEnd < len(ln) && ln[lineEnd] >= '0' && ln[lineEnd] <= '9' {
lineEnd++
}
file := ln[:colon]
line, err := strconv.Atoi(ln[colon+1 : lineEnd])
if err != nil || fn == "" || fn == "??" || file == "" || file == "??" || line < 0 {
continue
}
if line == 0 {
line = -1
}
frames = append(frames, Frame{
PC: pc,
Func: interner.Do(fn),
File: interner.Do(file),
Line: line,
Inline: true,
})
}
if err := s.Err(); err != nil {
return nil, err
}
if len(frames) != 0 {
frames[len(frames)-1].Inline = false
}
return frames, nil
}
// Copyright 2024 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package symbolizer
import (
"strings"
"sync"
)
// Cache caches symbolization results from Symbolizer in a thread-safe way.
type Cache struct {
mu sync.RWMutex
cache map[cacheKey]cacheVal
}
type cacheKey struct {
bin string
pc uint64
}
type cacheVal struct {
frames []Frame
err error
}
func (c *Cache) Symbolize(inner func(string, ...uint64) ([]Frame, error), bin string, pc uint64) ([]Frame, error) {
key := cacheKey{bin, pc}
c.mu.RLock()
val, ok := c.cache[key]
c.mu.RUnlock()
if ok {
return val.frames, val.err
}
frames, err := inner(bin, pc)
c.mu.Lock()
if c.cache == nil {
c.cache = make(map[cacheKey]cacheVal)
}
c.cache[key] = cacheVal{frames, err}
c.mu.Unlock()
return frames, err
}
// Interner allows to intern/deduplicate strings.
// Interner.Do semantically returns the same string, but physically it will point
// to an existing string with the same contents (if there was one passed to Do in the past).
// Interned strings are also "cloned", that is, if the passed string points to a large
// buffer, it won't after interning (and won't prevent GC'ing of the large buffer).
// The type is not thread-safe.
type Interner struct {
m sync.Map
}
func (in *Interner) Do(s string) string {
if interned, ok := in.m.Load(s); ok {
return interned.(string)
}
s = strings.Clone(s)
in.m.Store(s, s)
return s
}
// Copyright 2016 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package symbolizer
import (
"debug/elf"
"fmt"
"sort"
)
type Symbol struct {
Addr uint64
Size int
}
// ReadTextSymbols returns list of text symbols in the binary bin.
func ReadTextSymbols(bin string) (map[string][]Symbol, error) {
return read(bin, true)
}
// ReadRodataSymbols returns list of rodata symbols in the binary bin.
func ReadRodataSymbols(bin string) (map[string][]Symbol, error) {
return read(bin, false)
}
func read(bin string, text bool) (map[string][]Symbol, error) {
raw, err := load(bin, text)
if err != nil {
return nil, err
}
sort.Slice(raw, func(i, j int) bool {
return raw[i].Value > raw[j].Value
})
symbols := make(map[string][]Symbol)
// Function sizes reported by the Linux kernel do not match symbol tables.
// The kernel computes size of a symbol based on the start of the next symbol.
// We need to do the same to match kernel sizes to be able to find the right
// symbol across multiple symbols with the same name.
var prevAddr uint64
var prevSize int
for _, symb := range raw {
size := int(symb.Size)
if text {
if symb.Value == prevAddr {
size = prevSize
} else if prevAddr != 0 {
size = int(prevAddr - symb.Value)
}
prevAddr, prevSize = symb.Value, size
}
symbols[symb.Name] = append(symbols[symb.Name], Symbol{symb.Value, size})
}
return symbols, nil
}
func load(bin string, text bool) ([]elf.Symbol, error) {
file, err := elf.Open(bin)
if err != nil {
return nil, fmt.Errorf("failed to open ELF file %v: %w", bin, err)
}
allSymbols, err := file.Symbols()
if err != nil {
return nil, fmt.Errorf("failed to read ELF symbols: %w", err)
}
var symbols []elf.Symbol
for _, symb := range allSymbols {
if symb.Size == 0 || symb.Section < 0 || int(symb.Section) >= len(file.Sections) {
continue
}
sect := file.Sections[symb.Section]
isText := sect.Type == elf.SHT_PROGBITS &&
sect.Flags&elf.SHF_ALLOC != 0 &&
sect.Flags&elf.SHF_EXECINSTR != 0
// Note: x86_64 vmlinux .rodata is marked as writable and according to flags it looks like .data,
// so we look at the name.
if text && !isText || !text && sect.Name != ".rodata" {
continue
}
symbols = append(symbols, symb)
}
return symbols, nil
}
// Copyright 2025 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package symbolizer
import "github.com/google/syzkaller/sys/targets"
type Frame struct {
PC uint64
Func string
File string
Line int
Inline bool
}
type Symbolizer interface {
Symbolize(bin string, pcs ...uint64) ([]Frame, error)
Close()
}
func Make(target *targets.Target) Symbolizer {
return &addr2Line{target: target}
}
// Copyright 2022 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package testutil
import (
"math/rand"
"os"
"reflect"
"strconv"
"testing"
"testing/quick"
"time"
)
func IterCount() int {
iters := 1000
if testing.Short() {
iters /= 10
}
if RaceEnabled {
iters /= 10
}
return iters
}
func RandSource(t *testing.T) rand.Source {
seed := time.Now().UnixNano()
if fixed := os.Getenv("SYZ_SEED"); fixed != "" {
seed, _ = strconv.ParseInt(fixed, 0, 64)
}
if os.Getenv("CI") != "" {
seed = 0 // required for deterministic coverage reports
}
t.Logf("seed=%v", seed)
return rand.NewSource(seed)
}
func RandMountImage(r *rand.Rand) []byte {
const maxLen = 1 << 20 // 1 MB.
len := r.Intn(maxLen)
slice := make([]byte, len)
r.Read(slice)
return slice
}
// RandValue creates a random value of the same type as the argument typ.
// It recursively fills structs/slices/maps similar to testing/quick.Value,
// but it handles time.Time as well w/o panicing (unfortunately testing/quick panics on time.Time).
func RandValue(t *testing.T, typ any) any {
return randValue(t, rand.New(RandSource(t)), reflect.TypeOf(typ)).Interface()
}
func randValue(t *testing.T, rnd *rand.Rand, typ reflect.Type) reflect.Value {
v := reflect.New(typ).Elem()
switch typ.Kind() {
default:
ok := false
v, ok = quick.Value(typ, rnd)
if !ok {
t.Fatalf("failed to generate random value of type %v", typ)
}
case reflect.Slice:
size := rand.Intn(4)
v.Set(reflect.MakeSlice(typ, size, size))
fallthrough
case reflect.Array:
for i := 0; i < v.Len(); i++ {
v.Index(i).Set(randValue(t, rnd, typ.Elem()))
}
case reflect.Struct:
if typ.String() == "time.Time" {
v = reflect.ValueOf(time.UnixMilli(rnd.Int63()))
} else {
for i := 0; i < v.NumField(); i++ {
v.Field(i).Set(randValue(t, rnd, typ.Field(i).Type))
}
}
case reflect.Pointer:
v.SetZero()
if rand.Intn(2) == 0 {
v.Set(reflect.New(typ.Elem()))
v.Elem().Set(randValue(t, rnd, typ.Elem()))
}
case reflect.Map:
v.Set(reflect.MakeMap(typ))
for i := rand.Intn(4); i > 0; i-- {
v.SetMapIndex(randValue(t, rnd, typ.Key()), randValue(t, rnd, typ.Elem()))
}
}
return v
}
type Writer struct {
testing.TB
}
func (w *Writer) Write(data []byte) (int, error) {
w.TB.Logf("%s", data)
return len(data), nil
}
// Copyright 2018 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package vcs
import (
"fmt"
"os"
"path/filepath"
"time"
"github.com/google/syzkaller/pkg/osutil"
)
// TODO: Check out branches and commits from Fuchsia's global integration repo
// rather than fuchsia.git.
type fuchsia struct {
dir string
repo *gitRepo
}
func newFuchsia(dir string, opts []RepoOpt) *fuchsia {
// For now, don't clean up the Fuchsia repo when checking out new commits or branches.
// Otherwise, subsequent builds will fail due to missing GN args and other build configuration.
// TODO: Implement selective cleanup with `fx clean`.
opts = append(opts, OptPrecious)
return &fuchsia{
dir: dir,
repo: newGitRepo(dir, nil, opts),
}
}
func (ctx *fuchsia) Poll(repo, branch string) (*Commit, error) {
if repo != "https://fuchsia.googlesource.com/fuchsia" || (branch != "main" && branch != "master") {
// Fuchsia ecosystem is hard-wired to the main repo + branch.
// The 'master' branch is a mirror of 'main'.
return nil, fmt.Errorf(
"fuchsia: can only check out 'main' or 'master' branch of https://fuchsia.googlesource.com/fuchsia",
)
}
if _, err := runSandboxed(ctx.dir, "./.jiri_root/bin/jiri", "update"); err != nil {
if err := ctx.initRepo(); err != nil {
return nil, err
}
}
return ctx.repo.Commit(HEAD)
}
func (ctx *fuchsia) initRepo() error {
if err := os.RemoveAll(ctx.dir); err != nil {
return fmt.Errorf("failed to remove repo dir: %w", err)
}
tmpDir := ctx.dir + ".tmp"
if err := osutil.MkdirAll(tmpDir); err != nil {
return fmt.Errorf("failed to create repo dir: %w", err)
}
defer os.RemoveAll(tmpDir)
if err := osutil.SandboxChown(tmpDir); err != nil {
return err
}
cmd := "curl -s 'https://fuchsia.googlesource.com/fuchsia/+/main/scripts/bootstrap?format=TEXT' |" +
"base64 --decode | bash"
// TODO: Remove the second `jiri update` once the `prebuilt_versions` hook is fixed.
// Expect and ignore an error from the bootstrap script's invocation of `jiri update`.
_, _ = runSandboxed(tmpDir, "bash", "-c", cmd)
// Run `jiri update` a second time; it should succeed.
if _, err := runSandboxed(filepath.Join(tmpDir, "fuchsia"), "./.jiri_root/bin/jiri", "update"); err != nil {
return err
}
return osutil.Rename(filepath.Join(tmpDir, "fuchsia"), ctx.dir)
}
func (ctx *fuchsia) CheckoutBranch(repo, branch string) (*Commit, error) {
return ctx.repo.CheckoutBranch(repo, branch)
}
func (ctx *fuchsia) CheckoutCommit(repo, commit string) (*Commit, error) {
return ctx.repo.CheckoutCommit(repo, commit)
}
func (ctx *fuchsia) SwitchCommit(commit string) (*Commit, error) {
return ctx.repo.SwitchCommit(commit)
}
func (ctx *fuchsia) Commit(commit string) (*Commit, error) {
return ctx.repo.Commit(commit)
}
func (ctx *fuchsia) GetCommitByTitle(title string) (*Commit, error) {
return ctx.repo.GetCommitByTitle(title)
}
func (ctx *fuchsia) GetCommitsByTitles(titles []string) ([]*Commit, []string, error) {
return ctx.repo.GetCommitsByTitles(titles)
}
func (ctx *fuchsia) ExtractFixTagsFromCommits(baseCommit, email string) ([]*Commit, error) {
return ctx.repo.ExtractFixTagsFromCommits(baseCommit, email)
}
func (ctx *fuchsia) ReleaseTag(commit string) (string, error) {
return ctx.repo.ReleaseTag(commit)
}
func (ctx *fuchsia) Contains(commit string) (bool, error) {
return ctx.repo.Contains(commit)
}
func (ctx *fuchsia) LatestCommits(afterCommit string, afterDate time.Time) ([]CommitShort, error) {
return ctx.repo.LatestCommits(afterCommit, afterDate)
}
func (ctx *fuchsia) Object(name, commit string) ([]byte, error) {
return ctx.repo.Object(name, commit)
}
func (ctx *fuchsia) MergeBases(firstCommit, secondCommit string) ([]*Commit, error) {
return ctx.repo.MergeBases(firstCommit, secondCommit)
}
func (ctx *fuchsia) CommitExists(commit string) (bool, error) {
return ctx.repo.CommitExists(commit)
}
func (ctx *fuchsia) PushCommit(repo, commit string) error {
// Fuchsia repo doesn't accept unauthenticated pushes.
return fmt.Errorf("not implemented for fuchsia: PushCommit")
}
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package vcs
import (
"bufio"
"bytes"
"errors"
"fmt"
"net/mail"
"os"
"os/exec"
"regexp"
"sort"
"strings"
"time"
"github.com/google/syzkaller/pkg/debugtracer"
"github.com/google/syzkaller/pkg/hash"
"github.com/google/syzkaller/pkg/log"
"github.com/google/syzkaller/pkg/osutil"
)
type gitRepo struct {
*Git
}
func newGitRepo(dir string, ignoreCC map[string]bool, opts []RepoOpt) *gitRepo {
git := &gitRepo{
Git: &Git{
Dir: dir,
Sandbox: true,
Env: filterEnv(),
ignoreCC: ignoreCC,
},
}
for _, opt := range opts {
switch opt {
case OptPrecious:
git.precious = true
case OptDontSandbox:
git.Sandbox = false
}
}
return git
}
func filterEnv() []string {
// We have to filter various git environment variables - if
// these variables are set (e.g. if a test is being run as
// part of a rebase) we're going to be acting on some other
// repository (e.g the syzkaller tree itself) rather than the
// intended repo.
env := os.Environ()
for i := 0; i < len(env); i++ {
if strings.HasPrefix(env[i], "GIT_DIR") ||
strings.HasPrefix(env[i], "GIT_WORK_TREE") ||
strings.HasPrefix(env[i], "GIT_INDEX_FILE") ||
strings.HasPrefix(env[i], "GIT_OBJECT_DIRECTORY") {
env = append(env[:i], env[i+1:]...)
i--
}
}
return env
}
func (git *gitRepo) Poll(repo, branch string) (*Commit, error) {
git.Reset()
origin, err := git.Run("remote", "get-url", "origin")
if err != nil || strings.TrimSpace(string(origin)) != repo {
// The repo is here, but it has wrong origin (e.g. repo in config has changed), re-clone.
if err := git.clone(repo, branch); err != nil {
return nil, err
}
}
// Use origin/branch for the case the branch was force-pushed,
// in such case branch is not the same is origin/branch and we will
// stuck with the local version forever (git checkout won't fail).
if _, err := git.Run("checkout", "origin/"+branch); err != nil {
// No such branch (e.g. branch in config has changed), re-clone.
if err := git.clone(repo, branch); err != nil {
return nil, err
}
}
if output, err := git.Run("fetch", "--force"); err != nil {
if git.isNetworkError(output) {
// The clone operation will fail as well, so no sense to re-clone.
return nil, err
}
if err := git.clone(repo, branch); err != nil {
return nil, err
}
}
if _, err := git.Run("checkout", "origin/"+branch); err != nil {
return nil, err
}
if _, err := git.Run("submodule", "update", "--init"); err != nil {
return nil, err
}
return git.Commit(HEAD)
}
func (git *gitRepo) isNetworkError(output []byte) bool {
// The list is not exhaustive and is meant to be extended over time.
return bytes.Contains(output, []byte("fatal: read error: Connection reset by peer"))
}
func (git *gitRepo) CheckoutBranch(repo, branch string) (*Commit, error) {
if err := git.repair(); err != nil {
return nil, err
}
repoHash := hash.String([]byte(repo))
// Because the HEAD is detached, submodules assumes "origin" to be the default
// remote when initializing.
// This sets "origin" to be the current remote.
// Ignore errors as we can double add or remove the same remote and that will fail.
git.Run("remote", "rm", "origin")
git.Run("remote", "add", "origin", repo)
git.Run("remote", "add", repoHash, repo)
_, err := git.Run("fetch", "--force", repoHash, branch)
if err != nil {
return nil, err
}
if _, err := git.Run("checkout", "FETCH_HEAD", "--force"); err != nil {
return nil, err
}
if _, err := git.Run("submodule", "update", "--init"); err != nil {
return nil, err
}
// If the branch checkout had to be "forced" the directory may
// contain remaining untracked files.
// Clean again to ensure the new branch is in a clean state.
if err := git.repair(); err != nil {
return nil, err
}
return git.Commit(HEAD)
}
func (git *gitRepo) CheckoutCommit(repo, commit string) (*Commit, error) {
if err := git.repair(); err != nil {
return nil, err
}
if err := git.fetchRemote(repo, commit); err != nil {
return nil, err
}
return git.SwitchCommit(commit)
}
func (git *gitRepo) fetchRemote(repo, commit string) error {
repoHash := hash.String([]byte(repo))
// Ignore error as we can double add the same remote and that will fail.
git.Run("remote", "add", repoHash, repo)
fetchArgs := []string{"fetch", "--force", "--tags", repoHash}
if commit != "" && gitFullHashRe.MatchString(commit) {
// This trick only works with full commit hashes.
fetchArgs = append(fetchArgs, commit)
}
_, err := git.Run(fetchArgs...)
if err != nil {
var verbose *osutil.VerboseError
if errors.As(err, &verbose) &&
bytes.Contains(verbose.Output, []byte("error: cannot lock ref")) {
// It can happen that the fetched repo has tags names that conflict
// with the ones already present in the repository.
// Try to fetch more, but this time prune tags, it should help.
// The --prune-tags option will remove all tags that are not present
// in this remote repo, so don't do it always. Only when necessary.
_, err = git.Run("fetch", "--force", "--tags", "--prune", "--prune-tags", repoHash)
}
}
return err
}
func (git *gitRepo) SwitchCommit(commit string) (*Commit, error) {
if !git.precious {
git.Run("reset", "--hard")
git.Run("clean", "-fdx")
}
if _, err := git.Run("checkout", commit); err != nil {
return nil, err
}
if _, err := git.Run("submodule", "update", "--init"); err != nil {
return nil, err
}
return git.Commit(HEAD)
}
func (git *gitRepo) clone(repo, branch string) error {
if git.precious {
return fmt.Errorf("won't reinit precious repo")
}
if err := git.initRepo(nil); err != nil {
return err
}
if _, err := git.Run("remote", "add", "origin", repo); err != nil {
return err
}
if _, err := git.Run("fetch", "origin", branch); err != nil {
return err
}
return nil
}
func (git *gitRepo) repair() error {
if err := git.Reset(); err != nil {
return git.initRepo(err)
}
return nil
}
func (git *gitRepo) initRepo(reason error) error {
if reason != nil {
log.Logf(1, "git: initializing repo at %v: %v", git.Dir, reason)
}
if err := os.RemoveAll(git.Dir); err != nil {
return fmt.Errorf("failed to remove repo dir: %w", err)
}
if err := osutil.MkdirAll(git.Dir); err != nil {
return fmt.Errorf("failed to create repo dir: %w", err)
}
if git.Sandbox {
if err := osutil.SandboxChown(git.Dir); err != nil {
return err
}
}
if _, err := git.Run("init"); err != nil {
return err
}
return nil
}
func (git *gitRepo) Contains(commit string) (bool, error) {
_, err := git.Run("merge-base", "--is-ancestor", commit, HEAD)
return err == nil, nil
}
const gitDateFormat = "Mon Jan 2 15:04:05 2006 -0700"
func gitParseCommit(output, user, domain []byte, ignoreCC map[string]bool) (*Commit, error) {
lines := bytes.Split(output, []byte{'\n'})
if len(lines) < 8 || len(lines[0]) != 40 {
return nil, fmt.Errorf("unexpected git log output: %q", output)
}
date, err := time.Parse(gitDateFormat, string(lines[4]))
if err != nil {
return nil, fmt.Errorf("failed to parse date in git log output: %w\n%q", err, output)
}
commitDate, err := time.Parse(gitDateFormat, string(lines[6]))
if err != nil {
return nil, fmt.Errorf("failed to parse date in git log output: %w\n%q", err, output)
}
recipients := make(map[string]bool)
recipients[strings.ToLower(string(lines[2]))] = true
var tags []string
// Use summary line + all description lines.
for _, line := range append([][]byte{lines[1]}, lines[7:]...) {
if user != nil {
userPos := bytes.Index(line, user)
if userPos != -1 {
domainPos := bytes.Index(line[userPos+len(user)+1:], domain)
if domainPos != -1 {
startPos := userPos + len(user)
endPos := userPos + len(user) + domainPos + 1
tag := string(line[startPos:endPos])
present := false
for _, tag1 := range tags {
if tag1 == tag {
present = true
break
}
}
if !present {
tags = append(tags, tag)
}
}
}
}
for _, re := range ccRes {
matches := re.FindSubmatchIndex(line)
if matches == nil {
continue
}
addr, err := mail.ParseAddress(string(line[matches[2]:matches[3]]))
if err != nil {
break
}
email := strings.ToLower(addr.Address)
if ignoreCC[email] {
continue
}
recipients[email] = true
break
}
}
sortedRecipients := make(Recipients, 0, len(recipients))
for addr := range recipients {
sortedRecipients = append(sortedRecipients, RecipientInfo{mail.Address{Address: addr}, To})
}
sort.Sort(sortedRecipients)
parents := strings.Split(string(lines[5]), " ")
com := &Commit{
Hash: string(lines[0]),
Title: string(lines[1]),
Author: string(lines[2]),
AuthorName: string(lines[3]),
Parents: parents,
Recipients: sortedRecipients,
Tags: tags,
Date: date,
CommitDate: commitDate,
}
return com, nil
}
func (git *gitRepo) GetCommitByTitle(title string) (*Commit, error) {
commits, _, err := git.GetCommitsByTitles([]string{title})
if err != nil || len(commits) == 0 {
return nil, err
}
return commits[0], nil
}
const (
fetchCommitsMaxAgeInYears = 5
)
func (git *gitRepo) GetCommitsByTitles(titles []string) ([]*Commit, []string, error) {
var greps []string
m := make(map[string]string)
for _, title := range titles {
canonical := CanonicalizeCommit(title)
greps = append(greps, canonical)
m[canonical] = title
}
since := time.Now().Add(-time.Hour * 24 * 365 * fetchCommitsMaxAgeInYears).Format("01-02-2006")
commits, err := git.fetchCommits(since, HEAD, "", "", greps, true)
if err != nil {
return nil, nil, err
}
var results []*Commit
for _, com := range commits {
canonical := CanonicalizeCommit(com.Title)
if orig := m[canonical]; orig != "" {
delete(m, canonical)
results = append(results, com)
com.Title = orig
}
}
var missing []string
for _, orig := range m {
missing = append(missing, orig)
}
return results, missing, nil
}
func (git *gitRepo) LatestCommits(afterCommit string, afterDate time.Time) ([]CommitShort, error) {
args := []string{"log", "--pretty=format:%h:%cd"}
if !afterDate.IsZero() {
args = append(args, "--since", afterDate.Format(time.RFC3339))
}
if afterCommit != "" {
args = append(args, afterCommit+"..")
}
output, err := git.Run(args...)
if err != nil {
return nil, err
}
if len(output) == 0 {
return nil, nil
}
var ret []CommitShort
for _, line := range strings.Split(string(output), "\n") {
hash, date, _ := strings.Cut(line, ":")
commitDate, err := time.Parse(gitDateFormat, date)
if err != nil {
return nil, fmt.Errorf("failed to parse date in %q: %w", line, err)
}
ret = append(ret, CommitShort{Hash: hash, CommitDate: commitDate})
}
return ret, nil
}
func (git *gitRepo) ExtractFixTagsFromCommits(baseCommit, email string) ([]*Commit, error) {
user, domain, err := splitEmail(email)
if err != nil {
return nil, fmt.Errorf("failed to parse email %q: %w", email, err)
}
grep := user + "+.*" + domain
since := time.Now().Add(-time.Hour * 24 * 365 * fetchCommitsMaxAgeInYears).Format("01-02-2006")
return git.fetchCommits(since, baseCommit, user, domain, []string{grep}, false)
}
func splitEmail(email string) (user, domain string, err error) {
addr, err := mail.ParseAddress(email)
if err != nil {
return "", "", err
}
at := strings.IndexByte(addr.Address, '@')
if at == -1 {
return "", "", fmt.Errorf("no @ in email address")
}
user = addr.Address[:at]
domain = addr.Address[at:]
if plus := strings.IndexByte(user, '+'); plus != -1 {
user = user[:plus]
}
return
}
func (git *gitRepo) Bisect(bad, good string, dt debugtracer.DebugTracer, pred func() (BisectResult,
error)) ([]*Commit, error) {
git.Reset()
firstBad, err := git.Commit(bad)
if err != nil {
return nil, err
}
output, err := git.Run("bisect", "start", bad, good)
if err != nil {
return nil, err
}
defer git.Reset()
dt.Log("# git bisect start %v %v\n%s", bad, good, output)
current, err := git.Commit(HEAD)
if err != nil {
return nil, err
}
var bisectTerms = [...]string{
BisectBad: "bad",
BisectGood: "good",
BisectSkip: "skip",
}
for {
res, err := pred()
// Linux EnvForCommit may cherry-pick some fixes, reset these before the next step.
git.Run("reset", "--hard")
if err != nil {
return nil, err
}
if res == BisectBad {
firstBad = current
}
output, err = git.Run("bisect", bisectTerms[res])
dt.Log("# git bisect %v %v\n%s", bisectTerms[res], current.Hash, output)
if err != nil {
if bytes.Contains(output, []byte("There are only 'skip'ped commits left to test")) {
return git.bisectInconclusive(output)
}
return nil, err
}
next, err := git.Commit(HEAD)
if err != nil {
return nil, err
}
if current.Hash == next.Hash {
return []*Commit{firstBad}, nil
}
current = next
}
}
var gitFullHashRe = regexp.MustCompile("[a-f0-9]{40}")
func (git *gitRepo) bisectInconclusive(output []byte) ([]*Commit, error) {
// For inconclusive bisection git prints the following message:
//
// There are only 'skip'ped commits left to test.
// The first bad commit could be any of:
// 1f43f400a2cbb02f3d34de8fe30075c070254816
// 4d96e13ee9cd1f7f801e8c7f4b12f09d1da4a5d8
// 5cd856a5ef9aa189df757c322be34ad735a5b17f
// We cannot bisect more!
//
// For conclusive bisection:
//
// 7c3850adbcccc2c6c9e7ab23a7dcbc4926ee5b96 is the first bad commit
var commits []*Commit
for _, hash := range gitFullHashRe.FindAll(output, -1) {
com, err := git.Commit(string(hash))
if err != nil {
return nil, err
}
commits = append(commits, com)
}
return commits, nil
}
func (git *gitRepo) ReleaseTag(commit string) (string, error) {
tags, err := git.previousReleaseTags(commit, true, true, true)
if err != nil {
return "", err
}
if len(tags) == 0 {
return "", fmt.Errorf("no release tags found for commit %v", commit)
}
return tags[0], nil
}
func (git *gitRepo) previousReleaseTags(commit string, self, onlyTop, includeRC bool) ([]string, error) {
var tags []string
if self {
output, err := git.Run("tag", "--list", "--points-at", commit, "--merged", commit, "v*.*")
if err != nil {
return nil, err
}
tags = gitParseReleaseTags(output, includeRC)
if onlyTop && len(tags) != 0 {
return tags, nil
}
}
output, err := git.Run("tag", "--no-contains", commit, "--merged", commit, "v*.*")
if err != nil {
return nil, err
}
tags1 := gitParseReleaseTags(output, includeRC)
tags = append(tags, tags1...)
if len(tags) == 0 {
return nil, fmt.Errorf("no release tags found for commit %v", commit)
}
return tags, nil
}
func (git *gitRepo) IsRelease(commit string) (bool, error) {
tags1, err := git.previousReleaseTags(commit, true, false, false)
if err != nil {
return false, err
}
tags2, err := git.previousReleaseTags(commit, false, false, false)
if err != nil {
return false, err
}
return len(tags1) != len(tags2), nil
}
func (git *gitRepo) Object(name, commit string) ([]byte, error) {
return git.Run("show", fmt.Sprintf("%s:%s", commit, name))
}
func (git *gitRepo) MergeBases(firstCommit, secondCommit string) ([]*Commit, error) {
output, err := git.Run("merge-base", firstCommit, secondCommit)
if err != nil {
return nil, err
}
ret := []*Commit{}
for _, hash := range strings.Fields(string(output)) {
commit, err := git.Commit(hash)
if err != nil {
return nil, err
}
ret = append(ret, commit)
}
return ret, nil
}
// CommitExists relies on 'git cat-file -e'.
// If object exists its exit status is 0.
// If object doesn't exist its exit status is 1 (not documented).
// Otherwise, the exit status is 128 (not documented).
func (git *gitRepo) CommitExists(commit string) (bool, error) {
_, err := git.Run("cat-file", "-e", commit)
var vErr *osutil.VerboseError
if errors.As(err, &vErr) && vErr.ExitCode == 1 {
return false, nil
}
if err != nil {
return false, err
}
return true, nil
}
func (git *gitRepo) PushCommit(repo, commit string) error {
tagName := "tag-" + commit // assign tag to guarantee remote persistence
git.Run("tag", tagName) // ignore errors on re-tagging
if _, err := git.Run("push", repo, "tag", tagName); err != nil {
return fmt.Errorf("git push %s tag %s: %w", repo, tagName, err)
}
return nil
}
var fileNameRe = regexp.MustCompile(`(?m)^diff.* b\/([^\s]+)`)
// ParseGitDiff extracts the files modified in the git patch.
func ParseGitDiff(patch []byte) []string {
var files []string
for _, match := range fileNameRe.FindAllStringSubmatch(string(patch), -1) {
files = append(files, match[1])
}
return files
}
type Git struct {
Dir string
Sandbox bool
Env []string
precious bool
ignoreCC map[string]bool
}
func (git Git) Run(args ...string) ([]byte, error) {
cmd, err := git.command(args...)
if err != nil {
return nil, err
}
return osutil.Run(3*time.Hour, cmd)
}
func (git Git) command(args ...string) (*exec.Cmd, error) {
cmd := osutil.Command("git", args...)
cmd.Dir = git.Dir
cmd.Env = git.Env
if git.Sandbox {
if err := osutil.Sandbox(cmd, true, false); err != nil {
return nil, err
}
}
return cmd, nil
}
// Apply invokes git apply for a series of git patches.
// It is different from Patch() in that it normally handles raw patch emails.
func (git Git) Apply(patch []byte) error {
cmd, err := git.command("apply", "-")
if err != nil {
return err
}
stdin, err := cmd.StdinPipe()
if err != nil {
return err
}
go func() {
stdin.Write(patch)
stdin.Close()
}()
_, err = osutil.Run(3*time.Hour, cmd)
return err
}
// Reset resets the git repo to a known clean state.
func (git Git) Reset() error {
if git.precious {
return nil
}
git.Run("reset", "--hard", "--recurse-submodules")
git.Run("clean", "-xfdf")
git.Run("submodule", "foreach", "--recursive", "git", "clean", "-xfdf")
git.Run("bisect", "reset")
_, err := git.Run("reset", "--hard", "--recurse-submodules")
return err
}
// Commit extracts the information about the particular git commit.
func (git Git) Commit(hash string) (*Commit, error) {
const patchSeparator = "---===syzkaller-patch-separator===---"
output, err := git.Run("log", "--format=%H%n%s%n%ae%n%an%n%ad%n%P%n%cd%n%b"+patchSeparator,
"-n", "1", "-p", "-U0", hash)
if err != nil {
return nil, err
}
pos := bytes.Index(output, []byte(patchSeparator))
if pos == -1 {
return nil, fmt.Errorf("git log output does not contain patch separator")
}
commit, err := gitParseCommit(output[:pos], nil, nil, git.ignoreCC)
if err != nil {
return nil, err
}
commit.Patch = output[pos+len(patchSeparator):]
for len(commit.Patch) != 0 && commit.Patch[0] == '\n' {
commit.Patch = commit.Patch[1:]
}
return commit, nil
}
func (git Git) fetchCommits(since, base, user, domain string, greps []string, fixedStrings bool) ([]*Commit, error) {
const commitSeparator = "---===syzkaller-commit-separator===---"
args := []string{"log", "--since", since, "--format=%H%n%s%n%ae%n%an%n%ad%n%P%n%cd%n%b%n" + commitSeparator}
if fixedStrings {
args = append(args, "--fixed-strings")
}
for _, grep := range greps {
args = append(args, "--grep", grep)
}
args = append(args, base)
cmd := exec.Command("git", args...)
cmd.Dir = git.Dir
cmd.Env = filterEnv()
if git.Sandbox {
if err := osutil.Sandbox(cmd, true, false); err != nil {
return nil, err
}
}
stdout, err := cmd.StdoutPipe()
if err != nil {
return nil, err
}
if err := cmd.Start(); err != nil {
return nil, err
}
defer cmd.Wait()
defer cmd.Process.Kill()
var (
s = bufio.NewScanner(stdout)
buf = new(bytes.Buffer)
separator = []byte(commitSeparator)
commits []*Commit
userBytes []byte
domainBytes []byte
)
if user != "" {
userBytes = []byte(user + "+")
domainBytes = []byte(domain)
}
for s.Scan() {
ln := s.Bytes()
if !bytes.Equal(ln, separator) {
buf.Write(ln)
buf.WriteByte('\n')
continue
}
com, err := gitParseCommit(buf.Bytes(), userBytes, domainBytes, git.ignoreCC)
if err != nil {
return nil, err
}
if user == "" || len(com.Tags) != 0 {
commits = append(commits, com)
}
buf.Reset()
}
return commits, s.Err()
}
// Copyright 2019 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package vcs
import (
"fmt"
"path/filepath"
"strings"
"testing"
"time"
"github.com/google/syzkaller/pkg/osutil"
)
const (
userEmail = `test@syzkaller.com`
userName = `Test Syzkaller`
extractFixTagsEmail = `"syzbot" <syzbot@my.mail.com>`
)
type TestRepo struct {
t *testing.T
Dir string
name string
Commits map[string]map[string]*Commit
repo *gitRepo
}
func (repo *TestRepo) Git(args ...string) {
repo.t.Helper()
cmd := osutil.Command("git", args...)
cmd.Dir = repo.Dir
cmd.Env = filterEnv()
if _, err := osutil.Run(time.Minute, cmd); err != nil {
repo.t.Fatal(err)
}
}
func MakeTestRepo(t *testing.T, dir string) *TestRepo {
if err := osutil.MkdirAll(dir); err != nil {
t.Fatal(err)
}
ignoreCC := map[string]bool{
"stable@vger.kernel.org": true,
}
repo := &TestRepo{
t: t,
Dir: dir,
name: filepath.Base(dir),
Commits: make(map[string]map[string]*Commit),
repo: newGitRepo(dir, ignoreCC, []RepoOpt{OptPrecious, OptDontSandbox}),
}
repo.Git("init")
repo.Git("config", "--add", "user.email", userEmail)
repo.Git("config", "--add", "user.name", userName)
return repo
}
func (repo *TestRepo) CommitFileChange(branch, change string) {
id := fmt.Sprintf("%v-%v-%v", repo.name, branch, change)
file := filepath.Join(repo.Dir, "file")
if err := osutil.WriteFile(file, []byte(id)); err != nil {
repo.t.Fatal(err)
}
repo.Git("add", file)
repo.Git("commit", "-m", id)
if repo.Commits[branch] == nil {
repo.Commits[branch] = make(map[string]*Commit)
}
com, err := repo.repo.Commit(HEAD)
if err != nil {
repo.t.Fatal(err)
}
repo.Commits[branch][change] = com
}
func (repo *TestRepo) CommitChange(description string) *Commit {
repo.Git("commit", "--allow-empty", "-m", description)
com, err := repo.repo.Commit(HEAD)
if err != nil {
repo.t.Fatal(err)
}
return com
}
func (repo *TestRepo) SetTag(tag string) {
repo.Git("tag", tag)
}
func (repo *TestRepo) SupportsBisection() bool {
// Detect too old git binary. --no-contains appeared in git 2.13.
_, err := repo.repo.previousReleaseTags("HEAD", true, false, false)
return err == nil ||
!strings.Contains(err.Error(), "usage: git tag") &&
!strings.Contains(err.Error(), "error: unknown option")
}
func CreateTestRepo(t *testing.T, baseDir, name string) *TestRepo {
repo := MakeTestRepo(t, filepath.Join(baseDir, name))
repo.Git("checkout", "-b", "master")
repo.CommitFileChange("master", "0")
for _, branch := range []string{"branch1", "branch2"} {
repo.Git("checkout", "-b", branch, "master")
repo.CommitFileChange(branch, "0")
repo.CommitFileChange(branch, "1")
}
repo.Git("checkout", "master")
repo.CommitFileChange("master", "1")
return repo
}
// Copyright 2019 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package vcs
import (
"bytes"
"errors"
"fmt"
"net/mail"
"path/filepath"
"regexp"
"sort"
"strings"
"time"
"github.com/google/syzkaller/pkg/debugtracer"
"github.com/google/syzkaller/pkg/kconfig"
"github.com/google/syzkaller/pkg/osutil"
"github.com/google/syzkaller/pkg/report/crash"
"github.com/google/syzkaller/prog"
"github.com/google/syzkaller/sys/targets"
)
type linux struct {
*gitRepo
vmType string
}
var (
_ Bisecter = new(linux)
_ ConfigMinimizer = new(linux)
)
func newLinux(dir string, opts []RepoOpt, vmType string) *linux {
ignoreCC := map[string]bool{
"stable@vger.kernel.org": true,
}
return &linux{
gitRepo: newGitRepo(dir, ignoreCC, opts),
vmType: vmType,
}
}
func (ctx *linux) PreviousReleaseTags(commit, compilerType string) ([]string, error) {
tags, err := ctx.gitRepo.previousReleaseTags(commit, false, false, false)
if err != nil {
return nil, err
}
cutoff := ""
switch compilerType {
case "gcc":
// Initially we tried to stop at 3.8 because:
// v3.8 does not work with modern perl, and as we go further in history
// make stops to work, then binutils, glibc, etc. So we stop at v3.8.
// Up to that point we only need an ancient gcc.
//
// But kernels don't boot starting from 4.0 and back.
// That was fixed by 99124e4db5b7b70daeaaf1d88a6a8078a0004c6e,
// and it can be cherry-picked into 3.14..4.0 but it conflicts for 3.13 and older.
//
// But starting from 4.0 our user-space binaries start crashing with
// assorted errors which suggests process memory corruption by kernel.
//
// We used to use 4.1 as the oldest tested release (it works in general).
// However, there is correlation between how far back we go and probability
// of getting correct result (see #1532). So we then stopped at 4.6.
// 4.6 is somewhat arbitrary, we've seen lots of wrong results in 4.5..4.6 range,
// but there is definitive reason for 4.6. Most likely later we want to bump it
// even more (as new releases are produced). Next good candidate may be 4.11
// because then we won't need gcc 5.5.
//
// TODO: The buildroot images deployed after #2820 can only boot v4.19+ kernels.
// This has caused lots of bad bisection results, see #3224. We either need a new
// universal image or a kernel version dependant image selection.
cutoff = "v4.18"
case "clang":
// v5.3 was the first release with solid clang support, however I was able to
// compile v5.1..v5.3 using a newer defconfig + make oldconfig. Everything older
// would require further cherry-picks.
cutoff = "v5.2"
}
for i, tag := range tags {
if tag == cutoff {
tags = tags[:i]
break
}
}
return tags, nil
}
func gitParseReleaseTags(output []byte, includeRC bool) []string {
var tags []string
for _, tag := range bytes.Split(output, []byte{'\n'}) {
if gitReleaseTagToInt(string(tag), includeRC) != 0 {
tags = append(tags, string(tag))
}
}
sort.Slice(tags, func(i, j int) bool {
return gitReleaseTagToInt(tags[i], includeRC) > gitReleaseTagToInt(tags[j], includeRC)
})
return tags
}
func gitReleaseTagToInt(tag string, includeRC bool) uint64 {
v1, v2, rc, v3 := ParseReleaseTag(tag)
if v1 < 0 {
return 0
}
v3 = max(v3, 0)
if rc >= 0 {
if !includeRC {
return 0
}
} else {
rc = 999
}
return uint64(v1)*1e9 + uint64(v2)*1e6 + uint64(rc)*1e3 + uint64(v3)
}
func (ctx *linux) EnvForCommit(
defaultCompiler, compilerType, binDir, commit string, kernelConfig []byte,
backports []BackportCommit,
) (*BisectEnv, error) {
tagList, err := ctx.previousReleaseTags(commit, true, false, false)
if err != nil {
return nil, err
}
tags := make(map[string]bool)
for _, tag := range tagList {
tags[tag] = true
}
cf, err := kconfig.ParseConfigData(kernelConfig, "config")
if err != nil {
return nil, err
}
setLinuxTagConfigs(cf, tags)
compiler := ""
switch compilerType {
case "gcc":
compiler = linuxGCCPath(tags, binDir, defaultCompiler)
case "clang":
compiler = linuxClangPath(tags, binDir, defaultCompiler)
default:
return nil, fmt.Errorf("unsupported bisect compiler: %v", compilerType)
}
env := &BisectEnv{
Compiler: compiler,
KernelConfig: cf.Serialize(),
}
err = linuxFixBackports(ctx.gitRepo, backports...)
if err != nil {
return nil, fmt.Errorf("failed to cherry pick fixes: %w", err)
}
return env, nil
}
func linuxClangPath(tags map[string]bool, binDir, defaultCompiler string) string {
version := ""
// The defaultCompiler and clang-15 are assumed to be available.
switch {
case tags["v6.15"]:
return defaultCompiler
case tags["v5.9"]:
return "clang-15"
default:
// everything before v5.3 might not work great
// everything before v5.1 does not work
version = "9.0.1"
}
return filepath.Join(binDir, "llvm-"+version, "bin", "clang")
}
func linuxGCCPath(tags map[string]bool, binDir, defaultCompiler string) string {
version := ""
switch {
case tags["v5.16"]:
// Verified to work with 15.0.7.
return defaultCompiler
case tags["v5.9"]:
version = "10.1.0"
case tags["v4.12"]:
version = "8.1.0"
case tags["v4.11"]:
version = "7.3.0"
default:
version = "5.5.0"
}
return filepath.Join(binDir, "gcc-"+version, "bin", "gcc")
}
func (ctx *linux) PrepareBisect() error {
if ctx.vmType != targets.GVisor {
// Some linux repos we fuzz don't import the upstream release git tags. We need tags
// to decide which compiler versions to use. Let's fetch upstream for its tags.
err := ctx.gitRepo.fetchRemote("https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git", "")
if err != nil {
return fmt.Errorf("fetching upstream linux failed: %w", err)
}
}
return nil
}
func (ctx *linux) Bisect(bad, good string, dt debugtracer.DebugTracer, pred func() (BisectResult,
error)) ([]*Commit, error) {
commits, err := ctx.gitRepo.Bisect(bad, good, dt, pred)
if len(commits) == 1 {
ctx.addMaintainers(commits[0])
}
return commits, err
}
func (ctx *linux) addMaintainers(com *Commit) {
if len(com.Recipients) > 2 {
return
}
mtrs := ctx.getMaintainers(com.Hash, false)
if len(mtrs) < 3 {
mtrs = ctx.getMaintainers(com.Hash, true)
}
com.Recipients = append(com.Recipients, mtrs...)
sort.Sort(com.Recipients)
}
func (ctx *linux) getMaintainers(hash string, blame bool) Recipients {
// See #1441 re --git-min-percent.
args := "git show " + hash + " | " +
filepath.FromSlash("scripts/get_maintainer.pl") +
" --git-min-percent=20"
if blame {
args += " --git-blame"
}
output, err := osutil.RunCmd(time.Minute, ctx.gitRepo.Dir, "bash", "-c", args)
if err != nil {
return nil
}
return ParseMaintainersLinux(output)
}
func ParseMaintainersLinux(text []byte) Recipients {
lines := strings.Split(string(text), "\n")
reRole := regexp.MustCompile(` \([^)]+\)$`)
var mtrs Recipients
// LMKL is To by default, but it changes to Cc if there's also a subsystem list.
lkmlType := To
foundLkml := false
for _, line := range lines {
role := reRole.FindString(line)
address := strings.Replace(line, role, "", 1)
addr, err := mail.ParseAddress(address)
if err != nil {
continue
}
var roleType RecipientType
if addr.Address == "linux-kernel@vger.kernel.org" {
foundLkml = true
continue
} else if strings.Contains(role, "list") {
lkmlType = Cc
roleType = To
} else if strings.Contains(role, "maintainer") || strings.Contains(role, "supporter") {
roleType = To
} else {
roleType = Cc // Reviewer or other role; default to Cc.
}
mtrs = append(mtrs, RecipientInfo{*addr, roleType})
}
if foundLkml {
mtrs = append(mtrs, RecipientInfo{mail.Address{Address: "linux-kernel@vger.kernel.org"}, lkmlType})
}
sort.Sort(mtrs)
return mtrs
}
var ErrBadKconfig = errors.New("failed to parse Kconfig")
const configBisectTag = "# Minimized by syzkaller"
// Minimize() attempts to drop Linux kernel configs that are unnecessary(*) for bug reproduction.
// 1. Remove sanitizers that are not needed to trigger the target class of bugs.
// 2. Disable unrelated kernel subsystems. This is done by bisecting config changes between
// `original` and `baseline`.
// (*) After an unnecessary config is deleted, we still have pred() == BisectBad.
func (ctx *linux) Minimize(target *targets.Target, original, baseline []byte, types []crash.Type,
dt debugtracer.DebugTracer, pred func(test []byte) (BisectResult, error)) ([]byte, error) {
if bytes.HasPrefix(original, []byte(configBisectTag)) {
dt.Log("# configuration already minimized\n")
return original, nil
}
kconf, err := kconfig.Parse(target, filepath.Join(ctx.gitRepo.Dir, "Kconfig"))
if err != nil {
return nil, fmt.Errorf("%w: %w", ErrBadKconfig, err)
}
config, err := kconfig.ParseConfigData(original, "original")
if err != nil {
return nil, err
}
minimizeCtx := &minimizeLinuxCtx{
kconf: kconf,
config: config,
pred: func(cfg *kconfig.ConfigFile) (bool, error) {
res, err := pred(serialize(cfg))
return res == BisectBad, err
},
transform: func(cfg *kconfig.ConfigFile) {
setLinuxTagConfigs(cfg, nil)
},
DebugTracer: dt,
}
if len(types) > 0 {
// Technically, as almost all sanitizers are Yes/No config options, we could have
// achieved this minimization simply by disabling them all in the baseline config.
// However, we are now trying to make the most out of the few config minimization
// iterations we're ready to make do during the bisection process.
// Since it's possible to quite reliably determine the needed and unneeded sanitizers
// just by looking at crash reports, let's prefer a more complicated logic over worse
// bisection results.
// Once we start doing proper config minimizations for every reproducer, we can delete
// most of the related code.
err := minimizeCtx.dropInstrumentation(types)
if err != nil {
return nil, err
}
}
if len(baseline) > 0 {
baselineConfig, err := kconfig.ParseConfigData(baseline, "baseline")
// If we fail to parse the baseline config proceed with original one as baseline config
// is an optional parameter.
if err != nil {
return nil, fmt.Errorf("%w: %w", ErrBadKconfig, err)
}
err = minimizeCtx.minimizeAgainst(baselineConfig)
if err != nil {
return nil, err
}
}
return minimizeCtx.getConfig(), nil
}
func serialize(cf *kconfig.ConfigFile) []byte {
return []byte(fmt.Sprintf("%v, rev: %v\n%s", configBisectTag, prog.GitRevision, cf.Serialize()))
}
type minimizeLinuxCtx struct {
kconf *kconfig.KConfig
config *kconfig.ConfigFile
pred func(*kconfig.ConfigFile) (bool, error)
transform func(*kconfig.ConfigFile)
debugtracer.DebugTracer
}
func (ctx *minimizeLinuxCtx) minimizeAgainst(base *kconfig.ConfigFile) error {
base = base.Clone()
ctx.transform(base)
// Don't do too many minimization runs, it will make bug bisections too long.
// The purpose is only to reduce the number of build/boot/test errors due to bugs
// in unrelated parts of the kernel.
// Bisection is not getting much faster with smaller configs, only more reliable,
// so there's a trade-off. Try to do best in 5 iterations, that's about 1.5 hours.
const minimizeRuns = 5
minConfig, err := ctx.kconf.Minimize(base, ctx.config, ctx.runPred, minimizeRuns, ctx)
if err != nil {
return err
}
ctx.config = minConfig
return nil
}
func (ctx *minimizeLinuxCtx) dropInstrumentation(types []crash.Type) error {
ctx.Log("check whether we can drop unnecessary instrumentation")
oldTransform := ctx.transform
transform := func(c *kconfig.ConfigFile) {
oldTransform(c)
setLinuxSanitizerConfigs(c, types, ctx)
}
newConfig := ctx.config.Clone()
transform(newConfig)
if bytes.Equal(ctx.config.Serialize(), newConfig.Serialize()) {
ctx.Log("there was nothing we could disable; skip")
return nil
}
ctx.SaveFile("no-instrumentation.config", newConfig.Serialize())
ok, err := ctx.runPred(newConfig)
if err != nil {
return err
}
if ok {
ctx.Log("the bug reproduces without the instrumentation")
ctx.transform = transform
ctx.config = newConfig
}
return nil
}
func (ctx *minimizeLinuxCtx) runPred(cfg *kconfig.ConfigFile) (bool, error) {
cfg = cfg.Clone()
ctx.transform(cfg)
return ctx.pred(cfg)
}
func (ctx *minimizeLinuxCtx) getConfig() []byte {
ctx.transform(ctx.config)
return serialize(ctx.config)
}
// Copyright 2023 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package vcs
import (
"strings"
"github.com/google/syzkaller/pkg/debugtracer"
"github.com/google/syzkaller/pkg/kconfig"
"github.com/google/syzkaller/pkg/report/crash"
)
// setLinuxTagConfigs() disables Linux kernel configurations depending on the Linux kernel version,
// which is determined by the git tags reachable from HEAD.
// The problem is that Linux kernel is regularly broken w.r.t syzbot configs, especially on older versions.
func setLinuxTagConfigs(cf *kconfig.ConfigFile, tags map[string]bool) {
const disableAlways = "disable-always"
// If tags is nil, disable only configs marked as disableAlways.
checkTag := func(tag string) bool {
return tags != nil && !tags[tag] ||
tags == nil && tag == disableAlways
}
disable := map[string]string{
// 5.2 has CONFIG_SECURITY_TOMOYO_INSECURE_BUILTIN_SETTING which allows to test tomoyo better.
// This config also enables CONFIG_SECURITY_TOMOYO_OMIT_USERSPACE_LOADER
// but we need it disabled to boot older kernels.
"SECURITY_TOMOYO_OMIT_USERSPACE_LOADER": "v5.2",
// Kernel is boot broken before 4.15 due to double-free in vudc_probe:
// https://lkml.org/lkml/2018/9/7/648
// Fixed by e28fd56ad5273be67d0fae5bedc7e1680e729952.
"USBIP_VUDC": "v4.15",
// CONFIG_CAN causes:
// all runs: crashed: INFO: trying to register non-static key in can_notifier
// for v4.11..v4.12 and v4.12..v4.13 ranges.
// Fixed by 74b7b490886852582d986a33443c2ffa50970169.
"CAN": "v4.13",
// Setup of network devices is broken before v4.12 with a "WARNING in hsr_get_node".
// Fixed by 675c8da049fd6556eb2d6cdd745fe812752f07a8.
"HSR": "v4.12",
// Setup of network devices is broken before v4.12 with a "WARNING: ODEBUG bug in __sk_destruct"
// coming from smc_release.
"SMC": "v4.12",
// Kernel is boot broken before 4.10 with a lockdep warning in vhci_hcd_probe.
"USBIP_VHCI_HCD": "v4.10",
"BT_HCIVHCI": "v4.10",
// Setup of network devices is broken before v4.7 with a deadlock involving team.
"NET_TEAM": "v4.7",
// Setup of network devices is broken before v4.5 with a warning in batadv_tvlv_container_remove.
"BATMAN_ADV": "v4.5",
// UBSAN is broken in multiple ways before v5.3, see:
// https://github.com/google/syzkaller/issues/1523#issuecomment-696514105
"UBSAN": "v5.3",
// First, we disable coverage in pkg/bisect because it fails machine testing starting from 4.7.
// Second, at 6689da155bdcd17abfe4d3a8b1e245d9ed4b5f2c CONFIG_KCOV selects CONFIG_GCC_PLUGIN_SANCOV
// (why?), which is build broken for hundreds of revisions.
// However, as there's a chance that KCOV might positively affect bug reproduction rate, let's
// keep it for newer kernel revisions. Bisection algorithm will try to drop it anyway during
// kernel config minimization.
"KCOV": "v5.4",
// This helps to produce stable binaries in presence of kernel tag changes.
"LOCALVERSION_AUTO": disableAlways,
// BTF fails lots of builds with:
// pahole version v1.9 is too old, need at least v1.13
// Failed to generate BTF for vmlinux. Try to disable CONFIG_DEBUG_INFO_BTF.
"DEBUG_INFO_BTF": disableAlways,
// This config only adds debug output. It should not be enabled at all,
// but it was accidentially enabled on some instances for some periods of time,
// and kernel is boot-broken for prolonged ranges of commits with deadlock
// which makes bisections take weeks.
"DEBUG_KOBJECT": disableAlways,
// This config is causing problems to kernel signature calculation as new initramfs is generated
// as a part of every build. Due to this init.data section containing this generated initramfs
// is differing between builds causing signture being random number.
"BLK_DEV_INITRD": disableAlways,
}
for cfg, tag := range disable {
if checkTag(tag) {
cf.Unset(cfg)
}
}
alter := []struct {
From string
To string
Tag string
}{
// Even though ORC unwinder was introduced a long time ago, it might have been broken for
// some time. 5.4 is chosen as a version tag, where ORC unwinder seems to work properly.
{"UNWINDER_ORC", "UNWINDER_FRAME_POINTER", "v5.4"},
}
for _, a := range alter {
if checkTag(a.Tag) {
cf.Unset(a.From)
cf.Set(a.To, kconfig.Yes)
}
}
}
// setLinuxSanitizerConfigs() removes Linux kernel sanitizers that are not necessary
// to trigger the specified crash types.
func setLinuxSanitizerConfigs(cf *kconfig.ConfigFile, types []crash.Type, dt debugtracer.DebugTracer) {
keep := map[string]struct {
pred crash.TypeGroupPred
disabler func()
}{
"hang": {
pred: crash.Type.IsHang,
disabler: func() {
cf.Unset("RCU_STALL_COMMON")
cf.Unset("LOCKUP_DETECTOR")
cf.Unset("SOFTLOCKUP_DETECTOR")
cf.Unset("HARDLOCKUP_DETECTOR")
cf.Unset("DETECT_HUNG_TASK")
// It looks like it's the only reliable way to completely disable hung errors.
cmdline := cf.Value("CMDLINE")
pos := strings.LastIndexByte(cmdline, '"')
const rcuStallSuppress = "rcupdate.rcu_cpu_stall_suppress=1"
if pos >= 0 && !strings.Contains(cmdline, rcuStallSuppress) {
cf.Set("CMDLINE", cmdline[:pos]+" "+rcuStallSuppress+cmdline[pos:])
}
},
},
"memleak": {
pred: crash.Type.IsMemoryLeak,
disabler: func() { cf.Unset("DEBUG_KMEMLEAK") },
},
"ubsan": {
pred: crash.Type.IsUBSAN,
disabler: func() { cf.Unset("UBSAN") },
},
"bug_or_warning": {
pred: crash.Type.IsBugOrWarning,
disabler: func() { cf.Unset("BUG") },
},
"kasan": {
pred: crash.Type.IsKASAN,
disabler: func() { cf.Unset("KASAN") },
},
"locking": {
pred: crash.Type.IsLockdep,
disabler: func() {
cf.Unset("LOCKDEP")
cf.Unset("PROVE_LOCKING") // it selects LOCKDEP
},
},
"atomic_sleep": {
pred: crash.Type.IsAtomicSleep,
disabler: func() { cf.Unset("DEBUG_ATOMIC_SLEEP") },
},
}
need := map[string]bool{}
for _, typ := range types {
for keepName, funcs := range keep {
if funcs.pred(typ) {
need[keepName] = true
}
}
}
var disabled []string
for categoryName, funcs := range keep {
if need[categoryName] {
continue
}
funcs.disabler()
disabled = append(disabled, categoryName)
}
if len(disabled) > 0 {
dt.Log("disabling configs for %v, they are not needed", disabled)
}
}
// Copyright 2023 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package vcs
import "fmt"
// BackportCommit describes a fix commit that must be cherry-picked to an older
// kernel revision in order to enable kernel build / boot.
type BackportCommit struct {
// Backport is only applied if the commit is reachable from HEAD.
GuiltyHash string `json:"guilty_hash"`
// The hash of the commit to cherry-pick.
FixHash string `json:"fix_hash"`
// The title of the commit to cherry-pick.
// It's used to determine whether the fix is already in place.
FixTitle string `json:"fix_title"`
// The field is only intended to make config files less cryptic.
Comment string `json:"comment"`
}
// linuxFixBackports() cherry-picks the commits necessary to compile/run older Linux kernel releases.
func linuxFixBackports(repo *gitRepo, extraCommits ...BackportCommit) error {
return applyFixBackports(repo,
append(
append([]BackportCommit{}, pickLinuxCommits...),
extraCommits...,
),
)
}
func applyFixBackports(repo *gitRepo, commits []BackportCommit) error {
for _, info := range commits {
if info.GuiltyHash != "" {
contains, err := repo.Contains(info.GuiltyHash)
if err != nil {
return fmt.Errorf("failed to check if %s is present: %w", info.GuiltyHash, err)
}
if !contains {
// There's no reason to backport a fix.
continue
}
}
fixCommit, err := repo.GetCommitByTitle(info.FixTitle)
if err != nil {
return err
}
if fixCommit != nil {
// The fix is already present.
continue
}
_, err = repo.Run("cherry-pick", "--no-commit", info.FixHash)
if err != nil {
return err
}
}
return nil
}
var pickLinuxCommits = []BackportCommit{
{
// Compiling v4.6..v5.11 with a modern objtool, w/o this patch, results in the
// following issue, when compiling with clang:
// arch/x86/entry/thunk_64.o: warning: objtool: missing symbol table
// We don't bisect that far back with neither clang nor gcc, so this should be fine:
FixHash: `1d489151e9f9d1647110277ff77282fe4d96d09b`,
FixTitle: `objtool: Don't fail on missing symbol table`,
},
{
// With newer compiler versions, kernel compilation fails with:
// subcmd-util.h:56:23: error: pointer may be used after ‘realloc’ [-Werror=use-after-free]
// 56 | ret = realloc(ptr, size);
// The guilty commit is from 2015, we don't bisect that far.
FixHash: `52a9dab6d892763b2a8334a568bd4e2c1a6fde66`,
FixTitle: `libsubcmd: Fix use-after-free for realloc(..., 0)`,
},
{
// A number of old releases fail with KASAN: use-after-free in task_active_pid_ns.
// The problem was actually present so long ago that we do not need to check whether
// the guilty commit is present. We don't bisect that back (v2.*) anyway.
FixHash: `0711f0d7050b9e07c44bc159bbc64ac0a1022c7f`,
FixTitle: "pid: take a reference when initializing `cad_pid`",
},
{
// Fixes the following error:
// check.c:2865:58: error: '%d' directive output may be truncated writing between 1 and
// 10 bytes into a region of size 9 [-Werror=format-truncation=]
GuiltyHash: `db2b0c5d7b6f19b3c2cab08c531b65342eb5252b`,
FixHash: `82880283d7fcd0a1d20964a56d6d1a5cc0df0713`,
FixTitle: `objtool: Fix truncated string warning`,
},
{
// Fixes `boot failed: WARNING in kvm_wait`.
GuiltyHash: `997acaf6b4b59c6a9c259740312a69ea549cc684`,
FixHash: `f4e61f0c9add3b00bd5f2df3c814d688849b8707`,
FixTitle: `x86/kvm: Fix broken irq restoration in kvm_wait`,
},
{
// Fixes `error: implicit declaration of function 'acpi_mps_check'`.
GuiltyHash: `342f43af70dbc74f8629381998f92c060e1763a2`,
FixHash: `ea7b4244b3656ca33b19a950f092b5bbc718b40c`,
FixTitle: `x86/setup: Explicitly include acpi.h`,
},
{
// Fixes `BUG: KASAN: slab-use-after-free in binder_add_device` at boot.
GuiltyHash: `12d909cac1e1c4147cc3417fee804ee12fc6b984`,
FixHash: `e77aff5528a183462714f750e45add6cc71e276a`,
FixTitle: `binderfs: fix use-after-free in binder_devices`,
},
{
// Fixes `unregister_netdevice: waiting for batadv0 to become free. Usage count = 3`.
// Several v6.15-rc* tags are essentially unfuzzeable because of this.
GuiltyHash: `00b35530811f2aa3d7ceec2dbada80861c7632a8`,
FixHash: `10a77965760c6e2b3eef483be33ae407004df894`,
FixTitle: `batman-adv: Fix double-hold of meshif when getting enabled`,
},
}
// Copyright 2019 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package vcs
import (
"fmt"
"github.com/google/syzkaller/pkg/debugtracer"
"github.com/google/syzkaller/pkg/report/crash"
"github.com/google/syzkaller/sys/targets"
)
type testos struct {
*gitRepo
}
var _ ConfigMinimizer = new(testos)
func newTestos(dir string, opts []RepoOpt) *testos {
return &testos{
gitRepo: newGitRepo(dir, nil, opts),
}
}
func (ctx *testos) PreviousReleaseTags(commit, compilerType string) ([]string, error) {
return ctx.gitRepo.previousReleaseTags(commit, false, false, false)
}
func (ctx *testos) EnvForCommit(
defaultCompiler, compilerType, binDir, commit string, kernelConfig []byte,
backports []BackportCommit,
) (*BisectEnv, error) {
return &BisectEnv{KernelConfig: kernelConfig}, nil
}
func (ctx *testos) Minimize(target *targets.Target, original, baseline []byte, types []crash.Type,
dt debugtracer.DebugTracer, pred func(test []byte) (BisectResult, error)) ([]byte, error) {
if len(baseline) == 0 {
return original, nil
}
if res, err := pred(baseline); err != nil {
return nil, err
} else if res == BisectBad {
return baseline, nil
}
switch string(baseline) {
case "minimize-fails":
return nil, fmt.Errorf("minimization failure")
case "minimize-succeeds":
config := []byte("new-minimized-config")
pred(config)
return config, nil
default:
return original, nil
}
}
func (ctx *testos) PrepareBisect() error {
return nil
}
// Copyright 2018 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
// Package vcs provides helper functions for working with various repositories (e.g. git).
package vcs
import (
"bytes"
"fmt"
"net/mail"
"regexp"
"sort"
"strconv"
"strings"
"time"
"github.com/google/syzkaller/dashboard/dashapi"
"github.com/google/syzkaller/pkg/debugtracer"
"github.com/google/syzkaller/pkg/osutil"
"github.com/google/syzkaller/pkg/report/crash"
"github.com/google/syzkaller/sys/targets"
)
type Repo interface {
// Poll checkouts the specified repository/branch.
// This involves fetching/resetting/cloning as necessary to recover from all possible problems.
// Returns hash of the HEAD commit in the specified branch.
Poll(repo, branch string) (*Commit, error)
// CheckoutBranch checkouts the specified repository/branch.
CheckoutBranch(repo, branch string) (*Commit, error)
// CheckoutCommit checkouts the specified repository on the specified commit.
CheckoutCommit(repo, commit string) (*Commit, error)
// SwitchCommit checkouts the specified commit without fetching.
SwitchCommit(commit string) (*Commit, error)
// Commit returns info about the specified commit hash.
// The commit may be the special value HEAD for the current commit.
Commit(com string) (*Commit, error)
// GetCommitByTitle finds commit info by the title. If the commit is not found, nil is returned.
// Remote is not fetched and only commits reachable from the checked out HEAD are searched
// (e.g. do CheckoutBranch before).
GetCommitByTitle(title string) (*Commit, error)
// GetCommitsByTitles is a batch version of GetCommitByTitle.
// Returns list of commits and titles of commits that are not found.
GetCommitsByTitles(titles []string) ([]*Commit, []string, error)
// ExtractFixTagsFromCommits extracts fixing tags for bugs from git log.
// Given email = "user@domain.com", it searches for tags of the form "user+tag@domain.com"
// and returns commits with these tags.
ExtractFixTagsFromCommits(baseCommit, email string) ([]*Commit, error)
// ReleaseTag returns the latest release tag that is reachable from the given commit.
ReleaseTag(commit string) (string, error)
// Returns true if the current tree contains the specified commit.
// Remote is not fetched and only commits reachable from the checked out HEAD are searched
// (e.g. do CheckoutBranch before).
Contains(commit string) (bool, error)
// LatestCommits lists all latest commit hashes well as their commit dates.
// If afterCommit is specified, the output only includes the commits from which afterCommit is reachable.
// If afterDate is specified, the output only includes the newe commits.
LatestCommits(afterCommit string, afterDate time.Time) ([]CommitShort, error)
// Object returns the contents of a git repository object at the particular moment in history.
Object(name, commit string) ([]byte, error)
// MergeBases returns good common ancestors of the two commits.
MergeBases(firstCommit, secondCommit string) ([]*Commit, error)
// CommitExists check for the commit presence in local checkout.
CommitExists(commit string) (bool, error)
// PushCommit is used to store commit in remote repo.
PushCommit(repo, commit string) error
}
// Bisecter may be optionally implemented by Repo.
type Bisecter interface {
// Can be used for last minute preparations like pulling release tags into the bisected repo, which
// is required to determin the compiler version to use on linux. Can be an empty function.
PrepareBisect() error
// Bisect bisects good..bad commit range against the provided predicate (wrapper around git bisect).
// The predicate should return an error only if there is no way to proceed
// (it will abort the process), if possible it should prefer to return BisectSkip.
// Progress of the process is streamed to the provided trace.
// Returns the first commit on which the predicate returns BisectBad,
// or multiple commits if bisection is inconclusive due to BisectSkip.
Bisect(bad, good string, dt debugtracer.DebugTracer, pred func() (BisectResult, error)) ([]*Commit, error)
// PreviousReleaseTags returns list of preceding release tags that are reachable from the given commit.
// If the commit itself has a release tag, this tag is not included.
PreviousReleaseTags(commit, compilerType string) ([]string, error)
IsRelease(commit string) (bool, error)
EnvForCommit(defaultCompiler, compilerType, binDir, commit string,
kernelConfig []byte, backports []BackportCommit) (*BisectEnv, error)
}
type ConfigMinimizer interface {
Minimize(target *targets.Target, original, baseline []byte, types []crash.Type,
dt debugtracer.DebugTracer, pred func(test []byte) (BisectResult, error)) ([]byte, error)
}
type Commit struct {
Hash string
Title string
Author string
AuthorName string
Recipients Recipients
Tags []string
Parents []string
Date time.Time
CommitDate time.Time
Patch []byte
}
type CommitShort struct {
Hash string
CommitDate time.Time
}
type RecipientType int
const (
To RecipientType = iota
Cc
)
func (t RecipientType) String() string {
return [...]string{"To", "Cc"}[t]
}
type RecipientInfo struct {
Address mail.Address
Type RecipientType
}
type Recipients []RecipientInfo
func (r Recipients) GetEmails(filter RecipientType) []string {
emails := []string{}
for _, user := range r {
if user.Type == filter {
emails = append(emails, user.Address.Address)
}
}
sort.Strings(emails)
return emails
}
func NewRecipients(emails []string, t RecipientType) Recipients {
r := Recipients{}
for _, e := range emails {
r = append(r, RecipientInfo{mail.Address{Address: e}, t})
}
sort.Sort(r)
return r
}
func (r Recipients) Len() int { return len(r) }
func (r Recipients) Less(i, j int) bool { return r[i].Address.Address < r[j].Address.Address }
func (r Recipients) Swap(i, j int) { r[i], r[j] = r[j], r[i] }
func (r Recipients) ToDash() dashapi.Recipients {
d := dashapi.Recipients{}
for _, user := range r {
d = append(d, dashapi.RecipientInfo{Address: user.Address, Type: dashapi.RecipientType(user.Type)})
}
return d
}
type BisectResult int
const (
BisectBad BisectResult = iota
BisectGood
BisectSkip
)
type BisectEnv struct {
Compiler string
KernelConfig []byte
}
type RepoOpt int
const (
// RepoPrecious is intended for command-line tools that work with a user-provided repo.
// Such repo won't be re-created to recover from errors, but rather return errors.
// If this option is not specified, the repo can be re-created from scratch to recover from any errors.
OptPrecious RepoOpt = iota
// Don't use sandboxing suitable for pkg/build.
OptDontSandbox
)
func NewRepo(os, vmType, dir string, opts ...RepoOpt) (Repo, error) {
switch os {
case targets.Linux:
if vmType == targets.Starnix {
return newFuchsia(dir, opts), nil
}
return newLinux(dir, opts, vmType), nil
case targets.Fuchsia:
return newFuchsia(dir, opts), nil
case targets.OpenBSD:
return newGitRepo(dir, nil, opts), nil
case targets.NetBSD:
return newGitRepo(dir, nil, opts), nil
case targets.FreeBSD:
return newGitRepo(dir, nil, opts), nil
case targets.TestOS:
return newTestos(dir, opts), nil
}
return nil, fmt.Errorf("vcs is unsupported for %v", os)
}
func NewSyzkallerRepo(dir string, opts ...RepoOpt) Repo {
git := newGitRepo(dir, nil, append(opts, OptDontSandbox))
return git
}
func NewLKMLRepo(dir string) Repo {
return newGitRepo(dir, nil, []RepoOpt{OptDontSandbox})
}
func Patch(dir string, patch []byte) error {
// Do --dry-run first to not mess with partially consistent state.
cmd := osutil.Command("patch", "-p1", "--force", "--ignore-whitespace", "--dry-run")
if err := osutil.Sandbox(cmd, true, true); err != nil {
return err
}
cmd.Stdin = bytes.NewReader(patch)
cmd.Dir = dir
if output, err := cmd.CombinedOutput(); err != nil {
// If it reverses clean, then it's already applied
// (seems to be the easiest way to detect it).
cmd = osutil.Command("patch", "-p1", "--force", "--ignore-whitespace", "--reverse", "--dry-run")
if err := osutil.Sandbox(cmd, true, true); err != nil {
return err
}
cmd.Stdin = bytes.NewReader(patch)
cmd.Dir = dir
if _, err := cmd.CombinedOutput(); err == nil {
return fmt.Errorf("patch is already applied")
}
return fmt.Errorf("failed to apply patch:\n%s", output)
}
// Now apply for real.
cmd = osutil.Command("patch", "-p1", "--force", "--ignore-whitespace")
if err := osutil.Sandbox(cmd, true, true); err != nil {
return err
}
cmd.Stdin = bytes.NewReader(patch)
cmd.Dir = dir
if output, err := cmd.CombinedOutput(); err != nil {
return fmt.Errorf("failed to apply patch after dry run:\n%s", output)
}
return nil
}
// CheckRepoAddress does a best-effort approximate check of a git repo address.
func CheckRepoAddress(repo string) bool {
return gitLocalRepoRe.MatchString(repo) ||
gitRemoteRepoRe.MatchString(repo) ||
gitSSHRepoRe.MatchString(repo)
}
// CheckBranch does a best-effort approximate check of a git branch name.
func CheckBranch(branch string) bool {
return gitBranchRe.MatchString(branch)
}
func CheckCommitHash(hash string) bool {
return gitHashRe.MatchString(hash)
}
func ParseReleaseTag(tag string) (v1, v2, rc, v3 int) {
invalid := func() {
v1, v2, rc, v3 = -1, -1, -1, -1
}
invalid()
matches := releaseTagRe.FindStringSubmatch(tag)
if matches == nil {
return
}
for ptr, idx := range map[*int]int{
&v1: 1, &v2: 2, &rc: 3, &v3: 4,
} {
if matches[idx] == "" {
continue
}
var err error
*ptr, err = strconv.Atoi(matches[idx])
if err != nil {
invalid()
return
}
}
return
}
func runSandboxed(dir, command string, args ...string) ([]byte, error) {
cmd := osutil.Command(command, args...)
cmd.Dir = dir
if err := osutil.Sandbox(cmd, true, false); err != nil {
return nil, err
}
return osutil.Run(time.Hour, cmd)
}
var (
// nolint: lll
gitLocalRepoRe = regexp.MustCompile(`^file:///[a-zA-Z0-9-_./~]+(/)?$`)
// nolint: lll
gitRemoteRepoRe = regexp.MustCompile(`^(git|ssh|http|https|ftp|ftps|sso)://[a-zA-Z0-9-_.]+(:[0-9]+)?(/[a-zA-Z0-9-_./~]+)?(/)?$`)
// nolint: lll
gitSSHRepoRe = regexp.MustCompile(`^(git|ssh|http|https|ftp|ftps|sso)@[a-zA-Z0-9-_.]+(:[a-zA-Z0-9-_]+)?(/[a-zA-Z0-9-_./~]+)?(/)?$`)
gitBranchRe = regexp.MustCompile("^[a-zA-Z0-9-_/.]{2,200}$")
gitHashRe = regexp.MustCompile("^[a-f0-9]{8,40}$")
releaseTagRe = regexp.MustCompile(`^v([0-9]+).([0-9]+)(?:-rc([0-9]+))?(?:\.([0-9]+))?$`)
// CC: is intentionally not on this list, see #1441.
ccRes = []*regexp.Regexp{
regexp.MustCompile(`^Reviewed\-.*: (.*)$`),
regexp.MustCompile(`^[A-Za-z-]+\-and\-[Rr]eviewed\-.*: (.*)$`),
regexp.MustCompile(`^Acked\-.*: (.*)$`),
regexp.MustCompile(`^[A-Za-z-]+\-and\-[Aa]cked\-.*: (.*)$`),
regexp.MustCompile(`^Tested\-.*: (.*)$`),
regexp.MustCompile(`^[A-Za-z-]+\-and\-[Tt]ested\-.*: (.*)$`),
regexp.MustCompile(`^Signed-off-by: (.*)$`),
}
)
// CanonicalizeCommit returns commit title that can be used when checking
// if a particular commit is present in a git tree.
// Some trees add prefixes to commit titles during backporting,
// so we want e.g. commit "foo bar" match "BACKPORT: foo bar".
func CanonicalizeCommit(title string) string {
for _, prefix := range commitPrefixes {
if strings.HasPrefix(title, prefix) {
title = title[len(prefix):]
break
}
}
return strings.TrimSpace(title)
}
var commitPrefixes = []string{
"UPSTREAM:",
"CHROMIUM:",
"FROMLIST:",
"BACKPORT:",
"FROMGIT:",
"net-backports:",
}
const SyzkallerRepo = "https://github.com/google/syzkaller"
const HEAD = "HEAD"
func CommitLink(url, hash string) string {
return link(url, hash, "", 0, 0)
}
// Used externally - do not remove.
func TreeLink(url, hash string) string {
return link(url, hash, "", 0, 1)
}
func LogLink(url, hash string) string {
return link(url, hash, "", 0, 2)
}
func FileLink(url, hash, file string, line int) string {
return link(url, hash, file, line, 3)
}
// nolint: goconst
func link(url, hash, file string, line, typ int) string {
if url == "" || hash == "" {
return ""
}
switch url {
case "https://fuchsia.googlesource.com":
// We collect hashes from the fuchsia repo.
return link(url+"/fuchsia", hash, file, line, typ)
}
if strings.HasPrefix(url, "https://github.com/") {
url = strings.TrimSuffix(url, ".git")
switch typ {
case 1:
return url + "/tree/" + hash
case 2:
return url + "/commits/" + hash
case 3:
return url + "/blob/" + hash + "/" + file + "#L" + fmt.Sprint(line)
default:
return url + "/commit/" + hash
}
}
if strings.HasPrefix(url, "https://git.kernel.org/pub/scm/") ||
strings.HasPrefix(url, "git://git.kernel.org/pub/scm/") {
url = strings.TrimPrefix(url, "git")
url = strings.TrimPrefix(url, "https")
url = "https" + url
switch typ {
case 1:
return url + "/tree/?id=" + hash
case 2:
return url + "/log/?id=" + hash
case 3:
return url + "/tree/" + file + "?id=" + hash + "#n" + fmt.Sprint(line)
default:
return url + "/commit/?id=" + hash
}
}
for _, cgitHost := range []string{"git.kernel.dk", "git.breakpoint.cc"} {
if strings.HasPrefix(url, "https://"+cgitHost) ||
strings.HasPrefix(url, "git://"+cgitHost) {
url = strings.TrimPrefix(strings.TrimPrefix(url, "git://"), "https://")
url = strings.TrimPrefix(url, cgitHost)
url = "https://" + cgitHost + "/cgit" + url
switch typ {
case 1:
return url + "/tree/?id=" + hash
case 2:
return url + "/log/?id=" + hash
case 3:
return url + "/tree/" + file + "?id=" + hash + "#n" + fmt.Sprint(line)
default:
return url + "/commit/?id=" + hash
}
}
}
if strings.HasPrefix(url, "https://") && strings.Contains(url, ".googlesource.com") {
switch typ {
case 1:
return url + "/+/" + hash + "/"
case 2:
return url + "/+log/" + hash
case 3:
return url + "/+/" + hash + "/" + file + "#" + fmt.Sprint(line)
default:
return url + "/+/" + hash + "^!"
}
}
return ""
}
// Copyright 2024 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package vminfo
import (
"fmt"
"strings"
"github.com/google/syzkaller/pkg/flatrpc"
"github.com/google/syzkaller/pkg/fuzzer/queue"
"github.com/google/syzkaller/prog"
)
type Feature struct {
Enabled bool
NeedSetup bool
Reason string
}
type Features map[flatrpc.Feature]Feature
func (features Features) Enabled() flatrpc.Feature {
var mask flatrpc.Feature
for feat, info := range features {
if info.Enabled {
mask |= feat
}
}
return mask
}
func (features Features) NeedSetup() flatrpc.Feature {
var mask flatrpc.Feature
for feat, info := range features {
if info.Enabled && info.NeedSetup {
mask |= feat
}
}
return mask
}
type featureResult struct {
id flatrpc.Feature
reason string
}
func (ctx *checkContext) startFeaturesCheck() {
testProg := ctx.target.DataMmapProg()
for feat := range flatrpc.EnumNamesFeature {
if ctx.cfg.Features&feat == 0 {
ctx.features <- featureResult{feat, "disabled by user"}
continue
}
go func() {
envFlags, execFlags := ctx.featureToFlags(feat)
req := &queue.Request{
Prog: testProg,
ReturnOutput: true,
ReturnError: true,
ExecOpts: flatrpc.ExecOpts{
EnvFlags: envFlags,
ExecFlags: execFlags,
SandboxArg: ctx.cfg.SandboxArg,
},
}
ctx.executor.Submit(req)
res := req.Wait(ctx.ctx)
reason := ctx.featureSucceeded(feat, testProg, res)
ctx.features <- featureResult{feat, reason}
}()
}
}
func (ctx *checkContext) finishFeatures(featureInfos []*flatrpc.FeatureInfo) (Features, error) {
// Feature checking consists of 2 parts:
// - we ask executor to try to setup each feature (results are returned in featureInfos)
// - we also try to run a simple program with feature-specific flags
// Here we combine both results.
features := make(Features)
for _, info := range featureInfos {
features[info.Id] = Feature{
Reason: info.Reason,
NeedSetup: info.NeedSetup,
}
}
outputReplacer := strings.NewReplacer(
"SYZFAIL:", "",
"\n", ". ",
)
for range flatrpc.EnumNamesFeature {
res := <-ctx.features
feat := features[res.id]
if feat.Reason == "" {
feat.Reason = res.reason
}
if feat.Reason == "" {
feat.Reason = "enabled"
feat.Enabled = true
}
if pos := strings.Index(feat.Reason, "loop exited with status"); pos != -1 {
feat.Reason = feat.Reason[:pos]
}
// If executor exited the output is prefixed with "executor 4: EOF".
const executorPrefix = ": EOF\n"
if pos := strings.Index(feat.Reason, executorPrefix); pos != -1 {
feat.Reason = feat.Reason[pos+len(executorPrefix):]
}
feat.Reason = strings.TrimSpace(outputReplacer.Replace(feat.Reason))
features[res.id] = feat
}
if feat := features[flatrpc.FeatureSandboxNone]; !feat.Enabled {
return features, fmt.Errorf("execution of simple program fails: %v", feat.Reason)
}
if feat := features[flatrpc.FeatureCoverage]; ctx.cfg.Cover && !feat.Enabled {
return features, fmt.Errorf("coverage is not supported: %v", feat.Reason)
}
return features, nil
}
// featureToFlags creates ipc flags required to test the feature on a simple program.
// For features that has setup procedure in the executor, we just execute with the default flags.
func (ctx *checkContext) featureToFlags(feat flatrpc.Feature) (flatrpc.ExecEnv, flatrpc.ExecFlag) {
envFlags := ctx.cfg.Sandbox
// These don't have a corresponding feature and are always enabled.
envFlags |= flatrpc.ExecEnvEnableCloseFds | flatrpc.ExecEnvEnableCgroups | flatrpc.ExecEnvEnableNetReset
execFlags := flatrpc.ExecFlagThreaded
switch feat {
case flatrpc.FeatureCoverage:
envFlags |= flatrpc.ExecEnvSignal
execFlags |= flatrpc.ExecFlagCollectSignal | flatrpc.ExecFlagCollectCover
case flatrpc.FeatureComparisons:
envFlags |= flatrpc.ExecEnvSignal
execFlags |= flatrpc.ExecFlagCollectComps
case flatrpc.FeatureExtraCoverage:
envFlags |= flatrpc.ExecEnvSignal | flatrpc.ExecEnvExtraCover
execFlags |= flatrpc.ExecFlagCollectSignal | flatrpc.ExecFlagCollectCover
case flatrpc.FeatureDelayKcovMmap:
envFlags |= flatrpc.ExecEnvSignal | flatrpc.ExecEnvDelayKcovMmap
execFlags |= flatrpc.ExecFlagCollectSignal | flatrpc.ExecFlagCollectCover
case flatrpc.FeatureSandboxNone:
envFlags &= ^ctx.cfg.Sandbox
envFlags |= flatrpc.ExecEnvSandboxNone
case flatrpc.FeatureSandboxSetuid:
envFlags &= ^ctx.cfg.Sandbox
envFlags |= flatrpc.ExecEnvSandboxSetuid
case flatrpc.FeatureSandboxNamespace:
envFlags &= ^ctx.cfg.Sandbox
envFlags |= flatrpc.ExecEnvSandboxNamespace
case flatrpc.FeatureSandboxAndroid:
envFlags &= ^ctx.cfg.Sandbox
envFlags |= flatrpc.ExecEnvSandboxAndroid
case flatrpc.FeatureFault:
case flatrpc.FeatureLeak:
case flatrpc.FeatureNetInjection:
envFlags |= flatrpc.ExecEnvEnableTun
case flatrpc.FeatureNetDevices:
envFlags |= flatrpc.ExecEnvEnableNetDev
case flatrpc.FeatureKCSAN:
case flatrpc.FeatureDevlinkPCI:
envFlags |= flatrpc.ExecEnvEnableDevlinkPCI
case flatrpc.FeatureNicVF:
envFlags |= flatrpc.ExecEnvEnableNicVF
case flatrpc.FeatureUSBEmulation:
case flatrpc.FeatureVhciInjection:
envFlags |= flatrpc.ExecEnvEnableVhciInjection
case flatrpc.FeatureWifiEmulation:
envFlags |= flatrpc.ExecEnvEnableWifi
case flatrpc.FeatureLRWPANEmulation:
case flatrpc.FeatureBinFmtMisc:
case flatrpc.FeatureSwap:
default:
panic(fmt.Sprintf("unknown feature %v", flatrpc.EnumNamesFeature[feat]))
}
return envFlags, execFlags
}
// featureSucceeded checks if execution of a simple program with feature-specific flags succeed.
// This generally checks that just all syscalls were executed and succeed,
// for coverage features we also check that we got actual coverage.
func (ctx *checkContext) featureSucceeded(feat flatrpc.Feature, testProg *prog.Prog,
res *queue.Result) string {
if res.Status != queue.Success {
if len(res.Output) != 0 {
return string(res.Output)
}
if res.Err != nil {
return res.Err.Error()
}
return fmt.Sprintf("test program execution failed: status=%v", res.Status)
}
if len(res.Info.Calls) != len(testProg.Calls) {
return fmt.Sprintf("only %v calls are executed out of %v",
len(res.Info.Calls), len(testProg.Calls))
}
for i, call := range res.Info.Calls {
if call.Error != 0 {
return fmt.Sprintf("call %v failed with errno %v", i, call.Error)
}
}
call := res.Info.Calls[0]
switch feat {
case flatrpc.FeatureCoverage:
if len(call.Cover) == 0 || len(call.Signal) == 0 {
return "got no coverage"
}
case flatrpc.FeatureComparisons:
if len(call.Comps) == 0 {
return "got no coverage"
}
}
return ""
}
// Copyright 2024 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package vminfo
import (
"bufio"
"bytes"
"fmt"
"io"
"path"
"regexp"
"sort"
"strconv"
"strings"
"github.com/google/syzkaller/sys/targets"
)
type linux struct {
vmType string
}
func (linux) RequiredFiles() []string {
return []string{
"/proc/cpuinfo",
"/proc/modules",
"/proc/kallsyms",
"/sys/module/*/sections/.text",
"/sys/module/kvm*/parameters/*",
}
}
func (linux) CheckFiles() []string {
return []string{
"/proc/version",
"/proc/filesystems",
"/sys/kernel/security/lsm",
}
}
func (linux) machineInfos() []machineInfoFunc {
return []machineInfoFunc{
linuxReadCPUInfo,
linuxReadKVMInfo,
}
}
func (linux linux) parseModules(files filesystem) ([]*KernelModule, error) {
if linux.vmType == targets.GVisor || linux.vmType == targets.Starnix {
return nil, nil
}
var modules []*KernelModule
re := regexp.MustCompile(`(\w+) ([0-9]+) .*(0[x|X][a-fA-F0-9]+)[^\n]*`)
modulesText, _ := files.ReadFile("/proc/modules")
for _, match := range re.FindAllSubmatch(modulesText, -1) {
name := string(match[1])
modAddr, err := strconv.ParseUint(string(match[3]), 0, 64)
if err != nil {
// /proc/modules is broken, bail out.
return nil, fmt.Errorf("module %v address parsing error: %w", name, err)
}
textAddr, err := linuxModuleTextAddr(files, name)
if err != nil {
// Module address unavailable, .text is probably 0. Skip this module.
continue
}
modSize, err := strconv.ParseUint(string(match[2]), 0, 64)
if err != nil {
// /proc/modules is broken, bail out.
return nil, fmt.Errorf("module %v size parsing error: %w", name, err)
}
offset := modAddr - textAddr
modules = append(modules, &KernelModule{
Name: name,
Addr: textAddr,
// The size is wrong as there is overlap in /proc/modules
// ex. module1['Addr'] + module1['Size'] > module2['Addr']
// runtime kernel doesn't export .text section size to /sys/module/*/sections/.text
// so we need to read it from elf
Size: modSize - offset,
})
}
_stext, _etext, err := linuxParseCoreKernel(files)
if err != nil {
return nil, err
}
modules = append(modules, &KernelModule{
Name: "",
Addr: _stext,
Size: _etext - _stext,
})
sort.Slice(modules, func(i, j int) bool {
return modules[i].Addr < modules[j].Addr
})
return modules, nil
}
func linuxModuleTextAddr(files filesystem, module string) (uint64, error) {
data, err := files.ReadFile("/sys/module/" + module + "/sections/.text")
if err != nil {
return 0, fmt.Errorf("could not read module %v .text address file: %w", module, err)
}
addrString := strings.TrimSpace(string(data))
addr, err := strconv.ParseUint(addrString, 0, 64)
if err != nil {
return 0, fmt.Errorf("address parsing error in %v: %w", module, err)
}
return addr, nil
}
func linuxParseCoreKernel(files filesystem) (uint64, uint64, error) {
_Text, _ := files.ReadFile("/proc/kallsyms")
re := regexp.MustCompile(`([a-fA-F0-9]+) T _stext\n`)
m := re.FindSubmatch(_Text)
if m == nil {
return 0, 0, fmt.Errorf("failed to get _stext symbol")
}
_stext, err := strconv.ParseUint("0x"+string(m[1]), 0, 64)
if err != nil {
return 0, 0, fmt.Errorf("address parsing error in /proc/kallsyms for _stext: %w", err)
}
// _etext symbol points to the _next_ section, so it has type of the next section.
// It can be at least T, D, or R in some cases:
// https://groups.google.com/g/syzkaller/c/LSx6YIK_Eeo
re = regexp.MustCompile(`([a-fA-F0-9]+) . _etext\n`)
m = re.FindSubmatch(_Text)
if m == nil {
return 0, 0, fmt.Errorf("failed to get _etext symbol")
}
_etext, err := strconv.ParseUint("0x"+string(m[1]), 0, 64)
if err != nil {
return 0, 0, fmt.Errorf("address parsing error in /proc/kallsyms for _etext: %w", err)
}
return _stext, _etext, nil
}
func linuxReadCPUInfo(files filesystem, w io.Writer) (string, error) {
data, err := files.ReadFile("/proc/cpuinfo")
if err != nil {
return "", fmt.Errorf("error reading CPU info:: %w", err)
}
keyIndices := make(map[string]int)
type keyValues struct {
key string
values []string
}
var info []keyValues
for s := bufio.NewScanner(bytes.NewReader(data)); s.Scan(); {
splitted := strings.Split(s.Text(), ":")
if len(splitted) != 2 {
continue
}
key := strings.TrimSpace(splitted[0])
val := strings.TrimSpace(splitted[1])
if idx, ok := keyIndices[key]; !ok {
idx = len(keyIndices)
keyIndices[key] = idx
info = append(info, keyValues{key, []string{val}})
} else {
info[idx].values = append(info[idx].values, val)
}
}
for _, kv := range info {
// It is guaranteed that len(vals) >= 1
key := kv.key
vals := kv.values
if allEqual(vals) {
fmt.Fprintf(w, "%-20s: %s\n", key, vals[0])
} else {
fmt.Fprintf(w, "%-20s: %s\n", key, strings.Join(vals, ", "))
}
}
return "CPU Info", nil
}
func allEqual(slice []string) bool {
for i := 1; i < len(slice); i++ {
if slice[i] != slice[0] {
return false
}
}
return true
}
func linuxReadKVMInfo(files filesystem, w io.Writer) (string, error) {
for _, module := range files.ReadDir("/sys/module") {
if !strings.HasPrefix(module, "kvm") {
continue
}
paramPath := path.Join("/sys", "module", module, "parameters")
fmt.Fprintf(w, "/sys/module/%s:\n", module)
for _, param := range files.ReadDir(paramPath) {
data, err := files.ReadFile(path.Join(paramPath, param))
if err != nil {
return "", fmt.Errorf("error reading KVM info: %w", err)
}
fmt.Fprintf(w, "\t%s: %s", param, data)
}
w.Write([]byte{'\n'})
}
return "KVM", nil
}
// Copyright 2024 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package vminfo
import (
"bytes"
"fmt"
"os"
"regexp"
"strconv"
"strings"
"syscall"
"github.com/google/syzkaller/prog"
"github.com/google/syzkaller/sys/targets"
)
func (linux) syscallCheck(ctx *checkContext, call *prog.Syscall) string {
check := linuxSyscallChecks[call.CallName]
if check == nil {
check = func(ctx *checkContext, call *prog.Syscall) string {
// Execute plain syscall (rather than a variation with $) to make test program
// deduplication effective. However, if the plain syscall does not exist take
// the first variant for this syscall, this still allows to dedup all variants.
// This works b/c in syscall test we only check for ENOSYS result.
name := call.CallName
if ctx.target.SyscallMap[name] == nil {
for _, call1 := range ctx.target.Syscalls {
if name == call1.CallName {
name = call1.Name
}
}
}
return ctx.supportedSyscalls([]string{name})
}
}
if reason := check(ctx, call); reason != "" {
return reason
}
return linuxSupportedLSM(ctx, call)
}
func linuxSupportedLSM(ctx *checkContext, call *prog.Syscall) string {
for _, lsm := range []string{"selinux", "apparmor", "smack"} {
if !strings.Contains(strings.ToLower(call.Name), lsm) {
continue
}
data, err := ctx.readFile("/sys/kernel/security/lsm")
if err != nil {
// Securityfs may not be mounted, but it does not mean that no LSMs are enabled.
if os.IsNotExist(err) {
break
}
return err.Error()
}
if !bytes.Contains(data, []byte(lsm)) {
return fmt.Sprintf("%v is not enabled", lsm)
}
}
return ""
}
var linuxSyscallChecks = map[string]func(*checkContext, *prog.Syscall) string{
"openat": supportedOpenat,
"mount": linuxSupportedMount,
"socket": linuxSupportedSocket,
"socketpair": linuxSupportedSocket,
"pkey_alloc": linuxPkeysSupported,
"syz_open_dev": linuxSyzOpenDevSupported,
"syz_open_procfs": linuxSyzOpenProcfsSupported,
"syz_open_pts": alwaysSupported,
"syz_execute_func": alwaysSupported,
"syz_emit_ethernet": linuxNetInjectionSupported,
"syz_extract_tcp_res": linuxNetInjectionSupported,
"syz_usb_connect": linuxCheckUSBEmulation,
"syz_usb_connect_ath9k": linuxCheckUSBEmulation,
"syz_usb_disconnect": linuxCheckUSBEmulation,
"syz_usb_control_io": linuxCheckUSBEmulation,
"syz_usb_ep_write": linuxCheckUSBEmulation,
"syz_usb_ep_read": linuxCheckUSBEmulation,
"syz_kvm_setup_cpu": linuxSyzKvmSupported,
"syz_kvm_vgic_v3_setup": linuxSyzSupportedOnArm64,
"syz_kvm_setup_syzos_vm": linuxSyzKvmSupported,
"syz_kvm_add_vcpu": linuxSyzKvmSupported,
"syz_kvm_assert_syzos_uexit": linuxSyzKvmSupported,
"syz_kvm_assert_reg": linuxSyzSupportedOnArm64,
"syz_emit_vhci": linuxVhciInjectionSupported,
"syz_init_net_socket": linuxSyzInitNetSocketSupported,
"syz_genetlink_get_family_id": linuxSyzGenetlinkGetFamilyIDSupported,
"syz_mount_image": linuxSyzMountImageSupported,
"syz_read_part_table": linuxSyzReadPartTableSupported,
"syz_io_uring_setup": alwaysSupported,
"syz_io_uring_submit": alwaysSupported,
"syz_io_uring_complete": alwaysSupported,
"syz_memcpy_off": alwaysSupported,
"syz_btf_id_by_name": linuxBtfVmlinuxSupported,
"syz_fuse_handle_req": alwaysSupported,
"syz_80211_inject_frame": linuxWifiEmulationSupported,
"syz_80211_join_ibss": linuxWifiEmulationSupported,
"syz_usbip_server_init": linuxSyzUsbIPSupported,
"syz_clone": alwaysSupported,
"syz_clone3": alwaysSupported,
"syz_pkey_set": linuxPkeysSupported,
"syz_socket_connect_nvme_tcp": linuxSyzSocketConnectNvmeTCPSupported,
"syz_pidfd_open": alwaysSupported,
"syz_create_resource": alwaysSupported,
}
func linuxSyzOpenDevSupported(ctx *checkContext, call *prog.Syscall) string {
if _, ok := call.Args[0].Type.(*prog.ConstType); ok || call.Attrs.Automatic {
// This is for syz_open_dev$char/block.
// second operand for when we have an automatically generated description
return ""
}
fname, ok := extractStringConst(call.Args[0].Type, call.Attrs.Automatic)
if !ok {
panic("first open arg is not a pointer to string const")
}
hashCount := strings.Count(fname, "#")
if hashCount == 0 {
panic(fmt.Sprintf("%v does not contain # in the file name", call.Name))
}
if hashCount > 2 {
// If this fails, the logic below needs an adjustment.
panic(fmt.Sprintf("%v contains too many #", call.Name))
}
var ids []int
if _, ok := call.Args[1].Type.(*prog.ProcType); ok {
ids = []int{0}
} else {
for i := 0; i < 5; i++ {
for j := 0; j < 5; j++ {
if j == 0 || hashCount > 1 {
ids = append(ids, i+j*10)
}
}
}
}
modes := ctx.allOpenModes()
var calls []string
for _, id := range ids {
for _, mode := range modes {
call := fmt.Sprintf("%s(&AUTO='%v', 0x%x, 0x%x)", call.Name, fname, id, mode)
calls = append(calls, call)
}
}
reason := ctx.anyCallSucceeds(calls, fmt.Sprintf("failed to open %v", fname))
if reason != "" {
// These entries might not be available at boot time,
// but will be created by connected USB devices.
for _, prefix := range []string{"/dev/hidraw", "/dev/usb/hiddev", "/dev/input/"} {
if strings.HasPrefix(fname, prefix) {
if ctx.rootCanOpen("/dev/raw-gadget") == "" {
reason = ""
}
}
}
}
return reason
}
func linuxNetInjectionSupported(ctx *checkContext, call *prog.Syscall) string {
return ctx.rootCanOpen("/dev/net/tun")
}
func linuxSyzOpenProcfsSupported(ctx *checkContext, call *prog.Syscall) string {
return ctx.canOpen("/proc/cmdline")
}
func linuxCheckUSBEmulation(ctx *checkContext, call *prog.Syscall) string {
return ctx.rootCanOpen("/dev/raw-gadget")
}
const unsupportedArch = "unsupported arch"
func linuxSyzKvmSupported(ctx *checkContext, call *prog.Syscall) string {
switch call.Name {
case "syz_kvm_setup_cpu$x86":
if ctx.target.Arch == targets.AMD64 || ctx.target.Arch == targets.I386 {
return ""
}
case "syz_kvm_setup_syzos_vm$x86", "syz_kvm_add_vcpu$x86", "syz_kvm_assert_syzos_uexit$x86":
if ctx.target.Arch == targets.AMD64 {
return ""
}
case "syz_kvm_setup_cpu$arm64", "syz_kvm_setup_syzos_vm$arm64", "syz_kvm_add_vcpu$arm64",
"syz_kvm_assert_syzos_uexit$arm64":
if ctx.target.Arch == targets.ARM64 {
return ""
}
case "syz_kvm_setup_cpu$ppc64":
if ctx.target.Arch == targets.PPC64LE {
return ""
}
}
return unsupportedArch
}
func linuxSyzSupportedOnArm64(ctx *checkContext, call *prog.Syscall) string {
if ctx.target.Arch == targets.ARM64 {
return ""
}
return unsupportedArch
}
func linuxSupportedMount(ctx *checkContext, call *prog.Syscall) string {
return linuxSupportedFilesystem(ctx, call, 2)
}
func linuxSyzMountImageSupported(ctx *checkContext, call *prog.Syscall) string {
return linuxSupportedFilesystem(ctx, call, 0)
}
func linuxSupportedFilesystem(ctx *checkContext, call *prog.Syscall, fsarg int) string {
if call.Attrs.Automatic {
return ""
}
fstype, ok := extractStringConst(call.Args[fsarg].Type, call.Attrs.Automatic)
if !ok {
panic(fmt.Sprintf("%v: filesystem is not string const", call.Name))
}
switch fstype {
case "fuse", "fuseblk":
if reason := ctx.canOpen("/dev/fuse"); reason != "" {
return reason
}
if reason := ctx.onlySandboxNoneOrNamespace(); reason != "" {
return reason
}
default:
if reason := ctx.onlySandboxNone(); reason != "" {
return reason
}
}
filesystems, err := ctx.readFile("/proc/filesystems")
if err != nil {
return err.Error()
}
if !bytes.Contains(filesystems, []byte("\t"+fstype+"\n")) {
return fmt.Sprintf("/proc/filesystems does not contain %v", fstype)
}
return ""
}
func linuxSyzReadPartTableSupported(ctx *checkContext, call *prog.Syscall) string {
return ctx.onlySandboxNone()
}
func linuxSupportedSocket(ctx *checkContext, call *prog.Syscall) string {
if call.Name == "socket" || call.Name == "socketpair" || call.Attrs.Automatic {
return "" // generic versions are always supported
}
af := uint64(0)
if arg, ok := call.Args[0].Type.(*prog.ConstType); ok {
af = arg.Val
} else {
panic(fmt.Sprintf("socket family is not const in %v", call.Name))
}
typ, hasType := uint64(0), false
if arg, ok := call.Args[1].Type.(*prog.ConstType); ok {
typ, hasType = arg.Val, true
} else if arg, ok := call.Args[1].Type.(*prog.FlagsType); ok {
typ, hasType = arg.Vals[0], true
}
proto, hasProto := uint64(0), false
if arg, ok := call.Args[2].Type.(*prog.ConstType); ok {
proto, hasProto = arg.Val, true
}
syscallName := call.Name
if call.CallName == "socketpair" {
syscallName = "socket"
}
callStr := fmt.Sprintf("%s(0x%x, 0x%x, 0x%x)", syscallName, af, typ, proto)
errno := ctx.execCall(callStr)
if errno == syscall.ENOSYS || errno == syscall.EAFNOSUPPORT || hasProto && hasType && errno != 0 {
return fmt.Sprintf("%v failed: %v", callStr, errno)
}
return ""
}
func linuxSyzGenetlinkGetFamilyIDSupported(ctx *checkContext, call *prog.Syscall) string {
// TODO: try to obtain actual family ID here. It will disable whole sets of sendmsg syscalls.
return ctx.callSucceeds(fmt.Sprintf("socket(0x%x, 0x%x, 0x%x)",
ctx.val("AF_NETLINK"), ctx.val("SOCK_RAW"), ctx.val("NETLINK_GENERIC")))
}
func linuxPkeysSupported(ctx *checkContext, call *prog.Syscall) string {
return ctx.callSucceeds("pkey_alloc(0x0, 0x0)")
}
func linuxSyzSocketConnectNvmeTCPSupported(ctx *checkContext, call *prog.Syscall) string {
return ctx.onlySandboxNone()
}
func linuxVhciInjectionSupported(ctx *checkContext, call *prog.Syscall) string {
return ctx.rootCanOpen("/dev/vhci")
}
func linuxSyzInitNetSocketSupported(ctx *checkContext, call *prog.Syscall) string {
if reason := ctx.onlySandboxNone(); reason != "" {
return reason
}
return linuxSupportedSocket(ctx, call)
}
func linuxBtfVmlinuxSupported(ctx *checkContext, call *prog.Syscall) string {
if reason := ctx.onlySandboxNone(); reason != "" {
return reason
}
return ctx.canOpen("/sys/kernel/btf/vmlinux")
}
func linuxSyzUsbIPSupported(ctx *checkContext, call *prog.Syscall) string {
return ctx.canWrite("/sys/devices/platform/vhci_hcd.0/attach")
}
func linuxWifiEmulationSupported(ctx *checkContext, call *prog.Syscall) string {
if reason := ctx.rootCanOpen("/sys/class/mac80211_hwsim/"); reason != "" {
return reason
}
// We use HWSIM_ATTR_PERM_ADDR which was added in 4.17.
return linuxRequireKernel(ctx, 4, 17)
}
func linuxRequireKernel(ctx *checkContext, major, minor int) string {
data, err := ctx.readFile("/proc/version")
if err != nil {
return err.Error()
}
if ok, bad := matchKernelVersion(string(data), major, minor); bad {
return fmt.Sprintf("failed to parse kernel version: %s", data)
} else if !ok {
return fmt.Sprintf("kernel %v.%v required, have %s", major, minor, data)
}
return ""
}
var kernelVersionRe = regexp.MustCompile(` ([0-9]+)\.([0-9]+)\.`)
func matchKernelVersion(ver string, x, y int) (bool, bool) {
match := kernelVersionRe.FindStringSubmatch(ver)
if match == nil {
return false, true
}
major, err := strconv.Atoi(match[1])
if err != nil {
return false, true
}
if major <= 0 || major > 999 {
return false, true
}
minor, err := strconv.Atoi(match[2])
if err != nil {
return false, true
}
if minor <= 0 || minor > 999 {
return false, true
}
return major*1000+minor >= x*1000+y, false
}
// Copyright 2024 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package vminfo
import (
"github.com/google/syzkaller/prog"
)
type netbsd struct {
nopChecker
}
func (netbsd) syscallCheck(ctx *checkContext, call *prog.Syscall) string {
switch call.CallName {
case "openat":
return supportedOpenat(ctx, call)
case "syz_usb_connect", "syz_usb_disconnect":
return ctx.rootCanOpen("/dev/vhci0")
default:
return ""
}
}
// Copyright 2024 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package vminfo
import (
"github.com/google/syzkaller/prog"
)
type openbsd struct {
nopChecker
}
func (openbsd) syscallCheck(ctx *checkContext, call *prog.Syscall) string {
switch call.CallName {
case "openat":
return supportedOpenat(ctx, call)
default:
return ""
}
}
// Copyright 2024 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package vminfo
import (
"context"
"fmt"
"strings"
"syscall"
"github.com/google/syzkaller/pkg/flatrpc"
"github.com/google/syzkaller/pkg/fuzzer/queue"
"github.com/google/syzkaller/prog"
"github.com/google/syzkaller/sys/targets"
)
// checkContext arranges checking of presence/support of all target syscalls.
// The actual checking is done by OS-specific impl.syscallCheck,
// while checkContext invokes that function for each syscall in a special manner
// and provides primitives for reading target VM files, checking if a file can be opened,
// executing test programs on the target VM, etc.
//
// The external interface of this type contains only 2 methods:
// startCheck - starts impl.syscallCheck goroutines and collects all test programs in progs,
// finishCheck - accepts results of program execution, unblocks impl.syscallCheck goroutines,
//
// waits and returns results of checking.
type checkContext struct {
ctx context.Context
impl checker
cfg *Config
target *prog.Target
executor queue.Executor
fs filesystem
// Once checking of a syscall is finished, the result is sent to syscalls.
// The main goroutine will wait for exactly pendingSyscalls messages.
syscalls chan syscallResult
pendingSyscalls int
features chan featureResult
}
type syscallResult struct {
call *prog.Syscall
reason string
}
func newCheckContext(ctx context.Context, cfg *Config, impl checker, executor queue.Executor) *checkContext {
return &checkContext{
ctx: ctx,
impl: impl,
cfg: cfg,
target: cfg.Target,
executor: executor,
syscalls: make(chan syscallResult),
features: make(chan featureResult, 100),
}
}
func (ctx *checkContext) do(fileInfos []*flatrpc.FileInfo, featureInfos []*flatrpc.FeatureInfo) (
map[*prog.Syscall]bool, map[*prog.Syscall]string, Features, error) {
sysTarget := targets.Get(ctx.cfg.Target.OS, ctx.cfg.Target.Arch)
ctx.fs = createVirtualFilesystem(fileInfos)
for _, id := range ctx.cfg.Syscalls {
call := ctx.target.Syscalls[id]
if call.Attrs.Disabled {
continue
}
ctx.pendingSyscalls++
syscallCheck := ctx.impl.syscallCheck
if strings.HasPrefix(call.CallName, "syz_ext_") {
// Non-mainline pseudo-syscalls in executor/common_ext.h can't have
// the checking function and are assumed to be unconditionally supported.
syscallCheck = alwaysSupported
}
// HostFuzzer targets can't run Go binaries on the targets,
// so we actually run on the host on another OS. The same for targets.TestOS OS.
if sysTarget.HostFuzzer || ctx.target.OS == targets.TestOS {
syscallCheck = alwaysSupported
}
go func() {
var reason string
deps := sysTarget.PseudoSyscallDeps[call.CallName]
if len(deps) != 0 {
reason = ctx.supportedSyscalls(deps)
}
// Only check the call if all its dependencies are satisfied.
if reason == "" {
reason = syscallCheck(ctx, call)
}
ctx.syscalls <- syscallResult{call, reason}
}()
}
ctx.startFeaturesCheck()
var globReqs []*queue.Request
for _, glob := range ctx.target.RequiredGlobs() {
req := &queue.Request{
Type: flatrpc.RequestTypeGlob,
GlobPattern: glob,
ExecOpts: flatrpc.ExecOpts{
EnvFlags: ctx.cfg.Sandbox,
SandboxArg: ctx.cfg.SandboxArg,
},
Important: true,
}
ctx.executor.Submit(req)
globReqs = append(globReqs, req)
}
// Up to this point we submit all requests (start submitting goroutines),
// so that all requests execute in parallel. After this point we wait
// for request completion and handle results.
globs := make(map[string][]string)
for _, req := range globReqs {
res := req.Wait(ctx.ctx)
if res.Err == queue.ErrRequestAborted {
// Don't return an error on context cancellation.
return nil, nil, nil, nil
} else if res.Status != queue.Success {
return nil, nil, nil, fmt.Errorf("failed to execute glob: %w (%v)\n%s\n%s",
res.Err, res.Status, req.GlobPattern, res.Output)
}
globs[req.GlobPattern] = res.GlobFiles()
}
ctx.target.UpdateGlobs(globs)
enabled := make(map[*prog.Syscall]bool)
disabled := make(map[*prog.Syscall]string)
for i := 0; i < ctx.pendingSyscalls; i++ {
res := <-ctx.syscalls
if res.reason == "" {
enabled[res.call] = true
} else {
disabled[res.call] = res.reason
}
}
features, err := ctx.finishFeatures(featureInfos)
return enabled, disabled, features, err
}
func (ctx *checkContext) rootCanOpen(file string) string {
return ctx.canOpenImpl(file, nil, true)
}
func (ctx *checkContext) canOpen(file string) string {
return ctx.canOpenImpl(file, nil, false)
}
func (ctx *checkContext) canWrite(file string) string {
return ctx.canOpenImpl(file, []uint64{ctx.val("O_WRONLY")}, false)
}
func (ctx *checkContext) canOpenImpl(file string, modes []uint64, root bool) string {
if len(modes) == 0 {
modes = ctx.allOpenModes()
}
var calls []string
for _, mode := range modes {
call := fmt.Sprintf("openat(0x%x, &AUTO='%s', 0x%x, 0x0)", ctx.val("AT_FDCWD"), file, mode)
calls = append(calls, call)
}
info := ctx.execRaw(calls, prog.StrictUnsafe, root)
for _, call := range info.Calls {
if call.Error == 0 {
return ""
}
}
who := ""
if root {
who = "root "
}
return fmt.Sprintf("%vfailed to open %s: %v", who, file, syscall.Errno(info.Calls[0].Error))
}
func (ctx *checkContext) supportedSyscalls(names []string) string {
var calls []string
for _, name := range names {
if strings.HasPrefix(name, "syz_") {
panic("generic syscall check used for pseudo-syscall: " + name)
}
calls = append(calls, name+"()")
}
info := ctx.execRaw(calls, prog.NonStrictUnsafe, false)
for i, res := range info.Calls {
if res.Error == int32(syscall.ENOSYS) {
return fmt.Sprintf("syscall %v is not present", names[i])
}
}
return ""
}
func supportedOpenat(ctx *checkContext, call *prog.Syscall) string {
fname, ok := extractStringConst(call.Args[1].Type, call.Attrs.Automatic)
if !ok || fname[0] != '/' {
return ""
}
modes := ctx.allOpenModes()
// Attempt to extract flags from the syscall description.
if mode, ok := call.Args[2].Type.(*prog.ConstType); ok {
modes = []uint64{mode.Val}
}
var calls []string
for _, mode := range modes {
call := fmt.Sprintf("openat(0x%0x, &AUTO='%v', 0x%x, 0x0)", ctx.val("AT_FDCWD"), fname, mode)
calls = append(calls, call)
}
return ctx.anyCallSucceeds(calls, fmt.Sprintf("failed to open %v", fname))
}
func (ctx *checkContext) allOpenModes() []uint64 {
// Various open modes we need to try if we don't have a concrete mode.
// Some files can be opened only for reading, some only for writing,
// and some only in non-blocking mode.
// Note: some of these consts are different for different arches.
return []uint64{ctx.val("O_RDONLY"), ctx.val("O_WRONLY"), ctx.val("O_RDWR"),
ctx.val("O_RDONLY") | ctx.val("O_NONBLOCK")}
}
func (ctx *checkContext) callSucceeds(call string) string {
return ctx.anyCallSucceeds([]string{call}, call+" failed")
}
func (ctx *checkContext) execCall(call string) syscall.Errno {
info := ctx.execRaw([]string{call}, prog.StrictUnsafe, false)
return syscall.Errno(info.Calls[0].Error)
}
func (ctx *checkContext) anyCallSucceeds(calls []string, msg string) string {
info := ctx.execRaw(calls, prog.StrictUnsafe, false)
for _, call := range info.Calls {
if call.Error == 0 {
return ""
}
}
return fmt.Sprintf("%s: %v", msg, syscall.Errno(info.Calls[0].Error))
}
func (ctx *checkContext) onlySandboxNone() string {
if ctx.cfg.Sandbox != flatrpc.ExecEnvSandboxNone {
return "only supported under root with sandbox=none"
}
return ""
}
func (ctx *checkContext) onlySandboxNoneOrNamespace() string {
if ctx.cfg.Sandbox != flatrpc.ExecEnvSandboxNone && ctx.cfg.Sandbox != flatrpc.ExecEnvSandboxNamespace {
return "only supported under root with sandbox=none/namespace"
}
return ""
}
func (ctx *checkContext) val(name string) uint64 {
val, ok := ctx.target.ConstMap[name]
if !ok {
panic(fmt.Sprintf("const %v is not present", name))
}
return val
}
func (ctx *checkContext) execRaw(calls []string, mode prog.DeserializeMode, root bool) *flatrpc.ProgInfo {
sandbox := ctx.cfg.Sandbox
if root {
sandbox = flatrpc.ExecEnvSandboxNone
}
info := &flatrpc.ProgInfo{}
for remain := calls; len(remain) != 0; {
// Don't put too many syscalls into a single program,
// it will have higher chances to time out.
ncalls := min(len(remain), prog.MaxCalls/2)
progStr := strings.Join(remain[:ncalls], "\n")
remain = remain[ncalls:]
p, err := ctx.target.Deserialize([]byte(progStr), mode)
if err != nil {
panic(fmt.Sprintf("failed to deserialize: %v\n%v", err, progStr))
}
req := &queue.Request{
Prog: p,
ExecOpts: flatrpc.ExecOpts{
EnvFlags: sandbox,
ExecFlags: 0,
SandboxArg: ctx.cfg.SandboxArg,
},
Important: true,
}
ctx.executor.Submit(req)
res := req.Wait(ctx.ctx)
if res.Status == queue.Success {
info.Calls = append(info.Calls, res.Info.Calls...)
} else {
// Pretend these calls were not executed.
info.Calls = append(info.Calls, flatrpc.EmptyProgInfo(ncalls).Calls...)
}
}
if len(info.Calls) != len(calls) {
panic(fmt.Sprintf("got %v != %v results for program:\n%s",
len(info.Calls), len(calls), strings.Join(calls, "\n")))
}
return info
}
func (ctx *checkContext) readFile(name string) ([]byte, error) {
return ctx.fs.ReadFile(name)
}
func alwaysSupported(ctx *checkContext, call *prog.Syscall) string {
return ""
}
func extractStringConst(typ prog.Type, isAutomatic bool) (string, bool) {
if isAutomatic {
return "", false
}
ptr, ok := typ.(*prog.PtrType)
if !ok {
return "", false
}
str, ok := ptr.Elem.(*prog.BufferType)
if !ok || str.Kind != prog.BufferString || len(str.Values) == 0 {
return "", false
}
v := str.Values[0]
for v != "" && v[len(v)-1] == 0 {
v = v[:len(v)-1] // string terminating \x00
}
return v, true
}
// Copyright 2024 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
// Package vminfo extracts information about the target VM.
// The package itself runs on the host, which may be a different OS/arch.
// User of the package first requests set of files that needs to be fetched from the VM
// and set of test programs that needs to be executed in the VM (Checker.RequiredThings),
// then fetches these files and executes test programs, and calls Checker.MachineInfo
// to parse the files and extract information about the VM, and optionally calls
// Checker.Check to obtain list of enabled/disabled syscalls.
// The information includes information about kernel modules and OS-specific info
// (for Linux that includes things like parsed /proc/cpuinfo).
package vminfo
import (
"bytes"
"context"
"errors"
"fmt"
"io"
"io/fs"
"os"
"strings"
"github.com/google/syzkaller/pkg/flatrpc"
"github.com/google/syzkaller/pkg/fuzzer/queue"
"github.com/google/syzkaller/prog"
"github.com/google/syzkaller/sys/targets"
)
type KernelModule struct {
Name string
Addr uint64
Size uint64
Path string
}
type Checker struct {
checker
cfg *Config
source queue.Source
executor queue.Executor
}
type Config struct {
Target *prog.Target
VMType string
// Set of features to check, missing features won't be checked/enabled after Run.
Features flatrpc.Feature
// Set of syscalls to check.
Syscalls []int
Debug bool
Cover bool
Sandbox flatrpc.ExecEnv
SandboxArg int64
}
func New(cfg *Config) *Checker {
var impl checker
switch cfg.Target.OS {
case targets.Linux:
impl = &linux{vmType: cfg.VMType}
case targets.NetBSD:
impl = new(netbsd)
case targets.OpenBSD:
impl = new(openbsd)
default:
impl = new(nopChecker)
}
executor := queue.Plain()
return &Checker{
cfg: cfg,
checker: impl,
executor: executor,
source: queue.Deduplicate(executor),
}
}
func (checker *Checker) MachineInfo(fileInfos []*flatrpc.FileInfo) ([]*KernelModule, []byte, error) {
files := createVirtualFilesystem(fileInfos)
modules, err := checker.parseModules(files)
if err != nil {
return nil, nil, err
}
info := new(bytes.Buffer)
tmp := new(bytes.Buffer)
for _, fn := range checker.machineInfos() {
tmp.Reset()
name, err := fn(files, tmp)
if err != nil {
if !os.IsNotExist(err) {
return nil, nil, err
}
continue
}
if tmp.Len() == 0 {
continue
}
fmt.Fprintf(info, "[%v]\n%s\n%v\n\n", name, tmp.Bytes(), strings.Repeat("-", 80))
}
return modules, info.Bytes(), nil
}
var ErrAborted = errors.New("aborted through the context")
func (checker *Checker) Run(ctx context.Context, files []*flatrpc.FileInfo, featureInfos []*flatrpc.FeatureInfo) (
map[*prog.Syscall]bool, map[*prog.Syscall]string, Features, error) {
cc := newCheckContext(ctx, checker.cfg, checker.checker, checker.executor)
enabled, disabled, features, err := cc.do(files, featureInfos)
if ctx.Err() != nil {
return nil, nil, nil, ErrAborted
}
return enabled, disabled, features, err
}
// Implementation of the queue.Source interface.
func (checker *Checker) Next() *queue.Request {
return checker.source.Next()
}
var _ queue.Source = &Checker{}
type machineInfoFunc func(files filesystem, w io.Writer) (string, error)
type checker interface {
RequiredFiles() []string
CheckFiles() []string
parseModules(files filesystem) ([]*KernelModule, error)
machineInfos() []machineInfoFunc
syscallCheck(*checkContext, *prog.Syscall) string
}
type filesystem map[string]*flatrpc.FileInfo
func createVirtualFilesystem(fileInfos []*flatrpc.FileInfo) filesystem {
files := make(filesystem)
for _, file := range fileInfos {
if file.Exists {
files[file.Name] = file
}
}
return files
}
func (files filesystem) ReadFile(name string) ([]byte, error) {
file, ok := files[name]
if !ok {
return nil, &fs.PathError{Op: "open", Path: name, Err: fs.ErrNotExist}
}
if file.Error != "" {
return nil, errors.New(file.Error)
}
return file.Data, nil
}
func (files filesystem) ReadDir(dir string) []string {
var res []string
dedup := make(map[string]bool)
for _, file := range files {
if len(file.Name) < len(dir)+2 ||
!strings.HasPrefix(file.Name, dir) ||
file.Name[len(dir)] != '/' {
continue
}
name := file.Name[len(dir)+1:]
if slash := strings.Index(name, "/"); slash != -1 {
name = name[:slash]
}
if dedup[name] {
continue
}
dedup[name] = true
res = append(res, name)
}
return res
}
type nopChecker int
func (nopChecker) RequiredFiles() []string {
return nil
}
func (nopChecker) CheckFiles() []string {
return nil
}
func (nopChecker) parseModules(files filesystem) ([]*KernelModule, error) {
return nil, nil
}
func (nopChecker) machineInfos() []machineInfoFunc {
return nil
}
func (nopChecker) syscallCheck(*checkContext, *prog.Syscall) string {
return ""
}
// Copyright 2018 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package prog
import (
"fmt"
)
// memAlloc keeps track of allocated objects in a program
// and decides where to allocate new objects.
// It has 2 main methods: noteAlloc which is called for existing allocations
// in a program as we analyze it; and alloc which decides where to allocate
// a new object.
// The implementation is based on a 2-level bitmap where each bit represents
// 64 bytes (memAllocGranule) of program memory.
type memAlloc struct {
size uint64
mem [memAllocL1Size]*[memAllocL0Size]uint64
buf [memAllocL0Size]uint64
}
const (
memAllocGranule = 64 // 1 bit per that many bytes (all allocations are rounded to this size)
memAllocMaxMem = 16 << 20
memAllocL0Size = 64
bitsPerUint64 = 8 * 8
memAllocL0Mem = memAllocL0Size * memAllocGranule * bitsPerUint64
memAllocL1Size = memAllocMaxMem / memAllocL0Mem
)
func newMemAlloc(totalMemSize uint64) *memAlloc {
if totalMemSize > memAllocMaxMem {
panic(fmt.Sprintf("newMemAlloc: too much mem %v (max: %v)", totalMemSize, memAllocMaxMem))
}
if totalMemSize%memAllocL0Mem != 0 {
panic(fmt.Sprintf("newMemAlloc: unaligned size %v (align: %v)", totalMemSize, memAllocL0Mem))
}
ma := &memAlloc{
size: totalMemSize / memAllocGranule,
}
ma.mem[0] = &ma.buf
return ma
}
func (ma *memAlloc) noteAlloc(addr0, size0 uint64) {
addr := addr0 / memAllocGranule
size := (addr0+size0+memAllocGranule-1)/memAllocGranule - addr
for i := uint64(0); i < size; i++ {
ma.set(addr + i)
}
}
// alloc returns the next free address of size0 with respect to the given alignment.
func (ma *memAlloc) alloc(r *randGen, size0, alignment0 uint64) uint64 {
if size0 == 0 {
size0 = 1
}
if alignment0 == 0 {
alignment0 = 1
}
size := (size0 + memAllocGranule - 1) / memAllocGranule
alignment := (alignment0 + memAllocGranule - 1) / memAllocGranule
end := ma.size - size
for start := uint64(0); start <= end; start += alignment {
empty := true
for i := uint64(0); i < size; i++ {
if ma.get(start + i) {
empty = false
break
}
}
if empty {
start0 := start * memAllocGranule
ma.noteAlloc(start0, size0)
return start0
}
}
ma.bankruptcy()
return ma.alloc(r, size0, alignment0)
}
func (ma *memAlloc) bankruptcy() {
for i1 := uint64(0); i1 < ma.size/(memAllocL0Size*bitsPerUint64); i1++ {
if ma.mem[i1] == nil {
continue
}
for i0 := range ma.mem[i1] {
ma.mem[i1][i0] = 0
}
}
}
func (ma *memAlloc) pos(idx uint64) (i1, i0, bit uint64) {
i1 = idx / (memAllocL0Size * bitsPerUint64)
r1 := idx % (memAllocL0Size * bitsPerUint64)
i0 = r1 / bitsPerUint64
bit = 1 << (r1 % bitsPerUint64)
return
}
func (ma *memAlloc) set(idx uint64) {
i1, i0, bit := ma.pos(idx)
if ma.mem[i1] == nil {
ma.mem[i1] = new([memAllocL0Size]uint64)
}
ma.mem[i1][i0] |= bit
}
func (ma *memAlloc) get(idx uint64) bool {
i1, i0, bit := ma.pos(idx)
if ma.mem[i1] == nil {
return false
}
return ma.mem[i1][i0]&bit != 0
}
type vmaAlloc struct {
numPages uint64
used []uint64
m map[uint64]struct{}
}
func newVmaAlloc(totalPages uint64) *vmaAlloc {
return &vmaAlloc{
numPages: totalPages,
m: make(map[uint64]struct{}),
}
}
func (va *vmaAlloc) noteAlloc(page, size uint64) {
for i := page; i < page+size; i++ {
if _, ok := va.m[i]; ok {
continue
}
va.m[i] = struct{}{}
va.used = append(va.used, i)
}
}
func (va *vmaAlloc) alloc(r *randGen, size uint64) uint64 {
if size > va.numPages {
panic(fmt.Sprintf("vmaAlloc: bad size=%v numPages=%v", size, va.numPages))
}
var page uint64
if len(va.used) == 0 || r.oneOf(5) {
page = r.rand(4)
if !r.oneOf(100) {
page = va.numPages - page - size
}
} else {
page = va.used[r.rand(len(va.used))]
if size > 1 && r.bin() {
page -= min(r.rand(int(size)), page)
}
page = min(page, va.numPages-size)
}
if page >= va.numPages || size > va.numPages || page+size > va.numPages {
panic(fmt.Sprintf("vmaAlloc: bad page=%v size=%v numPages=%v", page, size, va.numPages))
}
va.noteAlloc(page, size)
return page
}
// Copyright 2015 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
// Conservative resource-related analysis of programs.
// The analysis figures out what files descriptors are [potentially] opened
// at a particular point in program, what pages are [potentially] mapped,
// what files were already referenced in calls, etc.
package prog
import (
"bytes"
"fmt"
"io"
"github.com/google/syzkaller/pkg/image"
)
type state struct {
target *Target
ct *ChoiceTable
corpus []*Prog
files map[string]bool
resources map[string][]*ResultArg
strings map[string]bool
ma *memAlloc
va *vmaAlloc
}
// analyze analyzes the program p up to but not including call c.
func analyze(ct *ChoiceTable, corpus []*Prog, p *Prog, c *Call) *state {
s := newState(p.Target, ct, corpus)
resources := true
for _, c1 := range p.Calls {
if c1 == c {
resources = false
}
s.analyzeImpl(c1, resources)
}
return s
}
func newState(target *Target, ct *ChoiceTable, corpus []*Prog) *state {
s := &state{
target: target,
ct: ct,
corpus: corpus,
files: make(map[string]bool),
resources: make(map[string][]*ResultArg),
strings: make(map[string]bool),
ma: newMemAlloc(target.NumPages * target.PageSize),
va: newVmaAlloc(target.NumPages),
}
return s
}
func (s *state) analyze(c *Call) {
s.analyzeImpl(c, true)
}
func (s *state) analyzeImpl(c *Call, resources bool) {
ForeachArg(c, func(arg Arg, _ *ArgCtx) {
switch a := arg.(type) {
case *PointerArg:
switch {
case a.IsSpecial():
case a.VmaSize != 0:
s.va.noteAlloc(a.Address/s.target.PageSize, a.VmaSize/s.target.PageSize)
case a.Res != nil:
s.ma.noteAlloc(a.Address, a.Res.Size())
}
}
switch typ := arg.Type().(type) {
case *ResourceType:
a := arg.(*ResultArg)
if resources && a.Dir() != DirIn {
s.resources[typ.Desc.Name] = append(s.resources[typ.Desc.Name], a)
// TODO: negative PIDs and add them as well (that's process groups).
}
case *BufferType:
a := arg.(*DataArg)
if a.Dir() != DirOut && len(a.Data()) != 0 &&
(typ.Kind == BufferString || typ.Kind == BufferFilename) {
val := string(a.Data())
// Remove trailing zero padding.
for len(val) >= 2 && val[len(val)-1] == 0 && val[len(val)-2] == 0 {
val = val[:len(val)-1]
}
switch typ.Kind {
case BufferString:
s.strings[val] = true
case BufferFilename:
if len(val) < 3 || escapingFilename(val) {
// This is not our file, probalby one of specialFiles.
return
}
if val[len(val)-1] == 0 {
val = val[:len(val)-1]
}
s.files[val] = true
}
}
}
})
}
type parentStack []Arg
func allocStack() parentStack {
// Let's save some allocations during stack traversal.
return make([]Arg, 0, 4)
}
func pushStack(ps parentStack, a Arg) parentStack {
return append(ps, a)
}
func popStack(ps parentStack) (parentStack, Arg) {
if len(ps) > 0 {
return ps[:len(ps)-1], ps[len(ps)-1]
}
return ps, nil
}
type ArgCtx struct {
Parent *[]Arg // GroupArg.Inner (for structs) or Call.Args containing this arg.
Fields []Field // Fields of the parent struct/syscall.
Field *Field // Syscall field for this arg, nil if there it's not a field.
Base *PointerArg // Pointer to the base of the heap object containing this arg.
Offset uint64 // Offset of this arg from the base.
Stop bool // If set by the callback, subargs of this arg are not visited.
parentStack parentStack // Struct and union arguments by which the argument can be reached.
}
func ForeachSubArg(arg Arg, f func(Arg, *ArgCtx)) {
foreachArgImpl(arg, nil, &ArgCtx{}, f)
}
func foreachSubArgWithStack(arg Arg, f func(Arg, *ArgCtx)) {
foreachArgImpl(arg, nil, &ArgCtx{parentStack: allocStack()}, f)
}
func ForeachArg(c *Call, f func(Arg, *ArgCtx)) {
ctx := &ArgCtx{}
if c.Ret != nil {
foreachArgImpl(c.Ret, nil, ctx, f)
}
ctx.Parent = &c.Args
ctx.Fields = c.Meta.Args
for i, arg := range c.Args {
foreachArgImpl(arg, &ctx.Fields[i], ctx, f)
}
}
func foreachArgImpl(arg Arg, field *Field, ctx *ArgCtx, f func(Arg, *ArgCtx)) {
ctx0 := *ctx
defer func() { *ctx = ctx0 }()
if ctx.parentStack != nil {
switch arg.Type().(type) {
case *StructType, *UnionType:
ctx.parentStack = pushStack(ctx.parentStack, arg)
}
}
ctx.Field = field
f(arg, ctx)
if ctx.Stop {
return
}
switch a := arg.(type) {
case *GroupArg:
overlayField := 0
if typ, ok := a.Type().(*StructType); ok {
ctx.Parent = &a.Inner
ctx.Fields = typ.Fields
overlayField = typ.OverlayField
}
var totalSize uint64
for i, arg1 := range a.Inner {
if i == overlayField {
ctx.Offset = ctx0.Offset
}
foreachArgImpl(arg1, nil, ctx, f)
size := arg1.Size()
ctx.Offset += size
if totalSize < ctx.Offset {
totalSize = ctx.Offset - ctx0.Offset
}
}
if debug {
claimedSize := a.Size()
varlen := a.Type().Varlen()
if varlen && totalSize > claimedSize || !varlen && totalSize != claimedSize {
panic(fmt.Sprintf("bad group arg size %v, should be <= %v for %#v type %#v",
totalSize, claimedSize, a, a.Type().Name()))
}
}
case *PointerArg:
if a.Res != nil {
ctx.Base = a
ctx.Offset = 0
foreachArgImpl(a.Res, nil, ctx, f)
}
case *UnionArg:
foreachArgImpl(a.Option, nil, ctx, f)
}
}
type RequiredFeatures struct {
Bitmasks bool
Csums bool
FaultInjection bool
Async bool
}
func (p *Prog) RequiredFeatures() RequiredFeatures {
features := RequiredFeatures{}
for _, c := range p.Calls {
ForeachArg(c, func(arg Arg, _ *ArgCtx) {
if a, ok := arg.(*ConstArg); ok {
if a.Type().BitfieldOffset() != 0 || a.Type().BitfieldLength() != 0 {
features.Bitmasks = true
}
}
if _, ok := arg.Type().(*CsumType); ok {
features.Csums = true
}
})
if c.Props.FailNth > 0 {
features.FaultInjection = true
}
if c.Props.Async {
features.Async = true
}
}
return features
}
type CallFlags int
const (
CallExecuted CallFlags = 1 << iota // was started at all
CallFinished // finished executing (rather than blocked forever)
CallBlocked // finished but blocked during execution
)
type CallInfo struct {
Flags CallFlags
Errno int
Signal []uint64
}
const (
fallbackSignalErrno = iota
fallbackSignalErrnoBlocked
fallbackSignalCtor
fallbackSignalFlags
// This allows us to have 2M syscalls and leaves 8 bits for 256 errno values.
// Linux currently have 133 errno's. Larger errno values will be truncated,
// which is acceptable for fallback coverage.
fallbackCallMask = 0x1fffff
)
func (p *Prog) FallbackSignal(info []CallInfo) {
resources := make(map[*ResultArg]*Call)
for i, c := range p.Calls {
inf := &info[i]
if inf.Flags&CallExecuted == 0 {
continue
}
id := c.Meta.ID
typ := fallbackSignalErrno
if inf.Flags&CallFinished != 0 && inf.Flags&CallBlocked != 0 {
typ = fallbackSignalErrnoBlocked
}
inf.Signal = append(inf.Signal, encodeFallbackSignal(typ, id, inf.Errno))
if c.Meta.Attrs.BreaksReturns {
break
}
if inf.Errno != 0 {
continue
}
ForeachArg(c, func(arg Arg, _ *ArgCtx) {
if a, ok := arg.(*ResultArg); ok {
resources[a] = c
}
})
// Specifically look only at top-level arguments,
// deeper arguments can produce too much false signal.
flags := 0
for _, arg := range c.Args {
flags = extractArgSignal(arg, id, flags, inf, resources)
}
if flags != 0 {
inf.Signal = append(inf.Signal,
encodeFallbackSignal(fallbackSignalFlags, id, flags))
}
}
}
func extractArgSignal(arg Arg, callID, flags int, inf *CallInfo, resources map[*ResultArg]*Call) int {
switch a := arg.(type) {
case *ResultArg:
flags <<= 1
if a.Res != nil {
ctor := resources[a.Res]
if ctor != nil {
inf.Signal = append(inf.Signal,
encodeFallbackSignal(fallbackSignalCtor, callID, ctor.Meta.ID))
}
} else {
if a.Val != a.Type().(*ResourceType).SpecialValues()[0] {
flags |= 1
}
}
case *ConstArg:
const width = 3
flags <<= width
switch typ := a.Type().(type) {
case *FlagsType:
if typ.BitMask {
for i, v := range typ.Vals {
if a.Val&v != 0 {
flags ^= 1 << (uint(i) % width)
}
}
} else {
for i, v := range typ.Vals {
if a.Val == v {
flags |= i % (1 << width)
break
}
}
}
case *LenType:
flags <<= 1
if a.Val == 0 {
flags |= 1
}
}
case *PointerArg:
flags <<= 1
if a.IsSpecial() {
flags |= 1
}
}
return flags
}
func DecodeFallbackSignal(s uint64) (callID, errno int) {
typ, id, aux := decodeFallbackSignal(s)
switch typ {
case fallbackSignalErrno, fallbackSignalErrnoBlocked:
return id, aux
case fallbackSignalCtor, fallbackSignalFlags:
return id, 0
default:
panic(fmt.Sprintf("bad fallback signal type %v", typ))
}
}
func encodeFallbackSignal(typ, id, aux int) uint64 {
checkMaxCallID(id)
if typ & ^7 != 0 {
panic(fmt.Sprintf("bad fallback signal type %v", typ))
}
return uint64(typ) | uint64(id&fallbackCallMask)<<3 | uint64(aux)<<24
}
func decodeFallbackSignal(s uint64) (typ, id, aux int) {
return int(s & 7), int((s >> 3) & fallbackCallMask), int(s >> 24)
}
func checkMaxCallID(id int) {
if id & ^fallbackCallMask != 0 {
panic(fmt.Sprintf("too many syscalls, have %v, max supported %v", id, fallbackCallMask+1))
}
}
type AssetType int
const (
MountInRepro AssetType = iota
)
func (p *Prog) ForEachAsset(cb func(name string, typ AssetType, r io.Reader, c *Call)) {
for id, c := range p.Calls {
ForeachArg(c, func(arg Arg, _ *ArgCtx) {
a, ok := arg.(*DataArg)
if !ok || a.Type().(*BufferType).Kind != BufferCompressed {
return
}
data, dtor := image.MustDecompress(a.Data())
defer dtor()
if len(data) == 0 {
return
}
cb(fmt.Sprintf("mount_%v", id), MountInRepro, bytes.NewReader(data), c)
})
}
}
func (p *Prog) ContainsAny() bool {
for _, c := range p.Calls {
if p.Target.CallContainsAny(c) {
return true
}
}
return false
}
// Copyright 2018 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package prog
import (
"fmt"
)
type anyTypes struct {
union *UnionType
array *ArrayType
blob *BufferType
ptrPtr *PtrType
ptr64 *PtrType
res8 *ResourceType
res16 *ResourceType
res32 *ResourceType
res64 *ResourceType
resdec *ResourceType
reshex *ResourceType
resoct *ResourceType
}
func (target *Target) initAnyTypes() {
var anyPtrs *UnionType
for _, typ := range target.Types {
if typ.Name() == "ANYPTRS" {
anyPtrs = typ.(*UnionType)
break
}
}
if anyPtrs == nil {
panic("no builtin ANYPTRS type")
}
// These types are generated by builtin descriptions in pkg/compiler/types.go.
target.any.ptrPtr = anyPtrs.Fields[0].Type.(*PtrType)
target.any.ptr64 = anyPtrs.Fields[1].Type.(*PtrType)
target.any.array = target.any.ptrPtr.Elem.(*ArrayType)
target.any.union = target.any.array.Elem.(*UnionType)
target.any.blob = target.any.union.Fields[0].Type.(*BufferType)
target.any.res8 = target.any.union.Fields[1].Type.(*ResourceType)
target.any.res16 = target.any.union.Fields[2].Type.(*ResourceType)
target.any.res32 = target.any.union.Fields[3].Type.(*ResourceType)
target.any.res64 = target.any.union.Fields[4].Type.(*ResourceType)
target.any.resdec = target.any.union.Fields[5].Type.(*ResourceType)
target.any.reshex = target.any.union.Fields[6].Type.(*ResourceType)
target.any.resoct = target.any.union.Fields[7].Type.(*ResourceType)
}
func (target *Target) getAnyPtrType(size uint64) *PtrType {
switch size {
case target.PtrSize:
return target.any.ptrPtr
case 8:
return target.any.ptr64
}
panic(fmt.Sprintf("bad pointer size %v", size))
}
func (target *Target) isAnyPtr(typ Type) bool {
ptr, ok := typ.(*PtrType)
return ok && ptr.Elem == target.any.array
}
type complexPtr struct {
arg *PointerArg
call *Call
}
func (p *Prog) complexPtrs() (res []complexPtr) {
for _, c := range p.Calls {
ForeachArg(c, func(arg Arg, ctx *ArgCtx) {
if ptrArg, ok := arg.(*PointerArg); ok && p.Target.isComplexPtr(ptrArg) {
res = append(res, complexPtr{ptrArg, c})
ctx.Stop = true
}
})
}
return
}
func (target *Target) isComplexPtr(arg *PointerArg) bool {
if arg.Res == nil || !arg.Type().(*PtrType).SquashableElem {
return false
}
if target.isAnyPtr(arg.Type()) {
return true
}
complex := false
ForeachSubArg(arg.Res, func(a1 Arg, ctx *ArgCtx) {
switch typ := a1.Type().(type) {
case *StructType:
if typ.Varlen() {
complex = true
ctx.Stop = true
}
case *UnionType:
if typ.Varlen() && len(typ.Fields) > 5 {
complex = true
ctx.Stop = true
}
}
})
return complex
}
func (target *Target) isAnyRes(name string) bool {
return name == target.any.res8.TypeName ||
name == target.any.res16.TypeName ||
name == target.any.res32.TypeName ||
name == target.any.res64.TypeName ||
name == target.any.resdec.TypeName ||
name == target.any.reshex.TypeName ||
name == target.any.resoct.TypeName
}
func (target *Target) CallContainsAny(c *Call) (res bool) {
ForeachArg(c, func(arg Arg, ctx *ArgCtx) {
if target.isAnyPtr(arg.Type()) || res {
res = true
ctx.Stop = true
}
})
return
}
func (target *Target) ArgContainsAny(arg0 Arg) (res bool) {
ForeachSubArg(arg0, func(arg Arg, ctx *ArgCtx) {
if target.isAnyPtr(arg.Type()) || res {
res = true
ctx.Stop = true
}
})
return
}
func (target *Target) squashPtr(arg *PointerArg) {
if arg.Res == nil || arg.VmaSize != 0 {
panic("bad ptr arg")
}
res0 := arg.Res
size0 := res0.Size()
var elems []Arg
target.squashPtrImpl(arg.Res, &elems)
newType := target.getAnyPtrType(arg.Type().Size())
arg.ref = newType.ref()
arg.Res = MakeGroupArg(newType.Elem, DirIn, elems)
if size := arg.Res.Size(); size != size0 {
panic(fmt.Sprintf("squash changed size %v->%v for %v", size0, size, res0.Type()))
}
}
func (target *Target) squashPtrImpl(a Arg, elems *[]Arg) {
if a.Type().BitfieldLength() != 0 {
panic("bitfield in squash")
}
var pad uint64
switch arg := a.(type) {
case *ConstArg:
target.squashConst(arg, elems)
case *ResultArg:
target.squashResult(arg, elems)
case *UnionArg:
if !arg.Type().Varlen() {
pad = arg.Size() - arg.Option.Size()
}
target.squashPtrImpl(arg.Option, elems)
case *DataArg:
if arg.Dir() == DirOut {
pad = arg.Size()
} else {
elem := target.ensureDataElem(elems)
elem.data = append(elem.Data(), arg.Data()...)
}
case *GroupArg:
target.squashGroup(arg, elems)
default:
panic(fmt.Sprintf("bad arg kind %v (%#v) %v", a, a, a.Type()))
}
if pad != 0 {
elem := target.ensureDataElem(elems)
elem.data = append(elem.Data(), make([]byte, pad)...)
}
}
func (target *Target) squashConst(arg *ConstArg, elems *[]Arg) {
if IsPad(arg.Type()) {
elem := target.ensureDataElem(elems)
elem.data = append(elem.Data(), make([]byte, arg.Size())...)
return
}
v, bf := target.squashedValue(arg)
var data []byte
switch bf {
case FormatNative:
for i := uint64(0); i < arg.Size(); i++ {
data = append(data, byte(v))
v >>= 8
}
case FormatStrDec:
data = []byte(fmt.Sprintf("%020v", v))
case FormatStrHex:
data = []byte(fmt.Sprintf("0x%016x", v))
case FormatStrOct:
data = []byte(fmt.Sprintf("%023o", v))
default:
panic(fmt.Sprintf("unknown binary format: %v", bf))
}
if uint64(len(data)) != arg.Size() {
panic("squashed value of wrong size")
}
elem := target.ensureDataElem(elems)
elem.data = append(elem.Data(), data...)
}
func (target *Target) squashResult(arg *ResultArg, elems *[]Arg) {
var typ *ResourceType
index := -1
switch arg.Type().Format() {
case FormatNative, FormatBigEndian:
switch arg.Size() {
case 1:
typ, index = target.any.res8, 1
case 2:
typ, index = target.any.res16, 2
case 4:
typ, index = target.any.res32, 3
case 8:
typ, index = target.any.res64, 4
default:
panic(fmt.Sprintf("bad size %v", arg.Size()))
}
case FormatStrDec:
typ, index = target.any.resdec, 5
case FormatStrHex:
typ, index = target.any.reshex, 6
case FormatStrOct:
typ, index = target.any.resoct, 7
default:
panic("bad")
}
arg.ref = typ.ref()
*elems = append(*elems, MakeUnionArg(target.any.union, DirIn, arg, index))
}
func (target *Target) squashGroup(arg *GroupArg, elems *[]Arg) {
if typ, ok := arg.Type().(*StructType); ok && typ.OverlayField != 0 {
panic("squashing out_overlay")
}
var bitfield, fieldsSize uint64
for _, fld := range arg.Inner {
fieldsSize += fld.Size()
// Squash bitfields separately.
if fld.Type().IsBitfield() {
bfLen := fld.Type().BitfieldLength()
bfOff := fld.Type().BitfieldOffset()
// Note: we can have a ResultArg here as well,
// but it is unsupported at the moment.
v, bf := target.squashedValue(fld.(*ConstArg))
if bf != FormatNative {
panic(fmt.Sprintf("bitfield has bad format %v", bf))
}
bitfield |= (v & ((1 << bfLen) - 1)) << bfOff
if fld.Size() != 0 {
elem := target.ensureDataElem(elems)
for i := uint64(0); i < fld.Size(); i++ {
elem.data = append(elem.Data(), byte(bitfield))
bitfield >>= 8
}
bitfield = 0
}
continue
}
target.squashPtrImpl(fld, elems)
}
// Add padding either due to dynamic alignment or overlay fields.
if pad := arg.Size() - fieldsSize; pad != 0 {
elem := target.ensureDataElem(elems)
elem.data = append(elem.Data(), make([]byte, pad)...)
}
}
func (target *Target) squashedValue(arg *ConstArg) (uint64, BinaryFormat) {
typ := arg.Type()
bf := typ.Format()
if _, ok := typ.(*CsumType); ok {
// We can't compute value for the checksum here,
// but at least leave something recognizable by hints code.
// TODO: hints code won't recognize this, because it won't find
// the const in any arg. We either need to put this const as
// actual csum arg value, or special case it in hints.
return 0xabcdef1234567890, FormatNative
}
// Note: we need a constant value, but it depends on pid for proc.
v, _ := arg.Value()
if bf == FormatBigEndian {
bf = FormatNative
switch typ.UnitSize() {
case 2:
v = uint64(swap16(uint16(v)))
case 4:
v = uint64(swap32(uint32(v)))
case 8:
v = swap64(v)
default:
panic(fmt.Sprintf("bad const size %v", arg.Size()))
}
}
return v, bf
}
func (target *Target) ensureDataElem(elems *[]Arg) *DataArg {
if len(*elems) == 0 {
res := MakeDataArg(target.any.blob, DirIn, nil)
*elems = append(*elems, MakeUnionArg(target.any.union, DirIn, res, 0))
return res
}
res, ok := (*elems)[len(*elems)-1].(*UnionArg).Option.(*DataArg)
if !ok {
res = MakeDataArg(target.any.blob, DirIn, nil)
*elems = append(*elems, MakeUnionArg(target.any.union, DirIn, res, 0))
}
return res
}
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package prog
import (
"fmt"
)
type CsumChunkKind int
const (
CsumChunkArg CsumChunkKind = iota
CsumChunkConst
)
type CsumInfo struct {
Kind CsumKind
Chunks []CsumChunk
}
type CsumChunk struct {
Kind CsumChunkKind
Arg Arg // for CsumChunkArg
Value uint64 // for CsumChunkConst
Size uint64 // for CsumChunkConst
}
func calcChecksumsCall(c *Call) (map[Arg]CsumInfo, map[Arg]struct{}) {
var inetCsumFields, pseudoCsumFields []Arg
// Find all csum fields.
ForeachArg(c, func(arg Arg, _ *ArgCtx) {
if typ, ok := arg.Type().(*CsumType); ok {
switch typ.Kind {
case CsumInet:
inetCsumFields = append(inetCsumFields, arg)
case CsumPseudo:
pseudoCsumFields = append(pseudoCsumFields, arg)
default:
panic(fmt.Sprintf("unknown csum kind %v", typ.Kind))
}
}
})
if len(inetCsumFields) == 0 && len(pseudoCsumFields) == 0 {
return nil, nil
}
// Build map of each field to its parent struct.
parentsMap := make(map[Arg]Arg)
ForeachArg(c, func(arg Arg, _ *ArgCtx) {
if _, ok := arg.Type().(*StructType); ok {
for _, field := range arg.(*GroupArg).Inner {
parentsMap[InnerArg(field)] = arg
}
}
})
csumMap := make(map[Arg]CsumInfo)
csumUses := make(map[Arg]struct{})
// Calculate generic inet checksums.
for _, arg := range inetCsumFields {
typ, _ := arg.Type().(*CsumType)
csummedArg := findCsummedArg(arg, typ, parentsMap)
csumUses[csummedArg] = struct{}{}
chunk := CsumChunk{CsumChunkArg, csummedArg, 0, 0}
csumMap[arg] = CsumInfo{Kind: CsumInet, Chunks: []CsumChunk{chunk}}
}
// No need to continue if there are no pseudo csum fields.
if len(pseudoCsumFields) == 0 {
return csumMap, csumUses
}
// Extract ipv4 or ipv6 source and destination addresses.
var ipSrcAddr, ipDstAddr Arg
ForeachArg(c, func(arg Arg, _ *ArgCtx) {
groupArg, ok := arg.(*GroupArg)
if !ok {
return
}
// syz_csum_* structs are used in tests
switch groupArg.Type().TemplateName() {
case "ipv4_header", "syz_csum_ipv4_header":
ipSrcAddr, ipDstAddr = extractHeaderParams(groupArg, 4)
case "ipv6_packet_t", "syz_csum_ipv6_header":
ipSrcAddr, ipDstAddr = extractHeaderParams(groupArg, 16)
}
})
if ipSrcAddr == nil || ipDstAddr == nil {
panic("no ipv4 nor ipv6 header found")
}
// Calculate pseudo checksums.
for _, arg := range pseudoCsumFields {
typ, _ := arg.Type().(*CsumType)
csummedArg := findCsummedArg(arg, typ, parentsMap)
protocol := uint8(typ.Protocol)
var info CsumInfo
if ipSrcAddr.Size() == 4 {
info = composePseudoCsumIPv4(csummedArg, ipSrcAddr, ipDstAddr, protocol)
} else {
info = composePseudoCsumIPv6(csummedArg, ipSrcAddr, ipDstAddr, protocol)
}
csumMap[arg] = info
csumUses[csummedArg] = struct{}{}
csumUses[ipSrcAddr] = struct{}{}
csumUses[ipDstAddr] = struct{}{}
}
return csumMap, csumUses
}
func findCsummedArg(arg Arg, typ *CsumType, parentsMap map[Arg]Arg) Arg {
if typ.Buf == ParentRef {
csummedArg := parentsMap[arg]
if csummedArg == nil {
panic(fmt.Sprintf("%q for %q is not in parents map", ParentRef, typ.Name()))
}
return csummedArg
}
for parent := parentsMap[arg]; parent != nil; parent = parentsMap[parent] {
// TODO(dvyukov): support template argument names as in size calculation.
if typ.Buf == parent.Type().Name() {
return parent
}
}
panic(fmt.Sprintf("csum field %q references non existent field %q", typ.Name(), typ.Buf))
}
func composePseudoCsumIPv4(tcpPacket, srcAddr, dstAddr Arg, protocol uint8) CsumInfo {
info := CsumInfo{Kind: CsumInet}
info.Chunks = append(info.Chunks, CsumChunk{CsumChunkArg, srcAddr, 0, 0})
info.Chunks = append(info.Chunks, CsumChunk{CsumChunkArg, dstAddr, 0, 0})
info.Chunks = append(info.Chunks, CsumChunk{CsumChunkConst, nil, uint64(swap16(uint16(protocol))), 2})
info.Chunks = append(info.Chunks, CsumChunk{CsumChunkConst, nil, uint64(swap16(uint16(tcpPacket.Size()))), 2})
info.Chunks = append(info.Chunks, CsumChunk{CsumChunkArg, tcpPacket, 0, 0})
return info
}
func composePseudoCsumIPv6(tcpPacket, srcAddr, dstAddr Arg, protocol uint8) CsumInfo {
info := CsumInfo{Kind: CsumInet}
info.Chunks = append(info.Chunks, CsumChunk{CsumChunkArg, srcAddr, 0, 0})
info.Chunks = append(info.Chunks, CsumChunk{CsumChunkArg, dstAddr, 0, 0})
info.Chunks = append(info.Chunks, CsumChunk{CsumChunkConst, nil, uint64(swap32(uint32(tcpPacket.Size()))), 4})
info.Chunks = append(info.Chunks, CsumChunk{CsumChunkConst, nil, uint64(swap32(uint32(protocol))), 4})
info.Chunks = append(info.Chunks, CsumChunk{CsumChunkArg, tcpPacket, 0, 0})
return info
}
func extractHeaderParams(arg *GroupArg, size uint64) (Arg, Arg) {
srcAddr := getFieldByName(arg, "src_ip")
dstAddr := getFieldByName(arg, "dst_ip")
if srcAddr.Size() != size || dstAddr.Size() != size {
panic(fmt.Sprintf("src/dst_ip fields in %v must be %v bytes", arg.Type().Name(), size))
}
return srcAddr, dstAddr
}
func getFieldByName(arg *GroupArg, name string) Arg {
typ := arg.Type().(*StructType)
for i, field := range arg.Inner {
if typ.Fields[i].Name == name {
return field
}
}
panic(fmt.Sprintf("failed to find %v field in %v", name, arg.Type().Name()))
}
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package prog
import (
"fmt"
)
func (p *Prog) Clone() *Prog {
return p.cloneWithMap(make(map[*ResultArg]*ResultArg))
}
func (p *Prog) cloneWithMap(newargs map[*ResultArg]*ResultArg) *Prog {
if p.isUnsafe {
// We could clone it, but since we prohibit mutation
// of unsafe programs, it's unclear why we would clone it.
// Note: this also covers cloning of corpus programs
// during mutation, so if this is removed, we may need
// additional checks during mutation.
panic("cloning of unsafe programs is not supposed to be done")
}
p1 := &Prog{
Target: p.Target,
Calls: cloneCalls(p.Calls, newargs),
}
p1.debugValidate()
return p1
}
func cloneCalls(origCalls []*Call, newargs map[*ResultArg]*ResultArg) []*Call {
calls := make([]*Call, len(origCalls))
for ci, c := range origCalls {
calls[ci] = cloneCall(c, newargs)
}
return calls
}
func cloneCall(c *Call, newargs map[*ResultArg]*ResultArg) *Call {
c1 := new(Call)
c1.Meta = c.Meta
if c.Ret != nil {
c1.Ret = clone(c.Ret, newargs).(*ResultArg)
}
c1.Args = make([]Arg, len(c.Args))
for ai, arg := range c.Args {
c1.Args[ai] = clone(arg, newargs)
}
c1.Props = c.Props
return c1
}
func CloneArg(arg Arg) Arg {
return clone(arg, nil)
}
func clone(arg Arg, newargs map[*ResultArg]*ResultArg) Arg {
var arg1 Arg
switch a := arg.(type) {
case *ConstArg:
a1 := new(ConstArg)
*a1 = *a
arg1 = a1
case *PointerArg:
a1 := new(PointerArg)
*a1 = *a
arg1 = a1
if a.Res != nil {
a1.Res = clone(a.Res, newargs)
}
case *DataArg:
a1 := new(DataArg)
*a1 = *a
a1.data = append([]byte{}, a.data...)
arg1 = a1
case *GroupArg:
a1 := new(GroupArg)
*a1 = *a
arg1 = a1
a1.Inner = make([]Arg, len(a.Inner))
for i, arg2 := range a.Inner {
a1.Inner[i] = clone(arg2, newargs)
}
case *UnionArg:
a1 := new(UnionArg)
*a1 = *a
arg1 = a1
a1.Option = clone(a.Option, newargs)
case *ResultArg:
a1 := new(ResultArg)
*a1 = *a
arg1 = a1
if a1.Res != nil {
r := a1.Res
if newargs != nil {
r = newargs[a1.Res]
a1.Res = r
}
if r.uses == nil {
r.uses = make(map[*ResultArg]bool)
}
r.uses[a1] = true
}
a1.uses = nil // filled when we clone the referent
if newargs != nil {
newargs[a] = a1
}
default:
panic(fmt.Sprintf("bad arg kind: %#v", arg))
}
return arg1
}
// Copyright 2021 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
// Contains prog transformations that intend to trigger more races.
package prog
import (
"fmt"
"math/rand"
)
// The executor has no more than 32 threads that are used both for async calls and for calls
// that timed out. If we just ignore that limit, we could end up generating programs that
// would force the executor to fail and thus stall the fuzzing process.
// As an educated guess, let's use no more than 24 async calls to let executor handle everything.
const maxAsyncPerProg = 24
// Ensures that if an async call produces a resource, then
// it is distanced from a call consuming the resource at least
// by one non-async call.
// This does not give 100% guarantee that the async call finishes
// by that time, but hopefully this is enough for most cases.
func AssignRandomAsync(origProg *Prog, rand *rand.Rand) *Prog {
var unassigned map[*ResultArg]bool
leftAsync := maxAsyncPerProg
prog := origProg.Clone()
for i := len(prog.Calls) - 1; i >= 0 && leftAsync > 0; i-- {
call := prog.Calls[i]
producesUnassigned := false
consumes := make(map[*ResultArg]bool)
ForeachArg(call, func(arg Arg, ctx *ArgCtx) {
res, ok := arg.(*ResultArg)
if !ok {
return
}
if res.Dir() != DirIn && unassigned[res] {
// If this call is made async, at least one of the resources
// will be empty when it's needed.
producesUnassigned = true
}
if res.Dir() != DirOut {
consumes[res.Res] = true
}
})
// Make async with a 66% chance (but never the last call).
if !producesUnassigned && i+1 != len(prog.Calls) && rand.Intn(3) != 0 {
call.Props.Async = true
for res := range consumes {
unassigned[res] = true
}
leftAsync--
} else {
call.Props.Async = false
unassigned = consumes
}
}
return prog
}
var rerunSteps = []int{32, 64}
func AssignRandomRerun(prog *Prog, rand *rand.Rand) {
for i := 0; i+1 < len(prog.Calls); i++ {
if !prog.Calls[i].Props.Async || rand.Intn(4) != 0 {
continue
}
// We assign rerun to consecutive pairs of calls, where the first call is async.
// TODO: consider assigning rerun also to non-collided progs.
rerun := rerunSteps[rand.Intn(len(rerunSteps))]
prog.Calls[i].Props.Rerun = rerun
prog.Calls[i+1].Props.Rerun = rerun
i++
}
}
// We append prog to itself, but let the second part only reference resource from the first one.
// Then we execute all the duplicated calls simultaneously.
// This somehow resembles the way the previous collide mode was implemented - a program was executed
// normally and then one more time again, while keeping resource values from the first execution and
// not waiting until every other call finishes.
func DoubleExecCollide(origProg *Prog, rand *rand.Rand) (*Prog, error) {
if len(origProg.Calls)*2 > MaxCalls {
return nil, fmt.Errorf("the prog is too big for the DoubleExecCollide transformation")
}
prog := origProg.Clone()
dupCalls := cloneCalls(prog.Calls, nil)
leftAsync := maxAsyncPerProg
for _, c := range dupCalls {
if leftAsync == 0 {
break
}
c.Props.Async = true
leftAsync--
}
prog.Calls = append(prog.Calls, dupCalls...)
return prog, nil
}
// DupCallCollide duplicates some of the calls in the program and marks them async.
// This should hopefully trigger races in a more granular way than DoubleExecCollide.
func DupCallCollide(origProg *Prog, rand *rand.Rand) (*Prog, error) {
if len(origProg.Calls) < 2 {
// For 1-call programs the behavior is similar to DoubleExecCollide.
return nil, fmt.Errorf("the prog is too small for the transformation")
}
// By default let's duplicate 1/3 calls in the original program (but at least one).
insert := max(len(origProg.Calls)/3, 1)
insert = min(insert, maxAsyncPerProg)
insert = min(insert, MaxCalls-len(origProg.Calls))
if insert == 0 {
return nil, fmt.Errorf("no calls could be duplicated")
}
duplicate := map[int]bool{}
for _, pos := range rand.Perm(len(origProg.Calls))[:insert] {
duplicate[pos] = true
}
prog := origProg.Clone()
var retCalls []*Call
for i, c := range prog.Calls {
if duplicate[i] {
dupCall := cloneCall(c, nil)
dupCall.Props.Async = true
retCalls = append(retCalls, dupCall)
}
retCalls = append(retCalls, c)
}
prog.Calls = retCalls
return prog, nil
}
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package prog
import (
"encoding/binary"
"fmt"
"reflect"
"strings"
)
type ExecProg struct {
Calls []ExecCall
Vars []uint64
}
type ExecCall struct {
Meta *Syscall
Props CallProps
Index uint64
Args []ExecArg
Copyin []ExecCopyin
Copyout []ExecCopyout
}
type ExecCopyin struct {
Addr uint64
Arg ExecArg
}
type ExecCopyout struct {
Index uint64
Addr uint64
Size uint64
}
type ExecArg interface{} // one of ExecArg*
type ExecArgConst struct {
Size uint64
Format BinaryFormat
Value uint64
BitfieldOffset uint64
BitfieldLength uint64
PidStride uint64
}
type ExecArgResult struct {
Size uint64
Format BinaryFormat
Index uint64
DivOp uint64
AddOp uint64
Default uint64
}
type ExecArgData struct {
Data []byte
Readable bool
}
type ExecArgCsum struct {
Size uint64
Kind uint64
Chunks []ExecCsumChunk
}
type ExecCsumChunk struct {
Kind uint64
Value uint64
Size uint64
}
func ExecCallCount(exec []byte) (int, error) {
v, n := binary.Varint(exec)
if n <= 0 {
return 0, fmt.Errorf("not enough data in the buffer")
}
if v > MaxCalls {
return 0, fmt.Errorf("too many calls (%v)", v)
}
return int(v), nil
}
func (target *Target) DeserializeExec(exec []byte, stats map[string]int) (ExecProg, error) {
dec := &execDecoder{target: target, data: exec, stats: stats}
dec.parse()
if dec.err != nil {
return ExecProg{}, dec.err
}
if uint64(len(dec.vars)) != dec.numVars {
return ExecProg{}, fmt.Errorf("mismatching number of vars: %v/%v",
len(dec.vars), dec.numVars)
}
p := ExecProg{
Calls: dec.calls,
Vars: dec.vars,
}
return p, nil
}
type execDecoder struct {
target *Target
data []byte
err error
numVars uint64
vars []uint64
call ExecCall
calls []ExecCall
stats map[string]int
}
func (dec *execDecoder) parse() {
ncalls := dec.read("header")
for dec.err == nil {
switch instr := dec.read("instr/opcode"); instr {
case execInstrCopyin:
dec.commitCall()
dec.call.Copyin = append(dec.call.Copyin, ExecCopyin{
Addr: dec.read("instr/copyin") + dec.target.DataOffset,
Arg: dec.readArg(),
})
case execInstrCopyout:
dec.call.Copyout = append(dec.call.Copyout, ExecCopyout{
Index: dec.read("instr/copyout/index"),
Addr: dec.read("instr/copyout/addr") + dec.target.DataOffset,
Size: dec.read("instr/copyout/size"),
})
case execInstrEOF:
dec.commitCall()
if ncalls != uint64(len(dec.calls)) {
dec.err = fmt.Errorf("bad number of calls: %v/%v", ncalls, len(dec.calls))
}
return
case execInstrSetProps:
dec.commitCall()
dec.readCallProps(&dec.call.Props)
default:
dec.commitCall()
if instr >= uint64(len(dec.target.Syscalls)) {
dec.setErr(fmt.Errorf("bad syscall %v", instr))
return
}
dec.call.Meta = dec.target.Syscalls[instr]
dec.call.Index = dec.read("instr/index")
for i := dec.read("instr/nargs"); i > 0; i-- {
switch arg := dec.readArg(); arg.(type) {
case ExecArgConst, ExecArgResult:
dec.call.Args = append(dec.call.Args, arg)
default:
dec.setErr(fmt.Errorf("bad call arg %+v", arg))
return
}
}
}
}
}
func (dec *execDecoder) readCallProps(props *CallProps) {
props.ForeachProp(func(_, _ string, value reflect.Value) {
arg := dec.read("call prop")
switch kind := value.Kind(); kind {
case reflect.Int:
value.SetInt(int64(arg))
case reflect.Bool:
if arg == 1 {
value.SetBool(true)
}
default:
panic("Unsupported (yet) kind: " + kind.String())
}
})
}
func (dec *execDecoder) readArg() ExecArg {
switch typ := dec.read("arg/type"); typ {
case execArgConst:
meta := dec.read("arg/const/meta")
return ExecArgConst{
Value: dec.read("arg/const/value"),
Size: meta & 0xff,
Format: BinaryFormat((meta >> 8) & 0xff),
BitfieldOffset: (meta >> 16) & 0xff,
BitfieldLength: (meta >> 24) & 0xff,
PidStride: meta >> 32,
}
case execArgAddr32:
fallthrough
case execArgAddr64:
size := 4
if typ == execArgAddr64 {
size = 8
}
return ExecArgConst{
Value: dec.read("arg/addr") + dec.target.DataOffset,
Size: uint64(size),
}
case execArgResult:
meta := dec.read("arg/result/meta")
arg := ExecArgResult{
Size: meta & 0xff,
Format: BinaryFormat((meta >> 8) & 0xff),
Index: dec.read("arg/result/index"),
DivOp: dec.read("arg/result/divop"),
AddOp: dec.read("arg/result/addop"),
Default: dec.read("arg/result/default"),
}
for uint64(len(dec.vars)) <= arg.Index {
dec.vars = append(dec.vars, 0)
}
dec.vars[arg.Index] = arg.Default
return arg
case execArgData:
flags := dec.read("arg/data/size")
size := flags & ^execArgDataReadable
dec.addStat("arg/data/blob", int(size))
readable := flags&execArgDataReadable != 0
return ExecArgData{
Data: dec.readBlob(size),
Readable: readable,
}
case execArgCsum:
size := dec.read("arg/csum/size")
switch kind := dec.read("arg/csum/kind"); kind {
case ExecArgCsumInet:
chunks := make([]ExecCsumChunk, dec.read("arg/csum/chunks"))
for i := range chunks {
kind := dec.read("arg/csum/chunk/kind")
addr := dec.read("arg/csum/chunk/addr")
size := dec.read("arg/csum/chunk/size")
if kind == ExecArgCsumChunkData {
addr += dec.target.DataOffset
}
chunks[i] = ExecCsumChunk{
Kind: kind,
Value: addr,
Size: size,
}
}
return ExecArgCsum{
Size: size,
Kind: kind,
Chunks: chunks,
}
default:
dec.setErr(fmt.Errorf("unknown csum kind %v", kind))
return nil
}
default:
dec.setErr(fmt.Errorf("bad argument type %v", typ))
return nil
}
}
func (dec *execDecoder) read(stat string) uint64 {
if dec.err != nil {
return 0
}
v, n := binary.Varint(dec.data)
if n <= 0 {
dec.setErr(fmt.Errorf("exec program overflow"))
return 0
}
dec.addStat(stat, n)
dec.data = dec.data[n:]
return uint64(v)
}
func (dec *execDecoder) readBlob(size uint64) []byte {
if uint64(len(dec.data)) < size {
dec.setErr(fmt.Errorf("exec program overflow"))
}
if dec.err != nil {
return nil
}
data := dec.data[:size]
dec.data = dec.data[size:]
return data
}
func (dec *execDecoder) setErr(err error) {
if dec.err == nil {
dec.err = err
}
}
func (dec *execDecoder) commitCall() {
if dec.call.Meta == nil {
return
}
if dec.call.Index != ExecNoCopyout && dec.numVars < dec.call.Index+1 {
dec.numVars = dec.call.Index + 1
}
for _, copyout := range dec.call.Copyout {
dec.numVars = max(dec.numVars, copyout.Index+1)
}
dec.calls = append(dec.calls, dec.call)
dec.call = ExecCall{}
}
func (dec *execDecoder) addStat(stat string, n int) {
if dec.stats == nil {
return
}
prefix := ""
for _, part := range strings.Split(stat, "/") {
dec.stats[prefix+part] += n
prefix += part + "/"
}
}
// Copyright 2015 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package prog
import (
"bytes"
"encoding/hex"
"fmt"
"reflect"
"strconv"
"strings"
"github.com/google/syzkaller/pkg/image"
)
// String generates a very compact program description (mostly for debug output).
func (p *Prog) String() string {
buf := new(bytes.Buffer)
for i, c := range p.Calls {
if i != 0 {
fmt.Fprintf(buf, "-")
}
fmt.Fprintf(buf, "%v", c.Meta.Name)
}
return buf.String()
}
func (p *Prog) Serialize() []byte {
return p.serialize(false)
}
func (p *Prog) SerializeVerbose() []byte {
return p.serialize(true)
}
func (p *Prog) serialize(verbose bool) []byte {
p.debugValidate()
ctx := &serializer{
target: p.Target,
buf: new(bytes.Buffer),
vars: make(map[*ResultArg]int),
verbose: verbose,
}
for _, c := range p.Calls {
ctx.call(c)
}
return ctx.buf.Bytes()
}
type serializer struct {
target *Target
buf *bytes.Buffer
vars map[*ResultArg]int
varSeq int
verbose bool
}
func (ctx *serializer) print(text string) {
ctx.printf("%v", text)
}
func (ctx *serializer) printf(text string, args ...interface{}) {
fmt.Fprintf(ctx.buf, text, args...)
}
func (ctx *serializer) allocVarID(arg *ResultArg) int {
id := ctx.varSeq
ctx.varSeq++
ctx.vars[arg] = id
return id
}
func (ctx *serializer) call(c *Call) {
if c.Ret != nil && len(c.Ret.uses) != 0 {
ctx.printf("r%v = ", ctx.allocVarID(c.Ret))
}
ctx.printf("%v(", c.Meta.Name)
for i, a := range c.Args {
if IsPad(a.Type()) {
continue
}
if i != 0 {
ctx.printf(", ")
}
ctx.arg(a)
}
ctx.print(")")
anyChangedProps := false
c.Props.ForeachProp(func(name, key string, value reflect.Value) {
// reflect.Value.IsZero is added in go1.13, not available in Appengine SDK.
if reflect.DeepEqual(value.Interface(), reflect.Zero(value.Type()).Interface()) {
return
}
if !anyChangedProps {
ctx.print(" (")
anyChangedProps = true
} else {
ctx.print(", ")
}
ctx.print(key)
switch kind := value.Kind(); kind {
case reflect.Int:
ctx.printf(": %d", value.Int())
case reflect.Bool:
default:
panic("unable to serialize call prop of type " + kind.String())
}
})
if anyChangedProps {
ctx.printf(")")
}
ctx.printf("\n")
}
func (ctx *serializer) arg(arg Arg) {
if arg == nil {
ctx.printf("nil")
return
}
arg.serialize(ctx)
}
func (a *ConstArg) serialize(ctx *serializer) {
ctx.printf("0x%x", a.Val)
}
func (a *PointerArg) serialize(ctx *serializer) {
if a.IsSpecial() {
ctx.printf("0x%x", a.Address)
return
}
target := ctx.target
ctx.printf("&%v", target.serializeAddr(a))
if a.Res != nil && !ctx.verbose && isDefault(a.Res) && !target.isAnyPtr(a.Type()) {
return
}
ctx.printf("=")
if target.isAnyPtr(a.Type()) {
ctx.printf("ANY=")
}
ctx.arg(a.Res)
}
func (a *DataArg) serialize(ctx *serializer) {
typ := a.Type().(*BufferType)
if a.Dir() == DirOut {
ctx.printf("\"\"/%v", a.Size())
return
}
data := a.Data()
if typ.IsCompressed() {
serializeCompressedData(ctx.buf, data)
} else {
// Statically typed data will be padded with 0s during deserialization,
// so we can strip them here for readability always. For variable-size
// data we strip trailing 0s only if we strip enough of them.
sz := len(data)
for len(data) >= 2 && data[len(data)-1] == 0 && data[len(data)-2] == 0 {
data = data[:len(data)-1]
}
if typ.Varlen() && len(data)+8 >= sz {
data = data[:sz]
}
serializeData(ctx.buf, data, isReadableDataType(typ))
if typ.Varlen() && sz != len(data) {
ctx.printf("/%v", sz)
}
}
}
func (a *GroupArg) serialize(ctx *serializer) {
var delims []byte
switch a.Type().(type) {
case *StructType:
delims = []byte{'{', '}'}
case *ArrayType:
delims = []byte{'[', ']'}
default:
panic("unknown group type")
}
ctx.buf.WriteByte(delims[0])
lastNonDefault := len(a.Inner) - 1
if !ctx.verbose && a.fixedInnerSize() {
for ; lastNonDefault >= 0; lastNonDefault-- {
if !isDefault(a.Inner[lastNonDefault]) {
break
}
}
}
for i := 0; i <= lastNonDefault; i++ {
arg1 := a.Inner[i]
if arg1 != nil && IsPad(arg1.Type()) {
continue
}
if i != 0 {
ctx.printf(", ")
}
ctx.arg(arg1)
}
ctx.buf.WriteByte(delims[1])
}
func (a *UnionArg) serialize(ctx *serializer) {
typ := a.Type().(*UnionType)
ctx.printf("@%v", typ.Fields[a.Index].Name)
if !ctx.verbose && isDefault(a.Option) {
return
}
ctx.printf("=")
ctx.arg(a.Option)
}
func (a *ResultArg) serialize(ctx *serializer) {
if len(a.uses) != 0 {
ctx.printf("<r%v=>", ctx.allocVarID(a))
}
if a.Res == nil {
ctx.printf("0x%x", a.Val)
return
}
id, ok := ctx.vars[a.Res]
if !ok {
panic("no result")
}
ctx.printf("r%v", id)
if a.OpDiv != 0 {
ctx.printf("/%v", a.OpDiv)
}
if a.OpAdd != 0 {
ctx.printf("+%v", a.OpAdd)
}
}
type DeserializeMode int
const (
// In strict mode deserialization fails if the program is malformed in any way.
// This mode is used for manually written programs to ensure that they are correct.
Strict DeserializeMode = iota
// In non-strict mode malformed programs silently fixed in a best-effort way,
// e.g. missing/wrong arguments are replaced with default values.
// This mode is used for the corpus programs to "repair" them after descriptions changes.
NonStrict
// Unsafe mode is used for VM checking programs. In this mode programs are not fixed
// for safety, e.g. can access global files, issue prohibited ioctl's, disabled syscalls, etc.
StrictUnsafe
NonStrictUnsafe
)
func (target *Target) Deserialize(data []byte, mode DeserializeMode) (*Prog, error) {
defer func() {
if err := recover(); err != nil {
panic(fmt.Errorf("%v\ntarget: %v/%v, rev: %v, mode=%v, prog:\n%q",
err, target.OS, target.Arch, GitRevision, mode, data))
}
}()
strict := mode == Strict || mode == StrictUnsafe
unsafe := mode == StrictUnsafe || mode == NonStrictUnsafe
p := newParser(target, data, strict, unsafe)
prog, err := p.parseProg()
if err := p.Err(); err != nil {
return nil, err
}
if err != nil {
return nil, err
}
// This validation is done even in non-debug mode because deserialization
// procedure does not catch all bugs (e.g. mismatched types).
// And we can receive bad programs from corpus and hub.
if err := prog.validateWithOpts(validationOptions{
// Don't validate auto-set conditional fields. We'll patch them later.
ignoreTransient: true,
}); err != nil {
return nil, err
}
p.fixupConditionals(prog)
if p.autos != nil {
p.fixupAutos(prog)
}
if !unsafe {
if err := prog.sanitize(!strict); err != nil {
return nil, err
}
}
return prog, nil
}
func (p *parser) parseProg() (*Prog, error) {
prog := &Prog{
Target: p.target,
isUnsafe: p.unsafe,
}
for p.Scan() {
if p.EOF() {
if p.comment != "" {
prog.Comments = append(prog.Comments, p.comment)
p.comment = ""
}
continue
}
if p.Char() == '#' {
if p.comment != "" {
prog.Comments = append(prog.Comments, p.comment)
}
p.comment = strings.TrimSpace(p.s[p.i+1:])
continue
}
name := p.Ident()
r := ""
if p.Char() == '=' {
r = name
p.Parse('=')
name = p.Ident()
}
meta := p.target.SyscallMap[name]
if meta == nil {
return nil, fmt.Errorf("unknown syscall %v", name)
}
c := MakeCall(meta, nil)
c.Comment = p.comment
prog.Calls = append(prog.Calls, c)
p.Parse('(')
for i := 0; p.Char() != ')'; i++ {
if i >= len(meta.Args) {
p.eatExcessive(false, "excessive syscall arguments")
break
}
field := meta.Args[i]
if IsPad(field.Type) {
return nil, fmt.Errorf("padding in syscall %v arguments", name)
}
arg, err := p.parseArg(field.Type, DirIn)
if err != nil {
return nil, err
}
c.Args = append(c.Args, arg)
if p.Char() != ')' {
p.Parse(',')
}
}
p.Parse(')')
if !p.EOF() && p.Char() == '(' {
p.Parse('(')
c.Props = p.parseCallProps()
p.Parse(')')
}
if !p.EOF() {
if p.Char() != '#' {
return nil, fmt.Errorf("tailing data (line #%v)", p.l)
}
if c.Comment != "" {
prog.Comments = append(prog.Comments, c.Comment)
}
c.Comment = strings.TrimSpace(p.s[p.i+1:])
}
for i := len(c.Args); i < len(meta.Args); i++ {
p.strictFailf("missing syscall args")
c.Args = append(c.Args, meta.Args[i].DefaultArg(DirIn))
}
if len(c.Args) != len(meta.Args) {
return nil, fmt.Errorf("wrong call arg count: %v, want %v", len(c.Args), len(meta.Args))
}
if r != "" && c.Ret != nil {
p.vars[r] = c.Ret
}
p.comment = ""
}
if p.comment != "" {
prog.Comments = append(prog.Comments, p.comment)
}
return prog, nil
}
func (p *parser) parseCallProps() CallProps {
nameToValue := map[string]reflect.Value{}
callProps := CallProps{}
callProps.ForeachProp(func(_, key string, value reflect.Value) {
nameToValue[key] = value
})
for p.e == nil && p.Char() != ')' {
propName := p.Ident()
value, ok := nameToValue[propName]
if !ok {
p.eatExcessive(true, "unknown call property: %s", propName)
if p.Char() == ',' {
p.Parse(',')
}
continue
}
switch kind := value.Kind(); kind {
case reflect.Int:
p.Parse(':')
strVal := p.Ident()
intV, err := strconv.ParseInt(strVal, 0, 64)
if err != nil {
p.strictFailf("invalid int value: %s", strVal)
} else {
value.SetInt(intV)
}
case reflect.Bool:
value.SetBool(true)
default:
panic("unable to handle call props of type " + kind.String())
}
if p.Char() != ')' {
p.Parse(',')
}
}
return callProps
}
func (p *parser) parseArg(typ Type, dir Dir) (Arg, error) {
r := ""
if p.Char() == '<' {
p.Parse('<')
r = p.Ident()
p.Parse('=')
p.Parse('>')
}
arg, err := p.parseArgImpl(typ, dir)
if err != nil {
return nil, err
}
if arg == nil {
if typ != nil {
arg = typ.DefaultArg(dir)
} else if r != "" {
return nil, fmt.Errorf("named nil argument")
}
}
if r != "" {
if res, ok := arg.(*ResultArg); ok {
p.vars[r] = res
} else {
p.strictFailf("variable %v doesn't refers to a resource", r)
}
}
return arg, nil
}
func (p *parser) parseArgImpl(typ Type, dir Dir) (Arg, error) {
if typ == nil && p.Char() != 'n' {
p.eatExcessive(true, "non-nil argument for nil type")
return nil, nil
}
switch p.Char() {
case '0':
return p.parseArgInt(typ, dir)
case 'r':
return p.parseArgRes(typ, dir)
case '&':
return p.parseArgAddr(typ, dir)
case '"', '\'':
return p.parseArgString(typ, dir)
case '{':
return p.parseArgStruct(typ, dir)
case '[':
return p.parseArgArray(typ, dir)
case '@':
return p.parseArgUnion(typ, dir)
case 'n':
p.Parse('n')
p.Parse('i')
p.Parse('l')
return nil, nil
case 'A':
p.Parse('A')
p.Parse('U')
p.Parse('T')
p.Parse('O')
return p.parseAuto(typ, dir)
default:
return nil, fmt.Errorf("failed to parse argument at '%c' (line #%v/%v: %v)",
p.Char(), p.l, p.i, highlightError(p.s, p.i))
}
}
func (p *parser) parseArgInt(typ Type, dir Dir) (Arg, error) {
val := p.Ident()
v, err := strconv.ParseUint(val, 0, 64)
if err != nil {
return nil, fmt.Errorf("wrong arg value '%v': %w", val, err)
}
switch typ.(type) {
case *ConstType, *IntType, *FlagsType, *ProcType, *CsumType:
arg := Arg(MakeConstArg(typ, dir, v))
if dir == DirOut && !typ.isDefaultArg(arg) {
p.strictFailf("out arg %v has non-default value: %v", typ, v)
arg = typ.DefaultArg(dir)
}
return arg, nil
case *LenType:
return MakeConstArg(typ, dir, v), nil
case *ResourceType:
return MakeResultArg(typ, dir, nil, v), nil
case *PtrType, *VmaType:
index := -v % uint64(len(p.target.SpecialPointers))
return MakeSpecialPointerArg(typ, dir, index), nil
default:
p.eatExcessive(true, "wrong int arg %T", typ)
return typ.DefaultArg(dir), nil
}
}
func (p *parser) parseAuto(typ Type, dir Dir) (Arg, error) {
switch t1 := typ.(type) {
case *ConstType, *LenType, *CsumType:
return p.auto(MakeConstArg(typ, dir, 0)), nil
case *StructType:
var inner []Arg
for len(inner) < len(t1.Fields) {
field := t1.Fields[len(inner)]
innerArg, err := p.parseAuto(field.Type, dir)
if err != nil {
return nil, err
}
inner = append(inner, innerArg)
}
return MakeGroupArg(typ, dir, inner), nil
default:
return nil, fmt.Errorf("wrong type %T for AUTO", typ)
}
}
func (p *parser) parseArgRes(typ Type, dir Dir) (Arg, error) {
id := p.Ident()
var div, add uint64
if p.Char() == '/' {
p.Parse('/')
op := p.Ident()
v, err := strconv.ParseUint(op, 0, 64)
if err != nil {
return nil, fmt.Errorf("wrong result div op: '%v'", op)
}
div = v
}
if p.Char() == '+' {
p.Parse('+')
op := p.Ident()
v, err := strconv.ParseUint(op, 0, 64)
if err != nil {
return nil, fmt.Errorf("wrong result add op: '%v'", op)
}
add = v
}
v := p.vars[id]
if v == nil {
p.strictFailf("undeclared variable %v", id)
return typ.DefaultArg(dir), nil
}
arg := MakeResultArg(typ, dir, v, 0)
arg.OpDiv = div
arg.OpAdd = add
return arg, nil
}
func (p *parser) parseArgAddr(typ Type, dir Dir) (Arg, error) {
var elem Type
elemDir := DirInOut
squashableElem := false
switch t1 := typ.(type) {
case *PtrType:
elem, elemDir, squashableElem = t1.Elem, t1.ElemDir, t1.SquashableElem
case *VmaType:
default:
p.eatExcessive(true, "wrong addr arg %T", typ)
return typ.DefaultArg(dir), nil
}
p.Parse('&')
auto := false
var addr, vmaSize uint64
if p.Char() == 'A' {
p.Parse('A')
p.Parse('U')
p.Parse('T')
p.Parse('O')
if elem == nil {
return nil, fmt.Errorf("vma type can't be AUTO")
}
auto = true
} else {
var err error
addr, vmaSize, err = p.parseAddr()
if err != nil {
return nil, err
}
}
var inner Arg
if p.Char() == '=' {
p.Parse('=')
if p.HasNext("ANY") {
p.Parse('A')
p.Parse('N')
p.Parse('Y')
p.Parse('=')
if squashableElem {
anyPtr := p.target.getAnyPtrType(typ.Size())
typ, elem, elemDir = anyPtr, anyPtr.Elem, anyPtr.ElemDir
}
}
var err error
inner, err = p.parseArg(elem, elemDir)
if err != nil {
return nil, err
}
}
if elem == nil {
if addr%p.target.PageSize != 0 {
p.strictFailf("unaligned vma address 0x%x", addr)
addr &= ^(p.target.PageSize - 1)
}
return MakeVmaPointerArg(typ, dir, addr, vmaSize), nil
}
if inner == nil {
inner = elem.DefaultArg(elemDir)
}
arg := MakePointerArg(typ, dir, addr, inner)
if auto {
p.auto(arg)
}
return arg, nil
}
func (p *parser) parseArgString(t Type, dir Dir) (Arg, error) {
typ, ok := t.(*BufferType)
if !ok {
p.eatExcessive(true, "wrong string arg")
return t.DefaultArg(dir), nil
}
data, b64, err := p.deserializeData()
if err != nil {
return nil, err
}
// Check compressed data for validity.
if typ.IsCompressed() {
if err := image.DecompressCheck(data); err != nil {
p.strictFailf("invalid compressed data in arg: %v", err)
// In non-strict mode, empty the data slice.
data = image.Compress(nil)
}
}
size := ^uint64(0)
if p.Char() == '/' && !b64 {
p.Parse('/')
sizeStr := p.Ident()
size, err = strconv.ParseUint(sizeStr, 0, 64)
if err != nil {
return nil, fmt.Errorf("failed to parse buffer size: %q", sizeStr)
}
maxMem := p.target.NumPages * p.target.PageSize
if size > maxMem {
p.strictFailf("too large string argument %v", size)
size = maxMem
}
}
if !typ.Varlen() {
size = typ.Size()
} else if size == ^uint64(0) {
size = uint64(len(data))
}
if dir == DirOut {
return MakeOutDataArg(typ, dir, size), nil
}
if diff := int(size) - len(data); diff > 0 {
data = append(data, make([]byte, diff)...)
}
data = data[:size]
if (typ.Kind == BufferString || typ.Kind == BufferGlob) &&
len(typ.Values) != 0 &&
// AUTOGENERATED will be padded by 0's.
!strings.HasPrefix(typ.Values[0], "AUTOGENERATED") {
matched := false
for _, val := range typ.Values {
if string(data) == val {
matched = true
break
}
}
if !matched {
p.strictFailf("bad string value %q, expect %q", data, typ.Values)
data = []byte(typ.Values[0])
}
}
return MakeDataArg(typ, dir, data), nil
}
func (p *parser) parseArgStruct(typ Type, dir Dir) (Arg, error) {
p.Parse('{')
t1, ok := typ.(*StructType)
if !ok {
p.eatExcessive(false, "wrong struct arg for %q", typ.Name())
p.Parse('}')
return typ.DefaultArg(dir), nil
}
var inner []Arg
for i := 0; p.Char() != '}'; i++ {
if i >= len(t1.Fields) {
p.eatExcessive(false, "excessive struct %v fields", typ.Name())
break
}
field := t1.Fields[i]
if IsPad(field.Type) {
inner = append(inner, MakeConstArg(field.Type, field.Dir(dir), 0))
} else {
arg, err := p.parseArg(field.Type, field.Dir(dir))
if err != nil {
return nil, err
}
inner = append(inner, arg)
if p.Char() != '}' {
p.Parse(',')
}
}
}
p.Parse('}')
for len(inner) < len(t1.Fields) {
field := t1.Fields[len(inner)]
if !IsPad(field.Type) {
p.strictFailf("missing struct %v fields %v/%v", typ.Name(), len(inner), len(t1.Fields))
}
inner = append(inner, field.Type.DefaultArg(field.Dir(dir)))
}
return MakeGroupArg(typ, dir, inner), nil
}
func (p *parser) parseArgArray(typ Type, dir Dir) (Arg, error) {
p.Parse('[')
t1, ok := typ.(*ArrayType)
if !ok {
p.eatExcessive(false, "wrong array arg %T", typ)
p.Parse(']')
return typ.DefaultArg(dir), nil
}
var inner []Arg
for i := 0; p.Char() != ']'; i++ {
arg, err := p.parseArg(t1.Elem, dir)
if err != nil {
return nil, err
}
inner = append(inner, arg)
if p.Char() != ']' {
p.Parse(',')
}
}
p.Parse(']')
if t1.Kind == ArrayRangeLen && t1.RangeBegin == t1.RangeEnd {
for uint64(len(inner)) < t1.RangeBegin {
p.strictFailf("missing array elements")
inner = append(inner, t1.Elem.DefaultArg(dir))
}
inner = inner[:t1.RangeBegin]
}
return MakeGroupArg(typ, dir, inner), nil
}
func (p *parser) parseArgUnion(typ Type, dir Dir) (Arg, error) {
t1, ok := typ.(*UnionType)
if !ok {
p.eatExcessive(true, "wrong union arg for %q", typ.Name())
return typ.DefaultArg(dir), nil
}
p.Parse('@')
name := p.Ident()
var (
optType Type
optDir Dir
options []string
)
index := -1
for i, field := range t1.Fields {
if name == field.Name {
optType, index, optDir = field.Type, i, field.Dir(dir)
break
}
options = append(options, fmt.Sprintf("%q", field.Name))
}
if optType == nil {
p.eatExcessive(true, "wrong option %q of union %q, available options are: %s",
name, typ.Name(), strings.Join(options, ", "))
return typ.DefaultArg(dir), nil
}
var opt Arg
if p.Char() == '=' {
p.Parse('=')
var err error
opt, err = p.parseArg(optType, optDir)
if err != nil {
return nil, err
}
} else {
opt = optType.DefaultArg(optDir)
}
return MakeUnionArg(typ, dir, opt, index), nil
}
// Eats excessive call arguments and struct fields to recover after description changes.
func (p *parser) eatExcessive(stopAtComma bool, what string, args ...interface{}) {
p.strictFailf(what, args...)
paren, brack, brace := 0, 0, 0
for !p.EOF() && p.e == nil {
ch := p.Char()
switch ch {
case '(':
paren++
case ')':
if paren == 0 {
return
}
paren--
case '[':
brack++
case ']':
if brack == 0 {
return
}
brack--
case '{':
brace++
case '}':
if brace == 0 {
return
}
brace--
case ',':
if stopAtComma && paren == 0 && brack == 0 && brace == 0 {
return
}
case '\'', '"':
p.Parse(ch)
for !p.EOF() && p.Char() != ch {
p.Parse(p.Char())
}
if p.EOF() {
return
}
}
p.Parse(ch)
}
}
const (
encodingAddrBase = 0x7f0000000000
)
func (target *Target) serializeAddr(arg *PointerArg) string {
ssize := ""
if arg.VmaSize != 0 {
ssize = fmt.Sprintf("/0x%x", arg.VmaSize)
}
return fmt.Sprintf("(0x%x%v)", encodingAddrBase+arg.Address, ssize)
}
func (p *parser) parseAddr() (uint64, uint64, error) {
p.Parse('(')
pstr := p.Ident()
addr, err := strconv.ParseUint(pstr, 0, 64)
if err != nil {
return 0, 0, fmt.Errorf("failed to parse addr: %q", pstr)
}
addr -= encodingAddrBase
target := p.target
var vmaSize uint64
if p.Char() == '/' {
p.Parse('/')
pstr := p.Ident()
size, err := strconv.ParseUint(pstr, 0, 64)
if err != nil {
return 0, 0, fmt.Errorf("failed to parse addr size: %q", pstr)
}
addr = addr & ^(target.PageSize - 1)
vmaSize = (size + target.PageSize - 1) & ^(target.PageSize - 1)
if vmaSize == 0 {
vmaSize = target.PageSize
}
if !p.unsafe {
maxMem := target.NumPages * target.PageSize
vmaSize = min(vmaSize, maxMem)
addr = min(addr, maxMem-vmaSize)
}
}
p.Parse(')')
return addr, vmaSize, nil
}
func serializeData(buf *bytes.Buffer, data []byte, readable bool) {
if !readable && !isReadableData(data) {
fmt.Fprintf(buf, "\"%v\"", hex.EncodeToString(data))
return
}
buf.WriteByte('\'')
encodeData(buf, data, true, false)
buf.WriteByte('\'')
}
func serializeCompressedData(buf *bytes.Buffer, data []byte) {
buf.WriteByte('"')
buf.WriteByte('$')
buf.Write(image.EncodeB64(data))
buf.WriteByte('"')
}
func EncodeData(buf *bytes.Buffer, data []byte, readable bool) {
if !readable && isReadableData(data) {
readable = true
}
encodeData(buf, data, readable, true)
}
func encodeData(buf *bytes.Buffer, data []byte, readable, cstr bool) {
for _, v := range data {
if !readable {
lo, hi := byteToHex(v)
buf.Write([]byte{'\\', 'x', hi, lo})
continue
}
switch v {
case '\a':
buf.Write([]byte{'\\', 'a'})
case '\b':
buf.Write([]byte{'\\', 'b'})
case '\f':
buf.Write([]byte{'\\', 'f'})
case '\n':
buf.Write([]byte{'\\', 'n'})
case '\r':
buf.Write([]byte{'\\', 'r'})
case '\t':
buf.Write([]byte{'\\', 't'})
case '\v':
buf.Write([]byte{'\\', 'v'})
case '\'':
buf.Write([]byte{'\\', '\''})
case '"':
buf.Write([]byte{'\\', '"'})
case '\\':
buf.Write([]byte{'\\', '\\'})
default:
if isPrintable(v) {
buf.WriteByte(v)
} else {
if cstr {
// We would like to use hex encoding with \x,
// but C's \x is hard to use: it can contain _any_ number of hex digits
// (not just 2 or 4), so later non-hex encoded chars will glue to \x.
c0 := (v>>6)&0x7 + '0'
c1 := (v>>3)&0x7 + '0'
c2 := (v>>0)&0x7 + '0'
buf.Write([]byte{'\\', c0, c1, c2})
} else {
lo, hi := byteToHex(v)
buf.Write([]byte{'\\', 'x', hi, lo})
}
}
}
}
}
func isReadableDataType(typ *BufferType) bool {
return typ.Kind == BufferString || typ.Kind == BufferFilename || typ.Kind == BufferGlob
}
func isReadableData(data []byte) bool {
if len(data) == 0 {
return false
}
for _, v := range data {
if isPrintable(v) {
continue
}
switch v {
case 0, '\a', '\b', '\f', '\n', '\r', '\t', '\v':
continue
}
return false
}
return true
}
// Deserialize data, returning the data and whether it was encoded in Base64.
func (p *parser) deserializeData() ([]byte, bool, error) {
var data []byte
if p.Char() == '"' {
p.Parse('"')
if p.Char() == '$' {
// Read Base64 data.
p.consume()
var rawData []byte
for !p.EOF() && p.Char() != '"' {
v := p.consume()
rawData = append(rawData, v)
}
p.Parse('"')
decoded, err := image.DecodeB64(rawData)
if err != nil {
return nil, false, fmt.Errorf("data arg is corrupt: %w", err)
}
return decoded, true, nil
}
val := ""
if p.Char() != '"' {
val = p.Ident()
}
p.Parse('"')
var err error
data, err = hex.DecodeString(val)
if err != nil {
return nil, false, fmt.Errorf("data arg has bad value %q", val)
}
} else {
if p.consume() != '\'' {
return nil, false, fmt.Errorf("data arg does not start with \" nor with '")
}
for p.Char() != '\'' && p.Char() != 0 {
v := p.consume()
if v != '\\' {
data = append(data, v)
continue
}
v = p.consume()
switch v {
case 'x':
hi := p.consume()
lo := p.consume()
b, ok := hexToByte(lo, hi)
if !ok {
return nil, false, fmt.Errorf("invalid hex \\x%v%v in data arg", hi, lo)
}
data = append(data, b)
case 'a':
data = append(data, '\a')
case 'b':
data = append(data, '\b')
case 'f':
data = append(data, '\f')
case 'n':
data = append(data, '\n')
case 'r':
data = append(data, '\r')
case 't':
data = append(data, '\t')
case 'v':
data = append(data, '\v')
case '\'':
data = append(data, '\'')
case '"':
data = append(data, '"')
case '\\':
data = append(data, '\\')
default:
return nil, false, fmt.Errorf("invalid \\%c escape sequence in data arg", v)
}
}
p.Parse('\'')
}
return data, false, nil
}
func isPrintable(v byte) bool {
return v >= 0x20 && v < 0x7f
}
func byteToHex(v byte) (lo, hi byte) {
return toHexChar(v & 0xf), toHexChar(v >> 4)
}
func hexToByte(lo, hi byte) (byte, bool) {
h, ok1 := fromHexChar(hi)
l, ok2 := fromHexChar(lo)
return h<<4 + l, ok1 && ok2
}
func toHexChar(v byte) byte {
if v >= 16 {
panic("bad hex char")
}
if v < 10 {
return '0' + v
}
return 'a' + v - 10
}
func fromHexChar(v byte) (byte, bool) {
if v >= '0' && v <= '9' {
return v - '0', true
}
if v >= 'a' && v <= 'f' {
return v - 'a' + 10, true
}
return 0, false
}
type parser struct {
target *Target
strict bool
unsafe bool
vars map[string]*ResultArg
autos map[Arg]bool
comment string
data []byte
s string
i int
l int
e error
}
func newParser(target *Target, data []byte, strict, unsafe bool) *parser {
p := &parser{
target: target,
strict: strict,
unsafe: unsafe,
vars: make(map[string]*ResultArg),
data: data,
}
return p
}
func (p *parser) auto(arg Arg) Arg {
if p.autos == nil {
p.autos = make(map[Arg]bool)
}
p.autos[arg] = true
return arg
}
func (p *parser) fixupAutos(prog *Prog) {
s := analyze(nil, nil, prog, nil)
for _, c := range prog.Calls {
p.target.assignSizesArray(c.Args, c.Meta.Args, p.autos)
ForeachArg(c, func(arg Arg, _ *ArgCtx) {
if !p.autos[arg] {
return
}
delete(p.autos, arg)
switch typ := arg.Type().(type) {
case *ConstType:
arg.(*ConstArg).Val = typ.Val
_ = s
case *PtrType:
a := arg.(*PointerArg)
a.Address = s.ma.alloc(nil, a.Res.Size(), a.Res.Type().Alignment())
default:
panic(fmt.Sprintf("unsupported auto type %T", typ))
}
})
}
if len(p.autos) != 0 {
panic(fmt.Sprintf("leftoever autos: %+v", p.autos))
}
}
func (p *parser) fixupConditionals(prog *Prog) {
for _, c := range prog.Calls {
// Only overwrite transient union fields.
c.setDefaultConditions(p.target, true)
}
}
func (p *parser) Scan() bool {
if p.e != nil || len(p.data) == 0 {
return false
}
nextLine := bytes.IndexByte(p.data, '\n')
if nextLine != -1 {
p.s = string(p.data[:nextLine])
p.data = p.data[nextLine+1:]
} else {
p.s = string(p.data)
p.data = nil
}
p.i = 0
p.l++
return true
}
func (p *parser) Err() error {
return p.e
}
func (p *parser) EOF() bool {
return p.i == len(p.s)
}
func (p *parser) Char() byte {
if p.e != nil {
return 0
}
if p.EOF() {
p.failf("unexpected eof")
return 0
}
return p.s[p.i]
}
func (p *parser) HasNext(str string) bool {
if p.e != nil {
return false
}
if len(p.s) < p.i+len(str) {
return false
}
for i := 0; i < len(str); i++ {
if p.s[p.i+i] != str[i] {
return false
}
}
return true
}
func (p *parser) Parse(ch byte) {
if p.e != nil {
return
}
if p.EOF() {
p.failf("want %s, got EOF", string(ch))
return
}
if p.s[p.i] != ch {
p.failf("want '%v', got '%v'", string(ch), string(p.s[p.i]))
return
}
p.i++
p.SkipWs()
}
func (p *parser) consume() byte {
if p.e != nil {
return 0
}
if p.EOF() {
p.failf("unexpected eof")
return 0
}
v := p.s[p.i]
p.i++
return v
}
func (p *parser) SkipWs() {
for p.i < len(p.s) && (p.s[p.i] == ' ' || p.s[p.i] == '\t') {
p.i++
}
}
func (p *parser) Ident() string {
i := p.i
for p.i < len(p.s) &&
(p.s[p.i] >= 'a' && p.s[p.i] <= 'z' ||
p.s[p.i] >= 'A' && p.s[p.i] <= 'Z' ||
p.s[p.i] >= '0' && p.s[p.i] <= '9' ||
p.s[p.i] == '_' || p.s[p.i] == '$') {
p.i++
}
if i == p.i {
p.failf("failed to parse identifier at pos %v", i)
return ""
}
s := p.s[i:p.i]
p.SkipWs()
return s
}
func (p *parser) failf(msg string, args ...interface{}) {
if p.e == nil {
p.e = fmt.Errorf("%v\nline #%v:%v: %v", fmt.Sprintf(msg, args...), p.l, p.i,
highlightError(p.s, p.i))
}
}
func (p *parser) strictFailf(msg string, args ...interface{}) {
if p.strict {
p.failf(msg, args...)
}
}
// CallSet returns a set of all calls in the program.
// It does very conservative parsing and is intended to parse past/future serialization formats.
func CallSet(data []byte) (map[string]struct{}, int, error) {
calls := make(map[string]struct{})
ncalls := 0
for len(data) > 0 {
ln := data
nextLine := bytes.IndexByte(data, '\n')
if nextLine != -1 {
ln = data[:nextLine]
data = data[nextLine+1:]
} else {
data = nil
}
if len(ln) == 0 || ln[0] == '#' {
continue
}
bracket := bytes.IndexByte(ln, '(')
if bracket == -1 {
return nil, 0, fmt.Errorf("line does not contain opening bracket")
}
call := ln[:bracket]
if eq := bytes.IndexByte(call, '='); eq != -1 {
eq++
for eq < len(call) && call[eq] == ' ' {
eq++
}
call = call[eq:]
}
if len(call) == 0 {
return nil, 0, fmt.Errorf("call name is empty")
}
calls[string(call)] = struct{}{}
ncalls++
}
if len(calls) == 0 {
return nil, 0, fmt.Errorf("program does not contain any calls")
}
return calls, ncalls, nil
}
func highlightError(s string, offset int) string {
return s[:offset] + "<<<!!ERROR!!>>>" + s[offset:]
}
// Copyright 2015 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
// This file does serialization of programs for executor binary.
// The format aims at simple parsing: binary and irreversible.
// Exec format is an sequence of uint64's which encodes a sequence of calls.
// The sequence is terminated by a speciall call execInstrEOF.
// Each call is (call ID, copyout index, number of arguments, arguments...).
// Each argument is (type, size, value).
// There are the following types of arguments:
// - execArgConst: value is const value
// - execArgAddr32/64: constant address
// - execArgResult: value is copyout index we want to reference
// - execArgData: value is a binary blob (represented as ]size/8[ uint64's)
// - execArgCsum: runtime checksum calculation
// There are the following special calls:
// - execInstrCopyin: copies its second argument into address specified by first argument
// - execInstrCopyout: reads value at address specified by first argument (result can be referenced by execArgResult)
// - execInstrSetProps: sets special properties for the previous call
package prog
import (
"encoding/binary"
"fmt"
"reflect"
"sort"
)
const (
execInstrEOF = ^uint64(iota)
execInstrCopyin
execInstrCopyout
execInstrSetProps
)
const (
execArgConst = uint64(iota)
execArgAddr32
execArgAddr64
execArgResult
execArgData
execArgCsum
execArgDataReadable = uint64(1 << 63)
)
const (
ExecArgCsumInet = uint64(iota)
)
const (
ExecArgCsumChunkData = uint64(iota)
ExecArgCsumChunkConst
)
const (
ExecBufferSize = 4 << 20 // keep in sync with kMaxInput in executor.cc
ExecNoCopyout = ^uint64(0)
execMaxCommands = 1000 // executor knows about this constant (kMaxCommands)
)
// SerializeForExec serializes program p for execution by process pid into the provided buffer.
// Returns number of bytes written to the buffer.
// If the provided buffer is too small for the program an error is returned.
func (p *Prog) SerializeForExec() ([]byte, error) {
p.debugValidate()
w := &execContext{
target: p.Target,
buf: make([]byte, 0, 4<<10),
args: make(map[Arg]argInfo),
}
w.write(uint64(len(p.Calls)))
for _, c := range p.Calls {
w.csumMap, w.csumUses = calcChecksumsCall(c)
w.serializeCall(c)
}
w.write(execInstrEOF)
if len(w.buf) > ExecBufferSize {
return nil, fmt.Errorf("encodingexec: too large program (%v/%v)", len(w.buf), ExecBufferSize)
}
if w.copyoutSeq > execMaxCommands {
return nil, fmt.Errorf("encodingexec: too many resources (%v/%v)", w.copyoutSeq, execMaxCommands)
}
return w.buf, nil
}
func (w *execContext) serializeCall(c *Call) {
// Calculate arg offsets within structs.
// Generate copyin instructions that fill in data into pointer arguments.
w.writeCopyin(c)
// Generate checksum calculation instructions starting from the last one,
// since checksum values can depend on values of the latter ones
w.writeChecksums()
if !reflect.DeepEqual(c.Props, CallProps{}) {
// Push call properties.
w.writeCallProps(c.Props)
}
// Generate the call itself.
w.write(uint64(c.Meta.ID))
if c.Ret != nil && len(c.Ret.uses) != 0 {
if _, ok := w.args[c.Ret]; ok {
panic("argInfo is already created for return value")
}
w.args[c.Ret] = argInfo{Idx: w.copyoutSeq, Ret: true}
w.write(w.copyoutSeq)
w.copyoutSeq++
} else {
w.write(ExecNoCopyout)
}
w.write(uint64(len(c.Args)))
for _, arg := range c.Args {
w.writeArg(arg)
}
// Generate copyout instructions that persist interesting return values.
w.writeCopyout(c)
}
type execContext struct {
target *Target
buf []byte
args map[Arg]argInfo
copyoutSeq uint64
// Per-call state cached here to not pass it through all functions.
csumMap map[Arg]CsumInfo
csumUses map[Arg]struct{}
}
type argInfo struct {
Addr uint64 // physical addr
Idx uint64 // copyout instruction index
Ret bool
}
func (w *execContext) writeCallProps(props CallProps) {
w.write(execInstrSetProps)
props.ForeachProp(func(_, _ string, value reflect.Value) {
var uintVal uint64
switch kind := value.Kind(); kind {
case reflect.Int:
uintVal = uint64(value.Int())
case reflect.Bool:
if value.Bool() {
uintVal = 1
}
default:
panic("Unsupported (yet) kind: " + kind.String())
}
w.write(uintVal)
})
}
func (w *execContext) writeCopyin(c *Call) {
ForeachArg(c, func(arg Arg, ctx *ArgCtx) {
if ctx.Base == nil {
return
}
addr := w.target.PhysicalAddr(ctx.Base) - w.target.DataOffset + ctx.Offset
addr -= arg.Type().UnitOffset()
if w.willBeUsed(arg) {
w.args[arg] = argInfo{Addr: addr}
}
switch arg.(type) {
case *GroupArg, *UnionArg:
return
}
typ := arg.Type()
if arg.Dir() == DirOut || IsPad(typ) || (arg.Size() == 0 && !typ.IsBitfield()) {
return
}
w.write(execInstrCopyin)
w.write(addr)
w.writeArg(arg)
})
}
func (w *execContext) willBeUsed(arg Arg) bool {
if res, ok := arg.(*ResultArg); ok && len(res.uses) != 0 {
return true
}
_, ok1 := w.csumMap[arg]
_, ok2 := w.csumUses[arg]
return ok1 || ok2
}
func (w *execContext) writeChecksums() {
if len(w.csumMap) == 0 {
return
}
csumArgs := make([]Arg, 0, len(w.csumMap))
for arg := range w.csumMap {
csumArgs = append(csumArgs, arg)
}
sort.Slice(csumArgs, func(i, j int) bool {
return w.args[csumArgs[i]].Addr < w.args[csumArgs[j]].Addr
})
for i := len(csumArgs) - 1; i >= 0; i-- {
arg := csumArgs[i]
info := w.csumMap[arg]
if _, ok := arg.Type().(*CsumType); !ok {
panic("csum arg is not csum type")
}
w.write(execInstrCopyin)
w.write(w.args[arg].Addr)
w.write(execArgCsum)
w.write(arg.Size())
switch info.Kind {
case CsumInet:
w.write(ExecArgCsumInet)
w.write(uint64(len(info.Chunks)))
for _, chunk := range info.Chunks {
switch chunk.Kind {
case CsumChunkArg:
w.write(ExecArgCsumChunkData)
w.write(w.args[chunk.Arg].Addr)
w.write(chunk.Arg.Size())
case CsumChunkConst:
w.write(ExecArgCsumChunkConst)
w.write(chunk.Value)
w.write(chunk.Size)
default:
panic(fmt.Sprintf("csum chunk has unknown kind %v", chunk.Kind))
}
}
default:
panic(fmt.Sprintf("csum arg has unknown kind %v", info.Kind))
}
}
}
func (w *execContext) writeCopyout(c *Call) {
ForeachArg(c, func(arg Arg, _ *ArgCtx) {
if res, ok := arg.(*ResultArg); ok && len(res.uses) != 0 {
// Create a separate copyout instruction that has own Idx.
info := w.args[arg]
if info.Ret {
return // Idx is already assigned above.
}
info.Idx = w.copyoutSeq
w.copyoutSeq++
w.args[arg] = info
w.write(execInstrCopyout)
w.write(info.Idx)
w.write(info.Addr)
w.write(arg.Size())
}
})
}
func (w *execContext) write(v uint64) {
w.buf = binary.AppendVarint(w.buf, int64(v))
}
func (w *execContext) writeArg(arg Arg) {
switch a := arg.(type) {
case *ConstArg:
val, pidStride := a.Value()
typ := a.Type()
w.writeConstArg(typ.UnitSize(), val, typ.BitfieldOffset(), typ.BitfieldLength(), pidStride, typ.Format())
case *ResultArg:
if a.Res == nil {
w.writeConstArg(a.Size(), a.Val, 0, 0, 0, a.Type().Format())
} else {
info, ok := w.args[a.Res]
if !ok {
panic("no copyout index")
}
w.write(execArgResult)
meta := a.Size() | uint64(a.Type().Format())<<8
w.write(meta)
w.write(info.Idx)
w.write(a.OpDiv)
w.write(a.OpAdd)
w.write(a.Type().(*ResourceType).Default())
}
case *PointerArg:
switch a.Size() {
case 4:
w.write(execArgAddr32)
case 8:
w.write(execArgAddr64)
default:
panic(fmt.Sprintf("bad pointer address size %v", a.Size()))
}
w.write(w.target.PhysicalAddr(a) - w.target.DataOffset)
case *DataArg:
data := a.Data()
if len(data) == 0 {
panic("writing data arg with 0 size")
}
w.write(execArgData)
flags := uint64(len(data))
if isReadableDataType(a.Type().(*BufferType)) {
flags |= execArgDataReadable
}
w.write(flags)
w.buf = append(w.buf, data...)
case *UnionArg:
w.writeArg(a.Option)
default:
panic("unknown arg type")
}
}
func (w *execContext) writeConstArg(size, val, bfOffset, bfLength, pidStride uint64, bf BinaryFormat) {
w.write(execArgConst)
meta := size | uint64(bf)<<8 | bfOffset<<16 | bfLength<<24 | pidStride<<32
w.write(meta)
w.write(val)
}
// Copyright 2023 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package prog
import (
"errors"
"fmt"
)
func (bo BinaryExpression) Evaluate(finder ArgFinder) (uint64, bool) {
left, ok := bo.Left.Evaluate(finder)
if !ok {
return 0, false
}
right, ok := bo.Right.Evaluate(finder)
if !ok {
return 0, false
}
switch bo.Operator {
case OperatorCompareEq:
if left == right {
return 1, true
}
return 0, true
case OperatorCompareNeq:
if left != right {
return 1, true
}
return 0, true
case OperatorBinaryAnd:
return left & right, true
case OperatorOr:
if left != 0 || right != 0 {
return 1, true
}
return 0, true
}
panic(fmt.Sprintf("unknown operator %q", bo.Operator))
}
func (v *Value) Evaluate(finder ArgFinder) (uint64, bool) {
if len(v.Path) == 0 {
return v.Value, true
}
found := finder(v.Path)
if found == SquashedArgFound {
// This is expectable.
return 0, false
}
if found == nil {
panic(fmt.Sprintf("no argument was found by %v", v.Path))
}
constArg, ok := found.(*ConstArg)
if !ok {
panic("value expressions must only rely on int fields")
}
return constArg.Val, true
}
func makeArgFinder(t *Target, c *Call, unionArg *UnionArg, parents parentStack) ArgFinder {
return func(path []string) Arg {
f := t.findArg(unionArg.Option, path, nil, nil, parents, 0)
if f == nil {
return nil
}
if f.isAnyPtr {
return SquashedArgFound
}
return f.arg
}
}
func (r *randGen) patchConditionalFields(c *Call, s *state) (extra []*Call, changed bool) {
if r.patchConditionalDepth > 1 {
// Some nested patchConditionalFields() calls are fine as we could trigger a resource
// constructor via generateArg(). But since nested createResource() calls are prohibited,
// patchConditionalFields() should never be nested more than 2 times.
panic("third nested patchConditionalFields call")
}
r.patchConditionalDepth++
defer func() { r.patchConditionalDepth-- }()
var extraCalls []*Call
var anyPatched bool
for {
replace := map[Arg]Arg{}
forEachStaleUnion(r.target, c,
func(unionArg *UnionArg, unionType *UnionType, okIndices []int) {
idx := okIndices[r.Intn(len(okIndices))]
newType, newDir := unionType.Fields[idx].Type,
unionType.Fields[idx].Dir(unionArg.Dir())
newTypeArg, newCalls := r.generateArg(s, newType, newDir)
replace[unionArg] = MakeUnionArg(unionType, newDir, newTypeArg, idx)
extraCalls = append(extraCalls, newCalls...)
anyPatched = true
})
for old, new := range replace {
replaceArg(old, new)
}
// The newly inserted argument might contain more arguments we need
// to patch.
// Repeat until we have to change nothing.
if len(replace) == 0 {
break
}
}
return extraCalls, anyPatched
}
func forEachStaleUnion(target *Target, c *Call, cb func(*UnionArg, *UnionType, []int)) {
for _, callArg := range c.Args {
foreachSubArgWithStack(callArg, func(arg Arg, argCtx *ArgCtx) {
if target.isAnyPtr(arg.Type()) {
argCtx.Stop = true
return
}
unionArg, ok := arg.(*UnionArg)
if !ok {
return
}
unionType, ok := arg.Type().(*UnionType)
if !ok || !unionType.isConditional() {
return
}
argFinder := makeArgFinder(target, c, unionArg, argCtx.parentStack)
ok, calculated := checkUnionArg(unionArg.Index, unionType, argFinder)
if !calculated {
// Let it stay as is.
return
}
if !unionArg.transient && ok {
return
}
matchingIndices := matchingUnionArgs(unionType, argFinder)
if len(matchingIndices) == 0 {
// Conditional fields are transformed in such a way
// that one field always matches.
// For unions we demand that there's a field w/o conditions.
panic(fmt.Sprintf("no matching union fields: %#v", unionType))
}
cb(unionArg, unionType, matchingIndices)
})
}
}
func checkUnionArg(idx int, typ *UnionType, finder ArgFinder) (ok, calculated bool) {
field := typ.Fields[idx]
if field.Condition == nil {
return true, true
}
val, ok := field.Condition.Evaluate(finder)
if !ok {
// We could not calculate the expression.
// Let the union stay as it was.
return true, false
}
return val != 0, true
}
func matchingUnionArgs(typ *UnionType, finder ArgFinder) []int {
var ret []int
for i := range typ.Fields {
ok, _ := checkUnionArg(i, typ, finder)
if ok {
ret = append(ret, i)
}
}
return ret
}
func (p *Prog) checkConditions() error {
for _, c := range p.Calls {
err := c.checkConditions(p.Target, false)
if err != nil {
return err
}
}
return nil
}
var ErrViolatedConditions = errors.New("conditional fields rules violation")
func (c *Call) checkConditions(target *Target, ignoreTransient bool) error {
var ret error
forEachStaleUnion(target, c,
func(a *UnionArg, t *UnionType, okIndices []int) {
if ignoreTransient && a.transient {
return
}
ret = fmt.Errorf("%w union %s field is #%d(%s), but %v satisfy conditions",
ErrViolatedConditions, t.Name(), a.Index, t.Fields[a.Index].Name,
okIndices)
})
return ret
}
func (c *Call) setDefaultConditions(target *Target, transientOnly bool) bool {
var anyReplaced bool
// Replace stale conditions with the default values of their correct types.
for {
replace := map[Arg]Arg{}
forEachStaleUnion(target, c,
func(unionArg *UnionArg, unionType *UnionType, okIndices []int) {
if transientOnly && !unionArg.transient {
return
}
idx := okIndices[0]
if defIdx, ok := unionType.defaultField(); ok {
// If there's a default value available, use it.
idx = defIdx
}
field := unionType.Fields[idx]
replace[unionArg] = MakeUnionArg(unionType,
unionArg.Dir(),
field.DefaultArg(field.Dir(unionArg.Dir())),
idx)
})
for old, new := range replace {
anyReplaced = true
replaceArg(old, new)
}
if len(replace) == 0 {
break
}
}
return anyReplaced
}
// Copyright 2015 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package prog
import (
"math/rand"
)
// Generate generates a random program with ncalls calls.
// ct contains a set of allowed syscalls, if nil all syscalls are used.
func (target *Target) Generate(rs rand.Source, ncalls int, ct *ChoiceTable) *Prog {
p := &Prog{
Target: target,
}
r := newRand(target, rs)
s := newState(target, ct, nil)
for len(p.Calls) < ncalls {
calls := r.generateCall(s, p, len(p.Calls))
for _, c := range calls {
s.analyze(c)
p.Calls = append(p.Calls, c)
}
}
// For the last generated call we could get additional calls that create
// resources and overflow ncalls. Remove some of these calls.
// The resources in the last call will be replaced with the default values,
// which is exactly what we want.
for len(p.Calls) > ncalls {
p.RemoveCall(ncalls - 1)
}
p.sanitizeFix()
p.debugValidate()
return p
}
// Copyright 2022 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package prog
import (
"fmt"
"math/rand"
)
// Our heatmaps are a flexible mechanism to assign a probability distribution to
// some collection of bytes. Usage:
// 1. Choose a heatmap and initialize it: `hm := MakeXYZHeatmap(data)`.
// Different heatmaps implement different probability distributions
// (for now there is only one).
// 2. Select random indices according to the probability distribution:
// `idx := hm.ChooseLocation(r)`.
type Heatmap interface {
NumMutations() int
ChooseLocation() int
}
// Generic heatmaps model a probability distribution based on sparse data,
// prioritising selection of regions which are not a single repeated byte. It
// views data as a series of chunks of length `granularity`, ignoring chunks
// which are a single repeated byte. Indices are chosen uniformly amongst the
// remaining "interesting" segments.
func MakeGenericHeatmap(data []byte, r *rand.Rand) Heatmap {
if len(data) == 0 {
panic("cannot create a GenericHeatmap with no data")
}
hm := &GenericHeatmap{
r: r,
}
hm.length, hm.segments = calculateLengthAndSegments(data, granularity)
return hm
}
func (hm *GenericHeatmap) NumMutations() int {
// At least one mutation.
n := 1
// + up to about one mutation every 4 KB of heatmap size.
n += hm.r.Intn(hm.length/(4<<10) + 1)
// + up to 4 mutations at random so that even small images can get more than one.
n += hm.r.Intn(5)
// But don't do too many as it will most likely corrupt the image.
return min(n, 10)
}
func (hm *GenericHeatmap) ChooseLocation() int {
// Uniformly choose an index within one of the segments.
heatmapIdx := hm.r.Intn(hm.length)
rawIdx := translateIdx(heatmapIdx, hm.segments)
return rawIdx
}
type GenericHeatmap struct {
r *rand.Rand
segments []segment // "Interesting" parts of the data.
length int // Sum of all segment lengths.
}
type segment struct {
offset int
length int
}
const granularity = 64 // Chunk size in bytes for processing the data.
// Determine the "interesting" segments of data, also returning their combined length.
func calculateLengthAndSegments(data []byte, granularity int) (int, []segment) {
// Offset and length of current segment, total length of all segments, length of original data.
offset, currentLength, totalLength, rawLength := 0, 0, 0, len(data)
segments := []segment{}
// Save a segment.
saveSegment := func() {
if currentLength != 0 {
segments = append(segments, segment{offset: offset, length: currentLength})
offset, totalLength, currentLength = offset+currentLength, totalLength+currentLength, 0
}
}
for len(data) > 0 {
var chunk []byte
if len(data) < granularity {
chunk, data = data, nil
} else {
chunk, data = data[:granularity], data[granularity:]
}
// Check if buffer contains only a single value.
byt0, isConstant := chunk[0], true
for _, byt := range chunk {
if byt != byt0 {
isConstant = false
break
}
}
if !isConstant {
// Non-constant - extend the current segment.
currentLength += len(chunk)
} else {
// Save current segment.
saveSegment()
// Skip past the constant bytes.
offset += len(chunk)
}
}
// Save final segment.
saveSegment()
if len(segments) == 0 {
// We found no segments, i.e. the data is all "boring". Fall back to a
// uniform probability distribution over the original data by considering it
// as one long segment.
return rawLength, append(segments, segment{offset: 0, length: rawLength})
}
return totalLength, segments
}
// Convert from an index into "interesting" segments to an index into raw data.
// I.e. view `idx` as an index into the concatenated segments, and translate
// this to an index into the original underlying data. E.g.:
//
// segs = []segment{{offset: 10, length: 20}, {offset: 50, length: 10}}
// translateIdx(25, segs) = 5
//
// I.e. we index element 5 of the second segment, so element 55 of the raw data.
func translateIdx(idx int, segs []segment) int {
if idx < 0 {
panic(fmt.Sprintf("translateIdx: negative index %v", idx))
}
savedIdx := idx
for _, seg := range segs {
if idx < seg.length {
return seg.offset + idx
}
idx -= seg.length
}
panic(fmt.Sprintf("translateIdx: index out of range %v", savedIdx))
}
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package prog
// A hint is basically a tuple consisting of a pointer to an argument
// in one of the syscalls of a program and a value, which should be
// assigned to that argument (we call it a replacer).
// A simplified version of hints workflow looks like this:
// 1. Fuzzer launches a program (we call it a hint seed) and collects all
// the comparisons' data for every syscall in the program.
// 2. Next it tries to match the obtained comparison operands' values
// vs. the input arguments' values.
// 3. For every such match the fuzzer mutates the program by
// replacing the pointed argument with the saved value.
// 4. If a valid program is obtained, then fuzzer launches it and
// checks if new coverage is obtained.
// For more insights on particular mutations please see prog/hints_test.go.
import (
"bytes"
"encoding/binary"
"fmt"
"sort"
"sync"
"github.com/google/syzkaller/pkg/image"
)
// CompMap maps comparison operand that could come from the input to the second operand to the PC.
type CompMap map[uint64]map[uint64]map[uint64]bool
const (
maxDataLength = 100
)
var specialIntsSet map[uint64]bool
func (m CompMap) Add(pc, arg1, arg2 uint64, isConst bool) {
if _, ok := m[arg1]; !ok {
m[arg1] = make(map[uint64]map[uint64]bool)
}
if _, ok := m[arg1][arg2]; !ok {
m[arg1][arg2] = make(map[uint64]bool)
}
m[arg1][arg2][pc] = true
if !isConst {
// Both operands could come from the input.
m.Add(pc, arg2, arg1, true)
}
}
func (m CompMap) String() string {
buf := new(bytes.Buffer)
for v, comps := range m {
if len(buf.Bytes()) != 0 {
fmt.Fprintf(buf, ", ")
}
fmt.Fprintf(buf, "0x%x:", v)
for c := range comps {
fmt.Fprintf(buf, " 0x%x", c)
}
}
return buf.String()
}
func (m CompMap) Len() int {
var count int
for _, nested := range m {
for _, nested2 := range nested {
count += len(nested2)
}
}
return count
}
// InplaceIntersect() only leaves the value pairs that are also present in other.
func (m CompMap) InplaceIntersect(other CompMap) {
for val1, nested := range m {
for val2, pcs := range nested {
for pc := range pcs {
if !other[val1][val2][pc] {
delete(pcs, pc)
}
}
if len(pcs) == 0 {
delete(nested, val2)
}
}
if len(nested) == 0 {
delete(m, val1)
}
}
}
// Mutates the program using the comparison operands stored in compMaps.
// For each of the mutants executes the exec callback.
// The callback must return whether we should continue substitution (true)
// or abort the process (false).
func (p *Prog) MutateWithHints(callIndex int, comps CompMap, exec func(p *Prog) bool) {
p = p.Clone()
c := p.Calls[callIndex]
doMore := true
execValidate := func() bool {
// Don't try to fix the candidate program.
// Assuming the original call was sanitized, we've got a bad call
// as the result of hint substitution, so just throw it away.
if p.Target.sanitize(c, false) != nil {
return true
}
if p.checkConditions() != nil {
// Patching unions that no longer satisfy conditions would
// require much deeped changes to prog arguments than
// generateHints() expects.
// Let's just ignore such mutations.
return true
}
p.debugValidate()
doMore = exec(p)
return doMore
}
ForeachArg(c, func(arg Arg, ctx *ArgCtx) {
if !doMore {
ctx.Stop = true
return
}
generateHints(comps, arg, ctx.Field, execValidate)
})
}
func generateHints(compMap CompMap, arg Arg, field *Field, exec func() bool) {
typ := arg.Type()
if typ == nil || arg.Dir() == DirOut {
return
}
switch t := typ.(type) {
case *ProcType:
// Random proc will not pass validation.
// We can mutate it, but only if the resulting value is within the legal range.
return
case *ConstType:
if IsPad(typ) {
return
}
case *CsumType:
// Csum will not pass validation and is always computed.
return
case *BufferType:
switch t.Kind {
case BufferFilename:
// This can generate escaping paths and is probably not too useful anyway.
return
case BufferString, BufferGlob:
if len(t.Values) != 0 {
// These are frequently file names or complete enumerations.
// Mutating these may be useful iff we intercept strcmp
// (and filter out file names).
return
}
}
}
switch a := arg.(type) {
case *ConstArg:
if arg.Type().TypeBitSize() <= 8 {
// Very small arg, hopefully we can guess it w/o hints help.
return
}
checkConstArg(a, field, compMap, exec)
case *DataArg:
if arg.Size() <= 3 {
// Let's assume it either does not contain anything interesting,
// or we can guess everything eventually by brute force.
return
}
if typ.(*BufferType).Kind == BufferCompressed {
checkCompressedArg(a, compMap, exec)
} else {
checkDataArg(a, compMap, exec)
}
}
}
func checkConstArg(arg *ConstArg, field *Field, compMap CompMap, exec func() bool) {
original := arg.Val
// Note: because shrinkExpand returns a map, order of programs is non-deterministic.
// This can affect test coverage reports.
replacerLoop:
for _, replacer := range shrinkExpand(original, compMap, arg.Type().TypeBitSize(), false) {
if field != nil && len(field.relatedFields) != 0 {
for related := range field.relatedFields {
if related.(uselessHinter).uselessHint(replacer) {
continue replacerLoop
}
}
} else if arg.Type().(uselessHinter).uselessHint(replacer) {
continue
}
arg.Val = replacer
if !exec() {
break
}
}
arg.Val = original
}
func checkDataArg(arg *DataArg, compMap CompMap, exec func() bool) {
bytes := make([]byte, 8)
data := arg.Data()
size := min(len(data), maxDataLength)
for i := 0; i < size; i++ {
original := make([]byte, 8)
copy(original, data[i:])
val := binary.LittleEndian.Uint64(original)
for _, replacer := range shrinkExpand(val, compMap, 64, false) {
binary.LittleEndian.PutUint64(bytes, replacer)
copy(data[i:], bytes)
if !exec() {
break
}
}
copy(data[i:], original)
}
}
func checkCompressedArg(arg *DataArg, compMap CompMap, exec func() bool) {
data0 := arg.Data()
data, dtor := image.MustDecompress(data0)
// Images are very large so the generic algorithm for data arguments
// can produce too many mutants. For images we consider only
// 4/8-byte aligned ints. This is enough to handle all magic
// numbers and checksums. We also ignore 0 and ^uint64(0) source bytes,
// because there are too many of these in lots of images.
bytes := make([]byte, 8)
doMore := true
for i := 0; i < len(data) && doMore; i += 4 {
original := make([]byte, 8)
copy(original, data[i:])
val := binary.LittleEndian.Uint64(original)
for _, replacer := range shrinkExpand(val, compMap, 64, true) {
binary.LittleEndian.PutUint64(bytes, replacer)
copy(data[i:], bytes)
arg.SetData(image.Compress(data))
// Unmap the image for the duration of the execution.
// Execution can take a while and uncompressed images are large,
// since hints jobs are executed round-robin, we can have thousands of them running.
dtor()
doMore = exec()
data, dtor = image.MustDecompress(data0)
if !doMore {
break
}
}
copy(data[i:], original)
}
dtor()
arg.SetData(data0)
}
// Shrink and expand mutations model the cases when the syscall arguments
// are casted to narrower (and wider) integer types.
//
// Motivation for shrink:
//
// void f(u16 x) {
// u8 y = (u8)x;
// if (y == 0xab) {...}
// }
//
// If we call f(0x1234), then we'll see a comparison 0x34 vs 0xab and we'll
// be unable to match the argument 0x1234 with any of the comparison operands.
// Thus we shrink 0x1234 to 0x34 and try to match 0x34.
// If there's a match for the shrank value, then we replace the corresponding
// bytes of the input (in the given example we'll get 0x12ab).
// Sometimes the other comparison operand will be wider than the shrank value
// (in the example above consider comparison if (y == 0xdeadbeef) {...}).
// In this case we ignore such comparison because we couldn't come up with
// any valid code example that does similar things. To avoid such comparisons
// we check the sizes with leastSize().
//
// Motivation for expand:
//
// void f(i8 x) {
// i16 y = (i16)x;
// if (y == -2) {...}
// }
//
// Suppose we call f(-1), then we'll see a comparison 0xffff vs 0xfffe and be
// unable to match input vs any operands. Thus we sign extend the input and
// check the extension.
// As with shrink we ignore cases when the other operand is wider.
// Note that executor sign extends all the comparison operands to int64.
func shrinkExpand(v uint64, compMap CompMap, bitsize uint64, image bool) []uint64 {
v = truncateToBitSize(v, bitsize)
limit := uint64(1<<bitsize - 1)
var replacers map[uint64]bool
for _, iwidth := range []int{8, 4, 2, 1, -4, -2, -1} {
var width int
var size, mutant uint64
if iwidth > 0 {
width = iwidth
size = uint64(width) * 8
mutant = v & ((1 << size) - 1)
} else {
width = -iwidth
size = min(uint64(width)*8, bitsize)
if v&(1<<(size-1)) == 0 {
continue
}
mutant = v | ^((1 << size) - 1)
}
if image {
// For images we can produce too many mutants for small integers.
if width < 4 {
continue
}
if mutant == 0 || (mutant|^((1<<size)-1)) == ^uint64(0) {
continue
}
}
// Use big-endian match/replace for both blobs and ints.
// Sometimes we have unmarked blobs (no little/big-endian info);
// for ANYBLOBs we intentionally lose all marking;
// but even for marked ints we may need this too.
// Consider that kernel code does not convert the data
// (i.e. not ntohs(pkt->proto) == ETH_P_BATMAN),
// but instead converts the constant (i.e. pkt->proto == htons(ETH_P_BATMAN)).
// In such case we will see dynamic operand that does not match what we have in the program.
for _, bigendian := range []bool{false, true} {
if bigendian {
if width == 1 {
continue
}
mutant = swapInt(mutant, width)
}
for newV := range compMap[mutant] {
// Check the limit for negative numbers.
if newV > limit && ((^(limit >> 1) & newV) != ^(limit >> 1)) {
continue
}
mask := uint64(1<<size - 1)
newHi := newV & ^mask
newV = newV & mask
if newHi != 0 && newHi^^mask != 0 {
continue
}
if bigendian {
newV = swapInt(newV, width)
}
// We insert special ints (like 0) with high probability,
// so we don't try to replace to special ints them here.
// Images are large so it's hard to guess even special
// ints with random mutations.
if !image && specialIntsSet[newV] {
continue
}
// Replace size least significant bits of v with
// corresponding bits of newV. Leave the rest of v as it was.
replacer := (v &^ mask) | newV
if replacer == v {
continue
}
replacer = truncateToBitSize(replacer, bitsize)
// TODO(dvyukov): should we try replacing with arg+/-1?
// This could trigger some off-by-ones.
if replacers == nil {
replacers = make(map[uint64]bool)
}
replacers[replacer] = true
}
}
}
if replacers == nil {
return nil
}
res := make([]uint64, 0, len(replacers))
for v := range replacers {
res = append(res, v)
}
sort.Slice(res, func(i, j int) bool {
return res[i] < res[j]
})
return res
}
type HintsLimiter struct {
mu sync.Mutex
attempts map[uint64]int // replacement attempts per PC
}
// Limit restricts hints to at most N replacement attempts per single kernel PC
// (globally, across all hints mutations for all programs).
// We are getting too many generated candidates, the fuzzer may not keep up
// with them at all (hints jobs keep growing infinitely). If a hint indeed came
// from the input w/o transformation, then we should guess it on the first
// attempt (or at least after few attempts). If it did not come from the input,
// or came with a non-trivial transformation, then any number of attempts won't
// help. So limit the total number of attempts (until the next restart).
func (limiter *HintsLimiter) Limit(comps CompMap) {
const N = 10
limiter.mu.Lock()
defer limiter.mu.Unlock()
if limiter.attempts == nil {
limiter.attempts = make(map[uint64]int)
}
for op1, ops2 := range comps {
for op2, pcs := range ops2 {
for pc := range pcs {
limiter.attempts[pc]++
if limiter.attempts[pc] > N {
delete(pcs, pc)
}
}
if len(pcs) == 0 {
delete(ops2, op2)
}
}
if len(ops2) == 0 {
delete(comps, op1)
}
}
}
func init() {
specialIntsSet = make(map[uint64]bool)
for _, v := range specialInts {
specialIntsSet[v] = true
}
}
// Copyright 2020 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package prog
import (
"strings"
"time"
)
const defaultGitRevision = "unknown"
var (
GitRevision = defaultGitRevision // emitted by Makefile, may contain + at the end
GitRevisionBase string // without +
gitRevisionDate string // emitted by Makefile
GitRevisionDate time.Time // parsed from gitRevisionDate
)
func GitRevisionKnown() bool {
return GitRevision != defaultGitRevision
}
func init() {
GitRevisionBase = strings.ReplaceAll(GitRevision, "+", "")
if gitRevisionDate != "" {
var err error
if GitRevisionDate, err = time.Parse("20060102-150405", gitRevisionDate); err != nil {
panic(err)
}
}
}
// Copyright 2018 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package prog
import (
"bytes"
"fmt"
"reflect"
"github.com/google/syzkaller/pkg/hash"
"github.com/google/syzkaller/pkg/stat"
)
var (
statMinRemoveCall = stat.New("minimize: call",
"Total number of remove call attempts during minimization", stat.StackedGraph("minimize"))
statMinRemoveProps = stat.New("minimize: props",
"Total number of remove properties attempts during minimization", stat.StackedGraph("minimize"))
statMinPtr = stat.New("minimize: pointer",
"Total number of pointer minimization attempts", stat.StackedGraph("minimize"))
statMinArray = stat.New("minimize: array",
"Total number of array minimization attempts", stat.StackedGraph("minimize"))
statMinInt = stat.New("minimize: integer",
"Total number of integer minimization attempts", stat.StackedGraph("minimize"))
statMinResource = stat.New("minimize: resource",
"Total number of resource minimization attempts", stat.StackedGraph("minimize"))
statMinBuffer = stat.New("minimize: buffer",
"Total number of buffer minimization attempts", stat.StackedGraph("minimize"))
statMinFilename = stat.New("minimize: filename",
"Total number of filename minimization attempts", stat.StackedGraph("minimize"))
)
type MinimizeMode int
const (
// Minimize for inclusion into corpus.
// This generally tries to reduce number of arguments for future mutation.
MinimizeCorpus MinimizeMode = iota
// Minimize crash reproducer.
// This mode assumes each test is expensive (need to reboot), so tries fewer things.
MinimizeCrash
// Minimize crash reproducer in snapshot mode.
// This mode does not assume that tests are expensive, and tries to minimize for reproducer readability.
MinimizeCrashSnapshot
// Only try to remove calls.
MinimizeCallsOnly
)
// Minimize minimizes program p into an equivalent program using the equivalence
// predicate pred. It iteratively generates simpler programs and asks pred
// whether it is equal to the original program or not. If it is equivalent then
// the simplification attempt is committed and the process continues.
func Minimize(p0 *Prog, callIndex0 int, mode MinimizeMode, pred0 func(*Prog, int) bool) (*Prog, int) {
// Generally we try to avoid generating duplicates, but in some cases they are hard to avoid.
// For example, if we have an array with several equal elements, removing them leads to the same program.
dedup := make(map[string]bool)
pred := func(p *Prog, callIndex int, what *stat.Val, path string) bool {
// Note: path is unused, but is useful for manual debugging.
what.Add(1)
p.sanitizeFix()
p.debugValidate()
id := hash.String(p.Serialize())
if _, ok := dedup[id]; !ok {
dedup[id] = pred0(p, callIndex)
}
return dedup[id]
}
name0 := ""
if callIndex0 != -1 {
if callIndex0 < 0 || callIndex0 >= len(p0.Calls) {
panic("bad call index")
}
name0 = p0.Calls[callIndex0].Meta.Name
}
// Try to remove all calls except the last one one-by-one.
p0, callIndex0 = removeCalls(p0, callIndex0, pred)
if mode != MinimizeCallsOnly {
// Try to reset all call props to their default values.
p0 = resetCallProps(p0, callIndex0, pred)
// Try to minimize individual calls.
for i := 0; i < len(p0.Calls); i++ {
if p0.Calls[i].Meta.Attrs.NoMinimize {
continue
}
ctx := &minimizeArgsCtx{
target: p0.Target,
p0: &p0,
callIndex0: callIndex0,
mode: mode,
pred: pred,
triedPaths: make(map[string]bool),
}
again:
ctx.p = p0.Clone()
ctx.call = ctx.p.Calls[i]
for j, field := range ctx.call.Meta.Args {
if ctx.do(ctx.call.Args[j], field.Name, fmt.Sprintf("call%v", i)) {
goto again
}
}
p0 = minimizeCallProps(p0, i, callIndex0, pred)
}
}
if callIndex0 != -1 {
if callIndex0 < 0 || callIndex0 >= len(p0.Calls) || name0 != p0.Calls[callIndex0].Meta.Name {
panic(fmt.Sprintf("bad call index after minimization: ncalls=%v index=%v call=%v/%v",
len(p0.Calls), callIndex0, name0, p0.Calls[callIndex0].Meta.Name))
}
}
return p0, callIndex0
}
type minimizePred func(*Prog, int, *stat.Val, string) bool
func removeCalls(p0 *Prog, callIndex0 int, pred minimizePred) (*Prog, int) {
if callIndex0 >= 0 && callIndex0+2 < len(p0.Calls) {
// It's frequently the case that all subsequent calls were not necessary.
// Try to drop them all at once.
p := p0.Clone()
for i := len(p0.Calls) - 1; i > callIndex0; i-- {
p.RemoveCall(i)
}
if pred(p, callIndex0, statMinRemoveCall, "trailing calls") {
p0 = p
}
}
if callIndex0 != -1 {
p0, callIndex0 = removeUnrelatedCalls(p0, callIndex0, pred)
}
for i := len(p0.Calls) - 1; i >= 0; i-- {
if i == callIndex0 {
continue
}
callIndex := callIndex0
if i < callIndex {
callIndex--
}
p := p0.Clone()
p.RemoveCall(i)
if !pred(p, callIndex, statMinRemoveCall, fmt.Sprintf("call %v", i)) {
continue
}
p0 = p
callIndex0 = callIndex
}
return p0, callIndex0
}
// removeUnrelatedCalls tries to remove all "unrelated" calls at once.
// Unrelated calls are the calls that don't use any resources/files from
// the transitive closure of the resources/files used by the target call.
// This may significantly reduce large generated programs in a single step.
func removeUnrelatedCalls(p0 *Prog, callIndex0 int, pred minimizePred) (*Prog, int) {
keepCalls := relatedCalls(p0, callIndex0)
if len(p0.Calls)-len(keepCalls) < 3 {
return p0, callIndex0
}
p, callIndex := p0.Clone(), callIndex0
for i := len(p0.Calls) - 1; i >= 0; i-- {
if keepCalls[i] {
continue
}
p.RemoveCall(i)
if i < callIndex {
callIndex--
}
}
if !pred(p, callIndex, statMinRemoveCall, "unrelated calls") {
return p0, callIndex0
}
return p, callIndex
}
func relatedCalls(p0 *Prog, callIndex0 int) map[int]bool {
keepCalls := map[int]bool{callIndex0: true}
used := uses(p0.Calls[callIndex0])
for {
n := len(used)
for i, call := range p0.Calls {
if keepCalls[i] {
continue
}
used1 := uses(call)
if intersects(used, used1) {
keepCalls[i] = true
for what := range used1 {
used[what] = true
}
}
}
if n == len(used) {
return keepCalls
}
}
}
func uses(call *Call) map[any]bool {
used := make(map[any]bool)
ForeachArg(call, func(arg Arg, _ *ArgCtx) {
switch typ := arg.Type().(type) {
case *ResourceType:
a := arg.(*ResultArg)
used[a] = true
if a.Res != nil {
used[a.Res] = true
}
for use := range a.uses {
used[use] = true
}
case *BufferType:
a := arg.(*DataArg)
if a.Dir() != DirOut && typ.Kind == BufferFilename {
val := string(bytes.TrimRight(a.Data(), "\x00"))
used[val] = true
}
}
})
return used
}
func intersects(list, list1 map[any]bool) bool {
for what := range list1 {
if list[what] {
return true
}
}
return false
}
func resetCallProps(p0 *Prog, callIndex0 int, pred minimizePred) *Prog {
// Try to reset all call props to their default values.
// This should be reasonable for many progs.
p := p0.Clone()
anyDifferent := false
for idx := range p.Calls {
if !reflect.DeepEqual(p.Calls[idx].Props, CallProps{}) {
p.Calls[idx].Props = CallProps{}
anyDifferent = true
}
}
if anyDifferent && pred(p, callIndex0, statMinRemoveProps, "props") {
return p
}
return p0
}
func minimizeCallProps(p0 *Prog, callIndex, callIndex0 int, pred minimizePred) *Prog {
props := p0.Calls[callIndex].Props
// Try to drop fault injection.
if props.FailNth > 0 {
p := p0.Clone()
p.Calls[callIndex].Props.FailNth = 0
if pred(p, callIndex0, statMinRemoveProps, "props") {
p0 = p
}
}
// Try to drop async.
if props.Async {
p := p0.Clone()
p.Calls[callIndex].Props.Async = false
if pred(p, callIndex0, statMinRemoveProps, "props") {
p0 = p
}
}
// Try to drop rerun.
if props.Rerun > 0 {
p := p0.Clone()
p.Calls[callIndex].Props.Rerun = 0
if pred(p, callIndex0, statMinRemoveProps, "props") {
p0 = p
}
}
return p0
}
type minimizeArgsCtx struct {
target *Target
p0 **Prog
p *Prog
call *Call
callIndex0 int
mode MinimizeMode
pred minimizePred
triedPaths map[string]bool
}
func (ctx *minimizeArgsCtx) do(arg Arg, field, path string) bool {
path += fmt.Sprintf("-%v", field)
if ctx.triedPaths[path] {
return false
}
p0 := *ctx.p0
if arg.Type().minimize(ctx, arg, path) {
return true
}
if *ctx.p0 == ctx.p {
// If minimize committed a new program, it must return true.
// Otherwise *ctx.p0 and ctx.p will point to the same program
// and any temp mutations to ctx.p will unintentionally affect ctx.p0.
panic("shared program committed")
}
if *ctx.p0 != p0 {
// New program was committed, but we did not start iteration anew.
// This means we are iterating over a stale tree and any changes won't be visible.
panic("iterating over stale program")
}
ctx.triedPaths[path] = true
return false
}
func (typ *TypeCommon) minimize(ctx *minimizeArgsCtx, arg Arg, path string) bool {
return false
}
func (typ *StructType) minimize(ctx *minimizeArgsCtx, arg Arg, path string) bool {
a := arg.(*GroupArg)
for i, innerArg := range a.Inner {
if ctx.do(innerArg, typ.Fields[i].Name, path) {
return true
}
}
return false
}
func (typ *UnionType) minimize(ctx *minimizeArgsCtx, arg Arg, path string) bool {
a := arg.(*UnionArg)
return ctx.do(a.Option, typ.Fields[a.Index].Name, path)
}
func (typ *PtrType) minimize(ctx *minimizeArgsCtx, arg Arg, path string) bool {
a := arg.(*PointerArg)
if a.Res == nil {
return false
}
if path1 := path + ">"; !ctx.triedPaths[path1] {
removeArg(a.Res)
replaceArg(a, MakeSpecialPointerArg(a.Type(), a.Dir(), 0))
ctx.target.assignSizesCall(ctx.call)
if ctx.pred(ctx.p, ctx.callIndex0, statMinPtr, path1) {
*ctx.p0 = ctx.p
}
ctx.triedPaths[path1] = true
return true
}
return ctx.do(a.Res, "", path)
}
func (typ *ArrayType) minimize(ctx *minimizeArgsCtx, arg Arg, path string) bool {
a := arg.(*GroupArg)
// If there are at least 3 elements, try to remove all at once first.
// If will be faster than removing them one-by-one if all of them are not needed.
if allPath := path + "-all"; len(a.Inner) >= 3 && typ.RangeBegin == 0 && !ctx.triedPaths[allPath] {
ctx.triedPaths[allPath] = true
for _, elem := range a.Inner {
removeArg(elem)
}
a.Inner = nil
ctx.target.assignSizesCall(ctx.call)
if ctx.pred(ctx.p, ctx.callIndex0, statMinArray, allPath) {
*ctx.p0 = ctx.p
}
return true
}
// Try to remove individual elements one-by-one.
for i := len(a.Inner) - 1; i >= 0; i-- {
elem := a.Inner[i]
elemPath := fmt.Sprintf("%v-%v", path, i)
if ctx.mode != MinimizeCrash && !ctx.triedPaths[elemPath] &&
(typ.Kind == ArrayRandLen ||
typ.Kind == ArrayRangeLen && uint64(len(a.Inner)) > typ.RangeBegin) {
ctx.triedPaths[elemPath] = true
copy(a.Inner[i:], a.Inner[i+1:])
a.Inner = a.Inner[:len(a.Inner)-1]
removeArg(elem)
ctx.target.assignSizesCall(ctx.call)
if ctx.pred(ctx.p, ctx.callIndex0, statMinArray, elemPath) {
*ctx.p0 = ctx.p
}
return true
}
if ctx.do(elem, "", elemPath) {
return true
}
}
return false
}
func (typ *IntType) minimize(ctx *minimizeArgsCtx, arg Arg, path string) bool {
return minimizeInt(ctx, arg, path)
}
func (typ *FlagsType) minimize(ctx *minimizeArgsCtx, arg Arg, path string) bool {
return minimizeInt(ctx, arg, path)
}
func (typ *ProcType) minimize(ctx *minimizeArgsCtx, arg Arg, path string) bool {
if !typ.Optional() {
// Default value for ProcType is 0 (same for all PID's).
// Usually 0 either does not make sense at all or make different PIDs collide
// (since we use ProcType to separate value ranges for different PIDs).
// So don't change ProcType to 0 unless the type is explicitly marked as opt
// (in that case we will also generate 0 anyway).
return false
}
return minimizeInt(ctx, arg, path)
}
func minimizeInt(ctx *minimizeArgsCtx, arg Arg, path string) bool {
if ctx.mode != MinimizeCrashSnapshot {
return false
}
a := arg.(*ConstArg)
def := arg.Type().DefaultArg(arg.Dir()).(*ConstArg)
if a.Val == def.Val {
return false
}
v0 := a.Val
a.Val = def.Val
// By mutating an integer, we risk violating conditional fields.
// If the fields are patched, the minimization process must be restarted.
patched := ctx.call.setDefaultConditions(ctx.p.Target, false)
if ctx.pred(ctx.p, ctx.callIndex0, statMinInt, path) {
*ctx.p0 = ctx.p
ctx.triedPaths[path] = true
return true
}
a.Val = v0
if patched {
// No sense to return here.
ctx.triedPaths[path] = true
}
return patched
}
func (typ *ResourceType) minimize(ctx *minimizeArgsCtx, arg Arg, path string) bool {
if ctx.mode != MinimizeCrashSnapshot {
return false
}
a := arg.(*ResultArg)
if a.Res == nil {
return false
}
r0 := a.Res
delete(a.Res.uses, a)
a.Res, a.Val = nil, typ.Default()
if ctx.pred(ctx.p, ctx.callIndex0, statMinResource, path) {
*ctx.p0 = ctx.p
} else {
a.Res, a.Val = r0, 0
a.Res.uses[a] = true
}
ctx.triedPaths[path] = true
return true
}
func (typ *BufferType) minimize(ctx *minimizeArgsCtx, arg Arg, path string) bool {
if arg.Dir() == DirOut {
return false
}
if typ.IsCompressed() {
panic(fmt.Sprintf("minimizing `no_minimize` call %v", ctx.call.Meta.Name))
}
a := arg.(*DataArg)
switch typ.Kind {
case BufferBlobRand, BufferBlobRange:
len0 := len(a.Data())
minLen := int(typ.RangeBegin)
for step := len(a.Data()) - minLen; len(a.Data()) > minLen && step > 0; {
if len(a.Data())-step >= minLen {
a.data = a.Data()[:len(a.Data())-step]
ctx.target.assignSizesCall(ctx.call)
if ctx.pred(ctx.p, ctx.callIndex0, statMinBuffer, path) {
step /= 2
continue
}
a.data = a.Data()[:len(a.Data())+step]
ctx.target.assignSizesCall(ctx.call)
}
step /= 2
if ctx.mode == MinimizeCrash {
break
}
}
if len(a.Data()) != len0 {
*ctx.p0 = ctx.p
ctx.triedPaths[path] = true
return true
}
case BufferFilename:
if ctx.mode == MinimizeCorpus {
return false
}
// Try to undo target.SpecialFileLenghts mutation
// and reduce file name length.
if !typ.Varlen() {
return false
}
data0 := append([]byte{}, a.Data()...)
a.data = bytes.TrimRight(a.Data(), specialFileLenPad+"\x00")
if !typ.NoZ {
a.data = append(a.data, 0)
}
if bytes.Equal(a.data, data0) {
return false
}
ctx.target.assignSizesCall(ctx.call)
if ctx.pred(ctx.p, ctx.callIndex0, statMinFilename, path) {
*ctx.p0 = ctx.p
}
ctx.triedPaths[path] = true
return true
}
return false
}
// Copyright 2015 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package prog
import (
"encoding/binary"
"fmt"
"math"
"math/rand"
"sort"
"github.com/google/syzkaller/pkg/image"
)
// Maximum length of generated binary blobs inserted into the program.
const maxBlobLen = uint64(100 << 10)
// Mutate program p.
//
// p: The program to mutate.
// rs: Random source.
// ncalls: The allowed maximum calls in mutated program.
// ct: ChoiceTable for syscalls.
// noMutate: Set of IDs of syscalls which should not be mutated.
// corpus: The entire corpus, including original program p.
func (p *Prog) Mutate(rs rand.Source, ncalls int, ct *ChoiceTable, noMutate map[int]bool, corpus []*Prog) {
p.MutateWithOpts(rs, ncalls, ct, noMutate, corpus, DefaultMutateOpts)
}
var DefaultMutateOpts = MutateOpts{
ExpectedIterations: 5,
MutateArgCount: 3,
SquashWeight: 50,
SpliceWeight: 200,
InsertWeight: 100,
MutateArgWeight: 100,
RemoveCallWeight: 10,
}
type MutateOpts struct {
ExpectedIterations int
MutateArgCount int
SquashWeight int
SpliceWeight int
InsertWeight int
MutateArgWeight int
RemoveCallWeight int
}
func (o MutateOpts) weight() int {
return o.SquashWeight + o.SpliceWeight + o.InsertWeight + o.MutateArgWeight + o.RemoveCallWeight
}
func (p *Prog) MutateWithOpts(rs rand.Source, ncalls int, ct *ChoiceTable, noMutate map[int]bool,
corpus []*Prog, opts MutateOpts) {
if p.isUnsafe {
panic("mutation of unsafe programs is not supposed to be done")
}
totalWeight := opts.weight()
r := newRand(p.Target, rs)
ncalls = max(ncalls, len(p.Calls))
ctx := &mutator{
p: p,
r: r,
ncalls: ncalls,
ct: ct,
noMutate: noMutate,
corpus: corpus,
opts: opts,
}
for stop, ok := false, false; !stop; stop = ok && len(p.Calls) != 0 && r.oneOf(opts.ExpectedIterations) {
val := r.Intn(totalWeight)
val -= opts.SquashWeight
if val < 0 {
// Not all calls have anything squashable,
// so this has lower priority in reality.
ok = ctx.squashAny()
continue
}
val -= opts.SpliceWeight
if val < 0 {
ok = ctx.splice()
continue
}
val -= opts.InsertWeight
if val < 0 {
ok = ctx.insertCall()
continue
}
val -= opts.MutateArgWeight
if val < 0 {
ok = ctx.mutateArg()
continue
}
ok = ctx.removeCall()
}
p.sanitizeFix()
p.debugValidate()
if got := len(p.Calls); got < 1 || got > ncalls {
panic(fmt.Sprintf("bad number of calls after mutation: %v, want [1, %v]", got, ncalls))
}
}
// Internal state required for performing mutations -- currently this matches
// the arguments passed to Mutate().
type mutator struct {
p *Prog // The program to mutate.
r *randGen // The randGen instance.
ncalls int // The allowed maximum calls in mutated program.
ct *ChoiceTable // ChoiceTable for syscalls.
noMutate map[int]bool // Set of IDs of syscalls which should not be mutated.
corpus []*Prog // The entire corpus, including original program p.
opts MutateOpts
}
// This function selects a random other program p0 out of the corpus, and
// mutates ctx.p as follows: preserve ctx.p's Calls up to a random index i
// (exclusive) concatenated with p0's calls from index i (inclusive).
func (ctx *mutator) splice() bool {
p, r := ctx.p, ctx.r
if len(ctx.corpus) == 0 || len(p.Calls) == 0 || len(p.Calls) >= ctx.ncalls {
return false
}
p0 := ctx.corpus[r.Intn(len(ctx.corpus))]
p0c := p0.Clone()
idx := r.Intn(len(p.Calls))
p.Calls = append(p.Calls[:idx], append(p0c.Calls, p.Calls[idx:]...)...)
for i := len(p.Calls) - 1; i >= ctx.ncalls; i-- {
p.RemoveCall(i)
}
return true
}
// Picks a random complex pointer and squashes its arguments into an ANY.
// Subsequently, if the ANY contains blobs, mutates a random blob.
func (ctx *mutator) squashAny() bool {
p, r := ctx.p, ctx.r
complexPtrs := p.complexPtrs()
if len(complexPtrs) == 0 {
return false
}
ptr := complexPtrs[r.Intn(len(complexPtrs))]
if ctx.noMutate[ptr.call.Meta.ID] {
return false
}
if !p.Target.isAnyPtr(ptr.arg.Type()) {
p.Target.squashPtr(ptr.arg)
}
var blobs []*DataArg
var bases []*PointerArg
ForeachSubArg(ptr.arg, func(arg Arg, ctx *ArgCtx) {
if data, ok := arg.(*DataArg); ok && arg.Dir() != DirOut {
blobs = append(blobs, data)
bases = append(bases, ctx.Base)
}
})
if len(blobs) == 0 {
return false
}
// Note: we need to call analyze before we mutate the blob.
// After mutation the blob can grow out of bounds of the data area
// and analyze will crash with out-of-bounds access while marking existing allocations.
s := analyze(ctx.ct, ctx.corpus, p, ptr.call)
// TODO(dvyukov): we probably want special mutation for ANY.
// E.g. merging adjacent ANYBLOBs (we don't create them,
// but they can appear in future); or replacing ANYRES
// with a blob (and merging it with adjacent blobs).
idx := r.Intn(len(blobs))
arg := blobs[idx]
base := bases[idx]
baseSize := base.Res.Size()
arg.data = mutateData(r, arg.Data(), 0, maxBlobLen)
// Update base pointer if size has increased.
if baseSize < base.Res.Size() {
newArg := r.allocAddr(s, base.Type(), base.Dir(), base.Res.Size(), base.Res)
*base = *newArg
}
return true
}
// Inserts a new call at a randomly chosen point (with bias towards the end of
// existing program). Does not insert a call if program already has ncalls.
func (ctx *mutator) insertCall() bool {
p, r := ctx.p, ctx.r
if len(p.Calls) >= ctx.ncalls {
return false
}
idx := r.biasedRand(len(p.Calls)+1, 5)
var c *Call
if idx < len(p.Calls) {
c = p.Calls[idx]
}
s := analyze(ctx.ct, ctx.corpus, p, c)
calls := r.generateCall(s, p, idx)
p.insertBefore(c, calls)
for len(p.Calls) > ctx.ncalls {
p.RemoveCall(idx)
}
return true
}
// Removes a random call from program.
func (ctx *mutator) removeCall() bool {
p, r := ctx.p, ctx.r
if len(p.Calls) == 0 {
return false
}
idx := r.Intn(len(p.Calls))
p.RemoveCall(idx)
return true
}
// Mutate an argument of a random call.
func (ctx *mutator) mutateArg() bool {
p, r := ctx.p, ctx.r
if len(p.Calls) == 0 {
return false
}
idx := chooseCall(p, r)
if idx < 0 {
return false
}
c := p.Calls[idx]
if ctx.noMutate[c.Meta.ID] {
return false
}
updateSizes := true
for stop, ok := false, false; !stop; stop = ok && r.oneOf(ctx.opts.MutateArgCount) {
ok = true
ma := &mutationArgs{target: p.Target}
ForeachArg(c, ma.collectArg)
if len(ma.args) == 0 {
return false
}
s := analyze(ctx.ct, ctx.corpus, p, c)
arg, argCtx := ma.chooseArg(r.Rand)
calls, ok1 := p.Target.mutateArg(r, s, arg, argCtx, &updateSizes)
if !ok1 {
ok = false
continue
}
moreCalls, fieldsPatched := r.patchConditionalFields(c, s)
calls = append(calls, moreCalls...)
p.insertBefore(c, calls)
idx += len(calls)
for len(p.Calls) > ctx.ncalls {
idx--
p.RemoveCall(idx)
}
if idx < 0 || idx >= len(p.Calls) || p.Calls[idx] != c {
panic(fmt.Sprintf("wrong call index: idx=%v calls=%v p.Calls=%v ncalls=%v",
idx, len(calls), len(p.Calls), ctx.ncalls))
}
if updateSizes || fieldsPatched {
p.Target.assignSizesCall(c)
}
}
return true
}
// Select a call based on the complexity of the arguments.
func chooseCall(p *Prog, r *randGen) int {
var prioSum float64
var callPriorities []float64
for _, c := range p.Calls {
var totalPrio float64
ForeachArg(c, func(arg Arg, ctx *ArgCtx) {
prio, stopRecursion := arg.Type().getMutationPrio(p.Target, arg, false)
totalPrio += prio
ctx.Stop = stopRecursion
})
prioSum += totalPrio
callPriorities = append(callPriorities, prioSum)
}
if prioSum == 0 {
return -1 // All calls are without arguments.
}
return sort.SearchFloat64s(callPriorities, prioSum*r.Float64())
}
func (target *Target) mutateArg(r *randGen, s *state, arg Arg, ctx ArgCtx, updateSizes *bool) ([]*Call, bool) {
var baseSize uint64
if ctx.Base != nil {
baseSize = ctx.Base.Res.Size()
}
calls, retry, preserve := arg.Type().mutate(r, s, arg, ctx)
if retry {
return nil, false
}
if preserve {
*updateSizes = false
}
// Update base pointer if size has increased.
if base := ctx.Base; base != nil && baseSize < base.Res.Size() {
newArg := r.allocAddr(s, base.Type(), base.Dir(), base.Res.Size(), base.Res)
replaceArg(base, newArg)
}
return calls, true
}
func regenerate(r *randGen, s *state, arg Arg) (calls []*Call, retry, preserve bool) {
var newArg Arg
newArg, calls = r.generateArg(s, arg.Type(), arg.Dir())
replaceArg(arg, newArg)
return
}
func mutateInt(r *randGen, a *ConstArg, t *IntType) uint64 {
switch {
case r.nOutOf(1, 3):
return a.Val + (uint64(r.Intn(4)) + 1)
case r.nOutOf(1, 2):
return a.Val - (uint64(r.Intn(4)) + 1)
default:
return a.Val ^ (1 << uint64(r.Intn(int(t.TypeBitSize()))))
}
}
func mutateAlignedInt(r *randGen, a *ConstArg, t *IntType) uint64 {
rangeEnd := t.RangeEnd
if t.RangeBegin == 0 && int64(rangeEnd) == -1 {
// Special [0:-1] range for all possible values.
rangeEnd = uint64(1<<t.TypeBitSize() - 1)
}
index := (a.Val - t.RangeBegin) / t.Align
misalignment := (a.Val - t.RangeBegin) % t.Align
switch {
case r.nOutOf(1, 3):
index += uint64(r.Intn(4)) + 1
case r.nOutOf(1, 2):
index -= uint64(r.Intn(4)) + 1
default:
index ^= 1 << uint64(r.Intn(int(t.TypeBitSize())))
}
lastIndex := (rangeEnd - t.RangeBegin) / t.Align
index %= lastIndex + 1
return t.RangeBegin + index*t.Align + misalignment
}
func (t *IntType) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls []*Call, retry, preserve bool) {
if r.bin() {
return regenerate(r, s, arg)
}
a := arg.(*ConstArg)
if t.Align == 0 {
a.Val = mutateInt(r, a, t)
} else {
a.Val = mutateAlignedInt(r, a, t)
}
a.Val = truncateToBitSize(a.Val, t.TypeBitSize())
return
}
func (t *FlagsType) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls []*Call, retry, preserve bool) {
a := arg.(*ConstArg)
for oldVal := a.Val; oldVal == a.Val; {
a.Val = r.flags(t.Vals, t.BitMask, a.Val)
}
return
}
func (t *LenType) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls []*Call, retry, preserve bool) {
if !r.mutateSize(arg.(*ConstArg), *ctx.Parent, ctx.Fields) {
retry = true
return
}
preserve = true
return
}
func (t *ResourceType) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls []*Call, retry, preserve bool) {
return regenerate(r, s, arg)
}
func (t *VmaType) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls []*Call, retry, preserve bool) {
return regenerate(r, s, arg)
}
func (t *ProcType) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls []*Call, retry, preserve bool) {
return regenerate(r, s, arg)
}
func (t *BufferType) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls []*Call, retry, preserve bool) {
minLen, maxLen := uint64(0), maxBlobLen
if t.Kind == BufferBlobRange {
minLen, maxLen = t.RangeBegin, t.RangeEnd
}
a := arg.(*DataArg)
if a.Dir() == DirOut {
if t.Kind == BufferFilename && r.oneOf(100) {
a.size = uint64(r.randFilenameLength())
} else {
mutateBufferSize(r, a, minLen, maxLen)
}
return
}
switch t.Kind {
case BufferBlobRand, BufferBlobRange:
data := append([]byte{}, a.Data()...)
a.data = mutateData(r, data, minLen, maxLen)
case BufferString:
if len(t.Values) != 0 {
a.data = r.randString(s, t)
} else {
if t.TypeSize != 0 {
minLen, maxLen = t.TypeSize, t.TypeSize
}
data := append([]byte{}, a.Data()...)
a.data = mutateData(r, data, minLen, maxLen)
}
case BufferFilename:
a.data = []byte(r.filename(s, t))
case BufferGlob:
if len(t.Values) != 0 {
a.data = r.randString(s, t)
} else {
a.data = []byte(r.filename(s, t))
}
case BufferText:
data := append([]byte{}, a.Data()...)
a.data = r.mutateText(t.Text, data)
case BufferCompressed:
a.data, retry = r.mutateImage(a.Data())
default:
panic("unknown buffer kind")
}
return
}
func (r *randGen) mutateImage(compressed []byte) (data []byte, retry bool) {
data, dtor := image.MustDecompress(compressed)
defer dtor()
if len(data) == 0 {
return compressed, true // Do not mutate empty data.
}
hm := MakeGenericHeatmap(data, r.Rand)
for i := hm.NumMutations(); i > 0; i-- {
index := hm.ChooseLocation()
width := 1 << uint(r.Intn(4))
if index+width > len(data) {
width = 1
}
storeInt(data[index:], r.randInt(uint64(width*8)), width)
}
return image.Compress(data), false
}
func mutateBufferSize(r *randGen, arg *DataArg, minLen, maxLen uint64) {
for oldSize := arg.Size(); oldSize == arg.Size(); {
arg.size += uint64(r.Intn(33)) - 16
// Cast to int64 to prevent underflows.
arg.size = uint64(max(int64(arg.size), int64(minLen)))
arg.size = min(arg.size, maxLen)
}
}
func (t *ArrayType) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls []*Call, retry, preserve bool) {
a := arg.(*GroupArg)
if len(a.Inner) > 1 && r.oneOf(5) {
// Swap array elements.
for r.nOutOf(2, 3) {
i, j := r.Intn(len(a.Inner)), r.Intn(len(a.Inner))
a.Inner[i], a.Inner[j] = a.Inner[j], a.Inner[i]
}
}
count := uint64(0)
switch t.Kind {
case ArrayRandLen:
if r.bin() {
for count = uint64(len(a.Inner)); r.bin(); {
count++
}
} else {
for count == uint64(len(a.Inner)) {
count = r.randArrayLen()
}
}
case ArrayRangeLen:
if t.RangeBegin == t.RangeEnd {
panic("trying to mutate fixed length array")
}
for count == uint64(len(a.Inner)) {
count = r.randRange(t.RangeBegin, t.RangeEnd)
}
}
if count > uint64(len(a.Inner)) {
for count > uint64(len(a.Inner)) {
newArg, newCalls := r.generateArg(s, t.Elem, a.Dir())
a.Inner = append(a.Inner, newArg)
calls = append(calls, newCalls...)
for _, c := range newCalls {
s.analyze(c)
}
}
} else if count < uint64(len(a.Inner)) {
for _, arg := range a.Inner[count:] {
removeArg(arg)
}
a.Inner = a.Inner[:count]
}
return
}
func (t *PtrType) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls []*Call, retry, preserve bool) {
a := arg.(*PointerArg)
if r.oneOf(1000) {
removeArg(a.Res)
index := r.rand(len(r.target.SpecialPointers))
newArg := MakeSpecialPointerArg(t, a.Dir(), index)
replaceArg(arg, newArg)
return
}
newArg := r.allocAddr(s, t, a.Dir(), a.Res.Size(), a.Res)
replaceArg(arg, newArg)
return
}
func (t *StructType) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls []*Call, retry, preserve bool) {
gen := r.target.SpecialTypes[t.Name()]
if gen == nil {
panic("bad arg returned by mutationArgs: StructType")
}
var newArg Arg
newArg, calls = gen(&Gen{r, s}, t, arg.Dir(), arg)
a := arg.(*GroupArg)
for i, f := range newArg.(*GroupArg).Inner {
replaceArg(a.Inner[i], f)
}
return
}
func (t *UnionType) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls []*Call, retry, preserve bool) {
if gen := r.target.SpecialTypes[t.Name()]; gen != nil {
var newArg Arg
newArg, calls = gen(&Gen{r, s}, t, arg.Dir(), arg)
replaceArg(arg, newArg)
return
}
a := arg.(*UnionArg)
index := r.Intn(len(t.Fields) - 1)
if index >= a.Index {
index++
}
optType, optDir := t.Fields[index].Type, t.Fields[index].Dir(a.Dir())
var newOpt Arg
newOpt, calls = r.generateArg(s, optType, optDir)
replaceArg(arg, MakeUnionArg(t, a.Dir(), newOpt, index))
return
}
func (t *CsumType) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls []*Call, retry, preserve bool) {
panic("CsumType can't be mutated")
}
func (t *ConstType) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls []*Call, retry, preserve bool) {
panic("ConstType can't be mutated")
}
type mutationArgs struct {
target *Target
ignoreSpecial bool
prioSum float64
args []mutationArg
argsBuffer [16]mutationArg
}
type mutationArg struct {
arg Arg
ctx ArgCtx
priority float64
}
const (
maxPriority = float64(10)
minPriority = float64(1)
dontMutate = float64(0)
)
func (ma *mutationArgs) collectArg(arg Arg, ctx *ArgCtx) {
ignoreSpecial := ma.ignoreSpecial
ma.ignoreSpecial = false
typ := arg.Type()
prio, stopRecursion := typ.getMutationPrio(ma.target, arg, ignoreSpecial)
ctx.Stop = stopRecursion
if prio == dontMutate {
return
}
_, isArrayTyp := typ.(*ArrayType)
_, isBufferTyp := typ.(*BufferType)
if !isBufferTyp && !isArrayTyp && arg.Dir() == DirOut || !typ.Varlen() && typ.Size() == 0 {
return
}
if len(ma.args) == 0 {
ma.args = ma.argsBuffer[:0]
}
ma.prioSum += prio
ma.args = append(ma.args, mutationArg{arg, *ctx, ma.prioSum})
}
func (ma *mutationArgs) chooseArg(r *rand.Rand) (Arg, ArgCtx) {
goal := ma.prioSum * r.Float64()
chosenIdx := sort.Search(len(ma.args), func(i int) bool { return ma.args[i].priority >= goal })
arg := ma.args[chosenIdx]
return arg.arg, arg.ctx
}
// TODO: find a way to estimate optimal priority values.
// Assign a priority for each type. The boolean is the reference type and it has
// the minimum priority, since it has only two possible values.
func (t *IntType) getMutationPrio(target *Target, arg Arg, ignoreSpecial bool) (prio float64, stopRecursion bool) {
// For a integer without a range of values, the priority is based on
// the number of bits occupied by the underlying type.
plainPrio := math.Log2(float64(t.TypeBitSize())) + 0.1*maxPriority
if t.Kind != IntRange {
return plainPrio, false
}
size := t.RangeEnd - t.RangeBegin + 1
if t.Align != 0 {
if t.RangeBegin == 0 && int64(t.RangeEnd) == -1 {
// Special [0:-1] range for all possible values.
size = (1<<t.TypeBitSize()-1)/t.Align + 1
} else {
size = (t.RangeEnd-t.RangeBegin)/t.Align + 1
}
}
switch {
case size <= 15:
// For a small range, we assume that it is effectively
// similar with FlagsType and we need to try all possible values.
prio = rangeSizePrio(size)
case size <= 256:
// We consider that a relevant range has at most 256
// values (the number of values that can be represented on a byte).
prio = maxPriority
default:
// Ranges larger than 256 are equivalent with a plain integer.
prio = plainPrio
}
return prio, false
}
func (t *StructType) getMutationPrio(target *Target, arg Arg, ignoreSpecial bool) (prio float64, stopRecursion bool) {
if target.SpecialTypes[t.Name()] == nil || ignoreSpecial {
return dontMutate, false
}
return maxPriority, true
}
func (t *UnionType) getMutationPrio(target *Target, arg Arg, ignoreSpecial bool) (prio float64, stopRecursion bool) {
if target.SpecialTypes[t.Name()] == nil && len(t.Fields) == 1 || ignoreSpecial {
return dontMutate, false
}
// For a non-special type union with more than one option
// we mutate the union itself and also the value of the current option.
if target.SpecialTypes[t.Name()] == nil {
return maxPriority, false
}
return maxPriority, true
}
func (t *FlagsType) getMutationPrio(target *Target, arg Arg, ignoreSpecial bool) (prio float64, stopRecursion bool) {
prio = rangeSizePrio(uint64(len(t.Vals)))
if t.BitMask {
// We want a higher priority because the mutation will include
// more possible operations (bitwise operations).
prio += 0.1 * maxPriority
}
return prio, false
}
// Assigns a priority based on the range size.
func rangeSizePrio(size uint64) (prio float64) {
switch size {
case 0:
prio = dontMutate
case 1:
prio = minPriority
default:
// Priority proportional with the number of values. After a threshold, the priority is constant.
// The threshold is 15 because most of the calls have <= 15 possible values for a flag.
prio = math.Min(float64(size)/3+0.4*maxPriority, 0.9*maxPriority)
}
return prio
}
func (t *PtrType) getMutationPrio(target *Target, arg Arg, ignoreSpecial bool) (prio float64, stopRecursion bool) {
if arg.(*PointerArg).IsSpecial() {
// TODO: we ought to mutate this, but we don't have code for this yet.
return dontMutate, false
}
return 0.3 * maxPriority, false
}
func (t *ConstType) getMutationPrio(target *Target, arg Arg, ignoreSpecial bool) (prio float64, stopRecursion bool) {
return dontMutate, false
}
func (t *CsumType) getMutationPrio(target *Target, arg Arg, ignoreSpecial bool) (prio float64, stopRecursion bool) {
return dontMutate, false
}
func (t *ProcType) getMutationPrio(target *Target, arg Arg, ignoreSpecial bool) (prio float64, stopRecursion bool) {
return 0.5 * maxPriority, false
}
func (t *ResourceType) getMutationPrio(target *Target, arg Arg, ignoreSpecial bool) (prio float64, stopRecursion bool) {
return 0.5 * maxPriority, false
}
func (t *VmaType) getMutationPrio(target *Target, arg Arg, ignoreSpecial bool) (prio float64, stopRecursion bool) {
return 0.5 * maxPriority, false
}
func (t *LenType) getMutationPrio(target *Target, arg Arg, ignoreSpecial bool) (prio float64, stopRecursion bool) {
// Mutating LenType only produces "incorrect" results according to descriptions.
return 0.1 * maxPriority, false
}
func (t *BufferType) getMutationPrio(target *Target, arg Arg, ignoreSpecial bool) (prio float64, stopRecursion bool) {
if arg.Dir() == DirOut && !t.Varlen() {
return dontMutate, false
}
if t.Kind == BufferString && len(t.Values) == 1 {
// These are effectively consts (and frequently file names).
return dontMutate, false
}
if t.Kind == BufferCompressed {
// Prioritise mutation of compressed buffers, e.g. disk images (`compressed_image`).
return maxPriority, false
}
return 0.8 * maxPriority, false
}
func (t *ArrayType) getMutationPrio(target *Target, arg Arg, ignoreSpecial bool) (prio float64, stopRecursion bool) {
if t.Kind == ArrayRangeLen && t.RangeBegin == t.RangeEnd {
return dontMutate, false
}
return maxPriority, false
}
func mutateData(r *randGen, data []byte, minLen, maxLen uint64) []byte {
for stop := false; !stop; stop = stop && r.oneOf(3) {
f := mutateDataFuncs[r.Intn(len(mutateDataFuncs))]
data, stop = f(r, data, minLen, maxLen)
}
return data
}
// The maximum delta for integer mutations.
const maxDelta = 35
var mutateDataFuncs = [...]func(r *randGen, data []byte, minLen, maxLen uint64) ([]byte, bool){
// TODO(dvyukov): duplicate part of data.
// Flip bit in byte.
func(r *randGen, data []byte, minLen, maxLen uint64) ([]byte, bool) {
if len(data) == 0 {
return data, false
}
byt := r.Intn(len(data))
bit := r.Intn(8)
data[byt] ^= 1 << uint(bit)
return data, true
},
// Insert random bytes.
func(r *randGen, data []byte, minLen, maxLen uint64) ([]byte, bool) {
if len(data) == 0 || uint64(len(data)) >= maxLen {
return data, false
}
n := min(r.Intn(16)+1, int(maxLen)-len(data))
pos := r.Intn(len(data))
for i := 0; i < n; i++ {
data = append(data, 0)
}
copy(data[pos+n:], data[pos:])
for i := 0; i < n; i++ {
data[pos+i] = byte(r.Int31())
}
if uint64(len(data)) > maxLen || r.bin() {
data = data[:len(data)-n] // preserve original length
}
return data, true
},
// Remove bytes.
func(r *randGen, data []byte, minLen, maxLen uint64) ([]byte, bool) {
if len(data) == 0 {
return data, false
}
n := min(r.Intn(16)+1, len(data))
pos := 0
if n < len(data) {
pos = r.Intn(len(data) - n)
}
copy(data[pos:], data[pos+n:])
data = data[:len(data)-n]
if uint64(len(data)) < minLen || r.bin() {
for i := 0; i < n; i++ {
data = append(data, 0) // preserve original length
}
}
return data, true
},
// Append a bunch of bytes.
func(r *randGen, data []byte, minLen, maxLen uint64) ([]byte, bool) {
if uint64(len(data)) >= maxLen {
return data, false
}
const max = 256
n := min(max-r.biasedRand(max, 10), int(maxLen)-len(data))
for i := 0; i < n; i++ {
data = append(data, byte(r.rand(256)))
}
return data, true
},
// Replace int8/int16/int32/int64 with a random value.
func(r *randGen, data []byte, minLen, maxLen uint64) ([]byte, bool) {
width := 1 << uint(r.Intn(4))
if len(data) < width {
return data, false
}
i := r.Intn(len(data) - width + 1)
storeInt(data[i:], r.Uint64(), width)
return data, true
},
// Add/subtract from an int8/int16/int32/int64.
func(r *randGen, data []byte, minLen, maxLen uint64) ([]byte, bool) {
width := 1 << uint(r.Intn(4))
if len(data) < width {
return data, false
}
i := r.Intn(len(data) - width + 1)
v := loadInt(data[i:], width)
delta := r.rand(2*maxDelta+1) - maxDelta
if delta == 0 {
delta = 1
}
if r.oneOf(10) {
v = swapInt(v, width)
v += delta
v = swapInt(v, width)
} else {
v += delta
}
storeInt(data[i:], v, width)
return data, true
},
// Set int8/int16/int32/int64 to an interesting value.
func(r *randGen, data []byte, minLen, maxLen uint64) ([]byte, bool) {
width := 1 << uint(r.Intn(4))
if len(data) < width {
return data, false
}
i := r.Intn(len(data) - width + 1)
value := r.randInt64()
if r.oneOf(10) {
value = swap64(value)
}
storeInt(data[i:], value, width)
return data, true
},
}
func swap16(v uint16) uint16 {
v0 := byte(v >> 0)
v1 := byte(v >> 8)
v = 0
v |= uint16(v1) << 0
v |= uint16(v0) << 8
return v
}
func swap32(v uint32) uint32 {
v0 := byte(v >> 0)
v1 := byte(v >> 8)
v2 := byte(v >> 16)
v3 := byte(v >> 24)
v = 0
v |= uint32(v3) << 0
v |= uint32(v2) << 8
v |= uint32(v1) << 16
v |= uint32(v0) << 24
return v
}
func swap64(v uint64) uint64 {
v0 := byte(v >> 0)
v1 := byte(v >> 8)
v2 := byte(v >> 16)
v3 := byte(v >> 24)
v4 := byte(v >> 32)
v5 := byte(v >> 40)
v6 := byte(v >> 48)
v7 := byte(v >> 56)
v = 0
v |= uint64(v7) << 0
v |= uint64(v6) << 8
v |= uint64(v5) << 16
v |= uint64(v4) << 24
v |= uint64(v3) << 32
v |= uint64(v2) << 40
v |= uint64(v1) << 48
v |= uint64(v0) << 56
return v
}
func swapInt(v uint64, size int) uint64 {
switch size {
case 1:
return v
case 2:
return uint64(swap16(uint16(v)))
case 4:
return uint64(swap32(uint32(v)))
case 8:
return swap64(v)
default:
panic(fmt.Sprintf("swapInt: bad size %v", size))
}
}
func loadInt(data []byte, size int) uint64 {
switch size {
case 1:
return uint64(data[0])
case 2:
return uint64(binary.LittleEndian.Uint16(data))
case 4:
return uint64(binary.LittleEndian.Uint32(data))
case 8:
return binary.LittleEndian.Uint64(data)
default:
panic(fmt.Sprintf("loadInt: bad size %v", size))
}
}
func storeInt(data []byte, v uint64, size int) {
switch size {
case 1:
data[0] = uint8(v)
case 2:
binary.LittleEndian.PutUint16(data, uint16(v))
case 4:
binary.LittleEndian.PutUint32(data, uint32(v))
case 8:
binary.LittleEndian.PutUint64(data, v)
default:
panic(fmt.Sprintf("storeInt: bad size %v", size))
}
}
// Copyright 2015 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package prog
import (
"bytes"
"strconv"
)
// LogEntry describes one program in execution log.
type LogEntry struct {
P *Prog
Proc int // index of parallel proc
ID int // ID of the executed program (-1 if not present)
Start int // start offset in log
End int // end offset in log
}
func (target *Target) ParseLog(data []byte, mode DeserializeMode) []*LogEntry {
var entries []*LogEntry
ent := &LogEntry{
ID: -1,
}
var cur []byte
faultCall, faultNth := -1, -1
for pos := 0; pos < len(data); {
nl := bytes.IndexByte(data[pos:], '\n')
if nl == -1 {
nl = len(data) - 1
} else {
nl += pos
}
line := data[pos : nl+1]
pos0 := pos
pos = nl + 1
if proc, ok := extractInt(line, "executing program "); ok {
if ent.P != nil && len(ent.P.Calls) != 0 {
ent.End = pos0
entries = append(entries, ent)
faultCall, faultNth = -1, -1
}
ent = &LogEntry{
Proc: proc,
Start: pos0,
ID: -1,
}
if id, ok := extractInt(line, "id="); ok {
ent.ID = id
}
// We no longer print it this way, but we still parse such fragments to preserve
// the backward compatibility.
if parsedFaultCall, ok := extractInt(line, "fault-call:"); ok {
faultCall = parsedFaultCall
faultNth, _ = extractInt(line, "fault-nth:")
}
cur = nil
continue
}
tmp := append(cur, line...)
p, err := target.Deserialize(tmp, mode)
if err != nil {
continue
}
if faultCall >= 0 && faultCall < len(p.Calls) {
// We add 1 because now the property is 1-based.
p.Calls[faultCall].Props.FailNth = faultNth + 1
}
cur = tmp
ent.P = p
}
if ent.P != nil && len(ent.P.Calls) != 0 {
ent.End = len(data)
entries = append(entries, ent)
}
return entries
}
func extractInt(line []byte, prefix string) (int, bool) {
pos := bytes.Index(line, []byte(prefix))
if pos == -1 {
return 0, false
}
pos += len(prefix)
end := pos
for end != len(line) && line[end] >= '0' && line[end] <= '9' {
end++
}
v, _ := strconv.Atoi(string(line[pos:end]))
return v, true
}
// Copyright 2015/2016 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package prog
import (
"fmt"
"math"
"math/rand"
"slices"
"sort"
)
// Calulation of call-to-call priorities.
// For a given pair of calls X and Y, the priority is our guess as to whether
// additional of call Y into a program containing call X is likely to give
// new coverage or not.
// The current algorithm has two components: static and dynamic.
// The static component is based on analysis of argument types. For example,
// if call X and call Y both accept fd[sock], then they are more likely to give
// new coverage together.
// The dynamic component is based on frequency of occurrence of a particular
// pair of syscalls in a single program in corpus. For example, if socket and
// connect frequently occur in programs together, we give higher priority to
// this pair of syscalls.
// Note: the current implementation is very basic, there is no theory behind any
// constants.
func (target *Target) CalculatePriorities(corpus []*Prog) [][]int32 {
static := target.calcStaticPriorities()
if len(corpus) != 0 {
// Let's just sum the static and dynamic distributions.
dynamic := target.calcDynamicPrio(corpus)
for i, prios := range dynamic {
dst := static[i]
for j, p := range prios {
dst[j] += p
}
}
}
return static
}
func (target *Target) calcStaticPriorities() [][]int32 {
uses := target.calcResourceUsage()
prios := make([][]int32, len(target.Syscalls))
for i := range prios {
prios[i] = make([]int32, len(target.Syscalls))
}
for _, weights := range uses {
for _, w0 := range weights {
for _, w1 := range weights {
if w0.call == w1.call {
// Self-priority is assigned below.
continue
}
// The static priority is assigned based on the direction of arguments. A higher priority will be
// assigned when c0 is a call that produces a resource and c1 a call that uses that resource.
prios[w0.call][w1.call] += w0.inout*w1.in*3/2 + w0.inout*w1.inout
}
}
}
// The value assigned for self-priority (call wrt itself) have to be high, but not too high.
for c0, pp := range prios {
max := slices.Max(pp)
if max == 0 {
pp[c0] = 1
} else {
pp[c0] = max * 3 / 4
}
}
normalizePrios(prios)
return prios
}
func (target *Target) calcResourceUsage() map[string]map[int]weights {
uses := make(map[string]map[int]weights)
ForeachType(target.Syscalls, func(t Type, ctx *TypeCtx) {
c := ctx.Meta
switch a := t.(type) {
case *ResourceType:
if target.AuxResources[a.Desc.Name] {
noteUsagef(uses, c, 1, ctx.Dir, "res%v", a.Desc.Name)
} else {
str := "res"
for i, k := range a.Desc.Kind {
str += "-" + k
w := int32(10)
if i < len(a.Desc.Kind)-1 {
w = 2
}
noteUsage(uses, c, w, ctx.Dir, str)
}
}
case *PtrType:
if _, ok := a.Elem.(*StructType); ok {
noteUsagef(uses, c, 10, ctx.Dir, "ptrto-%v", a.Elem.Name())
}
if _, ok := a.Elem.(*UnionType); ok {
noteUsagef(uses, c, 10, ctx.Dir, "ptrto-%v", a.Elem.Name())
}
if arr, ok := a.Elem.(*ArrayType); ok {
noteUsagef(uses, c, 10, ctx.Dir, "ptrto-%v", arr.Elem.Name())
}
case *BufferType:
switch a.Kind {
case BufferBlobRand, BufferBlobRange, BufferText, BufferCompressed:
case BufferString, BufferGlob:
if a.SubKind != "" {
noteUsagef(uses, c, 2, ctx.Dir, "str-%v", a.SubKind)
}
case BufferFilename:
noteUsage(uses, c, 10, DirIn, "filename")
default:
panic("unknown buffer kind")
}
case *VmaType:
noteUsage(uses, c, 5, ctx.Dir, "vma")
case *IntType:
switch a.Kind {
case IntPlain, IntRange:
default:
panic("unknown int kind")
}
}
})
return uses
}
type weights struct {
call int
in int32
inout int32
}
func noteUsage(uses map[string]map[int]weights, c *Syscall, weight int32, dir Dir, str string) {
noteUsagef(uses, c, weight, dir, "%v", str)
}
func noteUsagef(uses map[string]map[int]weights, c *Syscall, weight int32, dir Dir, str string, args ...interface{}) {
id := fmt.Sprintf(str, args...)
if uses[id] == nil {
uses[id] = make(map[int]weights)
}
callWeight := uses[id][c.ID]
callWeight.call = c.ID
if dir != DirOut {
if weight > uses[id][c.ID].in {
callWeight.in = weight
}
}
if weight > uses[id][c.ID].inout {
callWeight.inout = weight
}
uses[id][c.ID] = callWeight
}
func (target *Target) calcDynamicPrio(corpus []*Prog) [][]int32 {
prios := make([][]int32, len(target.Syscalls))
for i := range prios {
prios[i] = make([]int32, len(target.Syscalls))
}
for _, p := range corpus {
for idx0, c0 := range p.Calls {
for _, c1 := range p.Calls[idx0+1:] {
prios[c0.Meta.ID][c1.Meta.ID]++
}
}
}
for i := range prios {
for j, val := range prios[i] {
// It's more important that some calls do coexist than whether
// it happened 50 or 100 times.
// Let's use sqrt() to lessen the effect of large counts.
prios[i][j] = int32(2.0 * math.Sqrt(float64(val)))
}
}
normalizePrios(prios)
return prios
}
// normalizePrio distributes |N| * 10 points proportional to the values in the matrix.
func normalizePrios(prios [][]int32) {
total := 10 * int32(len(prios))
for _, prio := range prios {
sum := int32(0)
for _, p := range prio {
sum += p
}
if sum == 0 {
continue
}
for i, p := range prio {
prio[i] = p * total / sum
}
}
}
// ChooseTable allows to do a weighted choice of a syscall for a given syscall
// based on call-to-call priorities and a set of enabled and generatable syscalls.
type ChoiceTable struct {
target *Target
runs [][]int32
calls []*Syscall
}
func (target *Target) BuildChoiceTable(corpus []*Prog, enabled map[*Syscall]bool) *ChoiceTable {
if enabled == nil {
enabled = make(map[*Syscall]bool)
for _, c := range target.Syscalls {
enabled[c] = true
}
}
noGenerateCalls := make(map[int]bool)
enabledCalls := make(map[*Syscall]bool)
for call := range enabled {
if call.Attrs.NoGenerate {
noGenerateCalls[call.ID] = true
} else if !call.Attrs.Disabled {
enabledCalls[call] = true
}
}
var generatableCalls []*Syscall
for c := range enabledCalls {
generatableCalls = append(generatableCalls, c)
}
if len(generatableCalls) == 0 {
panic("no syscalls enabled and generatable")
}
sort.Slice(generatableCalls, func(i, j int) bool {
return generatableCalls[i].ID < generatableCalls[j].ID
})
for _, p := range corpus {
for _, call := range p.Calls {
if !enabledCalls[call.Meta] && !noGenerateCalls[call.Meta.ID] {
fmt.Printf("corpus contains disabled syscall %v\n", call.Meta.Name)
for call := range enabled {
fmt.Printf("%s: enabled\n", call.Name)
}
panic("disabled syscall")
}
}
}
prios := target.CalculatePriorities(corpus)
run := make([][]int32, len(target.Syscalls))
// ChoiceTable.runs[][] contains cumulated sum of weighted priority numbers.
// This helps in quick binary search with biases when generating programs.
// This only applies for system calls that are enabled for the target.
for i := range run {
if !enabledCalls[target.Syscalls[i]] {
continue
}
run[i] = make([]int32, len(target.Syscalls))
var sum int32
for j := range run[i] {
if enabledCalls[target.Syscalls[j]] {
sum += prios[i][j]
}
run[i][j] = sum
}
}
return &ChoiceTable{target, run, generatableCalls}
}
func (ct *ChoiceTable) Generatable(call int) bool {
return ct.runs[call] != nil
}
func (ct *ChoiceTable) choose(r *rand.Rand, bias int) int {
if r.Intn(100) < 5 {
// Let's make 5% decisions totally at random.
return ct.calls[r.Intn(len(ct.calls))].ID
}
if bias < 0 {
bias = ct.calls[r.Intn(len(ct.calls))].ID
}
if !ct.Generatable(bias) {
fmt.Printf("bias to disabled or non-generatable syscall %v\n", ct.target.Syscalls[bias].Name)
panic("disabled or non-generatable syscall")
}
run := ct.runs[bias]
runSum := int(run[len(run)-1])
x := int32(r.Intn(runSum) + 1)
res := sort.Search(len(run), func(i int) bool {
return run[i] >= x
})
if !ct.Generatable(res) {
panic("selected disabled or non-generatable syscall")
}
return res
}
// Copyright 2015 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package prog
import (
"fmt"
"reflect"
)
type Prog struct {
Target *Target
Calls []*Call
Comments []string
// Was deserialized using Unsafe mode, so can do unsafe things.
isUnsafe bool
}
const ExtraCallName = ".extra"
func (p *Prog) CallName(call int) string {
if call >= len(p.Calls) || call < -1 {
panic(fmt.Sprintf("bad call index %v/%v", call, len(p.Calls)))
}
if call == -1 {
return ExtraCallName
}
return p.Calls[call].Meta.Name
}
// OnlyContains determines whether the program only consists of the syscalls from the first argument.
func (p *Prog) OnlyContains(syscalls map[*Syscall]bool) bool {
for _, c := range p.Calls {
if !syscalls[c.Meta] {
return false
}
}
return true
}
// FilterInplace only leaves the allowed system calls and deletes all remaining ones.
func (p *Prog) FilterInplace(allowed map[*Syscall]bool) {
for i := 0; i < len(p.Calls); {
c := p.Calls[i]
if !allowed[c.Meta] {
p.RemoveCall(i)
continue
}
i++
}
}
// These properties are parsed and serialized according to the tag and the type
// of the corresponding fields.
// IMPORTANT: keep the exact values of "key" tag for existing props unchanged,
// otherwise the backwards compatibility would be broken.
type CallProps struct {
FailNth int `key:"fail_nth"`
Async bool `key:"async"`
Rerun int `key:"rerun"`
}
type Call struct {
Meta *Syscall
Args []Arg
Ret *ResultArg
Props CallProps
Comment string
}
func MakeCall(meta *Syscall, args []Arg) *Call {
return &Call{
Meta: meta,
Args: args,
Ret: MakeReturnArg(meta.Ret),
}
}
type Arg interface {
Type() Type
Dir() Dir
Size() uint64
validate(ctx *validCtx, dir Dir) error
serialize(ctx *serializer)
}
type ArgCommon struct {
ref Ref
dir Dir
}
func (arg *ArgCommon) Type() Type {
if arg.ref == 0 {
panic("broken type ref")
}
return typeRefs.Load().([]Type)[arg.ref]
}
func (arg *ArgCommon) Dir() Dir {
return arg.dir
}
// Used for ConstType, IntType, FlagsType, LenType, ProcType and CsumType.
type ConstArg struct {
ArgCommon
Val uint64
}
func MakeConstArg(t Type, dir Dir, v uint64) *ConstArg {
return &ConstArg{ArgCommon: ArgCommon{ref: t.ref(), dir: dir}, Val: v}
}
func (arg *ConstArg) Size() uint64 {
return arg.Type().Size()
}
// Value returns value and pid stride.
func (arg *ConstArg) Value() (uint64, uint64) {
switch typ := (*arg).Type().(type) {
case *IntType:
return arg.Val, 0
case *ConstType:
return arg.Val, 0
case *FlagsType:
return arg.Val, 0
case *LenType:
return arg.Val, 0
case *ResourceType:
return arg.Val, 0
case *CsumType:
// Checksums are computed dynamically in executor.
return 0, 0
case *ProcType:
if arg.Val == procDefaultValue {
return 0, 0
}
return typ.ValuesStart + arg.Val, typ.ValuesPerProc
default:
panic(fmt.Sprintf("unknown ConstArg type %#v", typ))
}
}
// Used for PtrType and VmaType.
type PointerArg struct {
ArgCommon
Address uint64
VmaSize uint64 // size of the referenced region for vma args
Res Arg // pointee (nil for vma)
}
func MakePointerArg(t Type, dir Dir, addr uint64, data Arg) *PointerArg {
if data == nil {
panic("nil pointer data arg")
}
return &PointerArg{
ArgCommon: ArgCommon{ref: t.ref(), dir: DirIn}, // pointers are always in
Address: addr,
Res: data,
}
}
func MakeVmaPointerArg(t Type, dir Dir, addr, size uint64) *PointerArg {
if addr%1024 != 0 {
panic("unaligned vma address")
}
return &PointerArg{
ArgCommon: ArgCommon{ref: t.ref(), dir: dir},
Address: addr,
VmaSize: size,
}
}
func MakeSpecialPointerArg(t Type, dir Dir, index uint64) *PointerArg {
if index >= maxSpecialPointers {
panic("bad special pointer index")
}
if _, ok := t.(*PtrType); ok {
dir = DirIn // pointers are always in
}
return &PointerArg{
ArgCommon: ArgCommon{ref: t.ref(), dir: dir},
Address: -index,
}
}
func (arg *PointerArg) Size() uint64 {
return arg.Type().Size()
}
func (arg *PointerArg) IsSpecial() bool {
return arg.VmaSize == 0 && arg.Res == nil && -arg.Address < maxSpecialPointers
}
func (target *Target) PhysicalAddr(arg *PointerArg) uint64 {
if arg.IsSpecial() {
return target.SpecialPointers[-arg.Address]
}
return target.DataOffset + arg.Address
}
// Used for BufferType.
type DataArg struct {
ArgCommon
data []byte // for in/inout args
size uint64 // for out Args
}
func MakeDataArg(t Type, dir Dir, data []byte) *DataArg {
if dir == DirOut {
panic("non-empty output data arg")
}
return &DataArg{ArgCommon: ArgCommon{ref: t.ref(), dir: dir}, data: append([]byte{}, data...)}
}
func MakeOutDataArg(t Type, dir Dir, size uint64) *DataArg {
if dir != DirOut {
panic("empty input data arg")
}
return &DataArg{ArgCommon: ArgCommon{ref: t.ref(), dir: dir}, size: size}
}
func (arg *DataArg) Size() uint64 {
if len(arg.data) != 0 {
return uint64(len(arg.data))
}
return arg.size
}
func (arg *DataArg) Data() []byte {
if arg.Dir() == DirOut {
panic("getting data of output data arg")
}
return arg.data
}
func (arg *DataArg) SetData(data []byte) {
if arg.Dir() == DirOut {
panic("setting data of output data arg")
}
arg.data = append([]byte{}, data...)
}
// Used for StructType and ArrayType.
// Logical group of args (struct or array).
type GroupArg struct {
ArgCommon
Inner []Arg
}
func MakeGroupArg(t Type, dir Dir, inner []Arg) *GroupArg {
return &GroupArg{ArgCommon: ArgCommon{ref: t.ref(), dir: dir}, Inner: inner}
}
func (arg *GroupArg) Size() uint64 {
typ0 := arg.Type()
if !typ0.Varlen() {
return typ0.Size()
}
switch typ := typ0.(type) {
case *StructType:
var size, offset uint64
for i, fld := range arg.Inner {
if i == typ.OverlayField {
offset = 0
}
offset += fld.Size()
// Add dynamic alignment at the end and before the overlay part.
if i+1 == len(arg.Inner) || i+1 == typ.OverlayField {
if typ.AlignAttr != 0 && offset%typ.AlignAttr != 0 {
offset += typ.AlignAttr - offset%typ.AlignAttr
}
}
size = max(size, offset)
}
return size
case *ArrayType:
var size uint64
for _, elem := range arg.Inner {
size += elem.Size()
}
return size
default:
panic(fmt.Sprintf("bad group arg type %v", typ))
}
}
func (arg *GroupArg) fixedInnerSize() bool {
switch typ := arg.Type().(type) {
case *StructType:
return true
case *ArrayType:
return typ.Kind == ArrayRangeLen && typ.RangeBegin == typ.RangeEnd
default:
panic(fmt.Sprintf("bad group arg type %v", typ))
}
}
// Used for UnionType.
type UnionArg struct {
ArgCommon
Option Arg
Index int // Index of the selected option in the union type.
// Used for unions with conditional fields.
// We first create a dummy arg with transient=True and then
// patch them.
transient bool
}
func MakeUnionArg(t Type, dir Dir, opt Arg, index int) *UnionArg {
return &UnionArg{ArgCommon: ArgCommon{ref: t.ref(), dir: dir}, Option: opt, Index: index}
}
func (arg *UnionArg) Size() uint64 {
if !arg.Type().Varlen() {
return arg.Type().Size()
}
return arg.Option.Size()
}
// Used for ResourceType.
// This is the only argument that can be used as syscall return value.
// Either holds constant value or reference another ResultArg.
type ResultArg struct {
ArgCommon
Res *ResultArg // reference to arg which we use
OpDiv uint64 // divide result (executed before OpAdd)
OpAdd uint64 // add to result
Val uint64 // value used if Res is nil
uses map[*ResultArg]bool // args that use this arg
}
func MakeResultArg(t Type, dir Dir, r *ResultArg, v uint64) *ResultArg {
arg := &ResultArg{ArgCommon: ArgCommon{ref: t.ref(), dir: dir}, Res: r, Val: v}
if r == nil {
return arg
}
if r.uses == nil {
r.uses = make(map[*ResultArg]bool)
}
r.uses[arg] = true
return arg
}
func MakeReturnArg(t Type) *ResultArg {
if t == nil {
return nil
}
return &ResultArg{ArgCommon: ArgCommon{ref: t.ref(), dir: DirOut}}
}
func (arg *ResultArg) Size() uint64 {
return arg.Type().Size()
}
// Returns inner arg for pointer args.
func InnerArg(arg Arg) Arg {
if _, ok := arg.Type().(*PtrType); ok {
res := arg.(*PointerArg).Res
if res == nil {
return nil
}
return InnerArg(res)
}
return arg // Not a pointer.
}
func isDefault(arg Arg) bool {
return arg.Type().isDefaultArg(arg)
}
func (p *Prog) insertBefore(c *Call, calls []*Call) {
idx := 0
for ; idx < len(p.Calls); idx++ {
if p.Calls[idx] == c {
break
}
}
var newCalls []*Call
newCalls = append(newCalls, p.Calls[:idx]...)
newCalls = append(newCalls, calls...)
if idx < len(p.Calls) {
newCalls = append(newCalls, p.Calls[idx])
newCalls = append(newCalls, p.Calls[idx+1:]...)
}
p.Calls = newCalls
}
// replaceArg replaces arg with arg1 in a program.
func replaceArg(arg, arg1 Arg) {
if arg == arg1 {
panic("replacing an argument with itself")
}
switch a := arg.(type) {
case *ConstArg:
*a = *arg1.(*ConstArg)
case *ResultArg:
replaceResultArg(a, arg1.(*ResultArg))
case *PointerArg:
*a = *arg1.(*PointerArg)
case *UnionArg:
if a.Option != nil {
removeArg(a.Option)
}
*a = *arg1.(*UnionArg)
case *DataArg:
*a = *arg1.(*DataArg)
case *GroupArg:
_, isStruct := arg.Type().(*StructType)
a1 := arg1.(*GroupArg)
if isStruct && len(a.Inner) != len(a1.Inner) {
panic(fmt.Sprintf("replaceArg: group fields don't match: %v/%v",
len(a.Inner), len(a1.Inner)))
}
a.ArgCommon = a1.ArgCommon
// Replace min(|a|, |a1|) arguments.
for i := 0; i < len(a.Inner) && i < len(a1.Inner); i++ {
replaceArg(a.Inner[i], a1.Inner[i])
}
// Remove extra arguments of a.
for len(a.Inner) > len(a1.Inner) {
i := len(a.Inner) - 1
removeArg(a.Inner[i])
a.Inner[i] = nil
a.Inner = a.Inner[:i]
}
// Add extra arguments to a.
for i := len(a.Inner); i < len(a1.Inner); i++ {
a.Inner = append(a.Inner, a1.Inner[i])
}
if debug && len(a.Inner) != len(a1.Inner) {
panic("replaceArg implementation bug")
}
default:
panic(fmt.Sprintf("replaceArg: bad arg kind %#v", arg))
}
}
func replaceResultArg(arg, arg1 *ResultArg) {
// Remove link from `a.Res` to `arg`.
if arg.Res != nil {
delete(arg.Res.uses, arg)
}
// Copy all fields from `arg1` to `arg` except for the list of args that use `arg`.
uses := arg.uses
*arg = *arg1
arg.uses = uses
// Make the link in `arg.Res` (which is now `Res` of `arg1`) to point to `arg` instead of `arg1`.
if arg.Res != nil {
resUses := arg.Res.uses
delete(resUses, arg1)
resUses[arg] = true
}
}
// removeArg removes all references to/from arg0 from a program.
func removeArg(arg0 Arg) {
ForeachSubArg(arg0, func(arg Arg, ctx *ArgCtx) {
a, ok := arg.(*ResultArg)
if !ok {
return
}
if a.Res != nil {
uses := a.Res.uses
if !uses[a] {
panic("broken tree")
}
delete(uses, a)
}
for arg1 := range a.uses {
arg2 := arg1.Type().DefaultArg(arg1.Dir()).(*ResultArg)
replaceResultArg(arg1, arg2)
}
})
}
// RemoveCall removes call idx from p.
func (p *Prog) RemoveCall(idx int) {
c := p.Calls[idx]
for _, arg := range c.Args {
removeArg(arg)
}
if c.Ret != nil {
removeArg(c.Ret)
}
copy(p.Calls[idx:], p.Calls[idx+1:])
p.Calls = p.Calls[:len(p.Calls)-1]
}
func (p *Prog) sanitizeFix() {
if err := p.sanitize(true); err != nil {
panic(err)
}
}
func (p *Prog) sanitize(fix bool) error {
for _, c := range p.Calls {
if err := p.Target.sanitize(c, fix); err != nil {
return err
}
}
return nil
}
// TODO: This method might be more generic - it can be applied to any struct.
func (props *CallProps) ForeachProp(f func(fieldName, key string, value reflect.Value)) {
valueObj := reflect.ValueOf(props).Elem()
typeObj := valueObj.Type()
for i := 0; i < valueObj.NumField(); i++ {
fieldValue := valueObj.Field(i)
fieldType := typeObj.Field(i)
f(fieldType.Name, fieldType.Tag.Get("key"), fieldValue)
}
}
// Copyright 2015/2016 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package prog
import (
"bytes"
"fmt"
"math"
"math/rand"
"path/filepath"
"sort"
"strings"
"github.com/google/syzkaller/pkg/ifuzz"
)
const (
// "Recommended" number of calls in programs that we try to aim at during fuzzing.
RecommendedCalls = 30
// "Recommended" max number of calls in programs.
// If we receive longer programs from hub/corpus we discard them.
MaxCalls = 40
)
type randGen struct {
*rand.Rand
target *Target
inGenerateResource bool
patchConditionalDepth int
recDepth map[string]int
}
func newRand(target *Target, rs rand.Source) *randGen {
return &randGen{
Rand: rand.New(rs),
target: target,
recDepth: make(map[string]int),
}
}
func (r *randGen) rand(n int) uint64 {
return uint64(r.Intn(n))
}
func (r *randGen) randRange(begin, end uint64) uint64 {
return begin + uint64(r.Intn(int(end-begin+1)))
}
func (r *randGen) bin() bool {
return r.Intn(2) == 0
}
func (r *randGen) oneOf(n int) bool {
return r.Intn(n) == 0
}
func (r *randGen) rand64() uint64 {
v := uint64(r.Int63())
if r.bin() {
v |= 1 << 63
}
return v
}
var (
// Some potentially interesting integers.
specialInts = []uint64{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
64, 127, 128, 129, 255, 256, 257, 511, 512,
1023, 1024, 1025, 2047, 2048, 4095, 4096,
(1 << 15) - 1, (1 << 15), (1 << 15) + 1,
(1 << 16) - 1, (1 << 16), (1 << 16) + 1,
(1 << 31) - 1, (1 << 31), (1 << 31) + 1,
(1 << 32) - 1, (1 << 32), (1 << 32) + 1,
(1 << 63) - 1, (1 << 63), (1 << 63) + 1,
(1 << 64) - 1,
}
// The indexes (exclusive) for the maximum specialInts values that fit in 1, 2, ... 8 bytes.
specialIntIndex [9]int
)
func init() {
sort.Slice(specialInts, func(i, j int) bool {
return specialInts[i] < specialInts[j]
})
for i := range specialIntIndex {
bitSize := uint64(8 * i)
specialIntIndex[i] = sort.Search(len(specialInts), func(i int) bool {
return specialInts[i]>>bitSize != 0
})
}
}
func (r *randGen) randInt64() uint64 {
return r.randInt(64)
}
func (r *randGen) randInt(bits uint64) uint64 {
v := r.rand64()
switch {
case r.nOutOf(100, 182):
v %= 10
case bits >= 8 && r.nOutOf(50, 82):
v = specialInts[r.Intn(specialIntIndex[bits/8])]
case r.nOutOf(10, 32):
v %= 256
case r.nOutOf(10, 22):
v %= 4 << 10
case r.nOutOf(10, 12):
v %= 64 << 10
default:
v %= 1 << 31
}
switch {
case r.nOutOf(100, 107):
case r.nOutOf(5, 7):
v = uint64(-int64(v))
default:
v <<= uint(r.Intn(int(bits)))
}
return truncateToBitSize(v, bits)
}
func truncateToBitSize(v, bitSize uint64) uint64 {
if bitSize == 0 || bitSize > 64 {
panic(fmt.Sprintf("invalid bitSize value: %d", bitSize))
}
return v & uint64(1<<bitSize-1)
}
func (r *randGen) randRangeInt(begin, end, bitSize, align uint64) uint64 {
if r.oneOf(100) {
return r.randInt(bitSize)
}
if align != 0 {
if begin == 0 && int64(end) == -1 {
// Special [0:-1] range for all possible values.
end = uint64(1<<bitSize - 1)
}
endAlign := (end - begin) / align
return begin + r.randRangeInt(0, endAlign, bitSize, 0)*align
}
return begin + (r.Uint64() % (end - begin + 1))
}
// biasedRand returns a random int in range [0..n),
// probability of n-1 is k times higher than probability of 0.
func (r *randGen) biasedRand(n, k int) int {
nf, kf := float64(n), float64(k)
rf := nf * (kf/2 + 1) * r.Float64()
bf := (-1 + math.Sqrt(1+2*kf*rf/nf)) * nf / kf
return int(bf)
}
const maxArrayLen = 10
func (r *randGen) randArrayLen() uint64 {
// biasedRand produces: 10, 9, ..., 1, 0,
// we want: 1, 2, ..., 9, 10, 0
return uint64(maxArrayLen-r.biasedRand(maxArrayLen+1, 10)+1) % (maxArrayLen + 1)
}
func (r *randGen) randBufLen() (n uint64) {
switch {
case r.nOutOf(50, 56):
n = r.rand(256)
case r.nOutOf(5, 6):
n = 4 << 10
}
return
}
func (r *randGen) randPageCount() (n uint64) {
switch {
case r.nOutOf(100, 106):
n = r.rand(4) + 1
case r.nOutOf(5, 6):
n = r.rand(20) + 1
default:
n = (r.rand(3) + 1) * r.target.NumPages / 4
}
return
}
// Change a flag value or generate a new one.
// If you are changing this function, run TestFlags and examine effect of results.
func (r *randGen) flags(vv []uint64, bitmask bool, oldVal uint64) uint64 {
// Get these simpler cases out of the way first.
// Once in a while we want to return completely random values,
// or 0 which is frequently special.
if r.oneOf(100) {
return r.rand64()
}
if r.oneOf(50) {
return 0
}
if !bitmask && oldVal != 0 && r.oneOf(100) {
// Slightly increment/decrement the old value.
// This is especially important during mutation when len(vv) == 1,
// otherwise in that case we produce almost no randomness
// (the value is always mutated to 0).
inc := uint64(1)
if r.bin() {
inc = ^uint64(0)
}
v := oldVal + inc
for r.bin() {
v += inc
}
return v
}
if len(vv) == 1 {
// This usually means that value or 0,
// at least that's our best (and only) bet.
if r.bin() {
return 0
}
return vv[0]
}
if !bitmask && !r.oneOf(10) {
// Enumeration, so just choose one of the values.
return vv[r.rand(len(vv))]
}
if r.oneOf(len(vv) + 4) {
return 0
}
// Flip rand bits. Do this for non-bitmask sometimes
// because we may have detected bitmask incorrectly for complex cases
// (e.g. part of the vlaue is bitmask and another is not).
v := oldVal
if v != 0 && r.oneOf(10) {
v = 0 // Ignore the old value sometimes.
}
// We don't want to return 0 here, because we already given 0
// fixed probability above (otherwise we get 0 too frequently).
// Note: this loop can hang if all values are equal to 0. We don't generate such flags in the compiler now,
// but it used to hang occasionally, so we keep the try < 10 logic b/c we don't have a local check for values.
for try := 0; try < 10 && (v == 0 || r.nOutOf(2, 3)); try++ {
flag := vv[r.rand(len(vv))]
if r.oneOf(20) {
// Try choosing adjacent bit values in case we forgot
// to add all relevant flags to the descriptions.
if r.bin() {
flag >>= 1
} else {
flag <<= 1
}
}
v ^= flag
}
return v
}
func (r *randGen) filename(s *state, typ *BufferType) string {
fn := r.filenameImpl(s)
if fn != "" && fn[len(fn)-1] == 0 {
panic(fmt.Sprintf("zero-terminated filename: %q", fn))
}
if escapingFilename(fn) {
panic(fmt.Sprintf("sandbox escaping file name %q, s.files are %v", fn, s.files))
}
if !typ.Varlen() {
size := typ.Size()
if uint64(len(fn)) < size {
fn += string(make([]byte, size-uint64(len(fn))))
}
fn = fn[:size]
} else if !typ.NoZ {
fn += "\x00"
}
return fn
}
func escapingFilename(file string) bool {
file = filepath.Clean(file)
return len(file) >= 1 && file[0] == '/' ||
len(file) >= 2 && file[0] == '.' && file[1] == '.'
}
var specialFiles = []string{"", "."}
const specialFileLenPad = "a"
func (r *randGen) filenameImpl(s *state) string {
if r.oneOf(100) {
return specialFiles[r.Intn(len(specialFiles))]
}
if len(s.files) == 0 || r.oneOf(10) {
// Generate a new name.
dir := "."
if r.oneOf(2) && len(s.files) != 0 {
dir = r.randFromMap(s.files)
if dir != "" && dir[len(dir)-1] == 0 {
dir = dir[:len(dir)-1]
}
if r.oneOf(10) && filepath.Clean(dir)[0] != '.' {
dir += "/.."
}
}
for i := 0; ; i++ {
f := fmt.Sprintf("%v/file%v", dir, i)
if r.oneOf(100) {
// Make file name very long using target.SpecialFileLenghts consts.
// Add/subtract some small const to account for our file name prefix
// and potential kernel off-by-one's.
fileLen := r.randFilenameLength()
if add := fileLen - len(f); add > 0 {
f += strings.Repeat(specialFileLenPad, add)
}
}
if !s.files[f] {
return f
}
}
}
return r.randFromMap(s.files)
}
func (r *randGen) randFilenameLength() int {
off := r.biasedRand(10, 5)
if r.bin() {
off = -off
}
lens := r.target.SpecialFileLenghts
return max(lens[r.Intn(len(lens))]+off, 0)
}
func (r *randGen) randFromMap(m map[string]bool) string {
files := make([]string, 0, len(m))
for f := range m {
files = append(files, f)
}
sort.Strings(files)
return files[r.Intn(len(files))]
}
func (r *randGen) randString(s *state, t *BufferType) []byte {
if len(t.Values) != 0 {
return []byte(t.Values[r.Intn(len(t.Values))])
}
if len(s.strings) != 0 && r.bin() {
// Return an existing string.
// TODO(dvyukov): make s.strings indexed by string SubKind.
return []byte(r.randFromMap(s.strings))
}
punct := []byte{'!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '-', '+', '\\',
'/', ':', '.', ',', '-', '\'', '[', ']', '{', '}'}
buf := new(bytes.Buffer)
for r.nOutOf(3, 4) {
if r.nOutOf(10, 11) {
buf.Write([]byte{punct[r.Intn(len(punct))]})
} else {
buf.Write([]byte{byte(r.Intn(256))})
}
}
if r.oneOf(100) == t.NoZ {
buf.Write([]byte{0})
}
return buf.Bytes()
}
func (r *randGen) allocAddr(s *state, typ Type, dir Dir, size uint64, data Arg) *PointerArg {
return MakePointerArg(typ, dir, s.ma.alloc(r, size, data.Type().Alignment()), data)
}
func (r *randGen) allocVMA(s *state, typ Type, dir Dir, numPages uint64) *PointerArg {
page := s.va.alloc(r, numPages)
return MakeVmaPointerArg(typ, dir, page*r.target.PageSize, numPages*r.target.PageSize)
}
func (r *randGen) pruneRecursion(name string) (bool, func()) {
if r.recDepth[name] >= 2 {
return false, nil
}
r.recDepth[name]++
return true, func() {
r.recDepth[name]--
if r.recDepth[name] == 0 {
delete(r.recDepth, name)
}
}
}
func (r *randGen) createResource(s *state, res *ResourceType, dir Dir) (Arg, []*Call) {
if !r.inGenerateResource {
panic("inGenerateResource is not set")
}
kind := res.Desc.Name
// Find calls that produce the necessary resources.
ctors := r.enabledCtors(s, kind)
// We may have no resources, but still be in createResource due to ANYRES.
if len(r.target.resourceMap) != 0 && r.oneOf(1000) {
// Spoof resource subkind.
var all []string
for kind1 := range r.target.resourceMap {
if r.target.isCompatibleResource(res.Desc.Kind[0], kind1) {
all = append(all, kind1)
}
}
if len(all) == 0 {
panic(fmt.Sprintf("got no spoof resources for %v in %v/%v",
kind, r.target.OS, r.target.Arch))
}
sort.Strings(all)
kind1 := all[r.Intn(len(all))]
ctors1 := r.enabledCtors(s, kind1)
if len(ctors1) != 0 {
// Don't use the resource for which we don't have any ctors.
// It's fine per-se because below we just return nil in such case.
// But in TestCreateResource tests we want to ensure that we don't fail
// to create non-optional resources, and if we spoof a non-optional
// resource with ctors with a optional resource w/o ctors, then that check will fail.
kind, ctors = kind1, ctors1
}
}
if len(ctors) == 0 {
// We may not have any constructors for optional input resources because we don't disable
// syscalls based on optional inputs resources w/o ctors in TransitivelyEnabledCalls.
return nil, nil
}
// Now we have a set of candidate calls that can create the necessary resource.
// Generate one of them.
var meta *Syscall
// Prefer precise constructors.
var precise []*Syscall
for _, info := range ctors {
if info.Precise {
precise = append(precise, info.Call)
}
}
if len(precise) > 0 {
// If the argument is optional, it's not guaranteed that there'd be a
// precise constructor.
meta = precise[r.Intn(len(precise))]
}
if meta == nil || r.oneOf(3) {
// Sometimes just take a random one.
meta = ctors[r.Intn(len(ctors))].Call
}
calls := r.generateParticularCall(s, meta)
s1 := newState(r.target, s.ct, nil)
s1.analyze(calls[len(calls)-1])
// Now see if we have what we want.
var allres []*ResultArg
for kind1, res1 := range s1.resources {
if r.target.isCompatibleResource(kind, kind1) {
allres = append(allres, res1...)
}
}
sort.SliceStable(allres, func(i, j int) bool {
return allres[i].Type().Name() < allres[j].Type().Name()
})
if len(allres) == 0 {
panic(fmt.Sprintf("failed to create a resource %v (%v) with %v",
res.Desc.Kind[0], kind, meta.Name))
}
arg := MakeResultArg(res, dir, allres[r.Intn(len(allres))], 0)
return arg, calls
}
func (r *randGen) enabledCtors(s *state, kind string) []ResourceCtor {
var ret []ResourceCtor
for _, info := range r.target.resourceCtors[kind] {
if s.ct.Generatable(info.Call.ID) {
ret = append(ret, info)
}
}
return ret
}
func (r *randGen) generateText(kind TextKind) []byte {
switch kind {
case TextTarget:
if cfg := createTargetIfuzzConfig(r.target); cfg != nil {
return ifuzz.Generate(cfg, r.Rand)
}
text := make([]byte, 50)
for i := range text {
text[i] = byte(r.Intn(256))
}
return text
default:
cfg := createIfuzzConfig(kind)
return ifuzz.Generate(cfg, r.Rand)
}
}
func (r *randGen) mutateText(kind TextKind, text []byte) []byte {
switch kind {
case TextTarget:
if cfg := createTargetIfuzzConfig(r.target); cfg != nil {
return ifuzz.Mutate(cfg, r.Rand, text)
}
return mutateData(r, text, 40, 60)
default:
cfg := createIfuzzConfig(kind)
return ifuzz.Mutate(cfg, r.Rand, text)
}
}
func createTargetIfuzzConfig(target *Target) *ifuzz.Config {
cfg := &ifuzz.Config{
Len: 10,
Priv: false,
Exec: true,
MemRegions: []ifuzz.MemRegion{
{Start: target.DataOffset, Size: target.NumPages * target.PageSize},
},
}
for _, p := range target.SpecialPointers {
cfg.MemRegions = append(cfg.MemRegions, ifuzz.MemRegion{
Start: p & ^target.PageSize, Size: p & ^target.PageSize + target.PageSize,
})
}
switch target.Arch {
case "amd64":
cfg.Mode = ifuzz.ModeLong64
cfg.Arch = ifuzz.ArchX86
case "386":
cfg.Mode = ifuzz.ModeProt32
cfg.Arch = ifuzz.ArchX86
case "ppc64":
cfg.Mode = ifuzz.ModeLong64
cfg.Arch = ifuzz.ArchPowerPC
case "arm64":
cfg.Mode = ifuzz.ModeLong64
cfg.Arch = ifuzz.ArchArm64
default:
return nil
}
return cfg
}
func createIfuzzConfig(kind TextKind) *ifuzz.Config {
cfg := &ifuzz.Config{
Len: 10,
Priv: true,
Exec: true,
MemRegions: []ifuzz.MemRegion{
{Start: 0 << 12, Size: 1 << 12},
{Start: 1 << 12, Size: 1 << 12},
{Start: 2 << 12, Size: 1 << 12},
{Start: 3 << 12, Size: 1 << 12},
{Start: 4 << 12, Size: 1 << 12},
{Start: 5 << 12, Size: 1 << 12},
{Start: 6 << 12, Size: 1 << 12},
{Start: 7 << 12, Size: 1 << 12},
{Start: 8 << 12, Size: 1 << 12},
{Start: 9 << 12, Size: 1 << 12},
{Start: 0xfec00000, Size: 0x100}, // ioapic
},
}
switch kind {
case TextX86Real:
cfg.Mode = ifuzz.ModeReal16
cfg.Arch = ifuzz.ArchX86
case TextX86bit16:
cfg.Mode = ifuzz.ModeProt16
cfg.Arch = ifuzz.ArchX86
case TextX86bit32:
cfg.Mode = ifuzz.ModeProt32
cfg.Arch = ifuzz.ArchX86
case TextX86bit64:
cfg.Mode = ifuzz.ModeLong64
cfg.Arch = ifuzz.ArchX86
case TextPpc64:
cfg.Mode = ifuzz.ModeLong64
cfg.Arch = ifuzz.ArchPowerPC
case TextArm64:
cfg.Mode = ifuzz.ModeLong64
cfg.Arch = ifuzz.ArchArm64
default:
panic(fmt.Sprintf("unknown text kind: %v", kind))
}
return cfg
}
// nOutOf returns true n out of outOf times.
func (r *randGen) nOutOf(n, outOf int) bool {
if n <= 0 || n >= outOf {
panic("bad probability")
}
v := r.Intn(outOf)
return v < n
}
func (r *randGen) generateCall(s *state, p *Prog, insertionPoint int) []*Call {
biasCall := -1
if insertionPoint > 0 {
// Choosing the base call is based on the insertion point of the new calls sequence.
insertionCall := p.Calls[r.Intn(insertionPoint)].Meta
if !insertionCall.Attrs.NoGenerate {
// We must be careful not to bias towards a non-generatable call.
biasCall = insertionCall.ID
}
}
idx := s.ct.choose(r.Rand, biasCall)
meta := r.target.Syscalls[idx]
return r.generateParticularCall(s, meta)
}
func (r *randGen) generateParticularCall(s *state, meta *Syscall) (calls []*Call) {
if meta.Attrs.Disabled {
panic(fmt.Sprintf("generating disabled call %v", meta.Name))
}
if meta.Attrs.NoGenerate {
panic(fmt.Sprintf("generating no_generate call: %v", meta.Name))
}
c := MakeCall(meta, nil)
c.Args, calls = r.generateArgs(s, meta.Args, DirIn)
moreCalls, _ := r.patchConditionalFields(c, s)
r.target.assignSizesCall(c)
return append(append(calls, moreCalls...), c)
}
// GenerateAllSyzProg generates a program that contains all pseudo syz_ calls for testing.
func (target *Target) GenerateAllSyzProg(rs rand.Source) *Prog {
p := &Prog{
Target: target,
}
r := newRand(target, rs)
s := newState(target, target.DefaultChoiceTable(), nil)
for _, meta := range target.PseudoSyscalls() {
calls := r.generateParticularCall(s, meta)
for _, c := range calls {
s.analyze(c)
p.Calls = append(p.Calls, c)
}
}
if err := p.validate(); err != nil {
panic(err)
}
return p
}
// PseudoSyscalls selects one *Syscall for each pseudosyscall.
func (target *Target) PseudoSyscalls() []*Syscall {
handled := make(map[string]bool)
var ret []*Syscall
for _, meta := range target.Syscalls {
if !strings.HasPrefix(meta.CallName, "syz_") ||
handled[meta.CallName] ||
meta.Attrs.Disabled ||
meta.Attrs.NoGenerate {
continue
}
ret = append(ret, meta)
handled[meta.CallName] = true
}
return ret
}
// GenSampleProg generates a single sample program for the call.
func (target *Target) GenSampleProg(meta *Syscall, rs rand.Source) *Prog {
r := newRand(target, rs)
s := newState(target, target.DefaultChoiceTable(), nil)
p := &Prog{
Target: target,
}
for _, c := range r.generateParticularCall(s, meta) {
s.analyze(c)
p.Calls = append(p.Calls, c)
}
if err := p.validate(); err != nil {
panic(err)
}
return p
}
// DataMmapProg creates program that maps data segment.
// Also used for testing as the simplest program.
func (target *Target) DataMmapProg() *Prog {
return &Prog{
Target: target,
Calls: target.MakeDataMmap(),
isUnsafe: true,
}
}
func (r *randGen) generateArgs(s *state, fields []Field, dir Dir) ([]Arg, []*Call) {
var calls []*Call
args := make([]Arg, len(fields))
// Generate all args. Size args have the default value 0 for now.
for i, field := range fields {
arg, calls1 := r.generateArg(s, field.Type, field.Dir(dir))
if arg == nil {
panic(fmt.Sprintf("generated arg is nil for field '%v', fields: %+v", field.Type.Name(), fields))
}
args[i] = arg
calls = append(calls, calls1...)
}
return args, calls
}
func (r *randGen) generateArg(s *state, typ Type, dir Dir) (arg Arg, calls []*Call) {
return r.generateArgImpl(s, typ, dir, false)
}
func (r *randGen) generateArgImpl(s *state, typ Type, dir Dir, ignoreSpecial bool) (arg Arg, calls []*Call) {
if dir == DirOut {
// No need to generate something interesting for output scalar arguments.
// But we still need to generate the argument itself so that it can be referenced
// in subsequent calls. For the same reason we do generate pointer/array/struct
// output arguments (their elements can be referenced in subsequent calls).
switch typ.(type) {
case *IntType, *FlagsType, *ConstType, *ProcType, *VmaType, *ResourceType:
return typ.DefaultArg(dir), nil
}
}
if typ.Optional() && r.oneOf(5) {
if res, ok := typ.(*ResourceType); ok {
v := res.Desc.Values[r.Intn(len(res.Desc.Values))]
return MakeResultArg(typ, dir, nil, v), nil
}
return typ.DefaultArg(dir), nil
}
if !ignoreSpecial && dir != DirOut {
switch typ.(type) {
case *StructType, *UnionType:
if gen := r.target.SpecialTypes[typ.Name()]; gen != nil {
return gen(&Gen{r, s}, typ, dir, nil)
}
}
}
return typ.generate(r, s, dir)
}
func (a *ResourceType) generate(r *randGen, s *state, dir Dir) (arg Arg, calls []*Call) {
canRecurse := false
if !r.inGenerateResource {
// Don't allow recursion for resourceCentric/createResource.
// That can lead to generation of huge programs and may be very slow
// (esp. if we are generating some failing attempts in createResource already).
r.inGenerateResource = true
defer func() { r.inGenerateResource = false }()
canRecurse = true
}
if canRecurse && r.nOutOf(8, 10) ||
!canRecurse && r.nOutOf(19, 20) {
arg = r.existingResource(s, a, dir)
if arg != nil {
return
}
}
if canRecurse {
if r.oneOf(4) {
arg, calls = r.resourceCentric(s, a, dir)
if arg != nil {
return
}
}
if r.nOutOf(4, 5) {
// If we could not reuse a resource, let's prefer resource creation over
// random int substitution.
arg, calls = r.createResource(s, a, dir)
if arg != nil {
return
}
}
}
special := a.SpecialValues()
arg = MakeResultArg(a, dir, nil, special[r.Intn(len(special))])
return
}
func (a *BufferType) generate(r *randGen, s *state, dir Dir) (arg Arg, calls []*Call) {
switch a.Kind {
case BufferBlobRand, BufferBlobRange:
sz := r.randBufLen()
if a.Kind == BufferBlobRange {
sz = r.randRange(a.RangeBegin, a.RangeEnd)
}
if dir == DirOut {
return MakeOutDataArg(a, dir, sz), nil
}
data := make([]byte, sz)
for i := range data {
data[i] = byte(r.Intn(256))
}
return MakeDataArg(a, dir, data), nil
case BufferString:
data := r.randString(s, a)
if dir == DirOut {
return MakeOutDataArg(a, dir, uint64(len(data))), nil
}
return MakeDataArg(a, dir, data), nil
case BufferFilename:
if dir == DirOut {
var sz uint64
switch {
case !a.Varlen():
sz = a.Size()
case r.nOutOf(1, 3):
sz = r.rand(100)
default:
sz = uint64(r.randFilenameLength())
}
return MakeOutDataArg(a, dir, sz), nil
}
return MakeDataArg(a, dir, []byte(r.filename(s, a))), nil
case BufferGlob:
return MakeDataArg(a, dir, r.randString(s, a)), nil
case BufferText:
if dir == DirOut {
return MakeOutDataArg(a, dir, uint64(r.Intn(100))), nil
}
return MakeDataArg(a, dir, r.generateText(a.Text)), nil
case BufferCompressed:
panic(fmt.Sprintf("can't generate compressed type %v", a))
default:
panic("unknown buffer kind")
}
}
func (a *VmaType) generate(r *randGen, s *state, dir Dir) (arg Arg, calls []*Call) {
npages := r.randPageCount()
if a.RangeBegin != 0 || a.RangeEnd != 0 {
npages = a.RangeBegin + uint64(r.Intn(int(a.RangeEnd-a.RangeBegin+1)))
}
return r.allocVMA(s, a, dir, npages), nil
}
func (a *FlagsType) generate(r *randGen, s *state, dir Dir) (arg Arg, calls []*Call) {
return MakeConstArg(a, dir, r.flags(a.Vals, a.BitMask, 0)), nil
}
func (a *ConstType) generate(r *randGen, s *state, dir Dir) (arg Arg, calls []*Call) {
return MakeConstArg(a, dir, a.Val), nil
}
func (a *IntType) generate(r *randGen, s *state, dir Dir) (arg Arg, calls []*Call) {
bits := a.TypeBitSize()
v := r.randInt(bits)
switch a.Kind {
case IntRange:
v = r.randRangeInt(a.RangeBegin, a.RangeEnd, bits, a.Align)
}
return MakeConstArg(a, dir, v), nil
}
func (a *ProcType) generate(r *randGen, s *state, dir Dir) (arg Arg, calls []*Call) {
return MakeConstArg(a, dir, r.rand(int(a.ValuesPerProc))), nil
}
func (a *ArrayType) generate(r *randGen, s *state, dir Dir) (arg Arg, calls []*Call) {
// Allow infinite recursion for arrays.
switch a.Elem.(type) {
case *StructType, *ArrayType, *UnionType:
ok, release := r.pruneRecursion(a.Elem.Name())
if !ok {
return MakeGroupArg(a, dir, nil), nil
}
defer release()
}
var count uint64
switch a.Kind {
case ArrayRandLen:
count = r.randArrayLen()
case ArrayRangeLen:
count = r.randRange(a.RangeBegin, a.RangeEnd)
}
// The resource we are trying to generate may be in the array elements, so create at least 1.
if r.inGenerateResource && count == 0 {
count = 1
}
var inner []Arg
for i := uint64(0); i < count; i++ {
arg1, calls1 := r.generateArg(s, a.Elem, dir)
inner = append(inner, arg1)
calls = append(calls, calls1...)
}
return MakeGroupArg(a, dir, inner), calls
}
func (a *StructType) generate(r *randGen, s *state, dir Dir) (arg Arg, calls []*Call) {
args, calls := r.generateArgs(s, a.Fields, dir)
group := MakeGroupArg(a, dir, args)
return group, calls
}
func (a *UnionType) generate(r *randGen, s *state, dir Dir) (arg Arg, calls []*Call) {
if a.isConditional() {
// Conditions may reference other fields that may not have already
// been generated. We'll fill them in later.
return a.DefaultArg(dir), nil
}
index := r.Intn(len(a.Fields))
optType, optDir := a.Fields[index].Type, a.Fields[index].Dir(dir)
opt, calls := r.generateArg(s, optType, optDir)
return MakeUnionArg(a, dir, opt, index), calls
}
func (a *PtrType) generate(r *randGen, s *state, dir Dir) (arg Arg, calls []*Call) {
// Allow infinite recursion for optional pointers.
if a.Optional() {
switch a.Elem.(type) {
case *StructType, *ArrayType, *UnionType:
ok, release := r.pruneRecursion(a.Elem.Name())
if !ok {
return MakeSpecialPointerArg(a, dir, 0), nil
}
defer release()
}
}
// The resource we are trying to generate may be in the pointer,
// so don't try to create an empty special pointer during resource generation.
if !r.inGenerateResource && r.oneOf(1000) {
index := r.rand(len(r.target.SpecialPointers))
return MakeSpecialPointerArg(a, dir, index), nil
}
inner, calls := r.generateArg(s, a.Elem, a.ElemDir)
arg = r.allocAddr(s, a, dir, inner.Size(), inner)
return arg, calls
}
func (a *LenType) generate(r *randGen, s *state, dir Dir) (arg Arg, calls []*Call) {
// Updated later in assignSizesCall.
return MakeConstArg(a, dir, 0), nil
}
func (a *CsumType) generate(r *randGen, s *state, dir Dir) (arg Arg, calls []*Call) {
// Filled at runtime by executor.
return MakeConstArg(a, dir, 0), nil
}
func (r *randGen) existingResource(s *state, res *ResourceType, dir Dir) Arg {
alltypes := make([][]*ResultArg, 0, len(s.resources))
for _, res1 := range s.resources {
alltypes = append(alltypes, res1)
}
sort.Slice(alltypes, func(i, j int) bool {
return alltypes[i][0].Type().Name() < alltypes[j][0].Type().Name()
})
var allres []*ResultArg
for _, res1 := range alltypes {
name1 := res1[0].Type().Name()
if r.target.isCompatibleResource(res.Desc.Name, name1) ||
r.oneOf(50) && r.target.isCompatibleResource(res.Desc.Kind[0], name1) {
allres = append(allres, res1...)
}
}
if len(allres) == 0 {
return nil
}
return MakeResultArg(res, dir, allres[r.Intn(len(allres))], 0)
}
// Finds a compatible resource with the type `t` and the calls that initialize that resource.
func (r *randGen) resourceCentric(s *state, t *ResourceType, dir Dir) (arg Arg, calls []*Call) {
var p *Prog
var resource *ResultArg
for _, idx := range r.Perm(len(s.corpus)) {
corpusProg := s.corpus[idx]
resources := getCompatibleResources(corpusProg, t.TypeName, r)
if len(resources) == 0 {
continue
}
argMap := make(map[*ResultArg]*ResultArg)
p = corpusProg.cloneWithMap(argMap)
resource = argMap[resources[r.Intn(len(resources))]]
break
}
// No compatible resource was found.
if resource == nil {
return nil, nil
}
// Set that stores the resources that appear in the same calls with the selected resource.
relatedRes := map[*ResultArg]bool{resource: true}
// Remove unrelated calls from the program.
for idx := len(p.Calls) - 1; idx >= 0; idx-- {
includeCall := false
var newResources []*ResultArg
ForeachArg(p.Calls[idx], func(arg Arg, _ *ArgCtx) {
if a, ok := arg.(*ResultArg); ok {
if a.Res != nil && !relatedRes[a.Res] {
newResources = append(newResources, a.Res)
}
if relatedRes[a] || relatedRes[a.Res] {
includeCall = true
}
}
})
if !includeCall {
p.RemoveCall(idx)
} else {
for _, res := range newResources {
relatedRes[res] = true
}
}
}
// Selects a biased random length of the returned calls (more calls could offer more
// interesting programs). The values returned (n = len(calls): n, n-1, ..., 2.
biasedLen := 2 + r.biasedRand(len(calls)-1, 10)
// Removes the references that are not used anymore.
for i := biasedLen; i < len(calls); i++ {
p.RemoveCall(i)
}
return MakeResultArg(t, dir, resource, 0), p.Calls
}
func getCompatibleResources(p *Prog, resourceType string, r *randGen) (resources []*ResultArg) {
for _, c := range p.Calls {
ForeachArg(c, func(arg Arg, _ *ArgCtx) {
// Collect only initialized resources (the ones that are already used in other calls).
a, ok := arg.(*ResultArg)
if !ok || len(a.uses) == 0 || a.Dir() != DirOut {
return
}
if !r.target.isCompatibleResource(resourceType, a.Type().Name()) {
return
}
resources = append(resources, a)
})
}
return resources
}
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package prog
import (
"fmt"
)
var (
// We need to support structs as resources,
// but for now we just special-case timespec/timeval.
timespecRes = &ResourceDesc{
Name: "timespec",
Kind: []string{"timespec"},
}
// On one hand these are resources, but they don't have constructors.
// It can make sense to provide generic support for such things,
// but for now we just special-case them.
filenameRes = &ResourceDesc{
Name: "filename",
Kind: []string{"filename"},
}
vmaRes = &ResourceDesc{
Name: "vma",
Kind: []string{"vma"},
}
)
func (target *Target) calcResourceCtors(res *ResourceDesc, preciseOnly bool) []ResourceCtor {
var ret []ResourceCtor
for _, ctor := range res.Ctors {
if !preciseOnly || ctor.Precise {
ret = append(ret, ctor)
}
}
if res.Kind[0] == timespecRes.Name {
if c := target.SyscallMap["clock_gettime"]; c != nil {
ret = append(ret, ResourceCtor{c, true})
}
}
return ret
}
func (target *Target) populateResourceCtors() {
// Find resources that are created by each call.
callsResources := make([][]*ResourceDesc, len(target.Syscalls))
for _, meta := range target.Syscalls {
dedup := make(map[*ResourceDesc]bool)
ForeachCallType(meta, func(typ Type, ctx *TypeCtx) {
if typ.Optional() {
ctx.Stop = true
return
}
switch typ1 := typ.(type) {
case *UnionType:
ctx.Stop = true
case *ResourceType:
if ctx.Dir == DirIn || dedup[typ1.Desc] || meta.Attrs.Disabled {
break
}
dedup[typ1.Desc] = true
meta.usesResources = append(meta.usesResources, typ1.Desc)
if !meta.Attrs.NoGenerate {
callsResources[meta.ID] = append(callsResources[meta.ID], typ1.Desc)
meta.createsResources = append(meta.createsResources, typ1.Desc)
}
}
})
}
if c := target.SyscallMap["clock_gettime"]; c != nil {
c.usesResources = append(c.usesResources, timespecRes)
c.createsResources = append(c.createsResources, timespecRes)
callsResources[c.ID] = append(callsResources[c.ID], timespecRes)
}
for _, c := range target.Syscalls {
c.inputResources = target.getInputResources(c)
c.usesResources = append(c.usesResources, c.inputResources...)
}
// Populate resource ctors accounting for resource compatibility.
for _, res := range target.Resources {
for call, callResources := range callsResources {
preciseOk := false
impreciseOk := false
for _, callRes := range callResources {
if preciseOk && impreciseOk {
break
}
if isCompatibleResourceImpl(res.Kind, callRes.Kind, true) {
preciseOk = true
}
if isCompatibleResourceImpl(res.Kind, callRes.Kind, false) {
impreciseOk = true
}
}
if preciseOk {
res.Ctors = append(res.Ctors, ResourceCtor{target.Syscalls[call], true})
}
if impreciseOk {
res.Ctors = append(res.Ctors, ResourceCtor{target.Syscalls[call], false})
}
}
}
}
// isCompatibleResource returns true if resource of kind src can be passed as an argument of kind dst.
func (target *Target) isCompatibleResource(dst, src string) bool {
if target.isAnyRes(dst) {
return true
}
if target.isAnyRes(src) {
return false
}
dstRes := target.resourceMap[dst]
if dstRes == nil {
panic(fmt.Sprintf("unknown resource %q", dst))
}
srcRes := target.resourceMap[src]
if srcRes == nil {
panic(fmt.Sprintf("unknown resource %q", src))
}
return isCompatibleResourceImpl(dstRes.Kind, srcRes.Kind, false)
}
// isCompatibleResourceImpl returns true if resource of kind src can be passed as an argument of kind dst.
// If precise is true, then it does not allow passing a less specialized resource (e.g. fd)
// as a more specialized resource (e.g. socket). Otherwise it does.
func isCompatibleResourceImpl(dst, src []string, precise bool) bool {
if len(dst) > len(src) {
// Destination resource is more specialized, e.g dst=socket, src=fd.
if precise {
return false
}
dst = dst[:len(src)]
}
if len(src) > len(dst) {
// Source resource is more specialized, e.g dst=fd, src=socket.
src = src[:len(dst)]
}
for i, k := range dst {
if k != src[i] {
return false
}
}
return true
}
func (target *Target) getInputResources(c *Syscall) []*ResourceDesc {
dedup := make(map[*ResourceDesc]bool)
var resources []*ResourceDesc
ForeachCallType(c, func(typ Type, ctx *TypeCtx) {
if ctx.Dir == DirOut {
return
}
switch typ1 := typ.(type) {
case *ResourceType:
if !ctx.Optional && !dedup[typ1.Desc] {
dedup[typ1.Desc] = true
resources = append(resources, typ1.Desc)
}
case *StructType:
if target.OS == "linux" && !dedup[timespecRes] && (typ1.Name() == "timespec" || typ1.Name() == "timeval") {
dedup[timespecRes] = true
resources = append(resources, timespecRes)
}
}
})
return resources
}
func (target *Target) transitivelyEnabled(enabled map[*Syscall]bool) (map[*Syscall]bool, map[string]bool) {
supported := make(map[*Syscall]bool, len(enabled))
canCreate := make(map[string]bool, len(enabled))
for {
n := len(supported)
nextCall:
for c := range enabled {
if supported[c] {
continue
}
for _, res := range c.inputResources {
if !canCreate[res.Name] {
continue nextCall
}
}
supported[c] = true
for _, res := range c.createsResources {
for _, kind := range res.Kind {
canCreate[kind] = true
}
}
}
if n == len(supported) {
break
}
}
return supported, canCreate
}
func (target *Target) TransitivelyEnabledCalls(enabled map[*Syscall]bool) (map[*Syscall]bool, map[*Syscall]string) {
supported, canCreate := target.transitivelyEnabled(enabled)
disabled := make(map[*Syscall]string)
ctors := make(map[string][]string)
for c := range enabled {
if supported[c] {
continue
}
for _, res := range c.inputResources {
if canCreate[res.Name] {
continue
}
if ctors[res.Name] == nil {
var names []string
for _, ctor := range target.calcResourceCtors(res, true) {
names = append(names, ctor.Call.Name)
}
if len(names) > 5 {
names = append(names[:3], "...")
}
ctors[res.Name] = names
}
disabled[c] = fmt.Sprintf("%v %v", res.Name, ctors[res.Name])
break
}
}
if len(enabled) != len(supported)+len(disabled) {
panic("lost syscalls")
}
return supported, disabled
}
// Copyright 2019 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package prog
import (
"math/rand"
"sort"
)
// Rotator selects a random subset of syscalls for corpus rotation.
type Rotator struct {
target *Target
calls map[*Syscall]bool
rnd *rand.Rand
resourceless []*Syscall
resources map[*ResourceDesc]rotatorResource
goal int
nresourceless int
}
type rotatorResource struct {
// 0 - precise ctors that don't require other resources as inputs (e.g. socket).
// 1 - precise ctors that require other resources (e.g. accept).
// 2 - all imprecise ctors.
ctors [3][]*Syscall
// 0 - precise uses of this resource.
// 1 - uses of parent resources (e.g. close for sock).
uses [2][]*Syscall
}
func MakeRotator(target *Target, calls map[*Syscall]bool, rnd *rand.Rand) *Rotator {
r := &Rotator{
target: target,
calls: calls,
rnd: rnd,
resources: make(map[*ResourceDesc]rotatorResource),
}
var sorted []*Syscall
for call := range calls {
sorted = append(sorted, call)
}
sort.Slice(sorted, func(i, j int) bool {
return sorted[i].Name < sorted[j].Name
})
for _, call := range sorted {
var inputs []*ResourceDesc
for _, res := range call.inputResources {
// Don't take into account pid/uid/etc, they create too many links.
if !target.AuxResources[res.Name] {
inputs = append(inputs, res)
}
}
// VMAs and filenames are effectively resources for our purposes
// (but they don't have ctors).
ForeachCallType(call, func(t Type, _ *TypeCtx) {
switch a := t.(type) {
case *BufferType:
switch a.Kind {
case BufferFilename:
inputs = append(inputs, filenameRes)
}
case *VmaType:
inputs = append(inputs, vmaRes)
}
})
inputDedup := make(map[string]bool, len(inputs))
for _, res := range inputs {
if inputDedup[res.Name] {
continue
}
inputDedup[res.Name] = true
info := r.resources[res]
info.uses[0] = append(info.uses[0], call)
r.resources[res] = info
for _, kind := range res.Kind[:len(res.Kind)-1] {
parent := target.resourceMap[kind]
info := r.resources[parent]
info.uses[1] = append(info.uses[1], call)
r.resources[parent] = info
}
}
outputDedup := make(map[string]bool, len(call.createsResources))
for _, res := range call.createsResources {
if outputDedup[res.Name] {
continue
}
outputDedup[res.Name] = true
info := r.resources[res]
class := 0
if len(inputs) != 0 {
class = 1
}
info.ctors[class] = append(info.ctors[class], call)
r.resources[res] = info
for _, kind := range res.Kind[:len(res.Kind)-1] {
parent := target.resourceMap[kind]
info := r.resources[parent]
info.ctors[2] = append(info.ctors[2], call)
r.resources[parent] = info
}
}
if len(inputs)+len(call.createsResources) == 0 {
r.resourceless = append(r.resourceless, call)
}
}
// For smaller syscall sets we drop ~5% of syscalls.
// However, we assume that 200 syscalls is enough for a fuzzing session,
// so we cap at that level to make fuzzing more targeted.
r.goal = len(calls) * 19 / 20
r.goal = max(r.goal, 1)
r.goal = min(r.goal, 200)
// How many syscalls that don't use any resources we want to add?
r.nresourceless = max(1, r.goal*len(r.resourceless)/len(calls))
return r
}
func (r *Rotator) Select() map[*Syscall]bool {
rs := rotatorState{
Rotator: r,
calls: make(map[*Syscall]bool, 3*r.goal),
}
return rs.Select()
}
type rotatorState struct {
*Rotator
calls map[*Syscall]bool
topQueue []*ResourceDesc
depQueue []*ResourceDesc
topHandled map[*ResourceDesc]bool
depHandled map[*ResourceDesc]bool
}
func (rs *rotatorState) Select() map[*Syscall]bool {
// The algorithm is centered around resources.
// But first we add some syscalls that don't use any resources at all
// Otherwise we will never add them in the loop.
// Then, we select a resource and add some ctors for this resources
// and some calls that use it. That's handled by topQueue.
// If any of the calls require other resources as inputs, we also add
// some ctors for these resources, but don't add calls that use them.
// That's handled by depQueue.
// However, a resource can be handled as dependency first, but then
// handled as top resource again. In such case we will still add calls
// that use this resource.
if len(rs.resources) == 0 {
return rs.Rotator.calls
}
for {
if len(rs.depQueue) == 0 && len(rs.calls) >= rs.goal || len(rs.calls) >= 2*rs.goal {
rs.calls, _ = rs.target.transitivelyEnabled(rs.calls)
if len(rs.calls) >= rs.goal {
return rs.calls
}
}
if len(rs.depQueue) != 0 {
// Handle a dependent resource, add only ctors for these.
// Pick a random one, this gives a mix of DFS and BFS.
idx := rs.rnd.Intn(len(rs.depQueue))
res := rs.depQueue[idx]
rs.depQueue[idx] = rs.depQueue[len(rs.depQueue)-1]
rs.depQueue = rs.depQueue[:len(rs.depQueue)-1]
info := rs.resources[res]
nctors0 := len(info.ctors[0]) != 0
nctors1 := nctors0 || len(info.ctors[1]) != 0
rs.selectCalls(info.ctors[0], 2, true)
if nctors0 {
continue
}
rs.selectCalls(info.ctors[1], 2, true)
if nctors1 {
continue
}
rs.selectCalls(info.ctors[2], 2, true)
continue
}
if len(rs.topQueue) == 0 {
// We either just started selection or we handled all resources,
// but did not gather enough syscalls. In both cases we need
// to reset all queues.
rs.topQueue = make([]*ResourceDesc, 0, len(rs.resources))
rs.depQueue = make([]*ResourceDesc, 0, len(rs.resources))
rs.topHandled = make(map[*ResourceDesc]bool, len(rs.resources))
rs.depHandled = make(map[*ResourceDesc]bool, len(rs.resources))
for res := range rs.resources {
rs.topQueue = append(rs.topQueue, res)
}
sort.Slice(rs.topQueue, func(i, j int) bool {
return rs.topQueue[i].Name < rs.topQueue[j].Name
})
rs.rnd.Shuffle(len(rs.topQueue), func(i, j int) {
rs.topQueue[i], rs.topQueue[j] = rs.topQueue[j], rs.topQueue[i]
})
rs.selectCalls(rs.resourceless, rs.nresourceless+1, false)
}
// Handle a top resource, add more syscalls for these.
res := rs.topQueue[0]
rs.topQueue = rs.topQueue[1:]
if rs.topHandled[res] {
panic("top queue already handled")
}
rs.topHandled[res] = true
info := rs.resources[res]
nctors0 := len(info.ctors[0]) != 0
nctors1 := nctors0 || len(info.ctors[1]) != 0
rs.selectCalls(info.ctors[0], 5, true)
rs.selectCalls(info.ctors[1], 3, !nctors0)
rs.selectCalls(info.ctors[2], 2, !nctors1)
rs.selectCalls(info.uses[0], 20, true)
rs.selectCalls(info.uses[1], 2, len(info.uses[0]) == 0)
}
}
func (rs *rotatorState) addCall(call *Syscall) {
if rs.calls[call] {
return
}
rs.calls[call] = true
for _, res := range call.usesResources {
if rs.topHandled[res] || rs.depHandled[res] {
continue
}
rs.depHandled[res] = true
rs.depQueue = append(rs.depQueue, res)
}
}
func (rs *rotatorState) selectCalls(set []*Syscall, probability int, force bool) {
if !force && probability < 2 {
panic("will never select anything")
}
for ; len(set) != 0 && (force || rs.rnd.Intn(probability) != 0); force = false {
call := set[rs.rnd.Intn(len(set))]
rs.addCall(call)
}
}
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package prog
import (
"fmt"
)
const (
// Special reference to the outer struct used in len targets.
ParentRef = "parent"
// Special reference directly to syscall arguments used in len targets.
SyscallRef = "syscall"
)
func (target *Target) assignSizes(args []Arg, fields []Field, parents parentStack,
syscallArgs []Arg, syscallFields []Field, autos map[Arg]bool, overlayField int) {
for _, arg := range args {
target.assignArgSize(arg, args, fields, parents, syscallArgs,
syscallFields, autos, overlayField)
}
}
// nolint:revive
func (target *Target) assignArgSize(arg Arg, args []Arg, fields []Field, parents parentStack,
syscallArgs []Arg, syscallFields []Field, autos map[Arg]bool, overlayField int) {
if arg = InnerArg(arg); arg == nil {
return // Pointer to optional len field, no need to fill in value.
}
typ, ok := arg.Type().(*LenType)
if !ok {
return
}
if autos != nil {
if !autos[arg] {
return
}
delete(autos, arg)
}
a := arg.(*ConstArg)
if typ.Path[0] == SyscallRef {
target.assignSize(a, nil, typ.Path[1:], syscallArgs, syscallFields, parents, 0)
} else {
target.assignSize(a, a, typ.Path, args, fields, parents, overlayField)
}
}
func (target *Target) assignSize(dst *ConstArg, pos Arg, path []string, args []Arg,
fields []Field, parents parentStack, overlayField int) {
found := target.findArg(pos, path, args, fields, parents, overlayField)
if found != nil && !found.isAnyPtr {
dst.Val = target.computeSize(found.arg, found.offset, dst.Type().(*LenType))
}
}
type foundArg struct {
arg Arg
offset uint64
isAnyPtr bool
}
func (target *Target) findFieldStruct(buf Arg, path []string, parents parentStack) *foundArg {
switch arg := buf.(type) {
case *GroupArg:
typ := arg.Type().(*StructType)
return target.findArg(buf, path, arg.Inner, typ.Fields, parents, typ.OverlayField)
case *UnionArg:
return target.findArg(buf, path, nil, nil, parents, 0)
default:
panic(fmt.Sprintf("unexpected arg type %#v", arg))
}
}
func (target *Target) findArg(pos Arg, path []string, args []Arg, fields []Field,
parents parentStack, overlayField int) *foundArg {
elem := path[0]
path = path[1:]
var offset uint64
for i, buf := range args {
if i == overlayField {
offset = 0
}
if buf == nil {
continue
}
if elem != fields[i].Name {
offset += buf.Size()
continue
}
if typ := buf.Type(); typ == target.any.ptrPtr || typ == target.any.ptr64 {
// If path points into squashed argument, we don't have the target argument.
// In such case we simply leave size argument as is. It can't happen during generation,
// only during mutation and mutation can set size to random values, so it should be fine.
return &foundArg{buf, offset, true}
}
buf = InnerArg(buf)
if buf == nil {
return &foundArg{nil, offset, false}
}
if len(path) != 0 {
return target.findFieldStruct(buf, path, parents)
}
return &foundArg{buf, offset, false}
}
if elem == ParentRef {
parents, buf := popStack(parents)
if len(path) != 0 {
return target.findFieldStruct(buf, path, parents)
}
return &foundArg{buf, noOffset, false}
}
for parents, buf := popStack(parents); buf != nil; parents, buf = popStack(parents) {
if elem != buf.Type().TemplateName() {
continue
}
if len(path) != 0 {
return target.findFieldStruct(buf, path, parents)
}
return &foundArg{buf, noOffset, false}
}
var fieldNames []string
for _, field := range fields {
fieldNames = append(fieldNames, field.Name)
}
posName := "nil"
if pos != nil {
posName = pos.Type().Name()
}
panic(fmt.Sprintf("path references non existent field %q, pos=%q, argsMap: %v, path: %v",
elem, posName, fieldNames, path))
}
const noOffset = ^uint64(0)
func (target *Target) computeSize(arg Arg, offset uint64, lenType *LenType) uint64 {
if lenType.Offset {
if offset == noOffset {
panic("offset of a non-field")
}
return offset * 8 / lenType.BitSize
}
if arg == nil {
// For e.g. optional pointers.
return 0
}
bitSize := lenType.BitSize
if bitSize == 0 {
bitSize = 8
}
switch arg.Type().(type) {
case *VmaType:
a := arg.(*PointerArg)
return a.VmaSize * 8 / bitSize
case *ArrayType:
a := arg.(*GroupArg)
if lenType.BitSize != 0 {
return a.Size() * 8 / bitSize
}
return uint64(len(a.Inner))
default:
return arg.Size() * 8 / bitSize
}
}
func (target *Target) assignSizesArray(args []Arg, fields []Field, autos map[Arg]bool) {
target.assignSizes(args, fields, nil, args, fields, autos, 0)
for _, arg := range args {
foreachSubArgWithStack(arg, func(arg Arg, ctx *ArgCtx) {
if typ, ok := arg.Type().(*StructType); ok {
target.assignSizes(arg.(*GroupArg).Inner, typ.Fields, ctx.parentStack, args, fields, autos, typ.OverlayField)
}
if v, ok := arg.(*UnionArg); ok {
target.assignArgSize(v.Option, nil, nil, ctx.parentStack, args, fields, autos, 0)
}
})
}
}
func (target *Target) assignSizesCall(c *Call) {
target.assignSizesArray(c.Args, c.Meta.Args, nil)
}
func (r *randGen) mutateSize(arg *ConstArg, parent []Arg, fields []Field) bool {
typ := arg.Type().(*LenType)
elemSize := typ.BitSize / 8
if elemSize == 0 {
elemSize = 1
// TODO(dvyukov): implement path support for size mutation.
if len(typ.Path) == 1 {
for i, field := range parent {
if typ.Path[0] != fields[i].Name {
continue
}
if inner := InnerArg(field); inner != nil {
switch targetType := inner.Type().(type) {
case *VmaType:
return false
case *BufferType:
// Don't mutate size of compressed images.
// If we do, then our code will fail/crash on decompression.
if targetType.Kind == BufferCompressed {
return false
}
case *ArrayType:
if targetType.Elem.Varlen() {
return false
}
elemSize = targetType.Elem.Size()
}
}
break
}
}
}
if r.oneOf(100) {
arg.Val = r.rand64()
return true
}
if r.bin() {
// Small adjustment to trigger missed size checks.
if arg.Val != 0 && r.bin() {
arg.Val = r.randRangeInt(0, arg.Val-1, arg.Type().TypeBitSize(), 0)
} else {
arg.Val = r.randRangeInt(arg.Val+1, arg.Val+100, arg.Type().TypeBitSize(), 0)
}
return true
}
// Try to provoke int overflows.
max := ^uint64(0)
if r.oneOf(3) {
max = 1<<32 - 1
if r.oneOf(2) {
max = 1<<16 - 1
if r.oneOf(2) {
max = 1<<8 - 1
}
}
}
n := max / elemSize
delta := uint64(1000 - r.biasedRand(1000, 10))
if elemSize == 1 || r.oneOf(10) {
n -= delta
} else {
n += delta
}
arg.Val = n
return true
}
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package prog
import (
"fmt"
"math/rand"
"slices"
"sort"
"strings"
"sync"
"sync/atomic"
"github.com/google/syzkaller/pkg/hash"
)
// Target describes target OS/arch pair.
type Target struct {
OS string
Arch string
Revision string // unique hash representing revision of the descriptions
PtrSize uint64
PageSize uint64
NumPages uint64
DataOffset uint64
BigEndian bool
Syscalls []*Syscall
Resources []*ResourceDesc
Consts []ConstValue
Flags []FlagDesc
Types []Type
// MakeDataMmap creates calls that mmaps target data memory range.
MakeDataMmap func() []*Call
// Neutralize neutralizes harmful calls by transforming them into non-harmful ones
// (e.g. an ioctl that turns off console output is turned into ioctl that turns on output).
// fixStructure determines whether it's allowed to make structural changes (e.g. add or
// remove arguments). It is helpful e.g. when we do neutralization while iterating over the
// arguments.
Neutralize func(c *Call, fixStructure bool) error
// AnnotateCall annotates a syscall invocation in C reproducers.
// The returned string will be placed inside a comment except for the
// empty string which will omit the comment.
AnnotateCall func(c ExecCall) string
// SpecialTypes allows target to do custom generation/mutation for some struct's and union's.
// Map key is struct/union name for which custom generation/mutation is required.
// Map value is custom generation/mutation function that will be called
// for the corresponding type. g is helper object that allows generate random numbers,
// allocate memory, etc. typ is the struct/union type. old is the old value of the struct/union
// for mutation, or nil for generation. The function returns a new value of the struct/union,
// and optionally any calls that need to be inserted before the arg reference.
SpecialTypes map[string]func(g *Gen, typ Type, dir Dir, old Arg) (Arg, []*Call)
// Resources that play auxiliary role, but widely used throughout all syscalls (e.g. pid/uid).
AuxResources map[string]bool
// Additional special invalid pointer values besides NULL to use.
SpecialPointers []uint64
// Special file name length that can provoke bugs (e.g. PATH_MAX).
SpecialFileLenghts []int
// Filled by prog package:
SyscallMap map[string]*Syscall
ConstMap map[string]uint64
FlagsMap map[string][]string
init sync.Once
fillArch func(target *Target)
initArch func(target *Target)
resourceMap map[string]*ResourceDesc
// Maps resource name to a list of calls that can create the resource.
resourceCtors map[string][]ResourceCtor
any anyTypes
// The default ChoiceTable is used only by tests and utilities, so we initialize it lazily.
defaultOnce sync.Once
defaultChoiceTable *ChoiceTable
}
const maxSpecialPointers = 16
var targets = make(map[string]*Target)
func RegisterTarget(target *Target, fill, init func(target *Target)) {
key := target.OS + "/" + target.Arch
if targets[key] != nil {
panic(fmt.Sprintf("duplicate target %v", key))
}
target.fillArch = fill
target.initArch = init
targets[key] = target
}
func GetTarget(OS, arch string) (*Target, error) {
key := OS + "/" + arch
target := targets[key]
if target == nil {
var supported []string
for _, t := range targets {
supported = append(supported, fmt.Sprintf("%v/%v", t.OS, t.Arch))
}
sort.Strings(supported)
return nil, fmt.Errorf("unknown target: %v (supported: %v)", key, supported)
}
target.init.Do(target.lazyInit)
return target, nil
}
func AllTargets() []*Target {
var res []*Target
for _, target := range targets {
target.init.Do(target.lazyInit)
res = append(res, target)
}
sort.Slice(res, func(i, j int) bool {
if res[i].OS != res[j].OS {
return res[i].OS < res[j].OS
}
return res[i].Arch < res[j].Arch
})
return res
}
func (target *Target) lazyInit() {
target.Neutralize = func(c *Call, fixStructure bool) error { return nil }
target.AnnotateCall = func(c ExecCall) string { return "" }
target.fillArch(target)
target.initTarget()
target.initUselessHints()
target.initRelatedFields()
target.initArch(target)
// Give these 2 known addresses fixed positions and prepend target-specific ones at the end.
target.SpecialPointers = append([]uint64{
0x0000000000000000, // NULL pointer (keep this first because code uses special index=0 as NULL)
0xffffffffffffffff, // unmapped kernel address (keep second because serialized value will match actual pointer value)
0x9999999999999999, // non-canonical address
}, target.SpecialPointers...)
if len(target.SpecialPointers) > maxSpecialPointers {
panic("too many special pointers")
}
if len(target.SpecialFileLenghts) == 0 {
// Just some common lengths that can be used as PATH_MAX/MAX_NAME.
target.SpecialFileLenghts = []int{256, 512, 4096}
}
for _, ln := range target.SpecialFileLenghts {
if ln <= 0 || ln >= memAllocMaxMem {
panic(fmt.Sprintf("bad special file length %v", ln))
}
}
// These are used only during lazyInit.
target.Types = nil
}
func (target *Target) initTarget() {
checkMaxCallID(len(target.Syscalls) - 1)
target.ConstMap = make(map[string]uint64)
for _, c := range target.Consts {
target.ConstMap[c.Name] = c.Value
}
target.resourceMap = restoreLinks(target.Syscalls, target.Resources, target.Types)
target.initAnyTypes()
target.SyscallMap = make(map[string]*Syscall)
for i, c := range target.Syscalls {
c.ID = i
target.SyscallMap[c.Name] = c
}
target.FlagsMap = make(map[string][]string)
for _, c := range target.Flags {
target.FlagsMap[c.Name] = c.Values
}
target.populateResourceCtors()
target.resourceCtors = make(map[string][]ResourceCtor)
for _, res := range target.Resources {
target.resourceCtors[res.Name] = target.calcResourceCtors(res, false)
}
}
func (target *Target) initUselessHints() {
// Pre-compute useless hints for each type and deduplicate resulting maps
// (there will be lots of duplicates).
computed := make(map[Type]bool)
dedup := make(map[string]map[uint64]struct{})
ForeachType(target.Syscalls, func(t Type, ctx *TypeCtx) {
hinter, ok := t.(uselessHinter)
if !ok || computed[t] {
return
}
computed[t] = true
hints := hinter.calcUselessHints()
if len(hints) == 0 {
return
}
slices.Sort(hints)
hints = slices.Compact(hints)
sig := hash.String(hints)
m := dedup[sig]
if m == nil {
m = make(map[uint64]struct{})
for _, v := range hints {
m[v] = struct{}{}
}
dedup[sig] = m
}
hinter.setUselessHints(m)
})
}
func (target *Target) initRelatedFields() {
// Compute sets of related fields that are used to reduce amount of produced hint replacements.
// Related fields are sets of arguments to the same syscall, in the same position, that operate
// on the same resource. The best example of related fields is a set of ioctl commands on the same fd:
//
// ioctl$FOO1(fd fd_foo, cmd const[FOO1], ...)
// ioctl$FOO2(fd fd_foo, cmd const[FOO2], ...)
// ioctl$FOO3(fd fd_foo, cmd const[FOO3], ...)
//
// All cmd args related and we should not try to replace them with each other
// (e.g. try to morph ioctl$FOO1 into ioctl$FOO2). This is both unnecessary, leads to confusing reproducers,
// and in some cases to badly confused argument types, see e.g.:
// https://github.com/google/syzkaller/issues/502
// https://github.com/google/syzkaller/issues/4939
//
// However, notion of related fields is wider and includes e.g. socket syscall family/type/proto,
// setsockopt consts, and in some cases even openat flags/mode.
//
// Related fields can include const, flags and int types.
//
// Notion of "same resource" is also quite generic b/c syscalls can accept several resource types,
// and filenames/strings are also considered as a resource in this context. For example, openat syscalls
// that operate on the same file are related, but are not related to openat calls that operate on other files.
groups := make(map[string]map[Type]struct{})
for _, call := range target.Syscalls {
// Id is used to identify related syscalls.
// We first collect all resources/strings/files. This needs to be done first b/c e.g. mmap has
// fd resource at the end, so we need to do this before the next loop.
id := call.CallName
for i, field := range call.Args {
switch arg := field.Type.(type) {
case *ResourceType:
id += fmt.Sprintf("-%v:%v", i, arg.Name())
case *PtrType:
if typ, ok := arg.Elem.(*BufferType); ok && typ.Kind == BufferString && len(typ.Values) == 1 {
id += fmt.Sprintf("-%v:%v", i, typ.Values[0])
}
}
}
// Now we group const/flags args together.
// But also if we see a const, we update id to include it. This is required for e.g.
// socket/socketpair/setsockopt calls. For these calls all families can be groups, but types should be
// grouped only for the same family, and protocols should be grouped only for the same family+type.
// We assume the "more important" discriminating arguments come first (this is not necessary true,
// but seems to be the case in real syscalls as it's unreasonable to pass less important things first).
for i, field := range call.Args {
switch field.Type.(type) {
case *ConstType:
case *FlagsType:
case *IntType:
default:
continue
}
argID := fmt.Sprintf("%v/%v", id, i)
group := groups[argID]
if group == nil {
group = make(map[Type]struct{})
groups[argID] = group
}
call.Args[i].relatedFields = group
group[field.Type] = struct{}{}
switch arg := field.Type.(type) {
case *ConstType:
id += fmt.Sprintf("-%v:%v", i, arg.Val)
}
}
}
// Drop groups that consist of only a single field as they are not useful.
for _, call := range target.Syscalls {
for i := range call.Args {
if len(call.Args[i].relatedFields) == 1 {
call.Args[i].relatedFields = nil
}
}
}
}
func (target *Target) GetConst(name string) uint64 {
v, ok := target.ConstMap[name]
if !ok {
panic(fmt.Sprintf("const %v is not defined for %v/%v", name, target.OS, target.Arch))
}
return v
}
func (target *Target) sanitize(c *Call, fix bool) error {
// For now, even though we accept the fix argument, it does not have the full effect.
// It de facto only denies structural changes, e.g. deletions of arguments.
// TODO: rewrite the corresponding sys/*/init.go code.
return target.Neutralize(c, fix)
}
func RestoreLinks(syscalls []*Syscall, resources []*ResourceDesc, types []Type) {
restoreLinks(syscalls, resources, types)
}
var (
typeRefMu sync.Mutex
typeRefs atomic.Value // []Type
)
func restoreLinks(syscalls []*Syscall, resources []*ResourceDesc, types []Type) map[string]*ResourceDesc {
typeRefMu.Lock()
defer typeRefMu.Unlock()
refs := []Type{nil}
if old := typeRefs.Load(); old != nil {
refs = old.([]Type)
}
for _, typ := range types {
typ.setRef(Ref(len(refs)))
refs = append(refs, typ)
}
typeRefs.Store(refs)
resourceMap := make(map[string]*ResourceDesc)
for _, res := range resources {
resourceMap[res.Name] = res
}
ForeachType(syscalls, func(typ Type, ctx *TypeCtx) {
if ref, ok := typ.(Ref); ok {
typ = types[ref]
*ctx.Ptr = typ
}
switch t := typ.(type) {
case *ResourceType:
t.Desc = resourceMap[t.TypeName]
if t.Desc == nil {
panic("no resource desc")
}
}
})
return resourceMap
}
func (target *Target) DefaultChoiceTable() *ChoiceTable {
target.defaultOnce.Do(func() {
target.defaultChoiceTable = target.BuildChoiceTable(nil, nil)
})
return target.defaultChoiceTable
}
func (target *Target) RequiredGlobs() []string {
globs := make(map[string]bool)
ForeachType(target.Syscalls, func(typ Type, ctx *TypeCtx) {
switch a := typ.(type) {
case *BufferType:
if a.Kind == BufferGlob {
for _, glob := range requiredGlobs(a.SubKind) {
globs[glob] = true
}
}
}
})
return stringMapToSlice(globs)
}
func (target *Target) UpdateGlobs(globFiles map[string][]string) {
// TODO: make host.DetectSupportedSyscalls below filter out globs with no values.
// Also make prog package more strict with respect to generation/mutation of globs
// with no values (they still can appear in tests and tools). We probably should
// generate an empty string for these and never mutate.
ForeachType(target.Syscalls, func(typ Type, ctx *TypeCtx) {
switch a := typ.(type) {
case *BufferType:
if a.Kind == BufferGlob {
a.Values = populateGlob(a.SubKind, globFiles)
}
}
})
}
func requiredGlobs(pattern string) []string {
var res []string
for _, tok := range strings.Split(pattern, ":") {
if tok[0] != '-' {
res = append(res, tok)
}
}
return res
}
func populateGlob(pattern string, globFiles map[string][]string) []string {
files := make(map[string]bool)
parts := strings.Split(pattern, ":")
for _, tok := range parts {
if tok[0] != '-' {
for _, file := range globFiles[tok] {
files[file] = true
}
}
}
for _, tok := range parts {
if tok[0] == '-' {
delete(files, tok[1:])
}
}
return stringMapToSlice(files)
}
func stringMapToSlice(m map[string]bool) []string {
var res []string
for k := range m {
res = append(res, k)
}
sort.Strings(res)
return res
}
type Gen struct {
r *randGen
s *state
}
func (g *Gen) Target() *Target {
return g.r.target
}
func (g *Gen) Rand() *rand.Rand {
return g.r.Rand
}
func (g *Gen) NOutOf(n, outOf int) bool {
return g.r.nOutOf(n, outOf)
}
func (g *Gen) Alloc(ptrType Type, dir Dir, data Arg) (Arg, []*Call) {
return g.r.allocAddr(g.s, ptrType, dir, data.Size(), data), nil
}
func (g *Gen) GenerateArg(typ Type, dir Dir, pcalls *[]*Call) Arg {
return g.generateArg(typ, dir, pcalls, false)
}
func (g *Gen) GenerateSpecialArg(typ Type, dir Dir, pcalls *[]*Call) Arg {
return g.generateArg(typ, dir, pcalls, true)
}
func (g *Gen) generateArg(typ Type, dir Dir, pcalls *[]*Call, ignoreSpecial bool) Arg {
arg, calls := g.r.generateArgImpl(g.s, typ, dir, ignoreSpecial)
*pcalls = append(*pcalls, calls...)
g.r.target.assignSizesArray([]Arg{arg}, []Field{{Name: "", Type: arg.Type()}}, nil)
return arg
}
func (g *Gen) MutateArg(arg0 Arg) (calls []*Call) {
updateSizes := true
for stop := false; !stop; stop = g.r.oneOf(3) {
ma := &mutationArgs{target: g.r.target, ignoreSpecial: true}
ForeachSubArg(arg0, ma.collectArg)
if len(ma.args) == 0 {
// TODO(dvyukov): probably need to return this condition
// and updateSizes to caller so that Mutate can act accordingly.
return
}
arg, ctx := ma.chooseArg(g.r.Rand)
newCalls, ok := g.r.target.mutateArg(g.r, g.s, arg, ctx, &updateSizes)
if !ok {
continue
}
calls = append(calls, newCalls...)
}
return calls
}
type Builder struct {
target *Target
ma *memAlloc
p *Prog
}
func MakeProgGen(target *Target) *Builder {
return &Builder{
target: target,
ma: newMemAlloc(target.NumPages * target.PageSize),
p: &Prog{
Target: target,
},
}
}
func (pg *Builder) Append(c *Call) error {
pg.target.assignSizesCall(c)
pg.target.sanitize(c, true)
pg.p.Calls = append(pg.p.Calls, c)
return nil
}
func (pg *Builder) Allocate(size, alignment uint64) uint64 {
return pg.ma.alloc(nil, size, alignment)
}
func (pg *Builder) AllocateVMA(npages uint64) uint64 {
return pg.ma.alloc(nil, npages*pg.target.PageSize, pg.target.PageSize)
}
func (pg *Builder) Finalize() (*Prog, error) {
if err := pg.p.validate(); err != nil {
return nil, err
}
if _, err := pg.p.SerializeForExec(); err != nil {
return nil, err
}
p := pg.p
pg.p = nil
return p, nil
}
// Copyright 2019 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package test
import (
"bytes"
"fmt"
"math/rand"
"github.com/google/syzkaller/prog"
_ "github.com/google/syzkaller/sys"
"github.com/google/syzkaller/sys/targets"
)
func FuzzDeserialize(data []byte) int {
p0, err0 := fuzzTarget.Deserialize(data, prog.NonStrict)
p1, err1 := fuzzTarget.Deserialize(data, prog.Strict)
if p0 == nil {
if p1 != nil {
panic("NonStrict is stricter than Strict")
}
if err0 == nil || err1 == nil {
panic("no error")
}
return 0
}
if err0 != nil {
panic("got program and error")
}
data0 := p0.Serialize()
if p1 != nil {
if err1 != nil {
panic("got program and error")
}
if !bytes.Equal(data0, p1.Serialize()) {
panic("got different data")
}
}
p2, err2 := fuzzTarget.Deserialize(data0, prog.NonStrict)
if err2 != nil {
panic(fmt.Sprintf("failed to parse serialized: %v\n%s", err2, data0))
}
if !bytes.Equal(data0, p2.Serialize()) {
panic("got different data")
}
p3 := p0.Clone()
if !bytes.Equal(data0, p3.Serialize()) {
panic("got different data")
}
if prodData, err := p0.SerializeForExec(); err == nil {
if _, err := fuzzTarget.DeserializeExec(prodData, nil); err != nil {
panic(err)
}
}
p3.Mutate(rand.NewSource(0), 3, fuzzChoiceTable, nil, nil)
return 0
}
func FuzzParseLog(data []byte) int {
if len(fuzzTarget.ParseLog(data, prog.NonStrict)) != 0 {
return 1
}
return 0
}
var fuzzTarget, fuzzChoiceTable = func() (*prog.Target, *prog.ChoiceTable) {
target, err := prog.GetTarget(targets.TestOS, targets.TestArch64)
if err != nil {
panic(err)
}
return target, target.DefaultChoiceTable()
}()
// Copyright 2020 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package prog
import (
"fmt"
"strings"
"testing"
)
func InitTargetTest(t *testing.T, os, arch string) *Target {
t.Parallel()
target, err := GetTarget(os, arch)
if err != nil {
t.Fatal(err)
}
return target
}
type DeserializeTest struct {
In string
Out string // if not set, equals to In
Err string
StrictErr string // if not set, equals to Err
}
func TestDeserializeHelper(t *testing.T, OS, arch string, transform func(*Target, *Prog), tests []DeserializeTest) {
target := InitTargetTest(t, OS, arch)
for testidx, test := range tests {
t.Run(fmt.Sprint(testidx), func(t *testing.T) {
if test.StrictErr == "" {
test.StrictErr = test.Err
}
if test.Err != "" && test.Out != "" {
t.Errorf("both Err and Out are set")
}
if test.In == test.Out {
t.Errorf("in and out are equal, remove Out in such case\n%v", test.In)
}
if test.Out == "" {
test.Out = test.In
}
for _, mode := range []DeserializeMode{NonStrict, Strict} {
p, err := target.Deserialize([]byte(test.In), mode)
wantErr := test.Err
if mode == Strict {
wantErr = test.StrictErr
}
if err != nil {
if wantErr == "" {
t.Fatalf("deserialization failed with\n%s\ndata:\n%s",
err, test.In)
}
if !strings.Contains(err.Error(), wantErr) {
t.Fatalf("deserialization failed with\n%s\nwhich doesn't match\n%s\ndata:\n%s",
err, wantErr, test.In)
}
} else {
if wantErr != "" {
t.Fatalf("deserialization should have failed with:\n%s\ndata:\n%s",
wantErr, test.In)
}
if transform != nil {
transform(target, p)
}
output := strings.TrimSpace(string(p.Serialize()))
outputVerbose := strings.TrimSpace(string(p.SerializeVerbose()))
want := strings.TrimSpace(test.Out)
// We want to compare both verbose & non verbose mode.
// Otherwise we cannot have just In: field for the calls where
// the verbose and non-verbose output don't match -- the strict parsing
// mode does not accept the non-verbose output as input.
if want != output && want != outputVerbose {
t.Fatalf("wrong serialized data:\n%s\nexpect:\n%s", outputVerbose, want)
}
p.SerializeForExec()
}
}
})
}
}
// Copyright 2015/2016 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package prog
import (
"fmt"
"strings"
"unicode"
)
type Syscall struct {
ID int
NR uint64 // kernel syscall number
Name string
CallName string
MissingArgs int // number of trailing args that should be zero-filled
Args []Field
Ret Type
Attrs SyscallAttrs
// Resources that are required for this call to be generated (in/inout).
inputResources []*ResourceDesc
// Resources that this call can be used to create (out, but excluding no_generate).
createsResources []*ResourceDesc
// Both inputs and output resources (including no_generate).
usesResources []*ResourceDesc
}
// SyscallAttrs represents call attributes in syzlang.
//
// This structure is the source of truth for the all other parts of the system.
// pkg/compiler uses this structure to parse descriptions.
// syz-sysgen uses this structure to generate code for executor.
//
// Only `bool`s, `string`s and `uint64`s are currently supported.
//
// See docs/syscall_descriptions_syntax.md for description of individual attributes.
type SyscallAttrs struct {
Disabled bool
Timeout uint64
ProgTimeout uint64
IgnoreReturn bool
BreaksReturns bool
NoGenerate bool
NoMinimize bool
RemoteCover bool
Automatic bool
AutomaticHelper bool
Fsck string
}
// MaxArgs is maximum number of syscall arguments.
// Executor also knows about this value.
const MaxArgs = 9
type Dir uint8
const (
DirIn Dir = iota
DirOut
DirInOut
)
func (dir Dir) String() string {
switch dir {
case DirIn:
return "in"
case DirOut:
return "out"
case DirInOut:
return "inout"
default:
panic("unknown dir")
}
}
type Field struct {
Name string
Type
HasDirection bool
Direction Dir
Condition Expression
// See Target.initRelatedFields.
relatedFields map[Type]struct{}
}
func (f *Field) Dir(def Dir) Dir {
if f.HasDirection {
return f.Direction
}
return def
}
type ArgFinder func(path []string) Arg
// Special case reply of ArgFinder.
var SquashedArgFound = &DataArg{}
type Expression interface {
fmt.GoStringer
ForEachValue(func(*Value))
Clone() Expression
Evaluate(ArgFinder) (uint64, bool)
}
type BinaryOperator int
const (
OperatorCompareEq BinaryOperator = iota
OperatorCompareNeq
OperatorBinaryAnd
OperatorOr
)
type BinaryExpression struct {
Operator BinaryOperator
Left Expression
Right Expression
}
func (bo BinaryExpression) GoString() string {
return fmt.Sprintf("&prog.BinaryExpression{%#v,%#v,%#v}", bo.Operator, bo.Left, bo.Right)
}
func (bo BinaryExpression) ForEachValue(cb func(*Value)) {
bo.Left.ForEachValue(cb)
bo.Right.ForEachValue(cb)
}
func (bo BinaryExpression) Clone() Expression {
return &BinaryExpression{
Operator: bo.Operator,
Left: bo.Left.Clone(),
Right: bo.Right.Clone(),
}
}
type Value struct {
// If Path is empty, Value is to be used.
Value uint64
// Path to the field.
Path []string
}
func (v *Value) GoString() string {
return fmt.Sprintf("&prog.Value{%#v,%#v}", v.Value, v.Path)
}
func (v *Value) ForEachValue(cb func(*Value)) {
cb(v)
}
func (v *Value) Clone() Expression {
return &Value{v.Value, append([]string{}, v.Path...)}
}
type BinaryFormat int
const (
FormatNative BinaryFormat = iota
FormatBigEndian
FormatStrDec
FormatStrHex
FormatStrOct
)
type Type interface {
String() string
Name() string
TemplateName() string // for template structs name without arguments
Optional() bool
Varlen() bool
Size() uint64
TypeBitSize() uint64
Alignment() uint64
Format() BinaryFormat
BitfieldOffset() uint64
BitfieldLength() uint64
IsBitfield() bool
// For most of the types UnitSize is equal to Size.
// These are different only for all but last bitfield in the group,
// where Size == 0 and UnitSize equals to the underlying bitfield type size.
UnitSize() uint64
UnitOffset() uint64
DefaultArg(dir Dir) Arg
isDefaultArg(arg Arg) bool
generate(r *randGen, s *state, dir Dir) (arg Arg, calls []*Call)
mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls []*Call, retry, preserve bool)
getMutationPrio(target *Target, arg Arg, ignoreSpecial bool) (prio float64, stopRecursion bool)
minimize(ctx *minimizeArgsCtx, arg Arg, path string) bool
ref() Ref
setRef(ref Ref)
}
type Ref uint32
func (ti Ref) String() string { panic("prog.Ref method called") }
func (ti Ref) Name() string { panic("prog.Ref method called") }
func (ti Ref) TemplateName() string { panic("prog.Ref method called") }
func (ti Ref) Optional() bool { panic("prog.Ref method called") }
func (ti Ref) Varlen() bool { panic("prog.Ref method called") }
func (ti Ref) Size() uint64 { panic("prog.Ref method called") }
func (ti Ref) TypeBitSize() uint64 { panic("prog.Ref method called") }
func (ti Ref) Alignment() uint64 { panic("prog.Ref method called") }
func (ti Ref) Format() BinaryFormat { panic("prog.Ref method called") }
func (ti Ref) BitfieldOffset() uint64 { panic("prog.Ref method called") }
func (ti Ref) BitfieldLength() uint64 { panic("prog.Ref method called") }
func (ti Ref) IsBitfield() bool { panic("prog.Ref method called") }
func (ti Ref) UnitSize() uint64 { panic("prog.Ref method called") }
func (ti Ref) UnitOffset() uint64 { panic("prog.Ref method called") }
func (ti Ref) DefaultArg(dir Dir) Arg { panic("prog.Ref method called") }
func (ti Ref) Clone() Type { panic("prog.Ref method called") }
func (ti Ref) isDefaultArg(arg Arg) bool { panic("prog.Ref method called") }
func (ti Ref) generate(r *randGen, s *state, dir Dir) (Arg, []*Call) { panic("prog.Ref method called") }
func (ti Ref) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) ([]*Call, bool, bool) {
panic("prog.Ref method called")
}
func (ti Ref) getMutationPrio(target *Target, arg Arg, ignoreSpecial bool) (float64, bool) {
panic("prog.Ref method called")
}
func (ti Ref) minimize(ctx *minimizeArgsCtx, arg Arg, path string) bool {
panic("prog.Ref method called")
}
func (ti Ref) ref() Ref { panic("prog.Ref method called") }
func (ti Ref) setRef(ref Ref) { panic("prog.Ref method called") }
func IsPad(t Type) bool {
if ct, ok := t.(*ConstType); ok && ct.IsPad {
return true
}
return false
}
type TypeCommon struct {
TypeName string
// Static size of the type, or 0 for variable size types and all but last bitfields in the group.
TypeSize uint64
TypeAlign uint64
IsOptional bool
IsVarlen bool
self Ref
}
func (t *TypeCommon) Name() string {
return t.TypeName
}
func (t *TypeCommon) TemplateName() string {
name := t.TypeName
if pos := strings.IndexByte(name, '['); pos != -1 {
name = name[:pos]
}
return name
}
func (t *TypeCommon) Optional() bool {
return t.IsOptional
}
func (t *TypeCommon) Size() uint64 {
if t.IsVarlen {
panic(fmt.Sprintf("static type size is not known: %#v", t))
}
return t.TypeSize
}
func (t *TypeCommon) TypeBitSize() uint64 {
panic("cannot get the bitsize for a non-integer type")
}
func (t *TypeCommon) Varlen() bool {
return t.IsVarlen
}
func (t *TypeCommon) Format() BinaryFormat {
return FormatNative
}
func (t *TypeCommon) BitfieldOffset() uint64 {
return 0
}
func (t *TypeCommon) BitfieldLength() uint64 {
return 0
}
func (t *TypeCommon) UnitSize() uint64 {
return t.Size()
}
func (t *TypeCommon) UnitOffset() uint64 {
return 0
}
func (t *TypeCommon) IsBitfield() bool {
return false
}
func (t *TypeCommon) ref() Ref {
if t.self == 0 {
panic("ref is not assigned yet")
}
return t.self
}
func (t *TypeCommon) setRef(ref Ref) {
t.self = ref
}
func (t *TypeCommon) Alignment() uint64 {
return t.TypeAlign
}
type FlagDesc struct {
Name string
Values []string
}
type ResourceDesc struct {
Name string
Kind []string
Values []uint64
Ctors []ResourceCtor
}
type ResourceCtor struct {
Call *Syscall
Precise bool
}
type ResourceType struct {
TypeCommon
ArgFormat BinaryFormat
Desc *ResourceDesc
}
func (t *ResourceType) String() string {
return t.Name()
}
func (t *ResourceType) DefaultArg(dir Dir) Arg {
return MakeResultArg(t, dir, nil, t.Default())
}
func (t *ResourceType) isDefaultArg(arg Arg) bool {
a := arg.(*ResultArg)
return a.Res == nil && a.OpDiv == 0 && a.OpAdd == 0 &&
len(a.uses) == 0 && a.Val == t.Default()
}
func (t *ResourceType) Default() uint64 {
return t.Desc.Values[0]
}
func (t *ResourceType) SpecialValues() []uint64 {
return t.Desc.Values
}
func (t *ResourceType) Format() BinaryFormat {
return t.ArgFormat
}
type IntTypeCommon struct {
TypeCommon
ArgFormat BinaryFormat
BitfieldOff uint64
BitfieldLen uint64
BitfieldUnit uint64
BitfieldUnitOff uint64
// Hint values that don't make sense to use for this type
// b/c they are expected to be easily guessed by generation/mutation.
// For example, flags values or combinations of few flags values.
uselessHints map[uint64]struct{}
}
func (t *IntTypeCommon) String() string {
return t.Name()
}
func (t *IntTypeCommon) Format() BinaryFormat {
return t.ArgFormat
}
// Returns the size in bits for integers in binary format or 64 for string-formatted integers. The return
// value is used in computing limits and truncating other values.
func (t *IntTypeCommon) TypeBitSize() uint64 {
if t.ArgFormat != FormatNative && t.ArgFormat != FormatBigEndian {
// TODO: add special cases for mutation and generation of string-formatted integers.
return 64
}
if t.BitfieldLen != 0 {
return t.BitfieldLen
}
return t.TypeSize * 8
}
func (t *IntTypeCommon) BitfieldOffset() uint64 {
return t.BitfieldOff
}
func (t *IntTypeCommon) BitfieldLength() uint64 {
return t.BitfieldLen
}
func (t *IntTypeCommon) UnitSize() uint64 {
if t.BitfieldLen != 0 {
return t.BitfieldUnit
}
return t.Size()
}
func (t *IntTypeCommon) UnitOffset() uint64 {
return t.BitfieldUnitOff
}
func (t *IntTypeCommon) IsBitfield() bool {
return t.BitfieldLen != 0
}
func (t *IntTypeCommon) uselessHint(v uint64) bool {
_, ok := t.uselessHints[v]
return ok
}
func (t *IntTypeCommon) setUselessHints(m map[uint64]struct{}) {
t.uselessHints = m
}
type uselessHinter interface {
uselessHint(uint64) bool
calcUselessHints() []uint64
setUselessHints(map[uint64]struct{})
}
type ConstType struct {
IntTypeCommon
Val uint64
IsPad bool
}
func (t *ConstType) DefaultArg(dir Dir) Arg {
return MakeConstArg(t, dir, t.Val)
}
func (t *ConstType) isDefaultArg(arg Arg) bool {
return arg.(*ConstArg).Val == t.Val
}
func (t *ConstType) String() string {
if t.IsPad {
return fmt.Sprintf("pad[%v]", t.Size())
}
return fmt.Sprintf("const[%v, %v]", t.Val, t.IntTypeCommon.String())
}
func (t *ConstType) calcUselessHints() []uint64 {
return []uint64{t.Val}
}
type IntKind int
const (
IntPlain IntKind = iota
IntRange
)
type IntType struct {
IntTypeCommon
Kind IntKind
RangeBegin uint64
RangeEnd uint64
Align uint64
}
func (t *IntType) DefaultArg(dir Dir) Arg {
return MakeConstArg(t, dir, 0)
}
func (t *IntType) isDefaultArg(arg Arg) bool {
return arg.(*ConstArg).Val == 0
}
func (t *IntType) calcUselessHints() []uint64 {
res := specialInts[:len(specialInts):len(specialInts)]
align := max(1, t.Align)
rangeVals := (t.RangeEnd - t.RangeBegin) / align
if rangeVals != 0 && rangeVals <= 100 {
for v := t.RangeBegin; v <= t.RangeEnd; v += align {
res = append(res, v)
}
}
return res
}
type FlagsType struct {
IntTypeCommon
Vals []uint64 // compiler ensures that it's not empty
BitMask bool
}
func (t *FlagsType) DefaultArg(dir Dir) Arg {
return MakeConstArg(t, dir, 0)
}
func (t *FlagsType) isDefaultArg(arg Arg) bool {
return arg.(*ConstArg).Val == 0
}
func (t *FlagsType) calcUselessHints() []uint64 {
// Combinations of up to 3 flag values + 0.
res := []uint64{0}
vals := t.Vals
for i0 := 0; i0 < len(vals); i0++ {
v0 := vals[i0]
res = append(res, v0)
if len(vals) <= 10 {
for i1 := i0 + 1; i1 < len(vals); i1++ {
v1 := v0 | vals[i1]
res = append(res, v1)
if len(vals) <= 7 {
for i2 := i1 + 1; i2 < len(vals); i2++ {
v2 := v1 | vals[i2]
res = append(res, v2)
}
}
}
}
}
return res
}
type LenType struct {
IntTypeCommon
BitSize uint64 // want size in multiple of bits instead of array size
Offset bool // offset from the beginning of the parent struct or base object
Path []string
}
func (t *LenType) DefaultArg(dir Dir) Arg {
return MakeConstArg(t, dir, 0)
}
func (t *LenType) isDefaultArg(arg Arg) bool {
return arg.(*ConstArg).Val == 0
}
func (t *LenType) calcUselessHints() []uint64 {
return nil
}
func (t *LenType) uselessHint(v uint64) bool {
return v <= maxArrayLen || v > 1<<20
}
type ProcType struct {
IntTypeCommon
ValuesStart uint64
ValuesPerProc uint64
}
const (
// Some aspects of the linux kernel configs also know about this const,
// e.g. they create that many devices of various types (usually these parameters are in CMDLINE).
MaxPids = 32
procDefaultValue = 0xffffffffffffffff // special value denoting 0 for all procs
)
func (t *ProcType) DefaultArg(dir Dir) Arg {
return MakeConstArg(t, dir, procDefaultValue)
}
func (t *ProcType) isDefaultArg(arg Arg) bool {
return arg.(*ConstArg).Val == procDefaultValue
}
type CsumKind int
const (
CsumInet CsumKind = iota
CsumPseudo
)
type CsumType struct {
IntTypeCommon
Kind CsumKind
Buf string
Protocol uint64 // for CsumPseudo
}
func (t *CsumType) String() string {
return "csum"
}
func (t *CsumType) DefaultArg(dir Dir) Arg {
return MakeConstArg(t, dir, 0)
}
func (t *CsumType) isDefaultArg(arg Arg) bool {
return arg.(*ConstArg).Val == 0
}
type VmaType struct {
TypeCommon
RangeBegin uint64 // in pages
RangeEnd uint64
}
func (t *VmaType) String() string {
return "vma"
}
func (t *VmaType) DefaultArg(dir Dir) Arg {
return MakeSpecialPointerArg(t, dir, 0)
}
func (t *VmaType) isDefaultArg(arg Arg) bool {
a := arg.(*PointerArg)
return a.IsSpecial() && a.Address == 0
}
type BufferKind int
const (
BufferBlobRand BufferKind = iota
BufferBlobRange
BufferString
BufferFilename
BufferText
BufferGlob
BufferCompressed
)
type TextKind int
const (
TextTarget TextKind = iota
TextX86Real
TextX86bit16
TextX86bit32
TextX86bit64
TextArm64
TextPpc64
)
type BufferType struct {
TypeCommon
Kind BufferKind
RangeBegin uint64 // for BufferBlobRange kind
RangeEnd uint64 // for BufferBlobRange kind
Text TextKind // for BufferText
SubKind string
Values []string // possible values for BufferString and BufferGlob kind
NoZ bool // non-zero terminated BufferString/BufferFilename
}
func (t *BufferType) String() string {
return "buffer"
}
func (t *BufferType) DefaultArg(dir Dir) Arg {
if dir == DirOut {
var sz uint64
if !t.Varlen() {
sz = t.Size()
}
return MakeOutDataArg(t, dir, sz)
}
var data []byte
if len(t.Values) == 1 {
data = []byte(t.Values[0])
} else if !t.Varlen() {
data = make([]byte, t.Size())
}
return MakeDataArg(t, dir, data)
}
func (t *BufferType) isDefaultArg(arg Arg) bool {
a := arg.(*DataArg)
sz := uint64(0)
if !t.Varlen() {
sz = t.Size()
}
if a.Size() != sz {
return false
}
if a.Dir() == DirOut {
return true
}
if len(t.Values) == 1 {
return string(a.Data()) == t.Values[0]
}
for _, v := range a.Data() {
if v != 0 {
return false
}
}
return true
}
func (t *BufferType) IsCompressed() bool {
return t.Kind == BufferCompressed
}
type ArrayKind int
const (
ArrayRandLen ArrayKind = iota
ArrayRangeLen
)
type ArrayType struct {
TypeCommon
Elem Type
Kind ArrayKind
RangeBegin uint64
RangeEnd uint64
}
func (t *ArrayType) String() string {
return fmt.Sprintf("array[%v]", t.Elem.String())
}
func (t *ArrayType) DefaultArg(dir Dir) Arg {
var elems []Arg
if t.Kind == ArrayRangeLen && t.RangeBegin == t.RangeEnd {
for i := uint64(0); i < t.RangeBegin; i++ {
elems = append(elems, t.Elem.DefaultArg(dir))
}
}
return MakeGroupArg(t, dir, elems)
}
func (t *ArrayType) isDefaultArg(arg Arg) bool {
a := arg.(*GroupArg)
if !a.fixedInnerSize() && len(a.Inner) != 0 {
return false
}
for _, elem := range a.Inner {
if !isDefault(elem) {
return false
}
}
return true
}
type PtrType struct {
TypeCommon
Elem Type
ElemDir Dir
SquashableElem bool
}
func (t *PtrType) String() string {
return fmt.Sprintf("ptr[%v, %v]", t.ElemDir, t.Elem.String())
}
func (t *PtrType) DefaultArg(dir Dir) Arg {
if t.Optional() {
return MakeSpecialPointerArg(t, dir, 0)
}
return MakePointerArg(t, dir, 0, t.Elem.DefaultArg(t.ElemDir))
}
func (t *PtrType) isDefaultArg(arg Arg) bool {
a := arg.(*PointerArg)
if t.Optional() {
return a.IsSpecial() && a.Address == 0
}
return a.Address == 0 && a.Res != nil && isDefault(a.Res)
}
type StructType struct {
TypeCommon
Fields []Field
AlignAttr uint64
OverlayField int // index of the field marked with out_overlay attribute (0 if no attribute)
}
func (t *StructType) String() string {
return t.Name()
}
func (t *StructType) DefaultArg(dir Dir) Arg {
inner := make([]Arg, len(t.Fields))
for i, field := range t.Fields {
inner[i] = field.DefaultArg(field.Dir(dir))
}
return MakeGroupArg(t, dir, inner)
}
func (t *StructType) isDefaultArg(arg Arg) bool {
a := arg.(*GroupArg)
for _, elem := range a.Inner {
if !isDefault(elem) {
return false
}
}
return true
}
type UnionType struct {
TypeCommon
Fields []Field
}
func (t *UnionType) String() string {
return t.Name()
}
func (t *UnionType) DefaultArg(dir Dir) Arg {
idx, _ := t.defaultField()
f := t.Fields[idx]
arg := MakeUnionArg(t, dir, f.DefaultArg(f.Dir(dir)), idx)
arg.transient = t.isConditional()
return arg
}
func (t *UnionType) defaultField() (int, bool) {
// If it's a conditional union, the last field is usually a safe choice for the default value as
// it must have no condition.
// Auto-generated wrappers for conditional fields are an exception since both fields will have
// conditions, and, moreover, these conditions will be mutually exclusive.
if t.isConditional() {
if t.Fields[len(t.Fields)-1].Condition != nil {
// There's no correct default index.
return 0, false
}
return len(t.Fields) - 1, true
}
// Otherwise, just take the first.
return 0, true
}
func (t *UnionType) isConditional() bool {
// Either all fields will have a conditions, or all except the last one, or none.
// So checking for the first one is always enough.
return t.Fields[0].Condition != nil
}
func (t *UnionType) isDefaultArg(arg Arg) bool {
a := arg.(*UnionArg)
defIdx, ok := t.defaultField()
if !ok {
// Any value is the only possible option.
return isDefault(a.Option)
}
return a.Index == defIdx && isDefault(a.Option)
}
type ConstValue struct {
Name string
Value uint64
}
type TypeCtx struct {
Meta *Syscall
Dir Dir
Ptr *Type
Optional bool
Stop bool // If set by the callback, subtypes of this type are not visited.
}
func ForeachType(syscalls []*Syscall, f func(t Type, ctx *TypeCtx)) {
for _, meta := range syscalls {
foreachCallTypeImpl(meta, true, f)
}
}
func ForeachTypePost(syscalls []*Syscall, f func(t Type, ctx *TypeCtx)) {
for _, meta := range syscalls {
foreachCallTypeImpl(meta, false, f)
}
}
func ForeachCallType(meta *Syscall, f func(t Type, ctx *TypeCtx)) {
foreachCallTypeImpl(meta, true, f)
}
// We need seen to be keyed by the type, the direction, and the optionality
// bit. Even if the first time we see a type it is optional or DirOut, it
// could be required or DirIn on another path. So to ensure that the
// information we report to the caller is correct, we need to visit both
// occurrences.
type seenKey struct {
t Type
d Dir
o bool
}
func foreachCallTypeImpl(meta *Syscall, preorder bool, f func(t Type, ctx *TypeCtx)) {
// Note: we specifically don't create seen in ForeachType.
// It would prune recursion more (across syscalls), but lots of users need to
// visit each struct per-syscall (e.g. prio, used resources).
seen := make(map[seenKey]bool)
for i := range meta.Args {
foreachTypeRec(f, meta, seen, &meta.Args[i].Type, DirIn, preorder, false)
}
if meta.Ret != nil {
foreachTypeRec(f, meta, seen, &meta.Ret, DirOut, preorder, false)
}
}
func ForeachArgType(typ Type, f func(t Type, ctx *TypeCtx)) {
foreachTypeRec(f, nil, make(map[seenKey]bool), &typ, DirIn, true, false)
}
func foreachTypeRec(cb func(t Type, ctx *TypeCtx), meta *Syscall, seen map[seenKey]bool, ptr *Type,
dir Dir, preorder, optional bool) {
if _, ref := (*ptr).(Ref); !ref {
optional = optional || (*ptr).Optional()
}
ctx := &TypeCtx{Meta: meta, Dir: dir, Ptr: ptr, Optional: optional}
if preorder {
cb(*ptr, ctx)
if ctx.Stop {
return
}
}
switch a := (*ptr).(type) {
case *PtrType:
foreachTypeRec(cb, meta, seen, &a.Elem, a.ElemDir, preorder, optional)
case *ArrayType:
foreachTypeRec(cb, meta, seen, &a.Elem, dir, preorder, optional)
case *StructType:
key := seenKey{
t: a,
d: dir,
o: optional,
}
if seen[key] {
break // prune recursion via pointers to structs/unions
}
seen[key] = true
for i, f := range a.Fields {
foreachTypeRec(cb, meta, seen, &a.Fields[i].Type, f.Dir(dir), preorder, optional)
}
case *UnionType:
key := seenKey{
t: a,
d: dir,
o: optional,
}
if seen[key] {
break // prune recursion via pointers to structs/unions
}
seen[key] = true
for i, f := range a.Fields {
foreachTypeRec(cb, meta, seen, &a.Fields[i].Type, f.Dir(dir), preorder, optional)
}
case *ResourceType, *BufferType, *VmaType, *LenType, *FlagsType,
*ConstType, *IntType, *ProcType, *CsumType:
case Ref:
// This is only needed for pkg/compiler.
default:
panic("unknown type")
}
if !preorder {
cb(*ptr, ctx)
if ctx.Stop {
panic("Stop is set in post-order iteration")
}
}
}
// CppName transforms PascalStyleNames to cpp_style_names.
func CppName(name string) string {
var res []byte
for i := range name {
c := rune(name[i])
if unicode.IsUpper(c) && i != 0 && !unicode.IsUpper(rune(name[i-1])) {
res = append(res, '_')
}
res = append(res, byte(unicode.ToLower(c)))
}
return string(res)
}
// Copyright 2015 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package prog
import (
"fmt"
"os"
"strings"
)
var debug = false // enabled in tests and fuzzers
func init() {
// Enable debug checking in all tests.
if strings.HasSuffix(os.Args[0], ".test") {
debug = true
}
}
func (p *Prog) debugValidate() {
if debug {
if err := p.validate(); err != nil {
panic(err)
}
}
}
func (p *Prog) validate() error {
return p.validateWithOpts(validationOptions{})
}
type validCtx struct {
target *Target
isUnsafe bool
opts validationOptions
args map[Arg]bool
uses map[Arg]Arg
}
type validationOptions struct {
ignoreTransient bool
}
func (p *Prog) validateWithOpts(opts validationOptions) error {
ctx := &validCtx{
target: p.Target,
isUnsafe: p.isUnsafe,
opts: opts,
args: make(map[Arg]bool),
uses: make(map[Arg]Arg),
}
for i, c := range p.Calls {
if c.Meta == nil {
return fmt.Errorf("call does not have meta information")
}
if err := ctx.validateCall(c); err != nil {
return fmt.Errorf("call #%d %v: %w", i, c.Meta.Name, err)
}
}
for u, orig := range ctx.uses {
if !ctx.args[u] {
return fmt.Errorf("use of %+v referes to an out-of-tree arg\narg: %#v", orig, u)
}
}
return nil
}
func (ctx *validCtx) validateCall(c *Call) error {
if !ctx.isUnsafe && c.Meta.Attrs.Disabled {
return fmt.Errorf("use of a disabled call")
}
if c.Props.Rerun > 0 && c.Props.FailNth > 0 {
return fmt.Errorf("rerun > 0 && fail_nth > 0")
}
if len(c.Args) != len(c.Meta.Args) {
return fmt.Errorf("wrong number of arguments, want %v, got %v",
len(c.Meta.Args), len(c.Args))
}
for i, arg := range c.Args {
if err := ctx.validateArg(arg, c.Meta.Args[i].Type, DirIn); err != nil {
return err
}
}
if err := c.checkConditions(ctx.target, ctx.opts.ignoreTransient); err != nil {
return err
}
return ctx.validateRet(c)
}
func (ctx *validCtx) validateRet(c *Call) error {
if c.Meta.Ret == nil {
if c.Ret != nil {
return fmt.Errorf("return value without type")
}
return nil
}
if c.Ret == nil {
return fmt.Errorf("return value is absent")
}
if c.Ret.Res != nil || c.Ret.Val != 0 || c.Ret.OpDiv != 0 || c.Ret.OpAdd != 0 {
return fmt.Errorf("return value %v is not empty", c.Ret)
}
return ctx.validateArg(c.Ret, c.Meta.Ret, DirOut)
}
func (ctx *validCtx) validateArg(arg Arg, typ Type, dir Dir) error {
if arg == nil {
return fmt.Errorf("nil arg")
}
if ctx.args[arg] {
return fmt.Errorf("arg %#v is referenced several times in the tree", arg)
}
if arg.Type() == nil {
return fmt.Errorf("no arg type")
}
if _, ok := typ.(*PtrType); ok {
dir = DirIn // pointers are always in
}
// We used to demand that Arg has exactly the same dir as Type, however,
// it leads to problems when dealing with ANYRES* types.
// If the resource was DirIn before squashing, we should not demand that
// it be DirInOut - it would only lead to mutations that make little sense.
// Let's only deny truly conflicting directions, e.g. DirIn vs DirOut.
if arg.Dir() != dir && dir != DirInOut {
return fmt.Errorf("arg %#v type %v has wrong dir %v, expect %v", arg, arg.Type(), arg.Dir(), dir)
}
if !ctx.target.isAnyPtr(arg.Type()) && arg.Type() != typ {
return fmt.Errorf("bad arg type %#v, expect %#v", arg.Type(), typ)
}
ctx.args[arg] = true
return arg.validate(ctx, dir)
}
func (arg *ConstArg) validate(ctx *validCtx, dir Dir) error {
switch typ := arg.Type().(type) {
case *IntType:
if arg.Dir() == DirOut && !isDefault(arg) {
return fmt.Errorf("out int arg '%v' has bad const value %v", typ.Name(), arg.Val)
}
case *ProcType:
if arg.Val >= typ.ValuesPerProc && !isDefault(arg) {
return fmt.Errorf("per proc arg '%v' has bad value %v", typ.Name(), arg.Val)
}
case *CsumType:
if arg.Val != 0 {
return fmt.Errorf("csum arg '%v' has nonzero value %v", typ.Name(), arg.Val)
}
case *ConstType, *FlagsType, *LenType:
default:
return fmt.Errorf("const arg %v has bad type %v", arg, typ.Name())
}
if arg.Dir() == DirOut {
// We generate output len arguments, which makes sense since it can be
// a length of a variable-length array which is not known otherwise.
typ := arg.Type()
if _, isLen := typ.(*LenType); !isLen {
if !typ.isDefaultArg(arg) {
return fmt.Errorf("output arg %q has non default value %+v", typ.Name(), arg)
}
}
}
return nil
}
func (arg *ResultArg) validate(ctx *validCtx, dir Dir) error {
typ, ok := arg.Type().(*ResourceType)
if !ok {
return fmt.Errorf("result arg %v has bad type %v", arg, arg.Type().Name())
}
for u := range arg.uses {
if u == nil {
return fmt.Errorf("nil reference in uses for arg %+v", arg)
}
if u.Res != arg {
return fmt.Errorf("result arg '%v' has broken uses link to (%+v)", arg, u)
}
ctx.uses[u] = arg
}
if arg.Dir() == DirOut && arg.Val != 0 && arg.Val != typ.Default() {
return fmt.Errorf("out resource arg '%v' has bad const value %v", typ.Name(), arg.Val)
}
if arg.Res != nil {
if !ctx.args[arg.Res] {
return fmt.Errorf("result arg %v references out-of-tree result: %#v -> %#v",
typ.Name(), arg, arg.Res)
}
if !arg.Res.uses[arg] {
return fmt.Errorf("result arg '%v' has broken link (%+v)", typ.Name(), arg.Res.uses)
}
}
if arg.Dir() == DirIn && len(arg.uses) > 0 {
return fmt.Errorf("result arg '%v' is DirIn, but is used %d times", typ.Name(), len(arg.uses))
}
if len(arg.uses) > 0 && arg.Size() > 8 {
return fmt.Errorf("result arg '%v' is to be copied out, yet it's bigger than int64 (%d > 8)", typ.Name(), arg.Size())
}
return nil
}
func (arg *DataArg) validate(ctx *validCtx, dir Dir) error {
typ, ok := arg.Type().(*BufferType)
if !ok {
return fmt.Errorf("data arg %v has bad type %v", arg, arg.Type().Name())
}
if arg.Dir() == DirOut && len(arg.data) != 0 {
return fmt.Errorf("output arg '%v' has data", typ.Name())
}
if !typ.Varlen() && typ.Size() != arg.Size() {
return fmt.Errorf("data arg %v has wrong size %v, want %v",
typ.Name(), arg.Size(), typ.Size())
}
switch typ.Kind {
case BufferString:
if typ.TypeSize != 0 && arg.Size() != typ.TypeSize {
return fmt.Errorf("string arg '%v' has size %v, which should be %v",
typ.Name(), arg.Size(), typ.TypeSize)
}
case BufferFilename:
if !ctx.isUnsafe && escapingFilename(string(arg.data)) {
return fmt.Errorf("escaping filename %q", arg.data)
}
}
return nil
}
func (arg *GroupArg) validate(ctx *validCtx, dir Dir) error {
switch typ := arg.Type().(type) {
case *StructType:
if len(arg.Inner) != len(typ.Fields) {
return fmt.Errorf("struct arg '%v' has wrong number of fields: want %v, got %v",
typ.Name(), len(typ.Fields), len(arg.Inner))
}
for i, field := range arg.Inner {
if err := ctx.validateArg(field, typ.Fields[i].Type, typ.Fields[i].Dir(dir)); err != nil {
return err
}
}
case *ArrayType:
if typ.Kind == ArrayRangeLen && typ.RangeBegin == typ.RangeEnd &&
uint64(len(arg.Inner)) != typ.RangeBegin {
return fmt.Errorf("array %v has wrong number of elements %v, want %v",
typ.Name(), len(arg.Inner), typ.RangeBegin)
}
for _, elem := range arg.Inner {
if err := ctx.validateArg(elem, typ.Elem, dir); err != nil {
return err
}
}
default:
return fmt.Errorf("group arg %v has bad type %v", arg, typ.Name())
}
return nil
}
func (arg *UnionArg) validate(ctx *validCtx, dir Dir) error {
typ, ok := arg.Type().(*UnionType)
if !ok {
return fmt.Errorf("union arg %v has bad type %v", arg, arg.Type().Name())
}
if arg.Index < 0 || arg.Index >= len(typ.Fields) {
return fmt.Errorf("union arg %v has bad index %v/%v", arg, arg.Index, len(typ.Fields))
}
if arg.transient && !ctx.opts.ignoreTransient {
// The union must have been patched via Call.setDefaultConditions.
return fmt.Errorf("union arg %v is transient (incomplete)", arg)
}
opt := typ.Fields[arg.Index]
return ctx.validateArg(arg.Option, opt.Type, opt.Dir(dir))
}
func (arg *PointerArg) validate(ctx *validCtx, dir Dir) error {
switch typ := arg.Type().(type) {
case *VmaType:
if arg.Res != nil {
return fmt.Errorf("vma arg '%v' has data", typ.Name())
}
case *PtrType:
if arg.Res != nil {
if err := ctx.validateArg(arg.Res, typ.Elem, typ.ElemDir); err != nil {
return err
}
}
if arg.VmaSize != 0 {
return fmt.Errorf("pointer arg '%v' has nonzero size", typ.Name())
}
if arg.Dir() == DirOut {
return fmt.Errorf("pointer arg '%v' has output direction", typ.Name())
}
default:
return fmt.Errorf("ptr arg %v has bad type %v", arg, typ.Name())
}
if arg.IsSpecial() {
if -arg.Address >= uint64(len(ctx.target.SpecialPointers)) {
return fmt.Errorf("special ptr arg %v has bad value 0x%x", arg.Type().Name(), arg.Address)
}
} else {
maxMem := ctx.target.NumPages * ctx.target.PageSize
addr, size := arg.Address, arg.VmaSize
if size == 0 && arg.Res != nil {
size = arg.Res.Size()
}
if ctx.isUnsafe {
// Allow mapping 2 surrounding pages for DataMmapProg.
addr += ctx.target.PageSize
maxMem += 2 * ctx.target.PageSize
}
if addr >= maxMem || addr+size > maxMem {
return fmt.Errorf("ptr %v has bad address %v/%v/%v",
arg.Type().Name(), arg.Address, arg.VmaSize, size)
}
}
return nil
}
// Copyright 2021 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package darwin
import (
"github.com/google/syzkaller/prog"
"github.com/google/syzkaller/sys/targets"
)
func InitTarget(target *prog.Target) {
arch := &arch{
unix: targets.MakeUnixNeutralizer(target),
}
target.MakeDataMmap = targets.MakePosixMmap(target, false, false)
target.Neutralize = arch.unix.Neutralize
}
type arch struct {
unix *targets.UnixNeutralizer
}
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package freebsd
import (
"github.com/google/syzkaller/prog"
"github.com/google/syzkaller/sys/targets"
)
func InitTarget(target *prog.Target) {
arch := &arch{
unix: targets.MakeUnixNeutralizer(target),
}
target.MakeDataMmap = targets.MakePosixMmap(target, true, false)
target.Neutralize = arch.unix.Neutralize
}
type arch struct {
unix *targets.UnixNeutralizer
}
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
//go:generate bash -c "TARGETARCH=amd64 go run fidlgen/main.go"
//go:generate bash -c "TARGETARCH=arm64 go run fidlgen/main.go"
package fuchsia
import (
"github.com/google/syzkaller/prog"
"github.com/google/syzkaller/sys/targets"
)
func InitTarget(target *prog.Target) {
target.MakeDataMmap = targets.MakeSyzMmap(target)
}
// Copyright 2025 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package generated
import (
"bytes"
"compress/flate"
"embed"
"encoding/gob"
"fmt"
"path/filepath"
"github.com/google/syzkaller/prog"
"github.com/google/syzkaller/sys/targets"
)
type Desc struct {
Syscalls []*prog.Syscall
Resources []*prog.ResourceDesc
Consts []prog.ConstValue
Flags []prog.FlagDesc
Types []prog.Type
}
func Register(os, arch, revision string, init func(*prog.Target), files embed.FS) {
sysTarget := targets.Get(os, arch)
target := &prog.Target{
OS: os,
Arch: arch,
Revision: revision,
PtrSize: sysTarget.PtrSize,
PageSize: sysTarget.PageSize,
NumPages: sysTarget.NumPages,
DataOffset: sysTarget.DataOffset,
BigEndian: sysTarget.BigEndian,
}
filler := func(target *prog.Target) {
fill(target, files)
}
prog.RegisterTarget(target, filler, init)
}
func fill(target *prog.Target, files embed.FS) {
data, err := files.ReadFile(FileName(target.OS, target.Arch))
if err != nil {
panic(err)
}
desc := new(Desc)
if err := gob.NewDecoder(flate.NewReader(bytes.NewReader(data))).Decode(desc); err != nil {
panic(err)
}
target.Syscalls = desc.Syscalls
target.Resources = desc.Resources
target.Consts = desc.Consts
target.Flags = desc.Flags
target.Types = desc.Types
}
func Serialize(desc *Desc) ([]byte, error) {
out := new(bytes.Buffer)
compressor, err := flate.NewWriter(out, flate.DefaultCompression)
if err != nil {
return nil, err
}
enc := gob.NewEncoder(compressor)
if err := enc.Encode(desc); err != nil {
return nil, err
}
if err := compressor.Close(); err != nil {
return nil, err
}
return out.Bytes(), nil
}
func FileName(os, arch string) string {
return fileName(fmt.Sprintf("%v_%v", os, arch))
}
func Glob() string {
return fileName("*")
}
func fileName(name string) string {
return filepath.Join("gen", fmt.Sprintf("%v.gob.flate", name))
}
func init() {
gob.Register(prog.Ref(0))
gob.Register(&prog.ResourceType{})
gob.Register(&prog.ConstType{})
gob.Register(&prog.IntType{})
gob.Register(&prog.FlagsType{})
gob.Register(&prog.LenType{})
gob.Register(&prog.ProcType{})
gob.Register(&prog.CsumType{})
gob.Register(&prog.VmaType{})
gob.Register(&prog.BufferType{})
gob.Register(&prog.ArrayType{})
gob.Register(&prog.PtrType{})
gob.Register(&prog.StructType{})
gob.Register(&prog.UnionType{})
gob.Register(&prog.BinaryExpression{})
gob.Register(&prog.Value{})
}
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package linux
import (
"github.com/google/syzkaller/prog"
"github.com/google/syzkaller/sys/targets"
)
func InitTarget(target *prog.Target) {
arch := &arch{
unix: targets.MakeUnixNeutralizer(target),
clockGettimeSyscall: target.SyscallMap["clock_gettime"],
MREMAP_MAYMOVE: target.GetConst("MREMAP_MAYMOVE"),
MREMAP_FIXED: target.GetConst("MREMAP_FIXED"),
SYSLOG_ACTION_CONSOLE_OFF: target.GetConst("SYSLOG_ACTION_CONSOLE_OFF"),
SYSLOG_ACTION_CONSOLE_ON: target.GetConst("SYSLOG_ACTION_CONSOLE_ON"),
SYSLOG_ACTION_CONSOLE_LEVEL: target.GetConst("SYSLOG_ACTION_CONSOLE_LEVEL"),
SYSLOG_ACTION_CLEAR: target.GetConst("SYSLOG_ACTION_CLEAR"),
SYSLOG_ACTION_SIZE_UNREAD: target.GetConst("SYSLOG_ACTION_SIZE_UNREAD"),
FIFREEZE: target.GetConst("FIFREEZE"),
FITHAW: target.GetConst("FITHAW"),
SNAPSHOT_FREEZE: target.GetConst("SNAPSHOT_FREEZE"),
SNAPSHOT_POWER_OFF: target.GetConst("SNAPSHOT_POWER_OFF"),
FAN_OPEN_PERM: target.GetConst("FAN_OPEN_PERM"),
FAN_ACCESS_PERM: target.GetConst("FAN_ACCESS_PERM"),
FAN_OPEN_EXEC_PERM: target.GetConst("FAN_OPEN_EXEC_PERM"),
PTRACE_TRACEME: target.GetConst("PTRACE_TRACEME"),
CLOCK_REALTIME: target.GetConst("CLOCK_REALTIME"),
AF_NFC: target.GetConst("AF_NFC"),
AF_LLC: target.GetConst("AF_LLC"),
AF_BLUETOOTH: target.GetConst("AF_BLUETOOTH"),
AF_X25: target.GetConst("AF_X25"),
AF_AX25: target.GetConst("AF_AX25"),
AF_NETROM: target.GetConst("AF_NETROM"),
AF_ROSE: target.GetConst("AF_ROSE"),
AF_IEEE802154: target.GetConst("AF_IEEE802154"),
AF_NETLINK: target.GetConst("AF_NETLINK"),
SOCK_RAW: target.GetConst("SOCK_RAW"),
NETLINK_GENERIC: target.GetConst("NETLINK_GENERIC"),
TIOCSSERIAL: target.GetConst("TIOCSSERIAL"),
TIOCGSERIAL: target.GetConst("TIOCGSERIAL"),
// These are not present on all arches.
ARCH_SET_FS: target.ConstMap["ARCH_SET_FS"],
ARCH_SET_GS: target.ConstMap["ARCH_SET_GS"],
}
target.MakeDataMmap = targets.MakePosixMmap(target, true, true)
target.Neutralize = arch.neutralize
target.SpecialTypes = map[string]func(g *prog.Gen, typ prog.Type, dir prog.Dir, old prog.Arg) (
prog.Arg, []*prog.Call){
"timespec": arch.generateTimespec,
"timeval": arch.generateTimespec,
"sockaddr_alg": arch.generateSockaddrAlg,
"alg_name": arch.generateAlgName,
"alg_aead_name": arch.generateAlgAeadName,
"alg_hash_name": arch.generateAlgHashName,
"alg_skcipher_name": arch.generateAlgSkcipherhName,
"ipt_replace": arch.generateIptables,
"ip6t_replace": arch.generateIptables,
"arpt_replace": arch.generateArptables,
"ebt_replace": arch.generateEbtables,
"usb_device_descriptor": arch.generateUsbDeviceDescriptor,
"usb_device_descriptor_hid": arch.generateUsbHidDeviceDescriptor,
}
target.AuxResources = map[string]bool{
"uid": true,
"pid": true,
"gid": true,
"timespec": true,
"timeval": true,
"time_sec": true,
"time_usec": true,
"time_nsec": true,
}
switch target.Arch {
case targets.AMD64:
target.SpecialPointers = []uint64{
0xffffffff81000000, // kernel text
0xffffffffff600000, // VSYSCALL_ADDR
}
case targets.RiscV64:
target.SpecialPointers = []uint64{
0xffffffe000000000, // PAGE_OFFSET
0xffffff0000000000, // somewhere in VMEMMAP range
}
case targets.I386, targets.ARM64, targets.ARM, targets.PPC64LE, targets.MIPS64LE, targets.S390x:
default:
panic("unknown arch")
}
target.SpecialFileLenghts = []int{
int(target.GetConst("PATH_MAX")),
int(target.GetConst("UNIX_PATH_MAX")),
int(target.GetConst("NAME_MAX")),
int(target.GetConst("BTRFS_INO_LOOKUP_PATH_MAX")),
int(target.GetConst("BTRFS_INO_LOOKUP_USER_PATH_MAX")),
int(target.GetConst("SMB_PATH_MAX")),
int(target.GetConst("XT_CGROUP_PATH_MAX")),
int(target.GetConst("XENSTORE_REL_PATH_MAX")),
1 << 16, // gVisor's MaxFilenameLen
}
}
type arch struct {
unix *targets.UnixNeutralizer
clockGettimeSyscall *prog.Syscall
MREMAP_MAYMOVE uint64
MREMAP_FIXED uint64
SYSLOG_ACTION_CONSOLE_OFF uint64
SYSLOG_ACTION_CONSOLE_ON uint64
SYSLOG_ACTION_CONSOLE_LEVEL uint64
SYSLOG_ACTION_CLEAR uint64
SYSLOG_ACTION_SIZE_UNREAD uint64
FIFREEZE uint64
FITHAW uint64
SNAPSHOT_FREEZE uint64
SNAPSHOT_POWER_OFF uint64
FAN_OPEN_PERM uint64
FAN_ACCESS_PERM uint64
FAN_OPEN_EXEC_PERM uint64
PTRACE_TRACEME uint64
CLOCK_REALTIME uint64
ARCH_SET_FS uint64
ARCH_SET_GS uint64
AF_NFC uint64
AF_LLC uint64
AF_BLUETOOTH uint64
AF_X25 uint64
AF_AX25 uint64
AF_NETROM uint64
AF_ROSE uint64
AF_IEEE802154 uint64
AF_NETLINK uint64
SOCK_RAW uint64
NETLINK_GENERIC uint64
TIOCSSERIAL uint64
TIOCGSERIAL uint64
}
func (arch *arch) neutralize(c *prog.Call, fixStructure bool) error {
err := arch.unix.Neutralize(c, fixStructure)
if err != nil {
return err
}
switch c.Meta.CallName {
case "mremap":
// Add MREMAP_FIXED flag, otherwise it produces non-deterministic results.
flags := c.Args[3].(*prog.ConstArg)
if flags.Val&arch.MREMAP_MAYMOVE != 0 {
flags.Val |= arch.MREMAP_FIXED
}
case "syslog":
cmd := c.Args[0].(*prog.ConstArg)
cmd.Val = uint64(uint32(cmd.Val))
// These disable console output, but we need it.
if cmd.Val == arch.SYSLOG_ACTION_CONSOLE_OFF ||
cmd.Val == arch.SYSLOG_ACTION_CONSOLE_ON ||
cmd.Val == arch.SYSLOG_ACTION_CONSOLE_LEVEL ||
cmd.Val == arch.SYSLOG_ACTION_CLEAR {
cmd.Val = arch.SYSLOG_ACTION_SIZE_UNREAD
}
case "ioctl":
arch.neutralizeIoctl(c)
case "fanotify_mark":
// FAN_*_PERM require the program to reply to open requests.
// If that does not happen, the program will hang in an unkillable state forever.
// See the following bug for details:
// https://groups.google.com/d/msg/syzkaller-bugs/pD-vbqJu6U0/kGH30p3lBgAJ
mask := c.Args[2].(*prog.ConstArg)
mask.Val &^= arch.FAN_OPEN_PERM | arch.FAN_ACCESS_PERM | arch.FAN_OPEN_EXEC_PERM
case "ptrace":
req := c.Args[0].(*prog.ConstArg)
// PTRACE_TRACEME leads to unkillable processes, see:
// https://groups.google.com/forum/#!topic/syzkaller/uGzwvhlCXAw
if uint64(uint32(req.Val)) == arch.PTRACE_TRACEME {
req.Val = ^uint64(0)
}
case "arch_prctl":
// fs holds address of tls, if a program messes it at least signal
// handling will break. This also allows a program to do writes
// at arbitrary addresses, which usually leads to machine outbreak.
cmd := c.Args[0].(*prog.ConstArg)
if uint64(uint32(cmd.Val)) == arch.ARCH_SET_FS {
cmd.Val = arch.ARCH_SET_GS
}
case "init_module":
// Kernel tries to vmalloc whatever we pass as size and it's not accounted against memcg.
// As the result it can lead to massive OOM kills of everything running on the machine.
// Strictly saying, the same applies to finit_module with a sparse file too,
// but there is no simple way to handle that.
sz := c.Args[1].(*prog.ConstArg)
sz.Val %= 1 << 20
case "syz_init_net_socket":
// Don't let it mess with arbitrary sockets in init namespace.
family := c.Args[0].(*prog.ConstArg)
switch uint64(uint32(family.Val)) {
case arch.AF_NFC, arch.AF_LLC, arch.AF_BLUETOOTH, arch.AF_IEEE802154,
arch.AF_X25, arch.AF_AX25, arch.AF_NETROM, arch.AF_ROSE:
case arch.AF_NETLINK:
c.Args[1].(*prog.ConstArg).Val = arch.SOCK_RAW
c.Args[2].(*prog.ConstArg).Val = arch.NETLINK_GENERIC
default:
family.Val = ^uint64(0)
}
case "syz_open_dev":
enforceIntArg(c.Args[0])
enforceIntArg(c.Args[1])
enforceIntArg(c.Args[2])
case "sched_setattr":
// Enabling a SCHED_FIFO or a SCHED_RR policy may lead to false positive stall-related crashes.
neutralizeSchedAttr(c.Args[1])
}
switch c.Meta.Name {
case "setsockopt$EBT_SO_SET_ENTRIES":
arch.neutralizeEbtables(c)
}
return nil
}
func neutralizeSchedAttr(a prog.Arg) {
switch attr := a.(type) {
case *prog.PointerArg:
if attr.Res == nil {
// If it's just a pointer to somewhere, still set it to NULL as there's a risk that
// it points to the valid memory and it can be interpreted as a sched_attr struct.
attr.Address = 0
return
}
groupArg, ok := attr.Res.(*prog.GroupArg)
if !ok || len(groupArg.Inner) == 0 {
return
}
if unionArg, ok := groupArg.Inner[0].(*prog.UnionArg); ok {
dataArg, ok := unionArg.Option.(*prog.DataArg)
if !ok {
return
}
if dataArg.Dir() == prog.DirOut {
return
}
// Clear the first 16 bytes to prevent overcoming the limitation by squashing the struct.
data := append([]byte{}, dataArg.Data()...)
for i := 0; i < 16 && i < len(data); i++ {
data[i] = 0
}
dataArg.SetData(data)
}
// Most likely it's the intended sched_attr structure.
if len(groupArg.Inner) > 1 {
policyField, ok := groupArg.Inner[1].(*prog.ConstArg)
if !ok {
return
}
const SCHED_FIFO = 0x1
const SCHED_RR = 0x2
if policyField.Val == SCHED_FIFO || policyField.Val == SCHED_RR {
policyField.Val = 0
}
}
case *prog.ConstArg:
attr.Val = 0
}
}
func enforceIntArg(a prog.Arg) {
arg, ok := a.(*prog.ConstArg)
if !ok {
return
}
switch typ := arg.Type().(type) {
case *prog.ConstType:
arg.Val = typ.Val
case *prog.IntType:
if typ.Kind == prog.IntRange && (arg.Val < typ.RangeBegin || arg.Val > typ.RangeEnd) {
arg.Val = typ.RangeBegin
}
}
}
func (arch *arch) neutralizeIoctl(c *prog.Call) {
cmd := c.Args[1].(*prog.ConstArg)
switch uint64(uint32(cmd.Val)) {
case arch.FIFREEZE:
// Freeze kills machine. Though, it is an interesting functions,
// so we need to test it somehow.
// TODO: not required if executor drops privileges.
// Fortunately, the value does not conflict with any other ioctl commands for now.
cmd.Val = arch.FITHAW
case arch.SNAPSHOT_FREEZE:
// SNAPSHOT_FREEZE freezes all processes and leaves the machine dead.
cmd.Val = arch.FITHAW
case arch.SNAPSHOT_POWER_OFF:
// SNAPSHOT_POWER_OFF shuts down the machine.
cmd.Val = arch.FITHAW
case arch.TIOCSSERIAL:
// TIOCSSERIAL can do nasty things under root, like causing writes to random memory
// pretty much like /dev/mem, but this is also working as intended.
// For details see:
// https://groups.google.com/g/syzkaller-bugs/c/1rVENJf9P4U/m/QtGpapRxAgAJ
// https://syzkaller.appspot.com/bug?extid=f4f1e871965064ae689e
// TODO: TIOCSSERIAL does some other things that are not dangerous
// and would be nice to test, if/when we can neutralize based on sandbox value
// we could prohibit it only under sandbox=none.
cmd.Val = arch.TIOCGSERIAL
}
}
func (arch *arch) generateTimespec(g *prog.Gen, typ0 prog.Type, dir prog.Dir, old prog.Arg) (
arg prog.Arg, calls []*prog.Call) {
typ := typ0.(*prog.StructType)
// We need to generate timespec/timeval that are either
// (1) definitely in the past, or
// (2) definitely in unreachable fututre, or
// (3) few ms ahead of now.
// Note: timespec/timeval can be absolute or relative to now.
// Note: executor has blocking syscall timeout of 45 ms,
// so we generate both 10ms and 60ms.
// TODO(dvyukov): this is now all outdated with tunable timeouts.
const (
timeout1 = uint64(10)
timeout2 = uint64(60)
)
usec := typ.Name() == "timeval"
switch {
case g.NOutOf(1, 4):
// Now for relative, past for absolute.
arg = prog.MakeGroupArg(typ, dir, []prog.Arg{
prog.MakeResultArg(typ.Fields[0].Type, dir, nil, 0),
prog.MakeResultArg(typ.Fields[1].Type, dir, nil, 0),
})
case g.NOutOf(1, 3):
// Few ms ahead for relative, past for absolute.
nsec := timeout1 * 1e6
if g.NOutOf(1, 2) {
nsec = timeout2 * 1e6
}
if usec {
nsec /= 1e3
}
arg = prog.MakeGroupArg(typ, dir, []prog.Arg{
prog.MakeResultArg(typ.Fields[0].Type, dir, nil, 0),
prog.MakeResultArg(typ.Fields[1].Type, dir, nil, nsec),
})
case g.NOutOf(1, 2):
// Unreachable fututre for both relative and absolute.
arg = prog.MakeGroupArg(typ, dir, []prog.Arg{
prog.MakeResultArg(typ.Fields[0].Type, dir, nil, 2e9),
prog.MakeResultArg(typ.Fields[1].Type, dir, nil, 0),
})
default:
// Few ms ahead for absolute.
meta := arch.clockGettimeSyscall
ptrArgType := meta.Args[1].Type.(*prog.PtrType)
argType := ptrArgType.Elem.(*prog.StructType)
tp := prog.MakeGroupArg(argType, prog.DirOut, []prog.Arg{
prog.MakeResultArg(argType.Fields[0].Type, prog.DirOut, nil, 0),
prog.MakeResultArg(argType.Fields[1].Type, prog.DirOut, nil, 0),
})
var tpaddr prog.Arg
tpaddr, calls = g.Alloc(ptrArgType, prog.DirIn, tp)
gettime := prog.MakeCall(meta, []prog.Arg{
prog.MakeConstArg(meta.Args[0].Type, prog.DirIn, arch.CLOCK_REALTIME),
tpaddr,
})
calls = append(calls, gettime)
sec := prog.MakeResultArg(typ.Fields[0].Type, dir, tp.Inner[0].(*prog.ResultArg), 0)
nsec := prog.MakeResultArg(typ.Fields[1].Type, dir, tp.Inner[1].(*prog.ResultArg), 0)
msec := timeout1
if g.NOutOf(1, 2) {
msec = timeout2
}
if usec {
nsec.OpDiv = 1e3
nsec.OpAdd = msec * 1e3
} else {
nsec.OpAdd = msec * 1e6
}
arg = prog.MakeGroupArg(typ, dir, []prog.Arg{sec, nsec})
}
return
}
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package linux
import (
"math/rand"
"github.com/google/syzkaller/prog"
)
func (arch *arch) generateSockaddrAlg(g *prog.Gen, typ0 prog.Type, dir prog.Dir, old prog.Arg) (
arg prog.Arg, calls []*prog.Call) {
typ := typ0.(*prog.StructType)
family := g.GenerateArg(typ.Fields[0].Type, dir, &calls)
// There is very little point in generating feat/mask,
// because that can only fail otherwise correct bind.
feat := prog.MakeConstArg(typ.Fields[2].Type, dir, 0)
mask := prog.MakeConstArg(typ.Fields[3].Type, dir, 0)
if g.NOutOf(1, 1000) {
feat = g.GenerateArg(typ.Fields[2].Type, dir, &calls).(*prog.ConstArg)
mask = g.GenerateArg(typ.Fields[3].Type, dir, &calls).(*prog.ConstArg)
}
algType, algName := generateAlgName(g.Rand())
// Extend/truncate type/name to their fixed sizes.
algTypeData := fixedSizeData(algType, typ.Fields[1].Type.Size())
algNameData := fixedSizeData(algName, typ.Fields[4].Type.Size())
arg = prog.MakeGroupArg(typ, dir, []prog.Arg{
family,
prog.MakeDataArg(typ.Fields[1].Type, dir, algTypeData),
feat,
mask,
prog.MakeDataArg(typ.Fields[4].Type, dir, algNameData),
})
return
}
func (arch *arch) generateAlgName(g *prog.Gen, typ prog.Type, dir prog.Dir, old prog.Arg) (
arg prog.Arg, calls []*prog.Call) {
return generateAlgNameStruct(g, typ, dir, allTypes[g.Rand().Intn(len(allTypes))].typ)
}
func (arch *arch) generateAlgAeadName(g *prog.Gen, typ prog.Type, dir prog.Dir, old prog.Arg) (
arg prog.Arg, calls []*prog.Call) {
return generateAlgNameStruct(g, typ, dir, ALG_AEAD)
}
func (arch *arch) generateAlgHashName(g *prog.Gen, typ prog.Type, dir prog.Dir, old prog.Arg) (
arg prog.Arg, calls []*prog.Call) {
return generateAlgNameStruct(g, typ, dir, ALG_HASH)
}
func (arch *arch) generateAlgSkcipherhName(g *prog.Gen, typ prog.Type, dir prog.Dir, old prog.Arg) (
arg prog.Arg, calls []*prog.Call) {
return generateAlgNameStruct(g, typ, dir, ALG_SKCIPHER)
}
func generateAlgNameStruct(g *prog.Gen, typ0 prog.Type, dir prog.Dir, algTyp int) (
arg prog.Arg, calls []*prog.Call) {
typ := typ0.(*prog.StructType)
algName := generateAlg(g.Rand(), algTyp)
algNameData := fixedSizeData(algName, typ.Fields[0].Size())
arg = prog.MakeGroupArg(typ, dir, []prog.Arg{
prog.MakeDataArg(typ.Fields[0].Type, dir, algNameData),
})
return
}
func generateAlgName(rnd *rand.Rand) (string, string) {
typ := allTypes[rnd.Intn(len(allTypes))]
name := generateAlg(rnd, typ.typ)
return typ.name, name
}
func generateAlg(rnd *rand.Rand, typ int) string {
algs := allAlgs[typ]
alg := algs[rnd.Intn(len(algs))]
return generateAlgImpl(rnd, alg)
}
func generateAlgImpl(rnd *rand.Rand, alg algDesc) string {
args := ""
if len(alg.args) != 0 {
args += "("
for i, a := range alg.args {
if i != 0 {
args += ","
}
args += generateAlg(rnd, a)
}
args += ")"
}
return alg.name + args
}
func fixedSizeData(str string, sz uint64) []byte {
return append([]byte(str), make([]byte, sz)...)[:sz]
}
type algType struct {
name string
typ int
}
type algDesc struct {
name string
args []int
}
const (
ALG_CIPHER = iota
ALG_SKCIPHER
ALG_AEAD
ALG_HASH
ALG_RNG
)
var allTypes = []algType{
{"aead", ALG_AEAD},
{"skcipher", ALG_SKCIPHER},
{"hash", ALG_HASH},
{"rng", ALG_RNG},
}
// Algorithms can be extracted with something along the following lines:
//
// cat /proc/crypto | grep -B 8 ": skcipher" | grep -B 7 "internal : no" | egrep "name |driver " | \
// cut -b 16- | sort | uniq | awk '{printf("{\"%s\", nil},\n", $1)}'
//
// Note: the kernel needs to include all crypto configs and CPU needs to support AVX/NEON/etc.
var allAlgs = map[int][]algDesc{
ALG_AEAD: {
// templates:
{"authenc", []int{ALG_HASH, ALG_SKCIPHER}},
{"authencesn", []int{ALG_HASH, ALG_SKCIPHER}},
{"ccm", []int{ALG_CIPHER}},
{"ccm_base", []int{ALG_SKCIPHER, ALG_HASH}},
{"echainiv", []int{ALG_AEAD}},
{"essiv", []int{ALG_AEAD, ALG_HASH}},
{"gcm", []int{ALG_CIPHER}},
{"gcm_base", []int{ALG_SKCIPHER, ALG_HASH}},
{"pcrypt", []int{ALG_AEAD}},
{"rfc4106", []int{ALG_AEAD}},
{"rfc4309", []int{ALG_AEAD}},
{"rfc4543", []int{ALG_AEAD}},
{"rfc7539", []int{ALG_SKCIPHER, ALG_HASH}},
{"rfc7539esp", []int{ALG_SKCIPHER, ALG_HASH}},
{"seqiv", []int{ALG_AEAD}},
// algorithms:
{"aegis128", nil},
{"aegis128-aesni", nil},
{"aegis128-generic", nil},
{"aegis128l", nil},
{"aegis128l-aesni", nil},
{"aegis128l-generic", nil},
{"aegis256", nil},
{"aegis256-aesni", nil},
{"aegis256-generic", nil},
{"ccm-aes-ce", nil},
{"gcm(aes)", nil},
{"gcm-aes-ce", nil},
{"gcm_base(ctr(aes-aesni),ghash-generic)", nil},
{"generic-gcm-aesni", nil},
{"morus1280", nil},
{"morus1280-avx2", nil},
{"morus1280-generic", nil},
{"morus1280-sse2", nil},
{"morus640", nil},
{"morus640-generic", nil},
{"morus640-sse2", nil},
{"rfc4106(gcm(aes))", nil},
{"rfc4106-gcm-aesni", nil},
},
ALG_SKCIPHER: {
// templates:
{"adiantum", []int{ALG_SKCIPHER, ALG_CIPHER, ALG_HASH}},
{"adiantum", []int{ALG_SKCIPHER, ALG_CIPHER}},
{"cbc", []int{ALG_CIPHER}},
{"cfb", []int{ALG_CIPHER}},
{"cryptd", []int{ALG_SKCIPHER}},
{"ctr", []int{ALG_CIPHER}},
{"cts", []int{ALG_SKCIPHER}},
{"ecb", []int{ALG_CIPHER}},
{"essiv", []int{ALG_SKCIPHER, ALG_HASH}},
{"fpu", []int{ALG_SKCIPHER}},
{"kw", []int{ALG_CIPHER}},
{"lrw", []int{ALG_SKCIPHER}},
{"lrw", []int{ALG_CIPHER}},
{"ofb", []int{ALG_CIPHER}},
{"pcbc", []int{ALG_CIPHER}},
{"rfc3686", []int{ALG_SKCIPHER}},
{"xts", []int{ALG_SKCIPHER}},
{"xts", []int{ALG_CIPHER}},
// algorithms:
{"cbc(aes)", nil},
{"cbc(aes-aesni)", nil},
{"cbc-aes-aesni", nil},
{"cbc(aes-arm)", nil},
{"cbc(aes-ce)", nil},
{"cbc-aes-ce", nil},
{"cbc-aes-neonbs", nil},
{"cbc(blowfish)", nil},
{"cbc-blowfish-asm", nil},
{"cbc(camellia)", nil},
{"cbc-camellia-aesni", nil},
{"cbc-camellia-aesni-avx2", nil},
{"cbc-camellia-asm", nil},
{"cbc(cast5)", nil},
{"cbc-cast5-avx", nil},
{"cbc(cast6)", nil},
{"cbc-cast6-avx", nil},
{"cbc(des3_ede)", nil},
{"cbc-des3_ede-asm", nil},
{"cbc(serpent)", nil},
{"cbc-serpent-avx", nil},
{"cbc-serpent-avx2", nil},
{"cbc-serpent-sse2", nil},
{"cbc(twofish)", nil},
{"cbc-twofish-3way", nil},
{"cbc-twofish-avx", nil},
{"chacha20", nil},
{"chacha20-arm", nil},
{"chacha20-generic", nil},
{"chacha20-neon", nil},
{"chacha20-simd", nil},
{"ctr(aes)", nil},
{"ctr(aes-aesni)", nil},
{"ctr(blowfish)", nil},
{"ctr(camellia)", nil},
{"ctr(cast5)", nil},
{"ctr(cast6)", nil},
{"ctr(des3_ede)", nil},
{"ctr(serpent)", nil},
{"ctr(twofish)", nil},
{"ctr-aes-aesni", nil},
{"ctr-aes-ce", nil},
{"ctr-aes-neon", nil},
{"ctr-aes-neonbs", nil},
{"ctr-aes-neonbs-sync", nil},
{"ctr-blowfish-asm", nil},
{"ctr-camellia-aesni", nil},
{"ctr-camellia-aesni-avx2", nil},
{"ctr-camellia-asm", nil},
{"ctr-cast5-avx", nil},
{"ctr-cast6-avx", nil},
{"ctr-des3_ede-asm", nil},
{"ctr-serpent-avx", nil},
{"ctr-serpent-avx2", nil},
{"ctr-serpent-sse2", nil},
{"ctr-twofish-3way", nil},
{"ctr-twofish-avx", nil},
{"cts(cbc(aes))", nil},
{"cts-cbc-aes-aesni", nil},
{"cts-cbc-aes-ce", nil},
{"cts-cbc-aes-neon", nil},
{"ecb(aes)", nil},
{"ecb-aes-aesni", nil},
{"ecb-aes-ce", nil},
{"ecb-aes-neonbs", nil},
{"ecb(arc4)", nil},
{"ecb(arc4)-generic", nil},
{"ecb(blowfish)", nil},
{"ecb(camellia)", nil},
{"ecb(cast5)", nil},
{"ecb(cast6)", nil},
{"ecb(cipher_null)", nil},
{"ecb(des3_ede)", nil},
{"ecb(serpent)", nil},
{"ecb(twofish)", nil},
{"ecb-aes-neon", nil},
{"ecb-blowfish-asm", nil},
{"ecb-camellia-aesni", nil},
{"ecb-camellia-aesni-avx2", nil},
{"ecb-camellia-asm", nil},
{"ecb-cast5-avx", nil},
{"ecb-cast6-avx", nil},
{"ecb-cipher_null", nil},
{"ecb-des3_ede-asm", nil},
{"ecb-serpent-avx", nil},
{"ecb-serpent-avx2", nil},
{"ecb-serpent-sse2", nil},
{"ecb-twofish-3way", nil},
{"ecb-twofish-avx", nil},
{"fpu(pcbc(aes))", nil},
{"fpu(pcbc(aes-aesni))", nil},
{"lrw(camellia)", nil},
{"lrw(cast6)", nil},
{"lrw(serpent)", nil},
{"lrw(twofish)", nil},
{"lrw-camellia-aesni", nil},
{"lrw-camellia-aesni-avx2", nil},
{"lrw-camellia-asm", nil},
{"lrw-cast6-avx", nil},
{"lrw-serpent-avx", nil},
{"lrw-serpent-avx2", nil},
{"lrw-serpent-sse2", nil},
{"lrw-twofish-3way", nil},
{"lrw-twofish-avx", nil},
{"pcbc(aes)", nil},
{"pcbc(aes-aesni)", nil},
{"pcbc-aes-aesni", nil},
{"salsa20", nil},
{"salsa20-asm", nil},
{"salsa20-generic", nil},
{"essiv(cbc(aes),sha256)", nil},
{"essiv-cbc-aes-sha256-ce", nil},
{"essiv-cbc-aes-sha256-neon", nil},
{"pcbc(fcrypt)", nil},
{"pcbc(fcrypt-generic)", nil},
{"xchacha12", nil},
{"xchacha12-arm", nil},
{"xchacha12-generic", nil},
{"xchacha12-neon", nil},
{"xchacha12-simd", nil},
{"xchacha20", nil},
{"xchacha20-arm", nil},
{"xchacha20-generic", nil},
{"xchacha20-neon", nil},
{"xchacha20-simd", nil},
{"xts(aes)", nil},
{"xts(camellia)", nil},
{"xts(cast6)", nil},
{"xts(serpent)", nil},
{"xts(twofish)", nil},
{"xts-aes-aesni", nil},
{"xts-aes-ce", nil},
{"xts-aes-neonbs", nil},
{"xts-aes-neon", nil},
{"xts-camellia-aesni", nil},
{"xts-camellia-aesni-avx2", nil},
{"xts-camellia-asm", nil},
{"xts-cast6-avx", nil},
{"xts-serpent-avx", nil},
{"xts-serpent-avx2", nil},
{"xts-serpent-sse2", nil},
{"xts-twofish-3way", nil},
{"xts-twofish-avx", nil},
},
ALG_CIPHER: {
{"aes", nil},
{"aes-aesni", nil},
{"aes-arm", nil},
{"aes-arm64", nil},
{"aes-asm", nil},
{"aes-ce", nil},
{"aes-fixed-time", nil},
{"aes-generic", nil},
{"anubis", nil},
{"anubis-generic", nil},
{"arc4", nil},
{"arc4-generic", nil},
{"blowfish", nil},
{"blowfish-asm", nil},
{"blowfish-generic", nil},
{"camellia", nil},
{"camellia-asm", nil},
{"camellia-generic", nil},
{"cast5", nil},
{"cast5-generic", nil},
{"cast6", nil},
{"cast6-generic", nil},
{"cipher_null", nil},
{"cipher_null-generic", nil},
{"compress_null-generic", nil},
{"des", nil},
{"des3_ede", nil},
{"des3_ede-asm", nil},
{"des3_ede-generic", nil},
{"des-generic", nil},
{"fcrypt", nil},
{"fcrypt-generic", nil},
{"khazad", nil},
{"khazad-generic", nil},
{"seed", nil},
{"seed-generic", nil},
{"serpent", nil},
{"serpent-generic", nil},
{"sm4", nil},
{"sm4-ce", nil},
{"sm4-generic", nil},
{"tea", nil},
{"tea-generic", nil},
{"tnepres", nil},
{"tnepres-generic", nil},
{"twofish", nil},
{"twofish-asm", nil},
{"twofish-generic", nil},
{"xeta", nil},
{"xeta-generic", nil},
{"xtea", nil},
{"xtea-generic", nil},
},
ALG_HASH: {
// templates:
{"cbcmac", []int{ALG_CIPHER}},
{"cmac", []int{ALG_CIPHER}},
{"cryptd", []int{ALG_HASH}},
{"hmac", []int{ALG_HASH}},
{"mcryptd", []int{ALG_HASH}},
{"vmac", []int{ALG_CIPHER}},
{"vmac64", []int{ALG_CIPHER}},
{"xcbc", []int{ALG_CIPHER}},
// algorithms:
{"blake2b-160", nil},
{"blake2b-160-generic", nil},
{"blake2b-256", nil},
{"blake2b-256-generic", nil},
{"blake2b-384", nil},
{"blake2b-384-generic", nil},
{"blake2b-512", nil},
{"blake2b-512-generic", nil},
{"blake2s-128", nil},
{"blake2s-128-arm", nil},
{"blake2s-128-generic", nil},
{"blake2s-128-x86", nil},
{"blake2s-160", nil},
{"blake2s-160-arm", nil},
{"blake2s-160-generic", nil},
{"blake2s-160-x86", nil},
{"blake2s-224", nil},
{"blake2s-224-arm", nil},
{"blake2s-224-generic", nil},
{"blake2s-224-x86", nil},
{"blake2s-256", nil},
{"blake2s-256-arm", nil},
{"blake2s-256-generic", nil},
{"blake2s-256-x86", nil},
{"cbcmac(aes)", nil},
{"cbcmac-aes-ce", nil},
{"cbcmac-aes-neon", nil},
{"cmac(aes)", nil},
{"cmac-aes-ce", nil},
{"cmac-aes-neon", nil},
{"crc32", nil},
{"crc32c", nil},
{"crc32c-generic", nil},
{"crc32c-intel", nil},
{"crc32-generic", nil},
{"crc32-pclmul", nil},
{"crct10dif", nil},
{"crct10dif-arm64-ce", nil},
{"crct10dif-arm64-neon", nil},
{"crct10dif-generic", nil},
{"crct10dif-pclmul", nil},
{"digest_null", nil},
{"digest_null-generic", nil},
{"ghash", nil},
{"ghash-ce", nil},
{"ghash-ce-sync", nil},
{"ghash-clmulni", nil},
{"ghash-generic", nil},
{"hmac(sha1)", nil},
{"hmac(sha1-avx2)", nil},
{"hmac(sha1-ce)", nil},
{"hmac(sha1-neon)", nil},
{"hmac(sha256)", nil},
{"hmac(sha256-avx2)", nil},
{"hmac(sha256-ce)", nil},
{"hmac(sha256-neon)", nil},
{"md4", nil},
{"md4-generic", nil},
{"md5", nil},
{"md5-generic", nil},
{"michael_mic", nil},
{"michael_mic-generic", nil},
{"nhpoly1305", nil},
{"nhpoly1305-avx2", nil},
{"nhpoly1305-generic", nil},
{"nhpoly1305-neon", nil},
{"nhpoly1305-sse2", nil},
{"poly1305", nil},
{"poly1305-arm", nil},
{"poly1305-generic", nil},
{"poly1305-neon", nil},
{"poly1305-simd", nil},
{"rmd128", nil},
{"rmd128-generic", nil},
{"rmd160", nil},
{"rmd160-generic", nil},
{"rmd256", nil},
{"rmd256-generic", nil},
{"rmd320", nil},
{"rmd320-generic", nil},
{"sha1", nil},
{"sha1-asm", nil},
{"sha1-avx", nil},
{"sha1-avx2", nil},
{"sha1-ce", nil},
{"sha1-generic", nil},
{"sha1_mb", nil},
{"sha1-neon", nil},
{"sha1-ni", nil},
{"sha1-ssse3", nil},
{"sha224", nil},
{"sha224-arm64", nil},
{"sha224-arm64-neon", nil},
{"sha224-asm", nil},
{"sha224-avx", nil},
{"sha224-avx2", nil},
{"sha224-ce", nil},
{"sha224-generic", nil},
{"sha224-neon", nil},
{"sha224-ni", nil},
{"sha224-ssse3", nil},
{"sha256", nil},
{"sha256-arm64", nil},
{"sha256-arm64-neon", nil},
{"sha256-asm", nil},
{"sha256-avx", nil},
{"sha256-avx2", nil},
{"sha256-ce", nil},
{"sha256-generic", nil},
{"sha256-mb", nil},
{"sha256-neon", nil},
{"sha256-ni", nil},
{"sha256-ssse3", nil},
{"sha3-224", nil},
{"sha3-224-ce", nil},
{"sha3-224-generic", nil},
{"sha3-256", nil},
{"sha3-256-ce", nil},
{"sha3-256-generic", nil},
{"sha3-384", nil},
{"sha3-384-ce", nil},
{"sha3-384-generic", nil},
{"sha3-512", nil},
{"sha3-512-ce", nil},
{"sha3-512-generic", nil},
{"sha384", nil},
{"sha384-arm", nil},
{"sha384-arm64", nil},
{"sha384-avx", nil},
{"sha384-avx2", nil},
{"sha384-ce", nil},
{"sha384-generic", nil},
{"sha384-neon", nil},
{"sha384-ssse3", nil},
{"sha512", nil},
{"sha512-arm", nil},
{"sha512-arm64", nil},
{"sha512-avx", nil},
{"sha512-avx2", nil},
{"sha512-ce", nil},
{"sha512-generic", nil},
{"sha512_mb", nil},
{"sha512-neon", nil},
{"sha512-ssse3", nil},
{"sm3", nil},
{"sm3-ce", nil},
{"sm3-generic", nil},
{"streebog256", nil},
{"streebog256-generic", nil},
{"streebog512", nil},
{"streebog512-generic", nil},
{"tgr128", nil},
{"tgr128-generic", nil},
{"tgr160", nil},
{"tgr160-generic", nil},
{"tgr192", nil},
{"tgr192-generic", nil},
{"wp256", nil},
{"wp256-generic", nil},
{"wp384", nil},
{"wp384-generic", nil},
{"wp512", nil},
{"wp512-generic", nil},
{"xcbc(aes)", nil},
{"xcbc-aes-ce", nil},
{"xcbc-aes-neon", nil},
{"xxhash64", nil},
{"xxhash64-generic", nil},
},
ALG_RNG: {
{"ansi_cprng", nil},
{"drbg_nopr_ctr_aes128", nil},
{"drbg_nopr_ctr_aes192", nil},
{"drbg_nopr_ctr_aes256", nil},
{"drbg_nopr_hmac_sha1", nil},
{"drbg_nopr_hmac_sha256", nil},
{"drbg_nopr_hmac_sha384", nil},
{"drbg_nopr_hmac_sha512", nil},
{"drbg_nopr_sha1", nil},
{"drbg_nopr_sha256", nil},
{"drbg_nopr_sha384", nil},
{"drbg_nopr_sha512", nil},
{"drbg_pr_ctr_aes128", nil},
{"drbg_pr_ctr_aes192", nil},
{"drbg_pr_ctr_aes256", nil},
{"drbg_pr_hmac_sha1", nil},
{"drbg_pr_hmac_sha256", nil},
{"drbg_pr_hmac_sha384", nil},
{"drbg_pr_hmac_sha512", nil},
{"drbg_pr_sha1", nil},
{"drbg_pr_sha256", nil},
{"drbg_pr_sha384", nil},
{"drbg_pr_sha512", nil},
{"jitterentropy_rng", nil},
{"stdrng", nil},
},
}
// Copyright 2018 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package linux
import (
"strings"
"github.com/google/syzkaller/prog"
)
func (arch *arch) generateIptables(g *prog.Gen, typ prog.Type, dir prog.Dir, old prog.Arg) (
arg prog.Arg, calls []*prog.Call) {
return arch.generateNetfilterTable(g, typ, dir, old, true, 5)
}
func (arch *arch) generateArptables(g *prog.Gen, typ prog.Type, dir prog.Dir, old prog.Arg) (
arg prog.Arg, calls []*prog.Call) {
return arch.generateNetfilterTable(g, typ, dir, old, false, 3)
}
func (arch *arch) generateNetfilterTable(g *prog.Gen, typ prog.Type, dir prog.Dir, old prog.Arg,
hasUnion bool, hookCount int) (arg prog.Arg, calls []*prog.Call) {
const (
hookStart = 4
nonHookFields = 7
unused = uint64(^uint32(0))
)
if old == nil {
arg = g.GenerateSpecialArg(typ, dir, &calls)
} else {
// TODO(dvyukov): try to restore original hook order after mutation
// instead of assigning brand new offsets.
arg = prog.CloneArg(old)
calls = g.MutateArg(arg)
}
var tableArg *prog.GroupArg
if hasUnion {
tableArg = arg.(*prog.UnionArg).Option.(*prog.GroupArg)
} else {
tableArg = arg.(*prog.GroupArg)
}
numFileds := nonHookFields + 2*hookCount
if len(tableArg.Inner) != numFileds {
panic("wrong number of fields in netfilter table")
}
entriesArg := tableArg.Inner[numFileds-1].(*prog.GroupArg)
if len(entriesArg.Inner) != 2 {
panic("netfilter entries is expected to have 2 fields")
}
entriesArray := entriesArg.Inner[0].(*prog.GroupArg)
// Collect offsets of entries.
offsets := make([]uint64, len(entriesArray.Inner))
var pos uint64
for i, entryArg := range entriesArray.Inner {
offsets[i] = pos
pos += entryArg.Size()
}
if pos != entriesArray.Size() {
panic("netfilter offsets are broken")
}
genOffset := func() uint64 {
if g.Rand().Intn(100) == 0 {
// Assign the underflow entry once in a while.
// We have it in underflow hooks, so no point in using it frequently.
return pos
}
return offsets[g.Rand().Intn(len(offsets))]
}
// Assign offsets to used hooks.
for hook := hookStart; hook < hookStart+hookCount; hook++ {
hookArg := tableArg.Inner[hook].(*prog.ConstArg)
if hookArg.Type().(*prog.ConstType).Val == unused {
continue // unused hook
}
hookArg.Val = genOffset()
}
// Assign offsets to used underflow entries.
for hook := hookStart + hookCount; hook < hookStart+2*hookCount; hook++ {
hookArg := tableArg.Inner[hook].(*prog.ConstArg)
if hookArg.Type().(*prog.ConstType).Val == unused {
continue // unused hook
}
hookArg.Val = pos
}
// Now update standard target jump offsets.
prog.ForeachSubArg(arg, func(arg prog.Arg, _ *prog.ArgCtx) {
if !strings.HasPrefix(arg.Type().Name(), `xt_target_t["", `) {
return
}
targetArg := arg.(*prog.GroupArg)
valArg := targetArg.Inner[3].(*prog.ConstArg)
flagsType, ok := valArg.Type().(*prog.FlagsType)
if !ok {
return
}
if int64(valArg.Val) < 0 {
for _, val := range flagsType.Vals {
if val == valArg.Val {
return // verdict
}
}
}
valArg.Val = genOffset()
})
return
}
func (arch *arch) generateEbtables(g *prog.Gen, typ prog.Type, dir prog.Dir, old prog.Arg) (
arg prog.Arg, calls []*prog.Call) {
if old == nil {
arg = g.GenerateSpecialArg(typ, dir, &calls)
} else {
// TODO(dvyukov): try to restore original hook order after mutation
// instead of assigning brand new offsets.
arg = prog.CloneArg(old)
calls = g.MutateArg(arg)
}
if g.Target().ArgContainsAny(arg) {
return
}
hooksField, entriesField := 4, 7
if g.Target().PtrSize == 8 {
// Account for paddings.
hooksField, entriesField = 5, 9
}
tableArg := arg.(*prog.UnionArg).Option.(*prog.GroupArg)
entriesPtr := tableArg.Inner[entriesField].(*prog.PointerArg)
if entriesPtr.Res == nil {
return
}
entriesArray := entriesPtr.Res.(*prog.GroupArg)
offsets := make([]uint64, len(entriesArray.Inner))
var pos, totalEntries uint64
for i, entriesArg0 := range entriesArray.Inner {
entriesArg := entriesArg0.(*prog.GroupArg)
arrayArg := entriesArg.Inner[len(entriesArg.Inner)-1].(*prog.GroupArg)
entriesArg.Inner[2].(*prog.ConstArg).Val = totalEntries
totalEntries += uint64(len(arrayArg.Inner))
offsets[i] = pos
pos += entriesArg.Size()
}
tableArg.Inner[2].(*prog.ConstArg).Val = totalEntries
if pos != entriesArray.Size() {
panic("netfilter offsets are broken")
}
// Assign offsets to used hooks.
validHooks := tableArg.Inner[1].(*prog.ConstArg).Val
hooksArg := tableArg.Inner[hooksField].(*prog.GroupArg)
for i, hookArg0 := range hooksArg.Inner {
hookArg := hookArg0.(*prog.ConstArg)
if validHooks&(1<<uint(i)) == 0 {
hookArg.Val = 0
continue
}
addr := g.Target().PhysicalAddr(entriesPtr)
if len(offsets) != 0 {
addr += offsets[0]
offsets = offsets[1:]
}
hookArg.Val = addr
}
// TODO(dvyukov): assign jump targets for targets.
return
}
func (arch *arch) neutralizeEbtables(c *prog.Call) {
// This is very hacky... just as netfilter interfaces.
// setsockopt's len argument must be equal to size of ebt_replace + entries size.
lenArg := c.Args[4].(*prog.ConstArg)
tablePtr := c.Args[3].(*prog.PointerArg).Res
if tablePtr == nil {
return
}
tableArg := tablePtr.(*prog.UnionArg).Option.(*prog.GroupArg)
entriesField := len(tableArg.Inner) - 1
entriesArg := tableArg.Inner[entriesField].(*prog.PointerArg).Res
if entriesArg == nil {
return
}
lenArg.Val = tableArg.Size() + entriesArg.Size()
}
// Copyright 2019 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package linux
import (
"encoding/binary"
"fmt"
"strings"
"github.com/google/syzkaller/prog"
)
const (
USB_DEVICE_ID_MATCH_VENDOR = 1 << iota
USB_DEVICE_ID_MATCH_PRODUCT
USB_DEVICE_ID_MATCH_DEV_LO
USB_DEVICE_ID_MATCH_DEV_HI
USB_DEVICE_ID_MATCH_DEV_CLASS
USB_DEVICE_ID_MATCH_DEV_SUBCLASS
USB_DEVICE_ID_MATCH_DEV_PROTOCOL
USB_DEVICE_ID_MATCH_INT_CLASS
USB_DEVICE_ID_MATCH_INT_SUBCLASS
USB_DEVICE_ID_MATCH_INT_PROTOCOL
USB_DEVICE_ID_MATCH_INT_NUMBER
BytesPerUsbID = 17
BytesPerHidID = 12
)
type UsbDeviceID struct {
MatchFlags uint16
IDVendor uint16
IDProduct uint16
BcdDeviceLo uint16
BcdDeviceHi uint16
BDeviceClass uint8
BDeviceSubClass uint8
BDeviceProtocol uint8
BInterfaceClass uint8
BInterfaceSubClass uint8
BInterfaceProtocol uint8
BInterfaceNumber uint8
}
type HidDeviceID struct {
Bus uint16
Group uint16
Vendor uint32
Product uint32
}
func (arch *arch) generateUsbDeviceDescriptor(g *prog.Gen, typ0 prog.Type, dir prog.Dir, old prog.Arg) (
arg prog.Arg, calls []*prog.Call) {
if old == nil {
arg = g.GenerateSpecialArg(typ0, dir, &calls)
} else {
arg = prog.CloneArg(old)
calls = g.MutateArg(arg)
}
if g.Target().ArgContainsAny(arg) {
return
}
id := randUsbDeviceID(g)
bcdDevice := id.BcdDeviceLo + uint16(g.Rand().Intn(int(id.BcdDeviceHi-id.BcdDeviceLo)+1))
devArg := arg.(*prog.GroupArg).Inner[0]
patchGroupArg(devArg, 7, "idVendor", uint64(id.IDVendor))
patchGroupArg(devArg, 8, "idProduct", uint64(id.IDProduct))
patchGroupArg(devArg, 9, "bcdDevice", uint64(bcdDevice))
patchGroupArg(devArg, 3, "bDeviceClass", uint64(id.BDeviceClass))
patchGroupArg(devArg, 4, "bDeviceSubClass", uint64(id.BDeviceSubClass))
patchGroupArg(devArg, 5, "bDeviceProtocol", uint64(id.BDeviceProtocol))
configArg := devArg.(*prog.GroupArg).Inner[14].(*prog.GroupArg).Inner[0].(*prog.GroupArg).Inner[0]
interfacesArg := configArg.(*prog.GroupArg).Inner[8]
for i, interfaceArg := range interfacesArg.(*prog.GroupArg).Inner {
interfaceArg = interfaceArg.(*prog.GroupArg).Inner[0]
if i > 0 {
// Generate new IDs for every interface after the first one.
id = randUsbDeviceID(g)
}
patchGroupArg(interfaceArg, 5, "bInterfaceClass", uint64(id.BInterfaceClass))
patchGroupArg(interfaceArg, 6, "bInterfaceSubClass", uint64(id.BInterfaceSubClass))
patchGroupArg(interfaceArg, 7, "bInterfaceProtocol", uint64(id.BInterfaceProtocol))
patchGroupArg(interfaceArg, 2, "bInterfaceNumber", uint64(id.BInterfaceNumber))
}
return
}
func randUsbDeviceID(g *prog.Gen) UsbDeviceID {
totalIds := len(usbIds) / BytesPerUsbID
idNum := g.Rand().Intn(totalIds)
base := usbIds[idNum*BytesPerUsbID : (idNum+1)*BytesPerUsbID]
p := strings.NewReader(base)
var id UsbDeviceID
if binary.Read(p, binary.LittleEndian, &id) != nil {
panic("not enough data to read")
}
if (id.MatchFlags & USB_DEVICE_ID_MATCH_VENDOR) == 0 {
id.IDVendor = uint16(g.Rand().Intn(0xffff + 1))
}
if (id.MatchFlags & USB_DEVICE_ID_MATCH_PRODUCT) == 0 {
id.IDProduct = uint16(g.Rand().Intn(0xffff + 1))
}
if (id.MatchFlags & USB_DEVICE_ID_MATCH_DEV_LO) == 0 {
id.BcdDeviceLo = 0x0
}
if (id.MatchFlags & USB_DEVICE_ID_MATCH_DEV_HI) == 0 {
id.BcdDeviceHi = 0xffff
}
if (id.MatchFlags & USB_DEVICE_ID_MATCH_DEV_CLASS) == 0 {
id.BDeviceClass = uint8(g.Rand().Intn(0xff + 1))
}
if (id.MatchFlags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) == 0 {
id.BDeviceSubClass = uint8(g.Rand().Intn(0xff + 1))
}
if (id.MatchFlags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) == 0 {
id.BDeviceProtocol = uint8(g.Rand().Intn(0xff + 1))
}
if (id.MatchFlags & USB_DEVICE_ID_MATCH_INT_CLASS) == 0 {
id.BInterfaceClass = uint8(g.Rand().Intn(0xff + 1))
}
if (id.MatchFlags & USB_DEVICE_ID_MATCH_INT_SUBCLASS) == 0 {
id.BInterfaceSubClass = uint8(g.Rand().Intn(0xff + 1))
}
if (id.MatchFlags & USB_DEVICE_ID_MATCH_INT_PROTOCOL) == 0 {
id.BInterfaceProtocol = uint8(g.Rand().Intn(0xff + 1))
}
if (id.MatchFlags & USB_DEVICE_ID_MATCH_INT_NUMBER) == 0 {
id.BInterfaceNumber = uint8(g.Rand().Intn(0xff + 1))
}
return id
}
func (arch *arch) generateUsbHidDeviceDescriptor(g *prog.Gen, typ0 prog.Type, dir prog.Dir, old prog.Arg) (
arg prog.Arg, calls []*prog.Call) {
if old == nil {
arg = g.GenerateSpecialArg(typ0, dir, &calls)
} else {
arg = prog.CloneArg(old)
calls = g.MutateArg(arg)
}
if g.Target().ArgContainsAny(arg) {
return
}
totalIds := len(hidIds) / BytesPerHidID
idNum := g.Rand().Intn(totalIds)
base := hidIds[idNum*BytesPerHidID : (idNum+1)*BytesPerHidID]
p := strings.NewReader(base)
var id HidDeviceID
if binary.Read(p, binary.LittleEndian, &id) != nil {
panic("not enough data to read")
}
devArg := arg.(*prog.GroupArg).Inner[0]
patchGroupArg(devArg, 7, "idVendor", uint64(id.Vendor))
patchGroupArg(devArg, 8, "idProduct", uint64(id.Product))
return
}
func patchGroupArg(arg prog.Arg, index int, field string, value uint64) {
a := arg.(*prog.GroupArg)
typ := a.Type().(*prog.StructType)
if field != typ.Fields[index].Name {
panic(fmt.Sprintf("bad field, expected %v, found %v", field, typ.Fields[index].Name))
}
a.Inner[index].(*prog.ConstArg).Val = value
}
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package netbsd
import (
"github.com/google/syzkaller/prog"
"github.com/google/syzkaller/sys/targets"
)
func InitTarget(target *prog.Target) {
arch := &arch{
unix: targets.MakeUnixNeutralizer(target),
}
target.MakeDataMmap = targets.MakePosixMmap(target, false, false)
target.Neutralize = arch.unix.Neutralize
}
type arch struct {
unix *targets.UnixNeutralizer
}
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package openbsd
import (
"fmt"
"math"
"github.com/google/syzkaller/prog"
"github.com/google/syzkaller/sys/targets"
)
func InitTarget(target *prog.Target) {
arch := &arch{
unix: targets.MakeUnixNeutralizer(target),
CLOCK_REALTIME: target.GetConst("CLOCK_REALTIME"),
CTL_KERN: target.GetConst("CTL_KERN"),
DIOCCLRSTATES: target.GetConst("DIOCCLRSTATES"),
DIOCKILLSTATES: target.GetConst("DIOCKILLSTATES"),
KERN_MAXCLUSTERS: target.GetConst("KERN_MAXCLUSTERS"),
KERN_MAXPROC: target.GetConst("KERN_MAXPROC"),
KERN_MAXFILES: target.GetConst("KERN_MAXFILES"),
KERN_MAXTHREAD: target.GetConst("KERN_MAXTHREAD"),
KERN_WITNESS: target.GetConst("KERN_WITNESS"),
S_IFCHR: target.GetConst("S_IFCHR"),
S_IFMT: target.GetConst("S_IFMT"),
MCL_FUTURE: target.GetConst("MCL_FUTURE"),
RLIMIT_DATA: target.GetConst("RLIMIT_DATA"),
RLIMIT_STACK: target.GetConst("RLIMIT_STACK"),
}
target.MakeDataMmap = targets.MakePosixMmap(target, false, false)
target.Neutralize = arch.neutralize
target.AnnotateCall = arch.annotateCall
}
type arch struct {
unix *targets.UnixNeutralizer
CLOCK_REALTIME uint64
CTL_KERN uint64
DIOCCLRSTATES uint64
DIOCKILLSTATES uint64
KERN_MAXCLUSTERS uint64
KERN_MAXPROC uint64
KERN_MAXFILES uint64
KERN_MAXTHREAD uint64
KERN_WITNESS uint64
S_IFCHR uint64
S_IFMT uint64
MCL_FUTURE uint64
RLIMIT_DATA uint64
RLIMIT_STACK uint64
}
const (
mknodMode = 0
mknodDev = 1
// openbsd:src/etc/etc.amd64/MAKEDEV
devFdMajor = 22
devNullDevT = 0x0202
// Mask covering all valid rlimit resources.
rlimitMask = 0xf
)
// openbsd:src/sys/sys/types.h
func devmajor(dev uint64) uint64 {
return (dev >> 8) & 0xff
}
// openbsd:src/sys/sys/types.h
func devminor(dev uint64) uint64 {
return (dev & 0xff) | ((dev & 0xffff0000) >> 8)
}
func isExecutorFd(dev uint64) bool {
major := devmajor(dev)
minor := devminor(dev)
return major == devFdMajor && minor >= 200
}
func (arch *arch) neutralize(c *prog.Call, fixStructure bool) error {
argStart := 1
switch c.Meta.CallName {
case "chflagsat":
argStart = 2
fallthrough
case "chflags", "fchflags":
// Prevent changing mutability flags on files. This is
// especially problematic for file descriptors referring to
// tty/pty devices since it can cause the SSH connection to the
// VM to die.
flags := c.Args[argStart].(*prog.ConstArg)
badflags := [...]uint64{
0x00000002, // UF_IMMUTABLE
0x00000004, // UF_APPEND
0x00020000, // SF_IMMUTABLE
0x00040000, // SF_APPEND
}
for _, f := range badflags {
flags.Val &= ^f
}
case "clock_settime":
arch.neutralizeClockSettime(c)
case "ioctl":
// Performing the following ioctl commands on a /dev/pf file
// descriptor causes the ssh VM connection to die. For now, just
// rewire them to an invalid command.
request := c.Args[1].(*prog.ConstArg)
if request.Val == arch.DIOCCLRSTATES || request.Val == arch.DIOCKILLSTATES {
request.Val = 0
}
case "mknodat":
argStart = 2
fallthrough
case "mknod":
// Prevent vnodes of type VBAD from being created. Such vnodes will
// likely trigger assertion errors by the kernel.
mode := c.Args[argStart+mknodMode].(*prog.ConstArg)
if mode.Val&arch.S_IFMT == arch.S_IFMT {
mode.Val &^= arch.S_IFMT
mode.Val |= arch.S_IFCHR
}
// Prevent certain /dev/fd/X devices from getting created since
// they belong to the executor. It's especially dangerous to let
// the executor interact with kcov file descriptors since it can
// interfere with the coverage collection and cause corpus
// explosion.
// https://groups.google.com/d/msg/syzkaller/_IRWeAjVoy4/Akl2XMZTDAAJ
dev := c.Args[argStart+mknodDev].(*prog.ConstArg)
if isExecutorFd(dev.Val) {
dev.Val = devNullDevT
}
// Prevent /dev/sd0b (swap partition) and /dev/sd0c (raw disk)
// nodes from being created. Writing to such devices can corrupt
// the file system.
if devmajor(dev.Val) == 4 && (devminor(dev.Val) == 1 || devminor(dev.Val) == 2) {
dev.Val = devNullDevT
}
case "mlockall":
flags := c.Args[0].(*prog.ConstArg)
flags.Val &= ^arch.MCL_FUTURE
case "setrlimit":
arch.neutralizeRlimit(c)
case "sysctl":
arch.neutralizeSysctl(c)
default:
return arch.unix.Neutralize(c, fixStructure)
}
return nil
}
func (arch *arch) neutralizeClockSettime(c *prog.Call) {
switch v := c.Args[0].(type) {
case *prog.ConstArg:
// Do not fiddle with the wall clock, one of the causes of "no
// output from test machine" reports.
if v.Val == arch.CLOCK_REALTIME {
v.Val = ^uint64(0)
}
}
}
func (arch *arch) neutralizeRlimit(c *prog.Call) {
rlimitMin := uint64(0)
rlimitMax := uint64(math.MaxUint64)
resource := c.Args[0].(*prog.ConstArg).Val & rlimitMask
switch resource {
case arch.RLIMIT_DATA:
// OpenBSD performs a strict validation of the RLIMIT_DATA soft
// limit during memory allocation. Lowering the same limit could
// cause syz-executor to run out of memory quickly. Therefore
// make sure to not go lower than the default soft limit for the
// staff group.
rlimitMin = 1536 * 1024 * 1024
case arch.RLIMIT_STACK:
// Do not allow the stack to grow beyond the initial soft limit
// chosen by syz-executor. Otherwise, syz-executor will most
// likely not be able to perform any more heap allocations since
// they majority of memory is reserved for the stack.
rlimitMax = 1 * 1024 * 1024
default:
return
}
ptr := c.Args[1].(*prog.PointerArg)
if ptr.Res == nil {
return
}
args := ptr.Res.(*prog.GroupArg).Inner
for _, arg := range args {
switch v := arg.(type) {
case *prog.ConstArg:
v.Val = max(v.Val, rlimitMin)
v.Val = min(v.Val, rlimitMax)
}
}
}
func (arch *arch) neutralizeSysctl(c *prog.Call) {
ptr := c.Args[0].(*prog.PointerArg)
if ptr.Res == nil {
return
}
var mib []*prog.ConstArg
for _, arg := range ptr.Res.(*prog.GroupArg).Inner {
switch v := arg.(type) {
case *prog.ConstArg:
mib = append(mib, v)
}
}
if !arch.neutralizeSysctlKern(mib) {
return
}
for _, m := range mib {
m.Val = 0
}
// Reflect changes in the namelen argument.
if len(c.Args) >= 1 {
switch v := c.Args[1].(type) {
case *prog.ConstArg:
v.Val = 0
}
}
}
func (arch *arch) neutralizeSysctlKern(mib []*prog.ConstArg) bool {
// Do not fiddle with root only knob kern.maxclusters, one of the causes
// of "no output from test machine" reports.
if len(mib) >= 2 &&
mib[0].Val == arch.CTL_KERN && mib[1].Val == arch.KERN_MAXCLUSTERS {
return true
}
// Do not fiddle with root only knob kern.maxproc, can cause the
// syz-execprog to run out of resources.
if len(mib) >= 2 &&
mib[0].Val == arch.CTL_KERN && mib[1].Val == arch.KERN_MAXPROC {
return true
}
// Do not fiddle with root only knob kern.maxfiles, can cause the
// syz-execprog to run out of resources.
if len(mib) >= 2 &&
mib[0].Val == arch.CTL_KERN && mib[1].Val == arch.KERN_MAXFILES {
return true
}
// Do not fiddle with root only knob kern.maxthread, can cause the
// syz-execprog process to panic.
if len(mib) >= 2 &&
mib[0].Val == arch.CTL_KERN && mib[1].Val == arch.KERN_MAXTHREAD {
return true
}
if len(mib) >= 2 &&
mib[0].Val == arch.CTL_KERN && mib[1].Val == arch.KERN_WITNESS {
return true
}
return false
}
func (arch *arch) annotateCall(c prog.ExecCall) string {
devArg := 2
switch c.Meta.Name {
case "mknodat":
devArg = 3
fallthrough
case "mknod":
dev := c.Args[devArg].(prog.ExecArgConst).Value
return fmt.Sprintf("major = %v, minor = %v", devmajor(dev), devminor(dev))
}
return ""
}
// Automatically generated by syz-sysgen; DO NOT EDIT.
package sys
import (
"embed"
"github.com/google/syzkaller/sys/generated"
"github.com/google/syzkaller/sys/darwin"
"github.com/google/syzkaller/sys/freebsd"
"github.com/google/syzkaller/sys/fuchsia"
"github.com/google/syzkaller/sys/linux"
"github.com/google/syzkaller/sys/netbsd"
"github.com/google/syzkaller/sys/openbsd"
"github.com/google/syzkaller/sys/test"
"github.com/google/syzkaller/sys/trusty"
"github.com/google/syzkaller/sys/windows"
)
//go:embed gen/*.gob.flate
var files embed.FS
func init() {
generated.Register("darwin", "amd64", "872bba2ae5409477b673378e8bd7f3c4cb76fb57", darwin.InitTarget, files)
generated.Register("freebsd", "386", "bd72a8d2d4e10c4b88de4c772c79f086e1e06af5", freebsd.InitTarget, files)
generated.Register("freebsd", "amd64", "b6bc947054c873f7b6c7b1c4943454047254951d", freebsd.InitTarget, files)
generated.Register("freebsd", "arm64", "b6bc947054c873f7b6c7b1c4943454047254951d", freebsd.InitTarget, files)
generated.Register("freebsd", "riscv64", "b6bc947054c873f7b6c7b1c4943454047254951d", freebsd.InitTarget, files)
generated.Register("fuchsia", "amd64", "964c7fd4b1c8b2f056ea0047c6f157b808eace6d", fuchsia.InitTarget, files)
generated.Register("fuchsia", "arm64", "aabea56d7a220b467494a72b09e415bcfe2e82a0", fuchsia.InitTarget, files)
generated.Register("linux", "386", "befe654444287d072b36ac31862a430820362e1b", linux.InitTarget, files)
generated.Register("linux", "amd64", "2b3d92f302b4299cf19086b22646f4267b3e569d", linux.InitTarget, files)
generated.Register("linux", "arm", "3eeff02085c6fd6555b083c5ad913658613dc318", linux.InitTarget, files)
generated.Register("linux", "arm64", "0d6e3c7a902c817f80e2e7da973eea45ffa3a027", linux.InitTarget, files)
generated.Register("linux", "mips64le", "ea5543f73922f62323f6ba0a86d8b2e76adc6290", linux.InitTarget, files)
generated.Register("linux", "ppc64le", "df7511947006ca2f5bfaa7859b921594c2bc10bf", linux.InitTarget, files)
generated.Register("linux", "riscv64", "f8b4c1b09e9b6b01b1d3c4fdf04ac8f001284e92", linux.InitTarget, files)
generated.Register("linux", "s390x", "5713ebc073169fc7bdb4d0d578fd9bc5ebd8aa0f", linux.InitTarget, files)
generated.Register("netbsd", "amd64", "e55c41320cbb764d170d09a2ed5dbe024471a081", netbsd.InitTarget, files)
generated.Register("openbsd", "amd64", "1ea000ab9607526f7e5426a3893355348153b581", openbsd.InitTarget, files)
generated.Register("test", "32", "774bd1833e3c8b50f116747de65cf245dbbe7492", test.InitTarget, files)
generated.Register("test", "32_fork", "b11ab04652e27605ae4a1816ebf7989860974245", test.InitTarget, files)
generated.Register("test", "64", "3f4c92b9a77e3109f812dc47cdb5d09ecbecd741", test.InitTarget, files)
generated.Register("test", "64_fork", "0282491ed7d87770001881623ce2ff0bd544caff", test.InitTarget, files)
generated.Register("test", "64_fuzz", "2fdc070f08aa526d39a3f3e403d6624b1ac963bd", test.InitTarget, files)
generated.Register("trusty", "arm", "e15883cf9bc294d71c2d4e06d02c4bda0414a94f", trusty.InitTarget, files)
generated.Register("windows", "amd64", "f14e4fef7483fea72b1b0867de524882897680c6", windows.InitTarget, files)
}
// Copyright 2018 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package targets
import (
"github.com/google/syzkaller/prog"
)
// MakePosixMmap creates a "normal" posix mmap call that maps the target data range.
// If exec is set, the mapping is mapped as PROT_EXEC.
// If contain is set, the mapping is surrounded by PROT_NONE pages.
// These flags should be in sync with what executor.
func MakePosixMmap(target *prog.Target, exec, contain bool) func() []*prog.Call {
meta := target.SyscallMap["mmap"]
protRW := target.GetConst("PROT_READ") | target.GetConst("PROT_WRITE")
if exec {
protRW |= target.GetConst("PROT_EXEC")
}
flags := target.GetConst("MAP_ANONYMOUS") | target.GetConst("MAP_PRIVATE") | target.GetConst("MAP_FIXED")
size := target.NumPages * target.PageSize
const invalidFD = ^uint64(0)
makeMmap := func(addr, size, prot uint64) *prog.Call {
call := prog.MakeCall(meta, []prog.Arg{
prog.MakeVmaPointerArg(meta.Args[0].Type, prog.DirIn, addr, size),
prog.MakeConstArg(meta.Args[1].Type, prog.DirIn, size),
prog.MakeConstArg(meta.Args[2].Type, prog.DirIn, prot),
prog.MakeConstArg(meta.Args[3].Type, prog.DirIn, flags),
prog.MakeResultArg(meta.Args[4].Type, prog.DirIn, nil, invalidFD),
})
i := len(call.Args)
// Some targets have a padding argument between fd and offset.
if len(meta.Args) > 6 {
call.Args = append(call.Args, prog.MakeConstArg(meta.Args[i].Type, prog.DirIn, 0))
i++
}
call.Args = append(call.Args, prog.MakeConstArg(meta.Args[i].Type, prog.DirIn, 0))
return call
}
return func() []*prog.Call {
if contain {
return []*prog.Call{
makeMmap(^target.PageSize+1, target.PageSize, 0),
makeMmap(0, size, protRW),
makeMmap(size, target.PageSize, 0),
}
}
return []*prog.Call{makeMmap(0, size, protRW)}
}
}
func MakeSyzMmap(target *prog.Target) func() []*prog.Call {
meta := target.SyscallMap["syz_mmap"]
size := target.NumPages * target.PageSize
return func() []*prog.Call {
return []*prog.Call{
prog.MakeCall(meta, []prog.Arg{
prog.MakeVmaPointerArg(meta.Args[0].Type, prog.DirIn, 0, size),
prog.MakeConstArg(meta.Args[1].Type, prog.DirIn, size),
}),
}
}
}
type UnixNeutralizer struct {
MAP_FIXED uint64
S_IFREG uint64
S_IFCHR uint64
S_IFBLK uint64
S_IFIFO uint64
S_IFSOCK uint64
}
func MakeUnixNeutralizer(target *prog.Target) *UnixNeutralizer {
return &UnixNeutralizer{
MAP_FIXED: target.GetConst("MAP_FIXED"),
S_IFREG: target.GetConst("S_IFREG"),
S_IFCHR: target.GetConst("S_IFCHR"),
S_IFBLK: target.GetConst("S_IFBLK"),
S_IFIFO: target.GetConst("S_IFIFO"),
S_IFSOCK: target.GetConst("S_IFSOCK"),
}
}
func (arch *UnixNeutralizer) Neutralize(c *prog.Call, fixStructure bool) error {
switch c.Meta.CallName {
case "mmap":
if c.Meta.Name == "mmap$bifrost" {
// Mali bifrost mmap doesn't support MAP_FIXED.
return nil
}
// Add MAP_FIXED flag, otherwise it produces non-deterministic results.
c.Args[3].(*prog.ConstArg).Val |= arch.MAP_FIXED
case "mknod", "mknodat", "compat_50_mknod":
pos := 1
if c.Meta.CallName == "mknodat" {
pos = 2
}
switch c.Args[pos+1].Type().(type) {
case *prog.ProcType, *prog.ResourceType:
return nil
}
mode := c.Args[pos].(*prog.ConstArg)
dev := c.Args[pos+1].(*prog.ConstArg)
dev.Val = uint64(uint32(dev.Val))
// Char and block devices read/write io ports, kernel memory and do other nasty things.
// TODO: not required if executor drops privileges.
mask := arch.S_IFREG | arch.S_IFCHR | arch.S_IFBLK | arch.S_IFIFO | arch.S_IFSOCK
switch mode.Val & mask {
case arch.S_IFREG, arch.S_IFIFO, arch.S_IFSOCK:
case arch.S_IFBLK:
if dev.Val>>8 == 7 {
break // loop
}
mode.Val &^= arch.S_IFBLK
mode.Val |= arch.S_IFREG
case arch.S_IFCHR:
if dev.Val == 0x103 {
break // /dev/null
}
mode.Val &^= arch.S_IFCHR
mode.Val |= arch.S_IFREG
}
case "exit", "exit_group":
code := c.Args[0].(*prog.ConstArg)
// This code is reserved by executor.
if code.Val%128 == 67 {
code.Val = 1
}
}
return nil
}
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package targets
import (
"bytes"
"encoding/binary"
"fmt"
"os"
"os/exec"
"runtime"
"strings"
"sync"
"time"
)
type Target struct {
osCommon
OS string
Arch string
VMArch string // e.g. amd64 for 386, or arm64 for arm
PtrSize uint64
PageSize uint64
NumPages uint64
DataOffset uint64
Int64Alignment uint64
BigEndian bool
CFlags []string
CxxFlags []string
Triple string
CCompiler string
CxxCompiler string
Objdump string // name of objdump executable
KernelCompiler string // override CC when running kernel make
KernelLinker string // override LD when running kernel make
KernelArch string
KernelHeaderArch string
BrokenCompiler string
// NeedSyscallDefine is used by csource package to decide when to emit __NR_* defines.
NeedSyscallDefine func(nr uint64) bool
HostEndian binary.ByteOrder
SyscallTrampolines map[string]string
Addr2Line func() (string, error)
KernelAddresses KernelAddresses
init *sync.Once
initOther *sync.Once
// Target for the other compiler. If SYZ_CLANG says to use gcc, this will be clang. Or the other way around.
other *Target
timeouts Timeouts
}
// KernelAddresses contain approximate rounded up kernel text/data ranges
// that are used to filter signal and comparisons for bogus/unuseful entries.
// Zero values mean no filtering.
type KernelAddresses struct {
TextStart uint64
TextEnd uint64
DataStart uint64
DataEnd uint64
}
func (target *Target) HasCallNumber(callName string) bool {
return target.SyscallNumbers && !strings.HasPrefix(callName, "syz_")
}
type osCommon struct {
// What OS can build native binaries for this OS.
// If not set, defaults to itself (i.e. native build).
// Later we can extend this to be a list, but so far we don't have more than one OS.
BuildOS string
// Does the OS use syscall numbers (e.g. Linux) or has interface based on functions (e.g. fuchsia).
SyscallNumbers bool
// Syscalls accept int64 arguments (>sizeof(void*)).
Int64SyscallArgs bool
// E.g. "__NR_" or "SYS_".
SyscallPrefix string
// ipc<->executor communication tuning.
// If ExecutorUsesForkServer, executor uses extended protocol with handshake.
ExecutorUsesForkServer bool
// Special mode for OSes that do not have support for building Go binaries.
// In this mode we run Go binaries on the host machine, only executor runs on target.
HostFuzzer bool
// How to run syz-execprog/executor directly.
// Some systems build syz-execprog/executor into their images.
// If this flag is not empty, syz-execprog/executor will not be copied to the machine, and will be run using
// this command instead.
ExecprogBin string
ExecutorBin string
// Extension of executable files (notably, .exe for windows).
ExeExtension string
// Name of the kernel object file.
KernelObject string
// Name of cpp(1) executable.
CPP string
// Syscalls on which pseudo syscalls depend. Syzkaller will make sure that __NR* or SYS* definitions
// for those syscalls are enabled.
PseudoSyscallDeps map[string][]string
// Common CFLAGS for this OS.
cflags []string
}
// Timeouts structure parametrizes timeouts throughout the system.
// It allows to support different operating system, architectures and execution environments
// (emulation, models, etc) without scattering and duplicating knowledge about their execution
// performance everywhere.
// Timeouts calculation consists of 2 parts: base values and scaling.
// Base timeout values consist of a single syscall timeout, program timeout and "no output" timeout
// and are specified by the target (OS/arch), or defaults are used.
// Scaling part is calculated from the execution environment in pkg/mgrconfig based on VM type,
// kernel build type, emulation, etc. Scaling is specifically converged to a single number so that
// it can be specified/overridden for command line tools (e.g. syz-execprog -slowdown=10).
type Timeouts struct {
// Base scaling factor, used only for a single syscall timeout.
Slowdown int
// Capped scaling factor used for timeouts other than syscall timeout.
// It's already applied to all values in this struct, but can be used for one-off timeout values
// in the system. This should also be applied to syscall/program timeout attributes in syscall descriptions.
// Derived from Slowdown and should not be greater than Slowdown.
// The idea behind capping is that slowdown can be large (10-20) and most timeouts already
// include some safety margin. If we just multiply them we will get too large timeouts,
// e.g. program timeout can become 5s*20 = 100s, or "no output" timeout: 5m*20 = 100m.
Scale time.Duration
// Timeout for a single syscall, after this time the syscall is considered "blocked".
Syscall time.Duration
// Timeout for a single program execution.
Program time.Duration
// Timeout for "no output" detection.
NoOutput time.Duration
// Limit on a single VM running time, after this time a VM is restarted.
VMRunningTime time.Duration
// How long we should test to get "no output" error (derivative of NoOutput, here to avoid duplication).
NoOutputRunningTime time.Duration
}
const (
FreeBSD = "freebsd"
Darwin = "darwin"
Fuchsia = "fuchsia"
Linux = "linux"
NetBSD = "netbsd"
OpenBSD = "openbsd"
TestOS = "test"
Trusty = "trusty"
Windows = "windows"
// These are VM types, but we put them here to prevent string duplication.
GVisor = "gvisor"
Starnix = "starnix"
AMD64 = "amd64"
ARM64 = "arm64"
ARM = "arm"
I386 = "386"
MIPS64LE = "mips64le"
PPC64LE = "ppc64le"
S390x = "s390x"
RiscV64 = "riscv64"
TestArch64 = "64"
TestArch64Fuzz = "64_fuzz"
TestArch64Fork = "64_fork"
TestArch32 = "32"
TestArch32Fork = "32_fork"
)
func Get(OS, arch string) *Target {
return GetEx(OS, arch, useClang)
}
func GetEx(OS, arch string, clang bool) *Target {
target := List[OS][arch]
if target == nil {
return nil
}
target.init.Do(target.lazyInit)
if clang == useClang {
return target
}
target.initOther.Do(func() {
other := new(Target)
*other = *target
other.setCompiler(clang)
other.lazyInit()
target.other = other
})
return target.other
}
// nolint: lll
var List = map[string]map[string]*Target{
TestOS: {
TestArch64: {
PtrSize: 8,
PageSize: 4 << 10,
CFlags: []string{
"-fsanitize=address",
// Compile with -no-pie due to issues with ASan + ASLR on ppc64le.
"-no-pie",
// Otherwise it conflicts with -fsanitize-coverage=trace-pc.
"-fno-exceptions",
},
osCommon: osCommon{
SyscallNumbers: true,
SyscallPrefix: "SYS_",
ExecutorUsesForkServer: false,
},
},
TestArch64Fuzz: {
PtrSize: 8,
PageSize: 8 << 10,
// -fsanitize=address causes SIGSEGV.
CFlags: []string{"-no-pie"},
osCommon: osCommon{
SyscallNumbers: true,
SyscallPrefix: "SYS_",
ExecutorUsesForkServer: true,
},
},
TestArch64Fork: {
PtrSize: 8,
PageSize: 8 << 10,
CFlags: []string{
"-fsanitize=address",
// Compile with -no-pie due to issues with ASan + ASLR on ppc64le.
"-no-pie",
// Otherwise it conflicts with -fsanitize-coverage=trace-pc.
"-fno-exceptions",
},
osCommon: osCommon{
SyscallNumbers: true,
SyscallPrefix: "SYS_",
ExecutorUsesForkServer: true,
},
},
TestArch32: {
PtrSize: 4,
PageSize: 8 << 10,
Int64Alignment: 4,
CFlags: []string{"-m32", "-static"},
osCommon: osCommon{
SyscallNumbers: true,
Int64SyscallArgs: true,
SyscallPrefix: "SYS_",
ExecutorUsesForkServer: false,
},
},
TestArch32Fork: {
PtrSize: 4,
PageSize: 4 << 10,
CFlags: []string{"-m32", "-static-pie"},
osCommon: osCommon{
SyscallNumbers: true,
Int64SyscallArgs: true,
SyscallPrefix: "SYS_",
ExecutorUsesForkServer: true,
HostFuzzer: true,
},
},
},
Linux: {
AMD64: {
PtrSize: 8,
PageSize: 4 << 10,
CFlags: []string{"-m64"},
Triple: "x86_64-linux-gnu",
KernelArch: "x86_64",
KernelHeaderArch: "x86",
NeedSyscallDefine: func(nr uint64) bool {
// Only generate defines for new syscalls
// (added after commit 8a1ab3155c2ac on 2012-10-04).
return nr >= 313
},
KernelAddresses: KernelAddresses{
// Text/modules range for x86_64.
TextStart: 0xffffffff80000000,
TextEnd: 0xffffffffff000000,
// This range corresponds to the first 1TB of the physical memory mapping,
// see Documentation/arch/x86/x86_64/mm.rst.
DataStart: 0xffff880000000000,
DataEnd: 0xffff890000000000,
},
},
I386: {
VMArch: AMD64,
PtrSize: 4,
PageSize: 4 << 10,
Int64Alignment: 4,
CFlags: []string{"-m32"},
Triple: "x86_64-linux-gnu",
KernelArch: "i386",
KernelHeaderArch: "x86",
},
ARM64: {
PtrSize: 8,
PageSize: 4 << 10,
Triple: "aarch64-linux-gnu",
KernelArch: "arm64",
KernelHeaderArch: "arm64",
},
ARM: {
VMArch: ARM64,
PtrSize: 4,
PageSize: 4 << 10,
Triple: "arm-linux-gnueabi",
KernelArch: "arm",
KernelHeaderArch: "arm",
},
MIPS64LE: {
PtrSize: 8,
PageSize: 4 << 10,
CFlags: []string{"-march=mips64r2", "-mabi=64", "-EL"},
Triple: "mips64el-linux-gnuabi64",
KernelArch: "mips",
KernelHeaderArch: "mips",
},
PPC64LE: {
PtrSize: 8,
PageSize: 64 << 10,
CFlags: []string{"-D__powerpc64__"},
Triple: "powerpc64le-linux-gnu",
KernelArch: "powerpc",
KernelHeaderArch: "powerpc",
},
S390x: {
PtrSize: 8,
PageSize: 4 << 10,
DataOffset: 0xfffff000,
CFlags: []string{"-fPIE"},
BigEndian: true,
Triple: "s390x-linux-gnu",
KernelArch: "s390",
KernelHeaderArch: "s390",
SyscallTrampolines: map[string]string{
// The s390x Linux syscall ABI allows for upto 5 input parameters passed in registers, and this is not enough
// for the mmap syscall. Therefore, all input parameters for the mmap syscall are packed into a struct
// on user stack and the pointer to the struct is passed as an input parameter to the syscall.
// To work around this problem we therefore reroute the mmap syscall to the glibc mmap wrapper.
"mmap": "mmap",
},
},
RiscV64: {
PtrSize: 8,
PageSize: 4 << 10,
Triple: "riscv64-linux-gnu",
KernelArch: "riscv",
KernelHeaderArch: "riscv",
},
},
FreeBSD: {
AMD64: {
PtrSize: 8,
PageSize: 4 << 10,
CCompiler: "clang",
CFlags: []string{"-m64", "--target=x86_64-unknown-freebsd14.0"},
NeedSyscallDefine: func(nr uint64) bool {
// freebsd_12_shm_open, shm_open2, shm_rename, __realpathat, close_range, copy_file_range
return nr == 482 || nr >= 569
},
KernelAddresses: KernelAddresses{
// On amd64 the kernel and KLDs are loaded into the top
// 2GB of the kernel address space.
TextStart: 0xffffffff80000000,
TextEnd: 0xffffffffffffffff,
},
},
ARM64: {
PtrSize: 8,
PageSize: 4 << 10,
CCompiler: "clang",
CFlags: []string{"-m64", "--target=aarch64-unknown-freebsd14.0"},
NeedSyscallDefine: func(nr uint64) bool {
// freebsd_12_shm_open, shm_open2, shm_rename, __realpathat, close_range, copy_file_range
return nr == 482 || nr >= 569
},
},
I386: {
VMArch: AMD64,
PtrSize: 4,
PageSize: 4 << 10,
// The default DataOffset doesn't work with 32-bit
// FreeBSD and using ld.lld due to collisions.
DataOffset: 256 << 20,
Int64Alignment: 4,
CCompiler: "clang",
CFlags: []string{"-m32", "--target=i386-unknown-freebsd14.0"},
NeedSyscallDefine: func(nr uint64) bool {
// freebsd_12_shm_open, shm_open2, shm_rename, __realpathat, close_range, copy_file_range
return nr == 482 || nr >= 569
},
},
RiscV64: {
PtrSize: 8,
PageSize: 4 << 10,
CCompiler: "clang",
CFlags: []string{"-m64", "--target=riscv64-unknown-freebsd14.0"},
NeedSyscallDefine: func(nr uint64) bool {
// freebsd_12_shm_open, shm_open2, shm_rename, __realpathat, close_range, copy_file_range
return nr == 482 || nr >= 569
},
},
},
Darwin: {
AMD64: {
PtrSize: 8,
PageSize: 4 << 10,
DataOffset: 512 << 24,
CCompiler: "clang",
CFlags: []string{
"-m64",
"-I", sourceDirVar + "/san",
// FIXME(HerrSpace): syscall was marked as deprecated on macos
"-Wno-deprecated-declarations",
},
NeedSyscallDefine: dontNeedSyscallDefine,
},
},
NetBSD: {
AMD64: {
PtrSize: 8,
PageSize: 4 << 10,
CFlags: []string{
"-m64",
"-static-pie",
"--sysroot", sourceDirVar + "/dest/",
},
CCompiler: sourceDirVar + "/tools/bin/x86_64--netbsd-g++",
},
},
OpenBSD: {
AMD64: {
PtrSize: 8,
PageSize: 4 << 10,
CCompiler: "c++",
// PIE is enabled on OpenBSD by default, so no need for -static-pie.
CFlags: []string{"-m64", "-static", "-lutil"},
NeedSyscallDefine: func(nr uint64) bool {
switch nr {
case 8: // SYS___tfork
return true
case 94: // SYS___thrsleep
return true
case 198: // SYS___syscall
return true
case 295: // SYS___semctl
return true
case 301: // SYS___thrwakeup
return true
case 302: // SYS___threxit
return true
case 303: // SYS___thrsigdivert
return true
case 304: // SYS___getcwd
return true
case 329: // SYS___set_tcb
return true
case 330: // SYS___get_tcb
return true
}
return false
},
},
},
Fuchsia: {
AMD64: {
PtrSize: 8,
PageSize: 4 << 10,
KernelHeaderArch: "x64",
CCompiler: sourceDirVar + "/prebuilt/third_party/clang/linux-x64/bin/clang",
Objdump: sourceDirVar + "/prebuilt/third_party/clang/linux-x64/bin/llvm-objdump",
CFlags: fuchsiaCFlags("x64", "x86_64"),
},
ARM64: {
PtrSize: 8,
PageSize: 4 << 10,
KernelHeaderArch: ARM64,
CCompiler: sourceDirVar + "/prebuilt/third_party/clang/linux-x64/bin/clang",
Objdump: sourceDirVar + "/prebuilt/third_party/clang/linux-x64/bin/llvm-objdump",
CFlags: fuchsiaCFlags(ARM64, "aarch64"),
},
},
Windows: {
AMD64: {
PtrSize: 8,
// TODO(dvyukov): what should we do about 4k vs 64k?
PageSize: 4 << 10,
},
},
Trusty: {
ARM: {
PtrSize: 4,
PageSize: 4 << 10,
NeedSyscallDefine: dontNeedSyscallDefine,
},
},
}
var oses = map[string]osCommon{
Linux: {
SyscallNumbers: true,
SyscallPrefix: "__NR_",
ExecutorUsesForkServer: true,
KernelObject: "vmlinux",
PseudoSyscallDeps: map[string][]string{
"syz_read_part_table": {"memfd_create"},
"syz_mount_image": {"memfd_create"},
"syz_io_uring_setup": {"io_uring_setup"},
"syz_clone3": {"clone3", "exit"},
"syz_clone": {"clone", "exit"},
"syz_pidfd_open": {"pidfd_open"},
},
cflags: []string{"-static-pie"},
},
FreeBSD: {
SyscallNumbers: true,
Int64SyscallArgs: true,
SyscallPrefix: "SYS_",
ExecutorUsesForkServer: true,
KernelObject: "kernel.full",
CPP: "g++",
// FreeBSD is missing toolchain support for static PIEs.
cflags: []string{
"-static",
"-lc++",
// For some configurations -no-pie is passed to the compiler,
// which is not used by clang.
// Ensure clang does not complain about it.
"-Wno-unused-command-line-argument",
},
},
Darwin: {
SyscallNumbers: true,
Int64SyscallArgs: true,
SyscallPrefix: "SYS_",
// FIXME(HerrSpace): ForkServer is b0rked in a peculiar way. I did some
// printf debugging in parseOutput in ipc.go. It usually works for a
// few executions. Eventually the reported ncmd stops making sense and
// the resulting replies are partially garbage. I also looked at the
// executor side of things, but that's harder to track as we are just
// banging bytes in the shmem there and don't use structs like on the
// go side.
ExecutorUsesForkServer: false,
KernelObject: "kernel.kasan",
// Note: We need a real g++ here, not the symlink to clang++ common on
// macOS systems. Homebrews gcc package suffixes these with the gcc
// version to avoid conflicting with the macOS symlink. Currently -11.
CPP: "g++-11",
cflags: []string{"-lc++"},
},
NetBSD: {
BuildOS: Linux,
SyscallNumbers: true,
SyscallPrefix: "SYS_",
ExecutorUsesForkServer: true,
KernelObject: "netbsd.gdb",
},
OpenBSD: {
SyscallNumbers: false,
SyscallPrefix: "SYS_",
ExecutorUsesForkServer: true,
KernelObject: "bsd.gdb",
CPP: "ecpp",
},
Fuchsia: {
BuildOS: Linux,
SyscallNumbers: false,
ExecutorUsesForkServer: false,
HostFuzzer: true,
ExecutorBin: "syz-executor",
KernelObject: "zircon.elf",
},
Windows: {
SyscallNumbers: false,
ExecutorUsesForkServer: false,
ExeExtension: ".exe",
KernelObject: "vmlinux",
},
Trusty: {
SyscallNumbers: true,
Int64SyscallArgs: true,
SyscallPrefix: "__NR_",
},
}
var (
commonCFlags = []string{
"-O2",
"-pthread",
"-Wall",
"-Werror",
"-Wparentheses",
"-Wunused-const-variable",
"-Wframe-larger-than=16384", // executor uses stacks of limited size, so no jumbo frames
"-Wno-stringop-overflow",
"-Wno-array-bounds",
"-Wno-format-overflow",
"-Wno-unused-but-set-variable",
"-Wno-unused-command-line-argument",
}
optionalCFlags = map[string]bool{
"-static": true, // some distributions don't have static libraries
"-static-pie": true, // this flag is also not supported everywhere
"-Wunused-const-variable": true, // gcc 5 does not support this flag
"-fsanitize=address": true, // some OSes don't have ASAN
"-Wno-stringop-overflow": true,
"-Wno-array-bounds": true,
"-Wno-format-overflow": true,
"-Wno-unused-but-set-variable": true,
"-Wno-unused-command-line-argument": true,
}
fallbackCFlags = map[string]string{
"-static-pie": "-static", // if an ASLR static binary is impossible, build just a static one
}
// These are used only when building executor.
// For C repros and syz-extract, we build C source files.
commonCxxFlags = []string{
"-std=c++17",
"-I.",
"-Iexecutor/_include",
}
)
func fuchsiaCFlags(arch, clangArch string) []string {
out := sourceDirVar + "/out/" + arch
return []string{
"-Wno-deprecated",
"-target", clangArch + "-fuchsia",
"-ldriver",
"-lfdio",
"-lzircon",
"--sysroot", out + "/zircon_toolchain/obj/zircon/public/sysroot/sysroot",
"-I", sourceDirVar + "/sdk/lib/fdio/include",
"-I", sourceDirVar + "/zircon/system/ulib/fidl/include",
"-I", sourceDirVar + "/src/lib/ddk/include",
"-I", out + "/fidling/gen/sdk/fidl/fuchsia.device",
"-I", out + "/fidling/gen/sdk/fidl/fuchsia.device.manager",
"-I", out + "/fidling/gen/sdk/fidl/fuchsia.hardware.nand",
"-I", out + "/fidling/gen/sdk/fidl/fuchsia.hardware.power.statecontrol",
"-I", out + "/fidling/gen/sdk/fidl/fuchsia.hardware.usb.peripheral",
"-I", out + "/fidling/gen/zircon/vdso/zx",
"-L", out + "/" + arch + "-shared",
}
}
func init() {
for OS, archs := range List {
for arch, target := range archs {
initTarget(target, OS, arch)
}
}
arch32, arch64 := splitArch(runtime.GOARCH)
goos := runtime.GOOS
for _, target := range List[TestOS] {
if List[goos] == nil {
continue
}
arch := arch64
if target.PtrSize == 4 {
arch = arch32
}
host := List[goos][arch]
if host == nil {
target.BrokenCompiler = fmt.Sprintf("TestOS %v unsupported", target.PtrSize*8)
continue
}
target.CCompiler = host.CCompiler
target.CxxCompiler = host.CxxCompiler
target.CPP = host.CPP
target.CFlags = append(append([]string{}, host.CFlags...), target.CFlags...)
target.CFlags = processMergedFlags(target.CFlags)
// At least FreeBSD/386 requires a non-default DataOffset value.
target.DataOffset = host.DataOffset
// In ESA/390 mode, the CPU is able to address only 31bit of memory but
// arithmetic operations are still 32bit
// Fix cflags by replacing compiler's -m32 option with -m31
if arch == S390x {
for i := range target.CFlags {
target.CFlags[i] = strings.ReplaceAll(target.CFlags[i], "-m32", "-m31")
}
}
if runtime.GOOS == OpenBSD {
target.BrokenCompiler = "can't build TestOS on OpenBSD due to missing syscall function."
}
// These are used only for pkg/runtest tests, executor also knows about these values.
target.KernelAddresses.TextStart = 0xc0dec0dec0000000
target.KernelAddresses.TextEnd = 0xc0dec0dec1000000
if target.PtrSize == 4 {
target.KernelAddresses.TextStart = uint64(uint32(target.KernelAddresses.TextStart))
target.KernelAddresses.TextEnd = uint64(uint32(target.KernelAddresses.TextEnd))
}
target.KernelAddresses.DataStart = 0xda1a0000
target.KernelAddresses.DataEnd = 0xda1a1000
}
}
func initTarget(target *Target, OS, arch string) {
if common, ok := oses[OS]; ok {
target.osCommon = common
}
target.init = new(sync.Once)
target.initOther = new(sync.Once)
target.OS = OS
target.Arch = arch
if target.KernelArch == "" {
target.KernelArch = target.Arch
}
if target.NeedSyscallDefine == nil {
target.NeedSyscallDefine = needSyscallDefine
}
if target.DataOffset == 0 {
target.DataOffset = target.defaultDataOffset()
}
target.NumPages = (16 << 20) / target.PageSize
sourceDir := getSourceDir(target)
for sourceDir != "" && sourceDir[len(sourceDir)-1] == '/' {
sourceDir = sourceDir[:len(sourceDir)-1]
}
target.replaceSourceDir(&target.CCompiler, sourceDir)
target.replaceSourceDir(&target.Objdump, sourceDir)
for i := range target.CFlags {
target.replaceSourceDir(&target.CFlags[i], sourceDir)
}
if cc := os.Getenv("SYZ_CC_" + OS + "_" + arch); cc != "" {
target.CCompiler = strings.Fields(cc)[0]
target.CFlags = append(target.CFlags, strings.Fields(cc)[1:]...)
}
if cxx := os.Getenv("SYZ_CXX_" + OS + "_" + arch); cxx != "" {
target.CxxCompiler = strings.Fields(cxx)[0]
target.CxxFlags = append(target.CxxFlags, strings.Fields(cxx)[1:]...)
}
if OS == Linux && arch == runtime.GOARCH {
// Don't use cross-compiler for native compilation, there are cases when this does not work:
// https://github.com/google/syzkaller/pull/619
// https://github.com/google/syzkaller/issues/387
// https://github.com/google/syzkaller/commit/06db3cec94c54e1cf720cdd5db72761514569d56
target.Triple = ""
}
if target.CCompiler == "" {
target.setCompiler(useClang)
}
if target.CxxCompiler == "" {
target.CxxCompiler = strings.TrimSuffix(strings.TrimSuffix(target.CCompiler, "cc"), "++") + "++"
}
if target.CPP == "" {
target.CPP = "cpp"
}
if target.Objdump == "" {
target.Objdump = "objdump"
if target.Triple != "" {
target.Objdump = target.Triple + "-objdump"
}
}
if target.BuildOS == "" {
if OS == TestOS {
target.BuildOS = runtime.GOOS
} else {
target.BuildOS = OS
}
}
if runtime.GOOS != target.BuildOS {
// Spoil native binaries if they are not usable, so that nobody tries to use them later.
target.CCompiler = fmt.Sprintf("cant-build-%v-on-%v", target.OS, runtime.GOOS)
target.CxxCompiler = target.CCompiler
target.CPP = target.CCompiler
}
for _, flags := range [][]string{commonCFlags, target.osCommon.cflags} {
target.CFlags = append(target.CFlags, flags...)
}
if OS == TestOS {
if runtime.GOARCH == S390x {
target.BigEndian = true
}
}
target.HostEndian = binary.LittleEndian
if target.BigEndian {
target.HostEndian = binary.BigEndian
}
target.initAddr2Line()
}
func (target *Target) defaultDataOffset() uint64 {
if target.Arch == ARM64 || target.Arch == ARM {
// On ARM/ARM64, in many cases we can't use many enough bits of the address space.
// Let's use the old value for now. It's also problematic (see #5770), but it's
// lesser of the two evils.
return 0x20000000
}
if target.PtrSize == 8 {
// An address from ASAN's 64-bit HighMem area.
// 0x200000000000 works both for arm64 and amd64. We don't run syzkaller tests on any other platform.
// During real fuzzing, we don't build with ASAN, so the address should not matter much as long as
// it's far enough from the area allocated by malloc().
// Another restriction is that on Starnix the available memory space ends at 0x400000000000.
return 0x200000000000
}
// From 32-bit HighMem area.
return 0x80000000
}
func (target *Target) initAddr2Line() {
// Initialize addr2line lazily since lots of tests don't need it,
// but we invoke a number of external binaries during addr2line detection.
var (
init sync.Once
bin string
err error
)
target.Addr2Line = func() (string, error) {
init.Do(func() { bin, err = target.findAddr2Line() })
return bin, err
}
}
func (target *Target) findAddr2Line() (string, error) {
// Try llvm-addr2line first as it's significantly faster on large binaries.
// But it's unclear if it works for darwin binaries.
if target.OS != Darwin {
if path, err := exec.LookPath("llvm-addr2line"); err == nil {
return path, nil
}
}
bin := "addr2line"
if target.Triple != "" {
bin = target.Triple + "-" + bin
}
if target.OS != Darwin || target.Arch != AMD64 {
return bin, nil
}
// A special check for darwin kernel to produce a more useful error.
cmd := exec.Command(bin, "--help")
cmd.Env = append(os.Environ(), "LC_ALL=C")
out, err := cmd.CombinedOutput()
if err != nil {
return "", fmt.Errorf("addr2line execution failed: %w", err)
}
if !bytes.Contains(out, []byte("supported targets:")) {
return "", fmt.Errorf("addr2line output didn't contain supported targets")
}
if !bytes.Contains(out, []byte("mach-o-x86-64")) {
return "", fmt.Errorf("addr2line was built without mach-o-x86-64 support")
}
return bin, nil
}
func (target *Target) Timeouts(slowdown int) Timeouts {
if slowdown <= 0 {
panic(fmt.Sprintf("bad slowdown %v", slowdown))
}
timeouts := target.timeouts
timeouts.Slowdown = slowdown
timeouts.Scale = min(time.Duration(slowdown), 3)
if timeouts.Syscall == 0 {
timeouts.Syscall = 50 * time.Millisecond
}
if timeouts.Program == 0 {
timeouts.Program = 5 * time.Second
}
if timeouts.NoOutput == 0 {
// The timeout used to be 3 mins for a long time.
// But (1) we were seeing flakes on linux where net namespace
// destruction can be really slow, and (2) gVisor watchdog timeout
// is 3 mins + 1/4 of that for checking period = 3m45s.
// Current linux max timeout is CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=140
// and workqueue.watchdog_thresh=140 which both actually result
// in 140-280s detection delay.
// So the current timeout is 5 mins (300s).
// We don't want it to be too long too because it will waste time on real hangs.
timeouts.NoOutput = 5 * time.Minute
}
if timeouts.VMRunningTime == 0 {
timeouts.VMRunningTime = time.Hour
}
timeouts.Syscall *= time.Duration(slowdown)
timeouts.Program *= timeouts.Scale
timeouts.NoOutput *= timeouts.Scale
timeouts.VMRunningTime *= timeouts.Scale
timeouts.NoOutputRunningTime = timeouts.NoOutput + time.Minute
return timeouts
}
const (
DefaultLLVMCompiler = "clang"
DefaultLLVMLinker = "ld.lld"
)
func (target *Target) setCompiler(clang bool) {
// setCompiler may be called effectively twice for target.other,
// so first we remove flags the previous call may have added.
pos := 0
for _, flag := range target.CFlags {
if flag == "-ferror-limit=0" ||
strings.HasPrefix(flag, "--target=") {
continue
}
target.CFlags[pos] = flag
pos++
}
target.CFlags = target.CFlags[:pos]
if clang {
target.CCompiler = DefaultLLVMCompiler
target.KernelCompiler = DefaultLLVMCompiler
target.KernelLinker = DefaultLLVMLinker
if target.Triple != "" {
target.CFlags = append(target.CFlags, "--target="+target.Triple)
}
target.CFlags = append(target.CFlags, "-ferror-limit=0")
} else {
target.CCompiler = "gcc"
target.KernelCompiler = ""
target.KernelLinker = ""
if target.Triple != "" {
target.CCompiler = target.Triple + "-" + target.CCompiler
}
}
}
func (target *Target) replaceSourceDir(param *string, sourceDir string) {
if !strings.Contains(*param, sourceDirVar) {
return
}
if sourceDir == "" {
target.BrokenCompiler = "SOURCEDIR is not set"
return
}
*param = strings.ReplaceAll(*param, sourceDirVar, sourceDir)
}
func (target *Target) lazyInit() {
if runtime.GOOS != target.BuildOS || target.BrokenCompiler != "" {
return
}
// Only fail on CI for native build.
// On CI we want to fail loudly if cross-compilation breaks.
// Also fail if SOURCEDIR_GOOS is set b/c in that case user probably assumes it will work.
if (target.OS != runtime.GOOS || !runningOnCI) && getSourceDir(target) == "" {
for _, comp := range []string{target.CCompiler, target.CxxCompiler} {
if _, err := exec.LookPath(comp); err != nil {
target.BrokenCompiler = fmt.Sprintf("%v is missing (%v)", comp, err)
return
}
}
}
flagsToCheck := append([]string{}, target.CFlags...)
for _, value := range fallbackCFlags {
flagsToCheck = append(flagsToCheck, value)
}
flags := make(map[string]*bool)
commonCFlags := []string{}
uncommonCFlags := []string{}
var wg sync.WaitGroup
for _, flag := range flagsToCheck {
if !optionalCFlags[flag] {
commonCFlags = append(commonCFlags, flag)
continue
}
uncommonCFlags = append(uncommonCFlags, flag)
}
for _, flag := range uncommonCFlags {
_, exists := flags[flag]
if exists {
continue
}
res := new(bool)
flags[flag] = res
wg.Add(1)
go func(flag string) {
defer wg.Done()
*res = checkFlagSupported(target, commonCFlags, flag)
}(flag)
}
wg.Wait()
newCFlags := []string{}
for _, flag := range target.CFlags {
for {
if res := flags[flag]; res == nil || *res {
// The flag is either verified to be supported or must be supported.
newCFlags = append(newCFlags, flag)
} else if fallback := fallbackCFlags[flag]; fallback != "" {
// The flag is not supported, but probably we can replace it by another one.
flag = fallback
continue
}
break
}
}
target.CFlags = newCFlags
target.CxxFlags = append(target.CFlags, commonCxxFlags...)
// Check that the compiler is actually functioning. It may be present, but still broken.
// Common for Linux distros, over time we've seen:
// Error: alignment too large: 15 assumed
// fatal error: asm/unistd.h: No such file or directory
// fatal error: asm/errno.h: No such file or directory
// collect2: error: ld terminated with signal 11 [Segmentation fault]
if runningOnCI || getSourceDir(target) != "" {
return // On CI all compilers are expected to work, so we don't do the following check.
}
for _, cxx := range []bool{false, true} {
lang, prog, comp, flags := "c", simpleCProg, target.CCompiler, target.CFlags
if cxx {
lang, prog, comp, flags = "c++", simpleCxxProg, target.CxxCompiler, target.CxxFlags
}
args := []string{"-x", lang, "-", "-o", "/dev/null"}
args = append(args, flags...)
cmd := exec.Command(comp, args...)
cmd.Stdin = strings.NewReader(prog)
if out, err := cmd.CombinedOutput(); err != nil {
target.BrokenCompiler = fmt.Sprintf("error running command: '%s':\ngotoutput: %s",
comp+" "+strings.Join(args, " "), out)
return
}
}
}
func checkFlagSupported(target *Target, targetCFlags []string, flag string) bool {
args := []string{"-x", "c++", "-", "-o", "/dev/null", "-Werror", flag}
args = append(args, targetCFlags...)
cmd := exec.Command(target.CCompiler, args...)
cmd.Stdin = strings.NewReader(simpleCProg)
return cmd.Run() == nil
}
// Split an arch into a pair of related 32 and 64 bit arch names.
// If the arch is unknown, we assume that the arch is 64 bit.
func splitArch(arch string) (string, string) {
type pair struct {
name32 string
name64 string
}
pairs := []pair{
{I386, AMD64},
{ARM, ARM64},
}
for _, p := range pairs {
if p.name32 == arch || p.name64 == arch {
return p.name32, p.name64
}
}
return "", arch
}
func processMergedFlags(flags []string) []string {
mutuallyExclusive := [][]string{
// For GCC, "-static-pie -static" is not equal to "-static".
// And since we do it anyway, also clean up those that do get overridden -
// this will improve the flags list readability.
{"-static", "-static-pie", "-no-pie", "-pie"},
}
// For mutually exclusive groups, keep only the last flag.
for _, group := range mutuallyExclusive {
m := map[string]bool{}
for _, s := range group {
m[s] = true
}
keep := ""
for i := len(flags) - 1; i >= 0; i-- {
if m[flags[i]] {
keep = flags[i]
break
}
}
if keep != "" {
newFlags := []string{}
for _, s := range flags {
if s == keep || !m[s] {
newFlags = append(newFlags, s)
}
}
flags = newFlags
}
}
// Clean up duplicates.
dup := map[string]bool{}
newFlags := []string{}
for _, s := range flags {
if dup[s] {
continue
}
newFlags = append(newFlags, s)
dup[s] = true
}
return newFlags
}
func getSourceDir(target *Target) string {
// First try the most granular env option.
name := fmt.Sprintf("SOURCEDIR_%s_%s_%s_%s",
strings.ToUpper(target.OS), strings.ToUpper(target.Arch),
strings.ToUpper(runtime.GOOS), strings.ToUpper(runtime.GOARCH),
)
if ret := os.Getenv(name); ret != "" {
return ret
}
// .. then the older one.
name = fmt.Sprintf("SOURCEDIR_%s", strings.ToUpper(target.OS))
if ret := os.Getenv(name); ret != "" {
return ret
}
return os.Getenv("SOURCEDIR")
}
func needSyscallDefine(nr uint64) bool { return true }
func dontNeedSyscallDefine(nr uint64) bool { return false }
var (
runningOnCI = os.Getenv("CI") != ""
useClang = os.Getenv("SYZ_CLANG") != ""
)
const (
sourceDirVar = "${SOURCEDIR}"
simpleCProg = `
#include <stdio.h>
#include <dirent.h> // ensures that system headers are installed
int main() { printf("Hello, World!\n"); }
`
simpleCxxProg = `
#include <algorithm> // ensures that C++ headers are installed
#include <vector>
int main() { std::vector<int> v(10); }
`
)
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package test
import (
"github.com/google/syzkaller/prog"
"github.com/google/syzkaller/sys/targets"
)
func InitTarget(target *prog.Target) {
target.MakeDataMmap = targets.MakeSyzMmap(target)
target.SpecialFileLenghts = []int{3, 256}
}
// Copyright 2018 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package trusty
import (
"github.com/google/syzkaller/prog"
"github.com/google/syzkaller/sys/targets"
)
func InitTarget(target *prog.Target) {
target.MakeDataMmap = targets.MakeSyzMmap(target)
}
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package windows
import (
"github.com/google/syzkaller/prog"
)
func InitTarget(target *prog.Target) {
arch := &arch{
target: target,
virtualAllocSyscall: target.SyscallMap["VirtualAlloc"],
MEM_COMMIT: target.GetConst("MEM_COMMIT"),
MEM_RESERVE: target.GetConst("MEM_RESERVE"),
PAGE_EXECUTE_READWRITE: target.GetConst("PAGE_EXECUTE_READWRITE"),
}
target.MakeDataMmap = arch.makeMmap
}
type arch struct {
target *prog.Target
virtualAllocSyscall *prog.Syscall
MEM_COMMIT uint64
MEM_RESERVE uint64
PAGE_EXECUTE_READWRITE uint64
}
func (arch *arch) makeMmap() []*prog.Call {
meta := arch.virtualAllocSyscall
size := arch.target.NumPages * arch.target.PageSize
return []*prog.Call{
prog.MakeCall(meta, []prog.Arg{
prog.MakeVmaPointerArg(meta.Args[0].Type, prog.DirIn, 0, size),
prog.MakeConstArg(meta.Args[1].Type, prog.DirIn, size),
prog.MakeConstArg(meta.Args[2].Type, prog.DirIn, arch.MEM_COMMIT|arch.MEM_RESERVE),
prog.MakeConstArg(meta.Args[3].Type, prog.DirIn, arch.PAGE_EXECUTE_READWRITE),
}),
}
}