File: optab.go

package info (click to toggle)
golang-github-mmcloughlin-avo 0.5.0-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 15,024 kB
  • sloc: xml: 71,029; asm: 14,862; sh: 194; makefile: 21; ansic: 11
file content (130 lines) | stat: -rw-r--r-- 3,015 bytes parent folder | download
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"

	"github.com/mmcloughlin/avo/ir"
	"github.com/mmcloughlin/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
}