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