// 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) } }