all: add GFNI instructions (#344)
Adds support for the GFNI "Galois Field New Instructions" instruction set. These instructions are not included in the Opcodes database, therefore they're added using the "extras" mechanism introduced in #345. For simplicity, the loading phase is updated slightly so that AVX-512 form expansion rules are applied after extras are added to the list. This greatly reduces the number of forms that have to be specified by hand. Based on #343 Fixes #335 Co-authored-by: Klaus Post <klauspost@gmail.com>
This commit is contained in:
committed by
GitHub
parent
a0ea0f3e6f
commit
946323570a
@@ -80,8 +80,7 @@ func (l *Loader) Load() ([]inst.Instruction, error) {
|
||||
Summary: i.Summary,
|
||||
}
|
||||
}
|
||||
forms := l.forms(opcode, f)
|
||||
im[opcode].Forms = append(im[opcode].Forms, forms...)
|
||||
im[opcode].Forms = append(im[opcode].Forms, l.form(opcode, f))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -91,6 +90,11 @@ func (l *Loader) Load() ([]inst.Instruction, error) {
|
||||
im[e.Opcode] = e
|
||||
}
|
||||
|
||||
// Generate additional AVX-512 forms.
|
||||
for _, i := range im {
|
||||
i.Forms = avx512forms(i.Opcode, i.Forms)
|
||||
}
|
||||
|
||||
// Merge aliased forms. This is primarily for MOVQ (issue #50).
|
||||
for _, a := range aliases {
|
||||
if existing, found := im[a.From]; found {
|
||||
@@ -122,6 +126,7 @@ func (l *Loader) Load() ([]inst.Instruction, error) {
|
||||
// Convert to a slice. Sort instructions and forms for reproducibility.
|
||||
is := make([]inst.Instruction, 0, len(im))
|
||||
for _, i := range im {
|
||||
sortforms(i.Forms)
|
||||
is = append(is, *i)
|
||||
}
|
||||
|
||||
@@ -129,10 +134,6 @@ func (l *Loader) Load() ([]inst.Instruction, error) {
|
||||
return is[i].Opcode < is[j].Opcode
|
||||
})
|
||||
|
||||
for _, i := range im {
|
||||
sortforms(i.Forms)
|
||||
}
|
||||
|
||||
return is, nil
|
||||
}
|
||||
|
||||
@@ -309,7 +310,7 @@ func (l Loader) gonames(f opcodesxml.Form) []string {
|
||||
return []string{n}
|
||||
}
|
||||
|
||||
func (l Loader) forms(opcode string, f opcodesxml.Form) []inst.Form {
|
||||
func (l Loader) form(opcode string, f opcodesxml.Form) inst.Form {
|
||||
// Map operands to avo format and ensure correct order.
|
||||
ops := operands(f.Operands)
|
||||
|
||||
@@ -366,34 +367,14 @@ func (l Loader) forms(opcode string, f opcodesxml.Form) []inst.Form {
|
||||
}
|
||||
sort.Strings(isas)
|
||||
|
||||
// Initialize form.
|
||||
form := inst.Form{
|
||||
// Build form.
|
||||
return inst.Form{
|
||||
ISA: isas,
|
||||
Operands: ops,
|
||||
ImplicitOperands: implicits,
|
||||
EncodingType: enctype(f),
|
||||
CancellingInputs: f.CancellingInputs,
|
||||
}
|
||||
|
||||
// Apply modification stages to produce final list of forms.
|
||||
stages := []func(string, inst.Form) []inst.Form{
|
||||
avx512rounding,
|
||||
avx512sae,
|
||||
avx512bcst,
|
||||
avx512masking,
|
||||
avx512zeroing,
|
||||
}
|
||||
|
||||
forms := []inst.Form{form}
|
||||
for _, stage := range stages {
|
||||
var next []inst.Form
|
||||
for _, f := range forms {
|
||||
next = append(next, stage(opcode, f)...)
|
||||
}
|
||||
forms = next
|
||||
}
|
||||
|
||||
return forms
|
||||
}
|
||||
|
||||
// operands maps Opcodes XML operands to avo format. Returned in Intel order.
|
||||
@@ -414,6 +395,31 @@ func operand(op opcodesxml.Operand) inst.Operand {
|
||||
}
|
||||
}
|
||||
|
||||
// avx512forms processes AVX-512 operands and expands them into additional
|
||||
// instruction forms as expected by the Go assembler.
|
||||
//
|
||||
// See: https://go.dev/wiki/AVX512
|
||||
func avx512forms(opcode string, forms []inst.Form) []inst.Form {
|
||||
// Apply modification stages to produce final list of forms.
|
||||
stages := []func(string, inst.Form) []inst.Form{
|
||||
avx512rounding,
|
||||
avx512sae,
|
||||
avx512bcst,
|
||||
avx512masking,
|
||||
avx512zeroing,
|
||||
}
|
||||
|
||||
for _, stage := range stages {
|
||||
var next []inst.Form
|
||||
for _, f := range forms {
|
||||
next = append(next, stage(opcode, f)...)
|
||||
}
|
||||
forms = next
|
||||
}
|
||||
|
||||
return forms
|
||||
}
|
||||
|
||||
// avx512rounding handles AVX-512 embedded rounding. Opcodes database represents
|
||||
// these as {er} operands, whereas Go uses instruction suffixes. Remove the
|
||||
// operand if present and set the corresponding flag.
|
||||
@@ -825,7 +831,6 @@ func vexevex(fs []inst.Form) ([]inst.Form, error) {
|
||||
}
|
||||
|
||||
if group[0].EncodingType != inst.EncodingTypeVEX || group[1].EncodingType != inst.EncodingTypeEVEX {
|
||||
fmt.Println(group)
|
||||
return nil, errors.New("expected pair of VEX/EVEX encoded forms")
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user