handle order differences

This commit is contained in:
Michael McLoughlin
2018-11-21 23:06:29 -06:00
parent c30d7fb743
commit b5c22e9464
3 changed files with 45 additions and 21 deletions

View File

@@ -1,7 +1,9 @@
package gen package gen
import ( import (
"fmt"
"io" "io"
"math"
"strings" "strings"
"github.com/mmcloughlin/avo/internal/inst" "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 { for _, i := range is {
p.printf("\t// %s %s\n", i.Opcode, i.Summary) p.printf("\t// %s %s\n", i.Opcode, i.Summary)
if strings.HasPrefix(i.Opcode, "RET") { if skip, msg := l.skip(i.Opcode); skip {
p.printf("\t// SKIP: early RET instruction would cause assembler error") p.printf("\t// SKIP: %s\n", msg)
continue continue
} }
@@ -25,7 +27,7 @@ func (l LoaderTest) Generate(w io.Writer, is []*inst.Instruction) error {
as := args(f.Operands) as := args(f.Operands)
p.printf("\t// %#v\n", f.Operands) p.printf("\t// %#v\n", f.Operands)
if as == nil { if as == nil {
p.printf("\t// SKIP:\n") p.printf("\t// TODO\n")
continue continue
} }
p.printf("\t%s\t%s\n", i.Opcode, strings.Join(as, ", ")) 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() 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 { func args(ops []inst.Operand) []string {
as := make([]string, len(ops)) as := make([]string, len(ops))
for i, op := range ops { for i, op := range ops {
@@ -58,8 +73,8 @@ func arg(t string) string {
// <xs:enumeration value="imm4" /> // <xs:enumeration value="imm4" />
// <xs:enumeration value="imm8" /> // <xs:enumeration value="imm8" />
// <xs:enumeration value="imm16" /> // <xs:enumeration value="imm16" />
// <xs:enumeration value="imm32" /> "imm32": fmt.Sprintf("$%d", math.MaxInt32), // <xs:enumeration value="imm32" />
// <xs:enumeration value="imm64" /> "imm64": fmt.Sprintf("$%d", math.MaxInt64), // <xs:enumeration value="imm64" />
// <xs:enumeration value="al" /> // <xs:enumeration value="al" />
// <xs:enumeration value="cl" /> // <xs:enumeration value="cl" />
// <xs:enumeration value="r8" /> // <xs:enumeration value="r8" />

View File

@@ -1,7 +1,6 @@
package load package load
import ( import (
"log"
"path/filepath" "path/filepath"
"strconv" "strconv"
"strings" "strings"
@@ -21,6 +20,7 @@ type Loader struct {
OpcodesXMLPath string OpcodesXMLPath string
alias map[opcodescsv.Alias]string alias map[opcodescsv.Alias]string
usesIntelOrder map[string]bool
} }
func NewLoaderFromDataDir(dir string) *Loader { 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 return err
} }
for a, op := range l.alias { l.usesIntelOrder = opcodescsv.BuildIntelOrderSet(icsv)
log.Printf("alias: %#v -> %s", a, op)
}
return nil return nil
} }
@@ -156,18 +154,24 @@ func (l Loader) goname(f opcodesxml.Form) string {
return n 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{ 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 { func operands(ops []opcodesxml.Operand) []inst.Operand {
n := len(ops) n := len(ops)
r := make([]inst.Operand, len(ops)) r := make([]inst.Operand, n)
for i, op := range ops { for i, op := range ops {
r[n-1-i] = operand(op) r[i] = operand(op)
} }
return r return r
} }

View File

@@ -1,6 +1,7 @@
package opcodescsv package opcodescsv
import ( import (
"reflect"
"strconv" "strconv"
"strings" "strings"
@@ -17,7 +18,7 @@ type Alias struct {
func BuildAliasMap(is []*x86csv.Inst) (map[Alias]string, error) { func BuildAliasMap(is []*x86csv.Inst) (map[Alias]string, error) {
m := map[Alias]string{} m := map[Alias]string{}
for _, i := range is { for _, i := range is {
s, err := datasize(i.DataSize) s, err := strconv.Atoi("0" + i.DataSize)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -40,9 +41,13 @@ func BuildAliasMap(is []*x86csv.Inst) (map[Alias]string, error) {
return m, nil return m, nil
} }
func datasize(s string) (int, error) { // BuildIntelOrderSet builds the set of instructions that use intel order rather than the usual GNU/AT&T order.
if s == "" { func BuildIntelOrderSet(is []*x86csv.Inst) map[string]bool {
return 0, nil 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
} }