From b5c22e94641200c97e044a7ebc53f8aefa918b71 Mon Sep 17 00:00:00 2001 From: Michael McLoughlin Date: Wed, 21 Nov 2018 23:06:29 -0600 Subject: [PATCH] handle order differences --- internal/gen/loadertest.go | 25 ++++++++++++++++++++----- internal/load/load.go | 26 +++++++++++++++----------- internal/opcodescsv/analysis.go | 15 ++++++++++----- 3 files changed, 45 insertions(+), 21 deletions(-) diff --git a/internal/gen/loadertest.go b/internal/gen/loadertest.go index b5cb7e1..af8ef9a 100644 --- a/internal/gen/loadertest.go +++ b/internal/gen/loadertest.go @@ -1,7 +1,9 @@ package gen import ( + "fmt" "io" + "math" "strings" "github.com/mmcloughlin/avo/internal/inst" @@ -16,8 +18,8 @@ func (l LoaderTest) Generate(w io.Writer, is []*inst.Instruction) error { for _, i := range is { p.printf("\t// %s %s\n", i.Opcode, i.Summary) - if strings.HasPrefix(i.Opcode, "RET") { - p.printf("\t// SKIP: early RET instruction would cause assembler error") + if skip, msg := l.skip(i.Opcode); skip { + p.printf("\t// SKIP: %s\n", msg) continue } @@ -25,7 +27,7 @@ func (l LoaderTest) Generate(w io.Writer, is []*inst.Instruction) error { as := args(f.Operands) p.printf("\t// %#v\n", f.Operands) if as == nil { - p.printf("\t// SKIP:\n") + p.printf("\t// TODO\n") continue } p.printf("\t%s\t%s\n", i.Opcode, strings.Join(as, ", ")) @@ -38,6 +40,19 @@ func (l LoaderTest) Generate(w io.Writer, is []*inst.Instruction) error { return p.Err() } +func (l LoaderTest) skip(opcode string) (bool, string) { + prefixes := map[string]string{ + "PUSH": "PUSH can produce 'unbalanced PUSH/POP' assembler error", + "POP": "POP can produce 'unbalanced PUSH/POP' assembler error", + } + for p, m := range prefixes { + if strings.HasPrefix(opcode, p) { + return true, m + } + } + return false, "" +} + func args(ops []inst.Operand) []string { as := make([]string, len(ops)) for i, op := range ops { @@ -58,8 +73,8 @@ func arg(t string) string { // // // - // - // + "imm32": fmt.Sprintf("$%d", math.MaxInt32), // + "imm64": fmt.Sprintf("$%d", math.MaxInt64), // // // // diff --git a/internal/load/load.go b/internal/load/load.go index 18e903a..1a12ca7 100644 --- a/internal/load/load.go +++ b/internal/load/load.go @@ -1,7 +1,6 @@ package load import ( - "log" "path/filepath" "strconv" "strings" @@ -20,7 +19,8 @@ type Loader struct { X86CSVPath string OpcodesXMLPath string - alias map[opcodescsv.Alias]string + alias map[opcodescsv.Alias]string + usesIntelOrder map[string]bool } func NewLoaderFromDataDir(dir string) *Loader { @@ -58,7 +58,7 @@ func (l *Loader) Load() ([]*inst.Instruction, error) { } } - im[opcode].Forms = append(im[opcode].Forms, l.form(f)) + im[opcode].Forms = append(im[opcode].Forms, l.form(opcode, f)) } } @@ -82,9 +82,7 @@ func (l *Loader) init() error { return err } - for a, op := range l.alias { - log.Printf("alias: %#v -> %s", a, op) - } + l.usesIntelOrder = opcodescsv.BuildIntelOrderSet(icsv) return nil } @@ -156,18 +154,24 @@ func (l Loader) goname(f opcodesxml.Form) string { return n } -func (l Loader) form(f opcodesxml.Form) inst.Form { +func (l Loader) form(opcode string, f opcodesxml.Form) inst.Form { + ops := operands(f.Operands) + if !l.usesIntelOrder[opcode] { + for l, r := 0, len(ops)-1; l < r; l, r = l+1, r-1 { + ops[l], ops[r] = ops[r], ops[l] + } + } return inst.Form{ - Operands: operands(f.Operands), + Operands: ops, } } -// operands maps Opcodes XML operands to avo format. +// operands maps Opcodes XML operands to avo format. Returned in Intel order. func operands(ops []opcodesxml.Operand) []inst.Operand { n := len(ops) - r := make([]inst.Operand, len(ops)) + r := make([]inst.Operand, n) for i, op := range ops { - r[n-1-i] = operand(op) + r[i] = operand(op) } return r } diff --git a/internal/opcodescsv/analysis.go b/internal/opcodescsv/analysis.go index 7f696aa..9cf8908 100644 --- a/internal/opcodescsv/analysis.go +++ b/internal/opcodescsv/analysis.go @@ -1,6 +1,7 @@ package opcodescsv import ( + "reflect" "strconv" "strings" @@ -17,7 +18,7 @@ type Alias struct { func BuildAliasMap(is []*x86csv.Inst) (map[Alias]string, error) { m := map[Alias]string{} for _, i := range is { - s, err := datasize(i.DataSize) + s, err := strconv.Atoi("0" + i.DataSize) if err != nil { return nil, err } @@ -40,9 +41,13 @@ func BuildAliasMap(is []*x86csv.Inst) (map[Alias]string, error) { return m, nil } -func datasize(s string) (int, error) { - if s == "" { - return 0, nil +// BuildIntelOrderSet builds the set of instructions that use intel order rather than the usual GNU/AT&T order. +func BuildIntelOrderSet(is []*x86csv.Inst) map[string]bool { + s := map[string]bool{} + for _, i := range is { + if !reflect.DeepEqual(i.GoArgs(), i.GNUArgs()) { + s[i.GoOpcode()] = true + } } - return strconv.Atoi(s) + return s }