internal/inst: doc exported symbols (#9)

This commit is contained in:
Michael McLoughlin
2019-01-05 11:43:39 -08:00
parent d54d413e54
commit f9a67bb2c0
2 changed files with 33 additions and 6 deletions

View File

@@ -3,6 +3,8 @@ package inst
//go:generate avogen -bootstrap -data ../data -output ztable.go godata //go:generate avogen -bootstrap -data ../data -output ztable.go godata
//go:generate avogen -bootstrap -data ../data -output ztable_test.go godatatest //go:generate avogen -bootstrap -data ../data -output ztable_test.go godatatest
// Lookup returns the instruction with the given opcode. Boolean return value
// indicates whether the instruction was found.
func Lookup(opcode string) (Instruction, bool) { func Lookup(opcode string) (Instruction, bool) {
for _, i := range Instructions { for _, i := range Instructions {
if i.Opcode == opcode { if i.Opcode == opcode {

View File

@@ -5,18 +5,22 @@ import (
"strings" "strings"
) )
// Instruction represents an x86 instruction.
type Instruction struct { type Instruction struct {
Opcode string Opcode string // Golang assembly mnemonic
AliasOf string AliasOf string // Opcode of instruction that this is an alias for
Summary string Summary string // Description of the instruction
Forms []Form Forms []Form // Accepted operand forms
} }
// IsTerminal reports whether the instruction exits a function.
func (i Instruction) IsTerminal() bool { func (i Instruction) IsTerminal() bool {
// TODO(mbm): how about the RETF* instructions // TODO(mbm): how about the RETF* instructions
return i.Opcode == "RET" return i.Opcode == "RET"
} }
// IsBranch reports whether the instruction is a branch; that is, if it can
// cause control flow to jump to another location.
func (i Instruction) IsBranch() bool { func (i Instruction) IsBranch() bool {
if i.Opcode == "CALL" { if i.Opcode == "CALL" {
return false return false
@@ -31,10 +35,12 @@ func (i Instruction) IsBranch() bool {
return false return false
} }
// IsConditionalBranch reports whether the instruction branches dependent on some condition.
func (i Instruction) IsConditionalBranch() bool { func (i Instruction) IsConditionalBranch() bool {
return i.IsBranch() && i.Opcode != "JMP" return i.IsBranch() && i.Opcode != "JMP"
} }
// Arities returns the unique arities among the instruction forms.
func (i Instruction) Arities() []int { func (i Instruction) Arities() []int {
s := map[int]bool{} s := map[int]bool{}
for _, f := range i.Forms { for _, f := range i.Forms {
@@ -48,6 +54,8 @@ func (i Instruction) Arities() []int {
return a return a
} }
// Arity is a convenience for returning the unique instruction arity when you
// know it is not variadic. Panics for a variadic instruction.
func (i Instruction) Arity() int { func (i Instruction) Arity() int {
if i.IsVariadic() { if i.IsVariadic() {
panic("variadic") panic("variadic")
@@ -56,25 +64,33 @@ func (i Instruction) Arity() int {
return a[0] return a[0]
} }
// IsVariadic reports whether the instruction has more than one arity.
func (i Instruction) IsVariadic() bool { func (i Instruction) IsVariadic() bool {
return len(i.Arities()) > 1 return len(i.Arities()) > 1
} }
// IsNiladic reports whether the instruction takes no operands.
func (i Instruction) IsNiladic() bool { func (i Instruction) IsNiladic() bool {
a := i.Arities() a := i.Arities()
return len(a) == 1 && a[0] == 0 return len(a) == 1 && a[0] == 0
} }
// Form specifies one accepted set of operands for an instruction.
type Form struct { type Form struct {
ISA []string // Instruction sets this instruction form requires.
Operands []Operand ISA []string
// Operands required for this form.
Operands []Operand
// Registers read or written but not explicitly passed to the instruction.
ImplicitOperands []ImplicitOperand ImplicitOperands []ImplicitOperand
} }
// Arity returns the number of operands this form expects.
func (f Form) Arity() int { func (f Form) Arity() int {
return len(f.Operands) return len(f.Operands)
} }
// Signature returns the list of operand types.
func (f Form) Signature() []string { func (f Form) Signature() []string {
s := make([]string, f.Arity()) s := make([]string, f.Arity())
for i, op := range f.Operands { for i, op := range f.Operands {
@@ -83,24 +99,29 @@ func (f Form) Signature() []string {
return s return s
} }
// Operand is an operand to an instruction, describing the expected type and read/write action.
type Operand struct { type Operand struct {
Type string Type string
Action Action Action Action
} }
// ImplicitOperand describes a register that is implicitly read/written by an instruction.
type ImplicitOperand struct { type ImplicitOperand struct {
Register string Register string
Action Action Action Action
} }
// Action specifies the read/write operation of an instruction on an operand.
type Action uint8 type Action uint8
// Possible Action types.
const ( const (
R Action = 0x1 R Action = 0x1
W Action = 0x2 W Action = 0x2
RW Action = R | W RW Action = R | W
) )
// ActionFromReadWrite builds an Action from boolean flags.
func ActionFromReadWrite(r, w bool) Action { func ActionFromReadWrite(r, w bool) Action {
var a Action var a Action
if r { if r {
@@ -112,18 +133,22 @@ func ActionFromReadWrite(r, w bool) Action {
return a return a
} }
// Contains reports whether a supports all actions in s.
func (a Action) Contains(s Action) bool { func (a Action) Contains(s Action) bool {
return (a & s) == s return (a & s) == s
} }
// Read reports whether a supports read.
func (a Action) Read() bool { func (a Action) Read() bool {
return a.Contains(R) return a.Contains(R)
} }
// Write reports whether a supports write.
func (a Action) Write() bool { func (a Action) Write() bool {
return a.Contains(W) return a.Contains(W)
} }
// String represents a as a human-readable string.
func (a Action) String() string { func (a Action) String() string {
s := "" s := ""
if a.Read() { if a.Read() {