1
2
3
4
5 package riscv
6
7 import (
8 "bytes"
9 "fmt"
10 "internal/testenv"
11 "io/ioutil"
12 "os"
13 "os/exec"
14 "path/filepath"
15 "runtime"
16 "testing"
17 )
18
19
20
21 func TestLargeBranch(t *testing.T) {
22 if testing.Short() {
23 t.Skip("Skipping test in short mode")
24 }
25 testenv.MustHaveGoBuild(t)
26
27 dir, err := ioutil.TempDir("", "testlargebranch")
28 if err != nil {
29 t.Fatalf("Could not create directory: %v", err)
30 }
31 defer os.RemoveAll(dir)
32
33
34 buf := bytes.NewBuffer(make([]byte, 0, 7000000))
35 genLargeBranch(buf)
36
37 tmpfile := filepath.Join(dir, "x.s")
38 if err := ioutil.WriteFile(tmpfile, buf.Bytes(), 0644); err != nil {
39 t.Fatalf("Failed to write file: %v", err)
40 }
41
42
43 cmd := exec.Command(testenv.GoToolPath(t), "tool", "asm", "-o", filepath.Join(dir, "x.o"), tmpfile)
44 cmd.Env = append(os.Environ(), "GOARCH=riscv64", "GOOS=linux")
45 out, err := cmd.CombinedOutput()
46 if err != nil {
47 t.Errorf("Build failed: %v, output: %s", err, out)
48 }
49 }
50
51 func genLargeBranch(buf *bytes.Buffer) {
52 fmt.Fprintln(buf, "TEXT f(SB),0,$0-0")
53 fmt.Fprintln(buf, "BEQ X0, X0, label")
54 for i := 0; i < 1<<19; i++ {
55 fmt.Fprintln(buf, "ADD $0, X0, X0")
56 }
57 fmt.Fprintln(buf, "label:")
58 fmt.Fprintln(buf, "ADD $0, X0, X0")
59 }
60
61
62
63
64 func TestLargeCall(t *testing.T) {
65 if testing.Short() {
66 t.Skip("Skipping test in short mode")
67 }
68 testenv.MustHaveGoBuild(t)
69
70 dir, err := ioutil.TempDir("", "testlargecall")
71 if err != nil {
72 t.Fatalf("could not create directory: %v", err)
73 }
74 defer os.RemoveAll(dir)
75
76 if err := ioutil.WriteFile(filepath.Join(dir, "go.mod"), []byte("module largecall"), 0644); err != nil {
77 t.Fatalf("Failed to write file: %v\n", err)
78 }
79 main := `package main
80 func main() {
81 x()
82 }
83
84 func x()
85 func y()
86 `
87 if err := ioutil.WriteFile(filepath.Join(dir, "x.go"), []byte(main), 0644); err != nil {
88 t.Fatalf("failed to write main: %v\n", err)
89 }
90
91
92 buf := bytes.NewBuffer(make([]byte, 0, 7000000))
93 genLargeCall(buf)
94
95 if err := ioutil.WriteFile(filepath.Join(dir, "x.s"), buf.Bytes(), 0644); err != nil {
96 t.Fatalf("Failed to write file: %v\n", err)
97 }
98
99
100 cmd := exec.Command(testenv.GoToolPath(t), "build", "-ldflags=-linkmode=internal")
101 cmd.Dir = dir
102 cmd.Env = append(os.Environ(), "GOARCH=riscv64", "GOOS=linux")
103 out, err := cmd.CombinedOutput()
104 if err != nil {
105 t.Errorf("Build failed: %v, output: %s", err, out)
106 }
107
108 if runtime.GOARCH == "riscv64" && testenv.HasCGO() {
109 cmd := exec.Command(testenv.GoToolPath(t), "build", "-ldflags=-linkmode=external")
110 cmd.Dir = dir
111 cmd.Env = append(os.Environ(), "GOARCH=riscv64", "GOOS=linux")
112 out, err := cmd.CombinedOutput()
113 if err != nil {
114 t.Errorf("Build failed: %v, output: %s", err, out)
115 }
116 }
117 }
118
119 func genLargeCall(buf *bytes.Buffer) {
120 fmt.Fprintln(buf, "TEXT ·x(SB),0,$0-0")
121 fmt.Fprintln(buf, "CALL ·y(SB)")
122 for i := 0; i < 1<<19; i++ {
123 fmt.Fprintln(buf, "ADD $0, X0, X0")
124 }
125 fmt.Fprintln(buf, "RET")
126 fmt.Fprintln(buf, "TEXT ·y(SB),0,$0-0")
127 fmt.Fprintln(buf, "ADD $0, X0, X0")
128 fmt.Fprintln(buf, "RET")
129 }
130
131
132 func TestNoRet(t *testing.T) {
133 dir, err := ioutil.TempDir("", "testnoret")
134 if err != nil {
135 t.Fatal(err)
136 }
137 defer os.RemoveAll(dir)
138 tmpfile := filepath.Join(dir, "x.s")
139 if err := ioutil.WriteFile(tmpfile, []byte("TEXT ·stub(SB),$0-0\nNOP\n"), 0644); err != nil {
140 t.Fatal(err)
141 }
142 cmd := exec.Command(testenv.GoToolPath(t), "tool", "asm", "-o", filepath.Join(dir, "x.o"), tmpfile)
143 cmd.Env = append(os.Environ(), "GOARCH=riscv64", "GOOS=linux")
144 if out, err := cmd.CombinedOutput(); err != nil {
145 t.Errorf("%v\n%s", err, out)
146 }
147 }
148
149 func TestImmediateSplitting(t *testing.T) {
150 dir, err := ioutil.TempDir("", "testimmsplit")
151 if err != nil {
152 t.Fatal(err)
153 }
154 defer os.RemoveAll(dir)
155 tmpfile := filepath.Join(dir, "x.s")
156 asm := `
157 TEXT _stub(SB),$0-0
158 LB 4096(X5), X6
159 LH 4096(X5), X6
160 LW 4096(X5), X6
161 LD 4096(X5), X6
162 LBU 4096(X5), X6
163 LHU 4096(X5), X6
164 LWU 4096(X5), X6
165 SB X6, 4096(X5)
166 SH X6, 4096(X5)
167 SW X6, 4096(X5)
168 SD X6, 4096(X5)
169
170 FLW 4096(X5), F6
171 FLD 4096(X5), F6
172 FSW F6, 4096(X5)
173 FSD F6, 4096(X5)
174
175 MOVB 4096(X5), X6
176 MOVH 4096(X5), X6
177 MOVW 4096(X5), X6
178 MOV 4096(X5), X6
179 MOVBU 4096(X5), X6
180 MOVHU 4096(X5), X6
181 MOVWU 4096(X5), X6
182
183 MOVB X6, 4096(X5)
184 MOVH X6, 4096(X5)
185 MOVW X6, 4096(X5)
186 MOV X6, 4096(X5)
187
188 MOVF 4096(X5), F6
189 MOVD 4096(X5), F6
190 MOVF F6, 4096(X5)
191 MOVD F6, 4096(X5)
192 `
193 if err := ioutil.WriteFile(tmpfile, []byte(asm), 0644); err != nil {
194 t.Fatal(err)
195 }
196 cmd := exec.Command(testenv.GoToolPath(t), "tool", "asm", "-o", filepath.Join(dir, "x.o"), tmpfile)
197 cmd.Env = append(os.Environ(), "GOARCH=riscv64", "GOOS=linux")
198 if out, err := cmd.CombinedOutput(); err != nil {
199 t.Errorf("%v\n%s", err, out)
200 }
201 }
202
203 func TestBranch(t *testing.T) {
204 if runtime.GOARCH != "riscv64" {
205 t.Skip("Requires riscv64 to run")
206 }
207
208 testenv.MustHaveGoBuild(t)
209
210 cmd := exec.Command(testenv.GoToolPath(t), "test")
211 cmd.Dir = "testdata/testbranch"
212 if out, err := testenv.CleanCmdEnv(cmd).CombinedOutput(); err != nil {
213 t.Errorf("Branch test failed: %v\n%s", err, out)
214 }
215 }
216
View as plain text