| // Copyright 2018 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package main |
| |
| import ( |
| "bytes" |
| "go/format" |
| "io" |
| "log" |
| "sort" |
| "text/template" |
| ) |
| |
| var tablesTemplate = template.Must(template.New("avx_optabs").Parse(` |
| // Code generated by x86avxgen. DO NOT EDIT. |
| |
| package x86 |
| |
| // VEX instructions that come in two forms: |
| // VTHING xmm2/m128, xmmV, xmm1 |
| // VTHING ymm2/m256, ymmV, ymm1 |
| // |
| // The opcode array in the corresponding Optab entry |
| // should contain the (VEX prefixes, opcode byte) pair |
| // for each of the two forms. |
| // For example, the entries for VPXOR are: |
| // |
| // VPXOR xmm2/m128, xmmV, xmm1 |
| // VEX.NDS.128.66.0F.WIG EF /r |
| // |
| // VPXOR ymm2/m256, ymmV, ymm1 |
| // VEX.NDS.256.66.0F.WIG EF /r |
| // |
| // Produce this optab entry: |
| // |
| // {AVPXOR, yvex_xy3, Pavx, opBytes{vex128|vex66|vex0F|vexWIG, 0xEF, vex256|vex66|vex0F|vexWIG, 0xEF}} |
| // |
| // VEX requires at least 2 bytes inside opBytes: |
| // - VEX prefixes (vex-prefixed constants) |
| // - Opcode byte |
| // |
| // EVEX instructions extend VEX form variety: |
| // VTHING zmm2/m512, zmmV, zmm1 -- implicit K0 (merging) |
| // VTHING zmm2/m512, zmmV, K, zmm1 -- explicit K mask (can't use K0) |
| // |
| // EVEX requires at least 3 bytes inside opBytes: |
| // - EVEX prefixes (evex-prefixed constants); similar to VEX |
| // - Displacement multiplier info (scale / broadcast scale) |
| // - Opcode byte; similar to VEX |
| // |
| // Both VEX and EVEX instructions may have opdigit (opcode extension) byte |
| // which follows the primary opcode byte. |
| // Because it can only have value of 0-7, it is written in octal notation. |
| // |
| // x86.csv can be very useful for figuring out proper [E]VEX parts. |
| |
| {{ range .Ylists }} |
| var {{.Name}} = []ytab{ |
| {{- range .Ytabs }} |
| {zcase: {{.Zcase}}, zoffset: {{.Zoffset}}, args: argList{ {{.ArgList}} }}, |
| {{- end }} |
| } |
| {{ end }} |
| |
| var avxOptab = [...]Optab{ |
| {{- range .Optabs }} |
| {as: {{.Opcode}}, ytab: {{.YtabList.Name}}, prefix: Pavx, op: opBytes{ |
| {{- range .OpLines }} |
| {{.}}, |
| {{- end }} |
| }}, |
| {{- end }} |
| } |
| `)) |
| |
| // writeTables writes avx optabs file contents to w. |
| func writeTables(w io.Writer, ctx *context) { |
| ylists := make([]*ytabList, 0, len(ctx.ytabLists)) |
| for _, ylist := range ctx.ytabLists { |
| ylists = append(ylists, ylist) |
| } |
| sort.Slice(ylists, func(i, j int) bool { |
| return ylists[i].Name < ylists[j].Name |
| }) |
| optabs := make([]*optab, 0, len(ctx.optabs)) |
| for _, o := range ctx.optabs { |
| optabs = append(optabs, o) |
| } |
| sort.Slice(optabs, func(i, j int) bool { |
| return optabs[i].Opcode < optabs[j].Opcode |
| }) |
| |
| var buf bytes.Buffer |
| err := tablesTemplate.Execute(&buf, struct { |
| Ylists []*ytabList |
| Optabs []*optab |
| }{ |
| Ylists: ylists, |
| Optabs: optabs, |
| }) |
| if err != nil { |
| log.Fatalf("template execute error: %v", err) |
| } |
| |
| // TODO: invoke "go fmt" or format.Gofmt? #22695. |
| prettyCode, err := format.Source(buf.Bytes()) |
| if err != nil { |
| log.Fatalf("gofmt error: %v", err) |
| } |
| |
| if _, err := w.Write(prettyCode); err != nil { |
| log.Fatalf("write output: %v", err) |
| } |
| } |