1
2
3
4
5 package x86
6
7 import (
8 "cmd/internal/obj"
9 "errors"
10 "fmt"
11 "strings"
12 )
13
14
15 type evexBits struct {
16 b1 byte
17 b2 byte
18
19
20 opcode byte
21 }
22
23
24 func newEVEXBits(z int, enc *opBytes) evexBits {
25 return evexBits{
26 b1: enc[z+0],
27 b2: enc[z+1],
28 opcode: enc[z+2],
29 }
30 }
31
32
33 func (evex evexBits) P() byte { return (evex.b1 & evexP) >> 0 }
34
35
36 func (evex evexBits) L() byte { return (evex.b1 & evexL) >> 2 }
37
38
39 func (evex evexBits) M() byte { return (evex.b1 & evexM) >> 4 }
40
41
42 func (evex evexBits) W() byte { return (evex.b1 & evexW) >> 7 }
43
44
45 func (evex evexBits) BroadcastEnabled() bool {
46 return evex.b2&evexBcst != 0
47 }
48
49
50 func (evex evexBits) ZeroingEnabled() bool {
51 return (evex.b2&evexZeroing)>>2 != 0
52 }
53
54
55
56 func (evex evexBits) RoundingEnabled() bool {
57 return (evex.b2&evexRounding)>>1 != 0
58 }
59
60
61 func (evex evexBits) SaeEnabled() bool {
62 return (evex.b2&evexSae)>>0 != 0
63 }
64
65
66
67
68 func (evex evexBits) DispMultiplier(bcst bool) int32 {
69 if bcst {
70 switch evex.b2 & evexBcst {
71 case evexBcstN4:
72 return 4
73 case evexBcstN8:
74 return 8
75 }
76 return 1
77 }
78
79 switch evex.b2 & evexN {
80 case evexN1:
81 return 1
82 case evexN2:
83 return 2
84 case evexN4:
85 return 4
86 case evexN8:
87 return 8
88 case evexN16:
89 return 16
90 case evexN32:
91 return 32
92 case evexN64:
93 return 64
94 case evexN128:
95 return 128
96 }
97 return 1
98 }
99
100
101
102 const (
103 evexW = 0x80
104 evexWIG = 0 << 7
105 evexW0 = 0 << 7
106 evexW1 = 1 << 7
107
108 evexM = 0x30
109 evex0F = 1 << 4
110 evex0F38 = 2 << 4
111 evex0F3A = 3 << 4
112
113 evexL = 0x0C
114 evexLIG = 0 << 2
115 evex128 = 0 << 2
116 evex256 = 1 << 2
117 evex512 = 2 << 2
118
119 evexP = 0x03
120 evex66 = 1 << 0
121 evexF3 = 2 << 0
122 evexF2 = 3 << 0
123
124
125
126
127 evexN = 0xE0
128 evexN1 = 0 << 5
129 evexN2 = 1 << 5
130 evexN4 = 2 << 5
131 evexN8 = 3 << 5
132 evexN16 = 4 << 5
133 evexN32 = 5 << 5
134 evexN64 = 6 << 5
135 evexN128 = 7 << 5
136
137
138 evexBcst = 0x18
139 evexBcstN4 = 1 << 3
140 evexBcstN8 = 2 << 3
141
142
143
144 evexZeroing = 0x4
145 evexZeroingEnabled = 1 << 2
146 evexRounding = 0x2
147 evexRoundingEnabled = 1 << 1
148 evexSae = 0x1
149 evexSaeEnabled = 1 << 0
150 )
151
152
153 func compressedDisp8(disp, elemSize int32) (disp8 byte, ok bool) {
154 if disp%elemSize == 0 {
155 v := disp / elemSize
156 if v >= -128 && v <= 127 {
157 return byte(v), true
158 }
159 }
160 return 0, false
161 }
162
163
164 func evexZcase(zcase uint8) bool {
165 return zcase > Zevex_first && zcase < Zevex_last
166 }
167
168
169
170
171
172
173
174
175
176 type evexSuffix struct {
177 rounding byte
178 sae bool
179 zeroing bool
180 broadcast bool
181 }
182
183
184
185 const (
186 rcRNSAE = 0
187 rcRDSAE = 1
188 rcRUSAE = 2
189 rcRZSAE = 3
190 rcUnset = 4
191 )
192
193
194 func newEVEXSuffix() evexSuffix {
195 return evexSuffix{rounding: rcUnset}
196 }
197
198
199
200 var evexSuffixMap [255]evexSuffix
201
202 func init() {
203
204 for i := range opSuffixTable {
205 suffix := newEVEXSuffix()
206 parts := strings.Split(opSuffixTable[i], ".")
207 for j := range parts {
208 switch parts[j] {
209 case "Z":
210 suffix.zeroing = true
211 case "BCST":
212 suffix.broadcast = true
213 case "SAE":
214 suffix.sae = true
215
216 case "RN_SAE":
217 suffix.rounding = rcRNSAE
218 case "RD_SAE":
219 suffix.rounding = rcRDSAE
220 case "RU_SAE":
221 suffix.rounding = rcRUSAE
222 case "RZ_SAE":
223 suffix.rounding = rcRZSAE
224 }
225 }
226 evexSuffixMap[i] = suffix
227 }
228 }
229
230
231 func toDisp8(disp int32, p *obj.Prog, asmbuf *AsmBuf) (disp8 byte, ok bool) {
232 if asmbuf.evexflag {
233 bcst := evexSuffixMap[p.Scond].broadcast
234 elemSize := asmbuf.evex.DispMultiplier(bcst)
235 return compressedDisp8(disp, elemSize)
236 }
237 return byte(disp), disp >= -128 && disp < 128
238 }
239
240
241
242 func EncodeRegisterRange(reg0, reg1 int16) int64 {
243 return (int64(reg0) << 0) |
244 (int64(reg1) << 16) |
245 obj.RegListX86Lo
246 }
247
248
249 func decodeRegisterRange(list int64) (reg0, reg1 int) {
250 return int((list >> 0) & 0xFFFF),
251 int((list >> 16) & 0xFFFF)
252 }
253
254
255
256
257
258 func ParseSuffix(p *obj.Prog, cond string) error {
259 cond = strings.TrimPrefix(cond, ".")
260
261 suffix := newOpSuffix(cond)
262 if !suffix.IsValid() {
263 return inferSuffixError(cond)
264 }
265
266 p.Scond = uint8(suffix)
267 return nil
268 }
269
270
271
272
273
274
275
276
277
278
279
280
281 func inferSuffixError(cond string) error {
282 suffixSet := make(map[string]bool)
283 unknownSet := make(map[string]bool)
284 hasBcst := false
285 hasRoundSae := false
286 var msg []string
287
288 suffixes := strings.Split(cond, ".")
289 for i, suffix := range suffixes {
290 switch suffix {
291 case "Z":
292 if i != len(suffixes)-1 {
293 msg = append(msg, "Z suffix should be the last")
294 }
295 case "BCST":
296 hasBcst = true
297 case "SAE", "RN_SAE", "RZ_SAE", "RD_SAE", "RU_SAE":
298 hasRoundSae = true
299 default:
300 if !unknownSet[suffix] {
301 msg = append(msg, fmt.Sprintf("unknown suffix %q", suffix))
302 }
303 unknownSet[suffix] = true
304 }
305
306 if suffixSet[suffix] {
307 msg = append(msg, fmt.Sprintf("duplicate suffix %q", suffix))
308 }
309 suffixSet[suffix] = true
310 }
311
312 if hasBcst && hasRoundSae {
313 msg = append(msg, "can't combine rounding/SAE and broadcast")
314 }
315
316 if len(msg) == 0 {
317 return errors.New("bad suffix combination")
318 }
319 return errors.New(strings.Join(msg, "; "))
320 }
321
322
323
324
325 var opSuffixTable = [...]string{
326 "",
327
328 "Z",
329
330 "SAE",
331 "SAE.Z",
332
333 "RN_SAE",
334 "RZ_SAE",
335 "RD_SAE",
336 "RU_SAE",
337 "RN_SAE.Z",
338 "RZ_SAE.Z",
339 "RD_SAE.Z",
340 "RU_SAE.Z",
341
342 "BCST",
343 "BCST.Z",
344
345 "<bad suffix>",
346 }
347
348
349
350
351
352 type opSuffix uint8
353
354
355 const badOpSuffix = opSuffix(len(opSuffixTable) - 1)
356
357
358
359
360
361 func newOpSuffix(suffixes string) opSuffix {
362 for i := range opSuffixTable {
363 if opSuffixTable[i] == suffixes {
364 return opSuffix(i)
365 }
366 }
367 return badOpSuffix
368 }
369
370
371
372 func (suffix opSuffix) IsValid() bool {
373 return suffix != badOpSuffix
374 }
375
376
377
378
379
380
381 func (suffix opSuffix) String() string {
382 return opSuffixTable[suffix]
383 }
384
View as plain text