golang.org/x/arch@v0.17.0/x86/x86avxgen/print.go (about) 1 // Copyright 2018 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 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 // writeTables writes avx optabs file contents to w. 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 // TODO: invoke "go fmt" or format.Gofmt? #22695. 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 }