forked from mmcloughlin/avo
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathoptab.go
More file actions
130 lines (109 loc) · 2.92 KB
/
optab.go
File metadata and controls
130 lines (109 loc) · 2.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package x86
import (
"errors"
"honnef.co/go/avo/ir"
"honnef.co/go/avo/operand"
)
// build constructs an instruction object from a list of acceptable forms, and
// given input operands and suffixes.
func build(forms []form, suffixes sffxs, ops []operand.Op) (*ir.Instruction, error) {
for i := range forms {
f := &forms[i]
if f.match(suffixes, ops) {
return f.build(suffixes, ops), nil
}
}
return nil, errors.New("bad operands")
}
// form represents an instruction form.
type form struct {
Opcode opc
SuffixesClass sffxscls
Features feature
ISAs isas
Arity uint8
Operands oprnds
}
// feature is a flags enumeration type representing instruction properties.
type feature uint8
const (
featureTerminal feature = 1 << iota
featureBranch
featureConditionalBranch
featureCancellingInputs
)
// oprnds is a list of explicit and implicit operands of an instruction form.
// The size of the array is output by optab generator.
type oprnds [maxoperands]oprnd
// oprnd represents an explicit or implicit operand to an instruction form.
type oprnd struct {
Type uint8
Implicit bool
Action action
}
// action an instruction form applies to an operand.
type action uint8
const (
actionN action = iota
actionR
actionW
actionRW action = actionR | actionW
)
// Read reports if the action includes read.
func (a action) Read() bool { return (a & actionR) != 0 }
// Read reports if the action includes write.
func (a action) Write() bool { return (a & actionW) != 0 }
// match reports whether this form matches the given suffixes and operand
// list.
func (f *form) match(suffixes sffxs, ops []operand.Op) bool {
// Match suffix.
accept := f.SuffixesClass.SuffixesSet()
if !accept[suffixes] {
return false
}
// Match operands.
if len(ops) != int(f.Arity) {
return false
}
for i, op := range ops {
t := oprndtype(f.Operands[i].Type)
if !t.Match(op) {
return false
}
}
return true
}
// build the full instruction object for this form and the given suffixes and
// operands. Assumes the form already matches the inputs.
func (f *form) build(suffixes sffxs, ops []operand.Op) *ir.Instruction {
// Base instruction properties.
i := &ir.Instruction{
Opcode: f.Opcode.String(),
Suffixes: suffixes.Strings(),
Operands: ops,
IsTerminal: (f.Features & featureTerminal) != 0,
IsBranch: (f.Features & featureBranch) != 0,
IsConditional: (f.Features & featureConditionalBranch) != 0,
CancellingInputs: (f.Features & featureCancellingInputs) != 0,
ISA: f.ISAs.List(),
}
// Input/output operands.
for _, spec := range f.Operands {
if spec.Type == 0 {
break
}
var op operand.Op
if spec.Implicit {
op = implreg(spec.Type).Register()
} else {
op, ops = ops[0], ops[1:]
}
if spec.Action.Read() {
i.Inputs = append(i.Inputs, op)
}
if spec.Action.Write() {
i.Outputs = append(i.Outputs, op)
}
}
return i
}