1
2
3
4
5 package main
6
7 import (
8 "bytes"
9 "log"
10 "strings"
11 )
12
13
14 type ytab struct {
15 Zcase string
16 Zoffset int
17 ArgList string
18 }
19
20
21
22 type ytabList struct {
23 Name string
24 Ytabs []ytab
25 }
26
27
28 type optab struct {
29 Opcode string
30 YtabList *ytabList
31 OpLines []string
32 }
33
34 type generator struct {
35 ctx *context
36 ytabLists map[string]*ytabList
37 }
38
39
40
41 func generateOptabs(ctx *context) {
42 gen := generator{ctx: ctx, ytabLists: make(map[string]*ytabList)}
43 optabs := make(map[string]*optab)
44 for _, g := range ctx.groups {
45 optabs[g.opcode] = gen.GenerateGroup(g)
46 }
47 ctx.optabs = optabs
48 ctx.ytabLists = gen.ytabLists
49 }
50
51
52
53 func (gen *generator) GenerateGroup(g *instGroup) *optab {
54 var opLines []string
55 for _, inst := range g.list {
56 opLines = append(opLines, gen.generateOpLine(inst))
57 }
58 return &optab{
59 Opcode: "A" + g.opcode,
60 OpLines: opLines,
61 YtabList: gen.internYtabList(g),
62 }
63 }
64
65
66 func (gen *generator) generateOpLine(inst *instruction) string {
67 parts := []string{gen.prefixExpr(inst)}
68 if inst.pset.Is("EVEX") {
69 parts = append(parts, gen.evexPrefixExpr(inst))
70 }
71 parts = append(parts, inst.enc.opbyte)
72 if inst.enc.opdigit != "" {
73 parts = append(parts, inst.enc.opdigit)
74 }
75 return strings.Join(parts, ", ")
76 }
77
78 func (gen *generator) prefixExpr(inst *instruction) string {
79 enc := inst.enc
80 return gen.joinPrefixParts([]string{
81
82
83
84
85 "avxEscape",
86 enc.vex.L,
87 enc.vex.P,
88 enc.vex.M,
89 enc.vex.W,
90 })
91 }
92
93 func (gen *generator) evexPrefixExpr(inst *instruction) string {
94 enc := inst.enc
95 parts := []string{
96 enc.evexScale,
97 enc.evexBcstScale,
98 }
99 if enc.evex.SAE {
100 parts = append(parts, "evexSaeEnabled")
101 }
102 if enc.evex.Rounding {
103 parts = append(parts, "evexRoundingEnabled")
104 }
105 if enc.evex.Zeroing {
106 parts = append(parts, "evexZeroingEnabled")
107 }
108 return gen.joinPrefixParts(parts)
109 }
110
111
112
113 func (gen *generator) joinPrefixParts(names []string) string {
114 filterEmptyStrings := func(xs []string) []string {
115 ys := xs[:0]
116 for _, x := range xs {
117 if x != "" {
118 ys = append(ys, x)
119 }
120 }
121 return ys
122 }
123
124 names = filterEmptyStrings(names)
125 if len(names) == 0 {
126 return "0"
127 }
128 return strings.Join(names, "|")
129 }
130
131
132
133
134
135 func (gen *generator) internYtabList(g *instGroup) *ytabList {
136 var key string
137 {
138 var buf bytes.Buffer
139 for _, inst := range g.list {
140 buf.WriteString(inst.zform)
141 buf.WriteByte('=')
142 buf.WriteString(inst.YtypeListString())
143 buf.WriteByte(';')
144 }
145 key = buf.String()
146 }
147 if ylist := gen.ytabLists[key]; ylist != nil {
148 return ylist
149 }
150
151 var ytabs []ytab
152 for _, inst := range g.list {
153 zoffset := 2
154 if inst.pset.Is("EVEX") {
155 zoffset++
156 }
157 if inst.enc.opdigit != "" {
158 zoffset++
159 }
160
161 if inst.mask != nil {
162 ytabs = append(ytabs, gen.makeMaskYtabs(zoffset, inst)...)
163 } else {
164 ytabs = append(ytabs, gen.makeYtab(zoffset, inst.zform, inst.args))
165 }
166 }
167 ylist := &ytabList{
168 Name: "_y" + strings.ToLower(g.opcode),
169 Ytabs: ytabs,
170 }
171 gen.ytabLists[key] = ylist
172 return ylist
173 }
174
175 var zcaseByZform = map[string]string{
176 "evex imm8 reg kmask reg/mem": "Zevex_i_r_k_rm",
177 "evex imm8 reg reg/mem": "Zevex_i_r_rm",
178 "evex imm8 reg/mem kmask reg": "Zevex_i_rm_k_r",
179 "evex imm8 reg/mem kmask regV opdigit": "Zevex_i_rm_k_vo",
180 "evex imm8 reg/mem reg": "Zevex_i_rm_r",
181 "evex imm8 reg/mem regV opdigit": "Zevex_i_rm_vo",
182 "evex imm8 reg/mem regV kmask reg": "Zevex_i_rm_v_k_r",
183 "evex imm8 reg/mem regV reg": "Zevex_i_rm_v_r",
184 "evex kmask reg/mem opdigit": "Zevex_k_rmo",
185 "evex reg kmask reg/mem": "Zevex_r_k_rm",
186 "evex reg reg/mem": "Zevex_r_v_rm",
187 "evex reg regV kmask reg/mem": "Zevex_r_v_k_rm",
188 "evex reg regV reg/mem": "Zevex_r_v_rm",
189 "evex reg/mem kmask reg": "Zevex_rm_k_r",
190 "evex reg/mem reg": "Zevex_rm_v_r",
191 "evex reg/mem regV kmask reg": "Zevex_rm_v_k_r",
192 "evex reg/mem regV reg": "Zevex_rm_v_r",
193
194 "": "Zvex",
195 "imm8 reg reg/mem": "Zvex_i_r_rm",
196 "imm8 reg/mem reg": "Zvex_i_rm_r",
197 "imm8 reg/mem regV opdigit": "Zvex_i_rm_vo",
198 "imm8 reg/mem regV reg": "Zvex_i_rm_v_r",
199 "reg reg/mem": "Zvex_r_v_rm",
200 "reg regV reg/mem": "Zvex_r_v_rm",
201 "reg/mem opdigit": "Zvex_rm_v_ro",
202 "reg/mem reg": "Zvex_rm_v_r",
203 "reg/mem regV opdigit": "Zvex_rm_r_vo",
204 "reg/mem regV reg": "Zvex_rm_v_r",
205 "reg/mem": "Zvex_rm_v_r",
206 "regIH reg/mem regV reg": "Zvex_hr_rm_v_r",
207 "regV reg/mem reg": "Zvex_v_rm_r",
208 }
209
210 func (gen *generator) makeYtab(zoffset int, zform string, args []*argument) ytab {
211 var ytypes []string
212 for _, arg := range args {
213 if arg.ytype != "Ynone" {
214 ytypes = append(ytypes, arg.ytype)
215 }
216 }
217 argList := strings.Join(ytypes, ", ")
218 zcase := zcaseByZform[zform]
219 if zcase == "" {
220 log.Fatalf("no zcase for %q", zform)
221 }
222 return ytab{
223 Zcase: zcase,
224 Zoffset: zoffset,
225 ArgList: argList,
226 }
227 }
228
229
230
231
232
233
234
235
236
237
238
239 func (gen *generator) makeMaskYtabs(zoffset int, inst *instruction) []ytab {
240 var k0 ytab
241 {
242 zform := strings.Replace(inst.zform, "MASK1() ", "", 1)
243 inst.mask.ytype = "Ynone"
244 k0 = gen.makeYtab(0, zform, inst.args)
245 }
246 var knot0 ytab
247 {
248 zform := strings.Replace(inst.zform, "MASK1() ", "kmask ", 1)
249 inst.mask.ytype = "Yknot0"
250 knot0 = gen.makeYtab(zoffset, zform, inst.args)
251 }
252
253 inst.mask.ytype = "MASK1()"
254 return []ytab{k0, knot0}
255 }
256
View as plain text