...

Source file src/golang.org/x/arch/x86/xeddata/operand.go

Documentation: golang.org/x/arch/x86/xeddata

     1  // Copyright 2018 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package xeddata
     6  
     7  import (
     8  	"errors"
     9  	"strings"
    10  )
    11  
    12  // OperandVisibility describes operand visibility in XED terms.
    13  type OperandVisibility int
    14  
    15  const (
    16  	// VisExplicit is a default operand visibility.
    17  	// Explicit operand is "real" kind of operands that
    18  	// is shown in syntax and can be specified by the programmer.
    19  	VisExplicit OperandVisibility = iota
    20  
    21  	// VisImplicit is for fixed arg (like EAX); usually shown in syntax.
    22  	VisImplicit
    23  
    24  	// VisSuppressed is like VisImplicit, but not shown in syntax.
    25  	// In some very rare exceptions, they are also shown in syntax string.
    26  	VisSuppressed
    27  
    28  	// VisEcond is encoder-only conditions. Can be ignored.
    29  	VisEcond
    30  )
    31  
    32  // Operand holds data that is encoded inside
    33  // instruction's "OPERANDS" field.
    34  //
    35  // Use NewOperand function to decode operand fields into Operand object.
    36  type Operand struct {
    37  	// Name is an ID with optional nonterminal name part.
    38  	//
    39  	// Possible values: "REG0=GPRv_B", "REG1", "MEM0", ...
    40  	//
    41  	// If nonterminal part is present, name
    42  	// can be split into LHS and RHS with NonTerminalName method.
    43  	Name string
    44  
    45  	// Action describes argument types.
    46  	//
    47  	// Possible values: "r", "w", "rw", "cr", "cw", "crw".
    48  	// Optional "c" prefix represents conditional access.
    49  	Action string
    50  
    51  	// Width descriptor. It can express simple width like "w" (word, 16bit)
    52  	// or meta-width like "v", which corresponds to {16, 32, 64} bits.
    53  	//
    54  	// Possible values: "", "q", "ds", "dq", ...
    55  	// Optional.
    56  	Width string
    57  
    58  	// Xtype holds XED-specific type information.
    59  	//
    60  	// Possible values: "", "f64", "i32", ...
    61  	// Optional.
    62  	Xtype string
    63  
    64  	// Attributes serves as container for all other properties.
    65  	//
    66  	// Possible values:
    67  	//   EVEX.b context {
    68  	//     TXT=ZEROSTR  - zeroing
    69  	//     TXT=SAESTR   - suppress all exceptions
    70  	//     TXT=ROUNDC   - rounding
    71  	//     TXT=BCASTSTR - broadcasting
    72  	//   }
    73  	//   MULTISOURCE4 - 4FMA multi-register operand.
    74  	//
    75  	// Optional. For most operands, it's nil.
    76  	Attributes map[string]bool
    77  
    78  	// Visibility tells if operand is explicit, implicit or suspended.
    79  	Visibility OperandVisibility
    80  }
    81  
    82  var xedVisibilities = map[string]OperandVisibility{
    83  	"EXPL":  VisExplicit,
    84  	"IMPL":  VisImplicit,
    85  	"SUPP":  VisSuppressed,
    86  	"ECOND": VisEcond,
    87  }
    88  
    89  // NewOperand decodes operand string.
    90  //
    91  // See "$XED/pysrc/opnds.py" to learn about fields format
    92  // and valid combinations.
    93  //
    94  // Requires database with xtypes and widths info.
    95  func NewOperand(db *Database, s string) (*Operand, error) {
    96  	if db.widths == nil {
    97  		return nil, errors.New("Database.widths is nil")
    98  	}
    99  
   100  	fields := strings.Split(s, ":")
   101  	switch len(fields) {
   102  	case 0:
   103  		return nil, errors.New("empty operand fields string")
   104  	case 1:
   105  		return &Operand{Name: fields[0]}, nil
   106  	}
   107  	var op Operand
   108  
   109  	// First two fields are fixed.
   110  	op.Name = fields[0]
   111  	op.Action = fields[1]
   112  
   113  	// Optional fields.
   114  	for _, f := range fields[2:] {
   115  		if db.widths[f] != nil && op.Width == "" {
   116  			op.Width = f
   117  		} else if vis, ok := xedVisibilities[f]; ok {
   118  			op.Visibility = vis
   119  		} else if xtype := db.xtypes[f]; xtype != nil {
   120  			op.Xtype = f
   121  		} else {
   122  			if op.Attributes == nil {
   123  				op.Attributes = make(map[string]bool)
   124  			}
   125  			op.Attributes[f] = true
   126  		}
   127  	}
   128  
   129  	return &op, nil
   130  }
   131  
   132  // NonterminalName returns true if op.Name consist
   133  // of LHS and RHS parts.
   134  //
   135  // RHS is non-terminal name lookup function expression.
   136  // Example: "REG0=GPRv()" has "GPRv()" name lookup function.
   137  func (op *Operand) NonterminalName() bool {
   138  	return strings.Contains(op.Name, "=")
   139  }
   140  
   141  // NameLHS returns left hand side part of the non-terminal name.
   142  // Example: NameLHS("REG0=GPRv()") => "REG0".
   143  func (op *Operand) NameLHS() string {
   144  	return strings.Split(op.Name, "=")[0]
   145  }
   146  
   147  // NameRHS returns right hand side part of the non-terminal name.
   148  // Example: NameLHS("REG0=GPRv()") => "GPRv()".
   149  func (op *Operand) NameRHS() string {
   150  	return strings.Split(op.Name, "=")[1]
   151  }
   152  
   153  // IsVisible returns true for operands that are usually
   154  // shown in syntax strings.
   155  func (op *Operand) IsVisible() bool {
   156  	return op.Visibility == VisExplicit ||
   157  		op.Visibility == VisImplicit
   158  }
   159  

View as plain text