Skip to content

Commit

Permalink
x86: isas in optab
Browse files Browse the repository at this point in the history
  • Loading branch information
mmcloughlin committed Jan 20, 2021
1 parent 21ed407 commit d270957
Show file tree
Hide file tree
Showing 13 changed files with 84,818 additions and 84,594 deletions.
15 changes: 15 additions & 0 deletions internal/api/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package api

import (
"path"
"sort"
"strings"
)

Expand Down Expand Up @@ -40,3 +41,17 @@ func OperandTypeIdentifier(t string) string {
func CheckerName(t string) string {
return "operand.Is" + OperandTypeIdentifier(t)
}

// ISAsIdentifier returns a string representation of an ISA list that suitable
// for use in a Go identifier.
func ISAsIdentifier(isas []string) string {
if len(isas) == 0 {
return "Base"
}
sorted := append([]string(nil), isas...)
sort.Strings(sorted)
ident := strings.Join(sorted, "_")
ident = strings.ReplaceAll(ident, ".", "") // SSE4.1
ident = strings.ReplaceAll(ident, "+", "") // MMX+
return ident
}
17 changes: 17 additions & 0 deletions internal/api/types_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package api

import (
"go/token"
"testing"

"github.com/mmcloughlin/avo/internal/inst"
)

func TestISAsIdentifier(t *testing.T) {
for _, isas := range inst.ISACombinations(inst.Instructions) {
ident := ISAsIdentifier(isas)
if !token.IsIdentifier(ident) {
t.Errorf("expected %q to be an identifier", ident)
}
}
}
25 changes: 17 additions & 8 deletions internal/gen/enum.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package gen

import (
"fmt"
"strconv"
"strings"

"github.com/mmcloughlin/avo/internal/prnt"
Expand All @@ -28,24 +29,32 @@ func (e *enum) Print(p *prnt.Generator) {
p.Printf(")\n\n")
}

func (e *enum) StringMethod(p *prnt.Generator) {
stringtab := strings.ToLower(e.name) + "strings"
func (e *enum) MapMethod(p *prnt.Generator, name, ret, zero string, mapping []string) {
table := strings.ToLower(e.name + name + "table")

r := e.Receiver()
p.Printf("func (%s %s) String() string {\n", r, e.name)
p.Printf("func (%s %s) %s() %s {\n", r, e.name, name, ret)
p.Printf("if %s < %s && %s < %s {\n", e.None(), r, r, e.MaxName())
p.Printf("return %s[%s-1]\n", stringtab, r)
p.Printf("return %s[%s-1]\n", table, r)
p.Printf("}\n")
p.Printf("return \"\"\n")
p.Printf("return %s\n", zero)
p.Printf("}\n\n")

p.Printf("var %s = []string{\n", stringtab)
for _, value := range e.values {
p.Printf("\t%q,\n", value)
p.Printf("var %s = []%s{\n", table, ret)
for _, value := range mapping {
p.Printf("\t%s,\n", value)
}
p.Printf("}\n\n")
}

func (e *enum) StringMethod(p *prnt.Generator) {
mapping := make([]string, len(e.values))
for i, s := range e.values {
mapping[i] = strconv.Quote(s)
}
e.MapMethod(p, "String", "string", `""`, mapping)
}

func (e *enum) Name() string {
return e.name
}
Expand Down
33 changes: 27 additions & 6 deletions internal/gen/optab.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package gen

import (
"fmt"
"strings"

"github.com/mmcloughlin/avo/internal/api"
Expand All @@ -16,6 +17,7 @@ type optab struct {

operandTypes *enum
implicitRegisters *enum
isas *enum
opcodes *enum
}

Expand All @@ -33,14 +35,11 @@ func (t *optab) Generate(is []inst.Instruction) ([]byte, error) {
// Size constants.
t.maxOperands(is)

// Operand types and implicit registers.
// Enums.
t.operandTypesEnum(is)
t.implicitRegistersEnum(is)

// Suffixes.
t.suffixesEnum(is)

// Opcodes.
t.isasEnum(is)
t.opcodesEnum(is)

// Forms table.
Expand Down Expand Up @@ -96,6 +95,27 @@ func (t *optab) implicitRegistersEnum(is []inst.Instruction) {
t.implicitRegisters = e
}

func (t *optab) isasEnum(is []inst.Instruction) {
combinations := inst.ISACombinations(is)

// Enum.
e := &enum{name: "ISAs"}
for _, isas := range combinations {
e.values = append(e.values, api.ISAsIdentifier(isas))
}

e.Print(&t.Generator)

// Mapping method to produce the list of ISAs.
lists := make([]string, len(combinations))
for i, isas := range combinations {
lists[i] = fmt.Sprintf("%#v", isas)
}
e.MapMethod(&t.Generator, "List", "[]string", "nil", lists)

t.isas = e
}

func (t *optab) suffixesEnum(is []inst.Instruction) {
e := &enum{name: "Suffix"}
for _, s := range inst.UniqueSuffixes(is) {
Expand Down Expand Up @@ -123,9 +143,10 @@ func (t *optab) forms(is []inst.Instruction) {
// Basic properties.
t.Printf("%s, ", t.opcodes.ConstName(i.Opcode))
t.Printf("%s, ", features(i, f))
t.Printf("%d, ", len(f.Operands))
t.Printf("%s, ", t.isas.ConstName(api.ISAsIdentifier(f.ISA)))

// Operands.
t.Printf("%d, ", len(f.Operands))
t.Printf("Operands{")
for _, op := range f.Operands {
t.Printf(
Expand Down
38 changes: 37 additions & 1 deletion internal/inst/table.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package inst

import "sort"
import (
"sort"
"strings"
)

//go:generate avogen -bootstrap -data ../data -output ztable.go godata
//go:generate avogen -bootstrap -data ../data -output ztable_test.go godatatest
Expand Down Expand Up @@ -72,6 +75,39 @@ func UniqueSuffixes(is []Instruction) []Suffix {
return suffixes
}

// ISAs returns all the unique ISAs seen in the given instructions.
func ISAs(is []Instruction) []string {
set := map[string]bool{}
for _, i := range is {
for _, f := range i.Forms {
for _, isa := range f.ISA {
set[isa] = true
}
}
}
return sortedslice(set)
}

// ISACombinations returns all the unique combinations of ISAs seen in the given
// instructions.
func ISACombinations(is []Instruction) [][]string {
var combinations [][]string
seen := map[string]bool{}
for _, i := range is {
for _, f := range i.Forms {
isas := append([]string(nil), f.ISA...)
sort.Strings(isas)
key := strings.Join(isas, ",")

if !seen[key] {
combinations = append(combinations, isas)
seen[key] = true
}
}
}
return combinations
}

// sortedslice builds a sorted slice of strings from a set.
func sortedslice(set map[string]bool) []string {
ss := make([]string, 0, len(set))
Expand Down
11 changes: 11 additions & 0 deletions internal/inst/table_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package inst_test
import (
"io/ioutil"
"reflect"
"sort"
"strings"
"testing"

Expand Down Expand Up @@ -117,6 +118,16 @@ func TestSuffixesHaveSummaries(t *testing.T) {
}
}

func TestISASorted(t *testing.T) {
for _, i := range inst.Instructions {
for _, f := range i.Forms {
if !sort.StringsAreSorted(f.ISA) {
t.Fatalf("%s: isa not sorted", i.Opcode)
}
}
}
}

func TestAssembles(t *testing.T) {
g := gen.NewAsmTest(printer.NewArgvConfig())
b, err := g.Generate(inst.Instructions)
Expand Down
Loading

0 comments on commit d270957

Please sign in to comment.