loadertest: rel8/32 operands
This commit is contained in:
@@ -9,12 +9,21 @@ import (
|
||||
"github.com/mmcloughlin/avo/internal/inst"
|
||||
)
|
||||
|
||||
type LoaderTest struct{}
|
||||
type LoaderTest struct {
|
||||
sym string // reference to the test function symbol
|
||||
rel8 string // label to be used for near jumps
|
||||
rel32 string // label for far jumps
|
||||
}
|
||||
|
||||
func (l LoaderTest) Generate(w io.Writer, is []*inst.Instruction) error {
|
||||
func (l *LoaderTest) Generate(w io.Writer, is []*inst.Instruction) error {
|
||||
p := &printer{w: w}
|
||||
|
||||
p.printf("TEXT loadertest(SB), 0, $0\n")
|
||||
l.sym = "\u00b7loadertest(SB)"
|
||||
p.printf("TEXT %s, 0, $0\n", l.sym)
|
||||
|
||||
// Define a label for far jumps.
|
||||
p.printf("rel32:\n")
|
||||
l.rel32 = "rel32"
|
||||
|
||||
counts := map[string]int{}
|
||||
|
||||
@@ -26,8 +35,14 @@ func (l LoaderTest) Generate(w io.Writer, is []*inst.Instruction) error {
|
||||
continue
|
||||
}
|
||||
|
||||
if i.Opcode[0] == 'J' {
|
||||
label := fmt.Sprintf("rel8_%s", strings.ToLower(i.Opcode))
|
||||
p.printf("%s:\n", label)
|
||||
l.rel8 = label
|
||||
}
|
||||
|
||||
for _, f := range i.Forms {
|
||||
as := args(f.Operands)
|
||||
as := l.args(i.Opcode, f.Operands)
|
||||
p.printf("\t// %#v\n", f.Operands)
|
||||
if as == nil {
|
||||
p.printf("\t// TODO\n")
|
||||
@@ -53,6 +68,7 @@ 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",
|
||||
"CALL": "handled specially",
|
||||
}
|
||||
for p, m := range prefixes {
|
||||
if strings.HasPrefix(opcode, p) {
|
||||
@@ -62,10 +78,15 @@ func (l LoaderTest) skip(opcode string) (bool, string) {
|
||||
return false, ""
|
||||
}
|
||||
|
||||
func args(ops []inst.Operand) []string {
|
||||
func (l LoaderTest) args(opcode string, ops []inst.Operand) []string {
|
||||
// Special case for CALL, since it needs a different type of rel32 argument than others.
|
||||
if opcode == "CALL" {
|
||||
return []string{l.sym}
|
||||
}
|
||||
|
||||
as := make([]string, len(ops))
|
||||
for i, op := range ops {
|
||||
a := arg(op.Type)
|
||||
a := l.arg(op.Type)
|
||||
if a == "" {
|
||||
return nil
|
||||
}
|
||||
@@ -75,7 +96,7 @@ func args(ops []inst.Operand) []string {
|
||||
}
|
||||
|
||||
// arg generates an argument for an operand of the given type.
|
||||
func arg(t string) string {
|
||||
func (l LoaderTest) arg(t string) string {
|
||||
m := map[string]string{
|
||||
"1": "$1", // <xs:enumeration value="1" />
|
||||
"3": "$3", // <xs:enumeration value="3" />
|
||||
@@ -145,8 +166,8 @@ func arg(t string) string {
|
||||
// <xs:enumeration value="vm32z{k}" />
|
||||
// <xs:enumeration value="vm64z" />
|
||||
// <xs:enumeration value="vm64z{k}" />
|
||||
// <xs:enumeration value="rel8" />
|
||||
// <xs:enumeration value="rel32" />
|
||||
"rel8": l.rel8, // <xs:enumeration value="rel8" />
|
||||
"rel32": l.rel32, // <xs:enumeration value="rel32" />
|
||||
// <xs:enumeration value="{er}" />
|
||||
// <xs:enumeration value="{sae}" />
|
||||
|
||||
|
||||
@@ -134,7 +134,17 @@ func (l Loader) include(f opcodesxml.Form) bool {
|
||||
|
||||
// Some specific exclusions.
|
||||
switch f.GASName {
|
||||
case "callq":
|
||||
// Certain branch instructions appear to not be supported.
|
||||
//
|
||||
// Reference: https://github.com/golang/go/blob/649b89377e91ad6dbe710784f9e662082d31a1ff/src/cmd/asm/internal/asm/testdata/amd64enc.s#L757
|
||||
//
|
||||
// //TODO: CALLQ* (BX) // ff13
|
||||
//
|
||||
// Reference: https://github.com/golang/go/blob/649b89377e91ad6dbe710784f9e662082d31a1ff/src/cmd/asm/internal/asm/testdata/amd64enc.s#L2108
|
||||
//
|
||||
// //TODO: LJMPL* (R11) // 41ff2b
|
||||
//
|
||||
case "callq", "jmpl":
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ func order(i *x86csv.Inst) OperandOrder {
|
||||
// skip decides whether to ignore the instruction for analysis purposes.
|
||||
func skip(i *x86csv.Inst) bool {
|
||||
switch {
|
||||
case strings.Contains(i.GoOpcode(), "/"):
|
||||
case strings.ContainsAny(i.GoOpcode(), "/*"):
|
||||
return true
|
||||
case i.Mode64 == "I": // Invalid in 64-bit mode.
|
||||
return true
|
||||
|
||||
Reference in New Issue
Block a user