1
2
3
4
5 package sve
6
7 import (
8 "cmp"
9 "fmt"
10 "slices"
11 "strings"
12
13 "simd/archsimd/_gen/unify"
14 )
15
16
17 func asComment(text string, width int) string {
18 text = strings.TrimSpace(text)
19 text = strings.ReplaceAll(text, "&", "&")
20 text = strings.ReplaceAll(text, "\n", " ")
21 words := strings.Fields(text)
22 var lines []string
23 line := ""
24 for _, w := range words {
25 if line != "" {
26 line += " "
27 }
28 line += w
29 if len(line) >= width {
30 lines = append(lines, "// "+line)
31 line = ""
32 }
33 }
34 if line != "" {
35 lines = append(lines, "// "+line)
36 }
37 return strings.Join(lines, "\n")
38 }
39
40
41
42
43 func (op *Operand) emit() *unify.Value {
44 var db unify.DefBuilder
45 db.Add("class", unify.NewValue(unify.NewStringExact(op.Class)))
46 if op.BaseType != "" {
47 db.Add("base", unify.NewValue(unify.NewStringExact(op.BaseType)))
48 }
49 switch {
50 case op.Bits > 0:
51
52 db.Add("bits", unify.NewValue(unify.NewStringExact(fmt.Sprint(op.Bits))))
53 if op.Lanes > 0 {
54 db.Add("lanes", unify.NewValue(unify.NewStringExact(fmt.Sprint(op.Lanes))))
55 }
56 case op.Class == "vreg" || op.Class == "mask":
57
58
59
60
61 db.Add("bits", unify.NewValue(unify.NewStringExact("scalable")))
62 }
63 if op.ElemBits > 0 {
64 db.Add("elemBits", unify.NewValue(unify.NewStringExact(fmt.Sprint(op.ElemBits))))
65 }
66 if op.Predication != "" {
67
68
69 db.Add("predication", unify.NewValue(unify.NewStringExact(op.Predication)))
70 }
71 if op.role == "mask" {
72
73
74
75
76
77
78
79
80
81
82
83
84
85 db.Add("implicitAllTrue", unify.NewValue(unify.NewStringExact("true")))
86 }
87 if op.isList {
88
89
90 db.Add("listNumber", unify.NewValue(unify.NewStringExact("0")))
91 }
92 db.Add("asmPos", unify.NewValue(unify.NewStringExact(fmt.Sprint(op.AsmPos))))
93 return unify.NewValue(db.Build())
94 }
95
96
97
98
99
100
101
102 func (inst *Instruction) emitOne(asm string, ops []Operand) *unify.Value {
103 var db unify.DefBuilder
104 db.Add("asm", unify.NewValue(unify.NewStringExact(asm)))
105 db.Add("goarch", unify.NewValue(unify.NewStringExact("arm64")))
106 db.Add("cpuFeature", unify.NewValue(unify.NewStringExact(inst.cpuFeature())))
107 if doc := inst.documentation(); doc != "" {
108 db.Add("details", unify.NewValue(unify.NewStringExact(asComment(doc, 80))))
109 }
110
111 var inOps, outOps []Operand
112 for _, op := range ops {
113 if op.role == "destination" {
114 outOps = append(outOps, op)
115 } else {
116 inOps = append(inOps, op)
117 }
118 }
119 priority := map[string]int{"immediate": 0, "vreg": 1, "greg": 1, "memory": 1, "mask": 2}
120 slices.SortStableFunc(inOps, func(a, b Operand) int {
121 pa := priority[a.Class]
122 pb := priority[b.Class]
123 if pa != pb {
124 return cmp.Compare(pa, pb)
125 }
126 return cmp.Compare(a.AsmPos, b.AsmPos)
127 })
128
129 var ins, outs []*unify.Value
130 for i := range inOps {
131 ins = append(ins, inOps[i].emit())
132 }
133 for i := range outOps {
134 outs = append(outs, outOps[i].emit())
135 }
136 db.Add("in", unify.NewValue(unify.NewTuple(ins...)))
137 db.Add("inVariant", unify.NewValue(unify.NewTuple()))
138 db.Add("out", unify.NewValue(unify.NewTuple(outs...)))
139 return unify.NewValue(db.Build())
140 }
141
142
143
144
145 func (inst *Instruction) emitAll() []*unify.Value {
146
147
148 defs, _, _ := inst.classify()
149 return defs
150 }
151
152
153 func lookup(rows []arngRow, size string) (int, bool) {
154 for _, r := range rows {
155 if r.size == size {
156 return r.bits, true
157 }
158 }
159 return 0, false
160 }
161
162
163
164
165
166
167
168
169
170 func (inst *Instruction) emitVariants(template []Operand) []*unify.Value {
171 asm := inst.goOpPrefix() + inst.mnemonic()
172
173 links := arngLinks(template)
174 tables := map[string][]arngRow{}
175 for _, l := range links {
176 tables[l] = inst.resolveArrangementTable(l)
177 }
178
179
180
181 var sizes []string
182 if len(links) > 0 {
183 for _, r := range tables[links[0]] {
184 sizes = append(sizes, r.size)
185 }
186 } else {
187 sizes = []string{""}
188 }
189
190 signs := inst.integerSignedness(template)
191
192
193
194 preds := predicationVariants(template)
195
196 var defs []*unify.Value
197 for _, sign := range signs {
198 for _, size := range sizes {
199 ops := make([]Operand, len(template))
200 copy(ops, template)
201 skip := false
202 for i := range ops {
203 eb := ops[i].fixedElem
204 if ops[i].fixedBits > 0 {
205
206
207 eb = ops[i].fixedBits
208 } else if l := ops[i].arngLink; l != "" {
209 b, ok := lookup(tables[l], size)
210 if !ok {
211
212
213 skip = true
214 break
215 }
216 eb = b
217 }
218 base := sign
219 if inst.laneIsFloat(&ops[i]) {
220 base = "float"
221 if eb > 0 && eb < 16 {
222
223 skip = true
224 break
225 }
226 }
227 ops[i].instantiate(base, eb)
228 }
229 if skip {
230 continue
231 }
232 for _, pred := range preds {
233 variant := make([]Operand, len(ops))
234 copy(variant, ops)
235 for i := range variant {
236 if variant[i].Class == "mask" && variant[i].role == "mask" {
237 variant[i].Predication = pred
238 }
239 }
240 defs = append(defs, inst.emitOne(asm, variant))
241 }
242 }
243 }
244 return defs
245 }
246
View as plain text