blob: c17dbaff1a631bc72c229ab08bbe9824f3e904b8 [file] [log] [blame]
// 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)
}
}