1
2
3
4
5 package main
6
7 import (
8 "bytes"
9 "go/format"
10 "io"
11 "log"
12 "sort"
13 "text/template"
14 )
15
16 var tablesTemplate = template.Must(template.New("avx_optabs").Parse(`
17 // Code generated by x86avxgen. DO NOT EDIT.
18
19 package x86
20
21 // VEX instructions that come in two forms:
22 // VTHING xmm2/m128, xmmV, xmm1
23 // VTHING ymm2/m256, ymmV, ymm1
24 //
25 // The opcode array in the corresponding Optab entry
26 // should contain the (VEX prefixes, opcode byte) pair
27 // for each of the two forms.
28 // For example, the entries for VPXOR are:
29 //
30 // VPXOR xmm2/m128, xmmV, xmm1
31 // VEX.NDS.128.66.0F.WIG EF /r
32 //
33 // VPXOR ymm2/m256, ymmV, ymm1
34 // VEX.NDS.256.66.0F.WIG EF /r
35 //
36 // Produce this optab entry:
37 //
38 // {AVPXOR, yvex_xy3, Pavx, opBytes{vex128|vex66|vex0F|vexWIG, 0xEF, vex256|vex66|vex0F|vexWIG, 0xEF}}
39 //
40 // VEX requires at least 2 bytes inside opBytes:
41 // - VEX prefixes (vex-prefixed constants)
42 // - Opcode byte
43 //
44 // EVEX instructions extend VEX form variety:
45 // VTHING zmm2/m512, zmmV, zmm1 -- implicit K0 (merging)
46 // VTHING zmm2/m512, zmmV, K, zmm1 -- explicit K mask (can't use K0)
47 //
48 // EVEX requires at least 3 bytes inside opBytes:
49 // - EVEX prefixes (evex-prefixed constants); similar to VEX
50 // - Displacement multiplier info (scale / broadcast scale)
51 // - Opcode byte; similar to VEX
52 //
53 // Both VEX and EVEX instructions may have opdigit (opcode extension) byte
54 // which follows the primary opcode byte.
55 // Because it can only have value of 0-7, it is written in octal notation.
56 //
57 // x86.csv can be very useful for figuring out proper [E]VEX parts.
58
59 {{ range .Ylists }}
60 var {{.Name}} = []ytab{
61 {{- range .Ytabs }}
62 {zcase: {{.Zcase}}, zoffset: {{.Zoffset}}, args: argList{ {{.ArgList}} }},
63 {{- end }}
64 }
65 {{ end }}
66
67 var avxOptab = [...]Optab{
68 {{- range .Optabs }}
69 {as: {{.Opcode}}, ytab: {{.YtabList.Name}}, prefix: Pavx, op: opBytes{
70 {{- range .OpLines }}
71 {{.}},
72 {{- end }}
73 }},
74 {{- end }}
75 }
76 `))
77
78
79 func writeTables(w io.Writer, ctx *context) {
80 ylists := make([]*ytabList, 0, len(ctx.ytabLists))
81 for _, ylist := range ctx.ytabLists {
82 ylists = append(ylists, ylist)
83 }
84 sort.Slice(ylists, func(i, j int) bool {
85 return ylists[i].Name < ylists[j].Name
86 })
87 optabs := make([]*optab, 0, len(ctx.optabs))
88 for _, o := range ctx.optabs {
89 optabs = append(optabs, o)
90 }
91 sort.Slice(optabs, func(i, j int) bool {
92 return optabs[i].Opcode < optabs[j].Opcode
93 })
94
95 var buf bytes.Buffer
96 err := tablesTemplate.Execute(&buf, struct {
97 Ylists []*ytabList
98 Optabs []*optab
99 }{
100 Ylists: ylists,
101 Optabs: optabs,
102 })
103 if err != nil {
104 log.Fatalf("template execute error: %v", err)
105 }
106
107
108 prettyCode, err := format.Source(buf.Bytes())
109 if err != nil {
110 log.Fatalf("gofmt error: %v", err)
111 }
112
113 if _, err := w.Write(prettyCode); err != nil {
114 log.Fatalf("write output: %v", err)
115 }
116 }
117
View as plain text