1
2
3
4
5 package x86_test
6
7 import (
8 "bytes"
9 "fmt"
10 "internal/testenv"
11 "io/ioutil"
12 "os"
13 "os/exec"
14 "path/filepath"
15 "testing"
16 )
17
18 const asmData = `
19 GLOBL zeros<>(SB),8,$64
20 TEXT ·testASM(SB),4,$0
21 VMOVUPS zeros<>(SB), %s // PC relative relocation is off by 1, for Y8-Y15, Z8-15 and Z24-Z31
22 RET
23 `
24
25 const goData = `
26 package main
27
28 func testASM()
29
30 func main() {
31 testASM()
32 }
33 `
34
35 func objdumpOutput(t *testing.T, mname, source string) []byte {
36 tmpdir, err := ioutil.TempDir("", mname)
37 if err != nil {
38 t.Fatal(err)
39 }
40 defer os.RemoveAll(tmpdir)
41 err = ioutil.WriteFile(filepath.Join(tmpdir, "go.mod"), []byte(fmt.Sprintf("module %s\n", mname)), 0666)
42 if err != nil {
43 t.Fatal(err)
44 }
45 tmpfile, err := os.Create(filepath.Join(tmpdir, "input.s"))
46 if err != nil {
47 t.Fatal(err)
48 }
49 defer tmpfile.Close()
50 _, err = tmpfile.WriteString(source)
51 if err != nil {
52 t.Fatal(err)
53 }
54 tmpfile2, err := os.Create(filepath.Join(tmpdir, "input.go"))
55 if err != nil {
56 t.Fatal(err)
57 }
58 defer tmpfile2.Close()
59 _, err = tmpfile2.WriteString(goData)
60 if err != nil {
61 t.Fatal(err)
62 }
63
64 cmd := exec.Command(
65 testenv.GoToolPath(t), "build", "-o",
66 filepath.Join(tmpdir, "output"))
67
68 cmd.Env = append(os.Environ(),
69 "GOARCH=amd64", "GOOS=linux", "GOPATH="+filepath.Join(tmpdir, "_gopath"))
70 cmd.Dir = tmpdir
71
72 out, err := cmd.CombinedOutput()
73 if err != nil {
74 t.Fatalf("error %s output %s", err, out)
75 }
76 cmd2 := exec.Command(
77 testenv.GoToolPath(t), "tool", "objdump", "-s", "testASM",
78 filepath.Join(tmpdir, "output"))
79 cmd2.Env = cmd.Env
80 cmd2.Dir = tmpdir
81 objout, err := cmd2.CombinedOutput()
82 if err != nil {
83 t.Fatalf("error %s output %s", err, objout)
84 }
85
86 return objout
87 }
88
89 func TestVexEvexPCrelative(t *testing.T) {
90 testenv.MustHaveGoBuild(t)
91 LOOP:
92 for _, reg := range []string{"Y0", "Y8", "Z0", "Z8", "Z16", "Z24"} {
93 asm := fmt.Sprintf(asmData, reg)
94 objout := objdumpOutput(t, "pcrelative", asm)
95 data := bytes.Split(objout, []byte("\n"))
96 for idx := len(data) - 1; idx >= 0; idx-- {
97
98 if bytes.Index(data[idx], []byte("RET")) != -1 {
99 if testing.Short() {
100 break LOOP
101 }
102 continue LOOP
103 }
104 }
105 t.Errorf("VMOVUPS zeros<>(SB), %s overwrote RET", reg)
106 }
107 }
108
View as plain text