loadertest: add memory operands
This commit is contained in:
@@ -18,15 +18,15 @@ type Alias struct {
|
||||
func BuildAliasMap(is []*x86csv.Inst) (map[Alias]string, error) {
|
||||
m := map[Alias]string{}
|
||||
for _, i := range is {
|
||||
if skip(i) {
|
||||
continue
|
||||
}
|
||||
|
||||
s, err := strconv.Atoi("0" + i.DataSize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if strings.Contains(i.GoOpcode(), "/") {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, alt := range []string{i.IntelOpcode(), i.GNUOpcode()} {
|
||||
if strings.ToUpper(alt) != i.GoOpcode() {
|
||||
a := Alias{
|
||||
@@ -41,13 +41,72 @@ func BuildAliasMap(is []*x86csv.Inst) (map[Alias]string, error) {
|
||||
return m, 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{}
|
||||
type OperandOrder uint8
|
||||
|
||||
const (
|
||||
UnknownOrder = iota
|
||||
IntelOrder
|
||||
ReverseIntelOrder
|
||||
CMP3Order
|
||||
)
|
||||
|
||||
// BuildOrderMap collects operand order information from the instruction list.
|
||||
func BuildOrderMap(is []*x86csv.Inst) map[string]OperandOrder {
|
||||
s := map[string]OperandOrder{}
|
||||
for _, i := range is {
|
||||
if !reflect.DeepEqual(i.GoArgs(), i.GNUArgs()) {
|
||||
s[i.GoOpcode()] = true
|
||||
if skip(i) {
|
||||
continue
|
||||
}
|
||||
s[i.GoOpcode()] = order(i)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// order categorizes the operand order of an instruction.
|
||||
func order(i *x86csv.Inst) OperandOrder {
|
||||
// Is it Intel order already?
|
||||
intel := i.IntelArgs()
|
||||
if reflect.DeepEqual(i.GoArgs(), intel) {
|
||||
return IntelOrder
|
||||
}
|
||||
|
||||
// Check if it's reverse Intel.
|
||||
for l, r := 0, len(intel)-1; l < r; l, r = l+1, r-1 {
|
||||
intel[l], intel[r] = intel[r], intel[l]
|
||||
}
|
||||
if reflect.DeepEqual(i.GoArgs(), intel) {
|
||||
return ReverseIntelOrder
|
||||
}
|
||||
|
||||
// Otherwise we could be in the bizarre special-case of 3-argument CMP instructions.
|
||||
//
|
||||
// Reference: https://github.com/golang/arch/blob/b19384d3c130858bb31a343ea8fce26be71b5998/x86/x86spec/format.go#L138-L144
|
||||
//
|
||||
// case "CMPPD", "CMPPS", "CMPSD", "CMPSS":
|
||||
// // rotate destination to end but don't swap comparison operands
|
||||
// if len(args) == 3 {
|
||||
// args[0], args[1], args[2] = args[2], args[0], args[1]
|
||||
// break
|
||||
// }
|
||||
// fallthrough
|
||||
//
|
||||
switch i.GoOpcode() {
|
||||
case "CMPPD", "CMPPS", "CMPSD", "CMPSS":
|
||||
if len(i.GoArgs()) == 3 {
|
||||
return CMP3Order
|
||||
}
|
||||
}
|
||||
|
||||
return UnknownOrder
|
||||
}
|
||||
|
||||
// skip decides whether to ignore the instruction for analysis purposes.
|
||||
func skip(i *x86csv.Inst) bool {
|
||||
switch {
|
||||
case strings.Contains(i.GoOpcode(), "/"):
|
||||
return true
|
||||
case i.Mode64 == "I": // Invalid in 64-bit mode.
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
20
internal/opcodescsv/analysis_test.go
Normal file
20
internal/opcodescsv/analysis_test.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package opcodescsv
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestBuildOrderMap(t *testing.T) {
|
||||
is, err := ReadFile("testdata/x86.v0.2.csv")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
orders := BuildOrderMap(is)
|
||||
|
||||
for opcode, order := range orders {
|
||||
if order == UnknownOrder {
|
||||
t.Errorf("%s has unknown order", opcode)
|
||||
}
|
||||
}
|
||||
}
|
||||
1
internal/opcodescsv/testdata
Symbolic link
1
internal/opcodescsv/testdata
Symbolic link
@@ -0,0 +1 @@
|
||||
../data
|
||||
Reference in New Issue
Block a user