1
2
3
4
5 package loong64
6
7 import (
8 "bytes"
9 "fmt"
10 "internal/testenv"
11 "os"
12 "path/filepath"
13 "regexp"
14 "runtime"
15 "testing"
16 )
17
18 const genBufSize = (1024 * 1024 * 32)
19
20
21
22 func TestLargeBranch(t *testing.T) {
23 if testing.Short() {
24 t.Skip("Skipping test in short mode")
25 }
26 testenv.MustHaveGoBuild(t)
27
28 dir := t.TempDir()
29
30
31 buf := bytes.NewBuffer(make([]byte, 0, genBufSize))
32 genLargeBranch(buf)
33
34 tmpfile := filepath.Join(dir, "x.s")
35 if err := os.WriteFile(tmpfile, buf.Bytes(), 0644); err != nil {
36 t.Fatalf("Failed to write file: %v", err)
37 }
38
39
40 cmd := testenv.Command(t, testenv.GoToolPath(t), "tool", "asm", "-o", filepath.Join(dir, "x.o"), tmpfile)
41 cmd.Env = append(os.Environ(), "GOARCH=loong64", "GOOS=linux")
42 out, err := cmd.CombinedOutput()
43 if err != nil {
44 t.Errorf("Build failed: %v, output: %s", err, out)
45 }
46 }
47
48 func genLargeBranch(buf *bytes.Buffer) {
49 genSize1 := (1 << 16) + 16
50 genSize2 := (1 << 21) + 16
51
52 fmt.Fprintln(buf, "TEXT f(SB),0,$0-0")
53 fmt.Fprintln(buf, "BEQ R5, R6, label18")
54 fmt.Fprintln(buf, "BNE R5, R6, label18")
55 fmt.Fprintln(buf, "BGE R5, R6, label18")
56
57 fmt.Fprintln(buf, "BGEU R5, R6, label18")
58 fmt.Fprintln(buf, "BLTU R5, R6, label18")
59
60 fmt.Fprintln(buf, "BLEZ R5, label18")
61 fmt.Fprintln(buf, "BGEZ R5, label18")
62 fmt.Fprintln(buf, "BLTZ R5, label18")
63 fmt.Fprintln(buf, "BGTZ R5, label18")
64
65 fmt.Fprintln(buf, "BFPT label23")
66 fmt.Fprintln(buf, "BFPF label23")
67
68 fmt.Fprintln(buf, "BEQ R5, label23")
69 fmt.Fprintln(buf, "BNE R5, label23")
70
71 for i := 0; i <= genSize1; i++ {
72 fmt.Fprintln(buf, "ADDV $0, R0, R0")
73 }
74
75 fmt.Fprintln(buf, "label18:")
76 for i := 0; i <= (genSize2 - genSize1); i++ {
77 fmt.Fprintln(buf, "ADDV $0, R0, R0")
78 }
79
80 fmt.Fprintln(buf, "label23:")
81 fmt.Fprintln(buf, "ADDV $0, R0, R0")
82 fmt.Fprintln(buf, "RET")
83 }
84
85
86
87 func TestPCALIGN(t *testing.T) {
88 testenv.MustHaveGoBuild(t)
89 dir := t.TempDir()
90 tmpfile := filepath.Join(dir, "testpcalign.s")
91 tmpout := filepath.Join(dir, "testpcalign.o")
92
93 code1 := []byte("TEXT ·foo(SB),$0-0\nMOVW $0, R0\nPCALIGN $8\nADDV $8, R0\nRET\n")
94 code2 := []byte("TEXT ·foo(SB),$0-0\nMOVW $0, R0\nPCALIGN $16\nADDV $16, R0\nRET\n")
95 code3 := []byte("TEXT ·foo(SB),$0-0\nMOVW $0, R0\nPCALIGN $32\nADDV $32, R0\nRET\n")
96 out1 := `0x0008\s00008\s\(.*\)\s*ADDV\s\$8,\sR0`
97 out2 := `0x0010\s00016\s\(.*\)\s*ADDV\s\$16,\sR0`
98 out3 := `0x0020\s00032\s\(.*\)\s*ADDV\s\$32,\sR0`
99 var testCases = []struct {
100 name string
101 source []byte
102 want string
103 }{
104 {"pcalign8", code1, out1},
105 {"pcalign16", code2, out2},
106 {"pcalign32", code3, out3},
107 }
108 for _, test := range testCases {
109 if err := os.WriteFile(tmpfile, test.source, 0644); err != nil {
110 t.Fatal(err)
111 }
112 cmd := testenv.Command(t, testenv.GoToolPath(t), "tool", "asm", "-S", "-o", tmpout, tmpfile)
113 cmd.Env = append(os.Environ(), "GOARCH=loong64", "GOOS=linux")
114 out, err := cmd.CombinedOutput()
115 if err != nil {
116 t.Errorf("The %s build failed: %v, output: %s", test.name, err, out)
117 continue
118 }
119 matched, err := regexp.MatchString(test.want, string(out))
120 if err != nil {
121 t.Fatal(err)
122 }
123 if !matched {
124 t.Errorf("The %s testing failed!\ninput: %s\noutput: %s\n", test.name, test.source, out)
125 }
126 }
127 }
128
129 func TestNoRet(t *testing.T) {
130 dir := t.TempDir()
131 tmpfile := filepath.Join(dir, "testnoret.s")
132 tmpout := filepath.Join(dir, "testnoret.o")
133 if err := os.WriteFile(tmpfile, []byte("TEXT ·foo(SB),$0-0\nNOP\n"), 0644); err != nil {
134 t.Fatal(err)
135 }
136 cmd := testenv.Command(t, testenv.GoToolPath(t), "tool", "asm", "-o", tmpout, tmpfile)
137 cmd.Env = append(os.Environ(), "GOARCH=loong64", "GOOS=linux")
138 if out, err := cmd.CombinedOutput(); err != nil {
139 t.Errorf("%v\n%s", err, out)
140 }
141 }
142
143 func TestLargeCall(t *testing.T) {
144 if testing.Short() {
145 t.Skip("Skipping test in short mode")
146 }
147 if runtime.GOARCH != "loong64" {
148 t.Skip("Require loong64 to run")
149 }
150 testenv.MustHaveGoBuild(t)
151
152 dir := t.TempDir()
153
154 if err := os.WriteFile(filepath.Join(dir, "go.mod"), []byte("module largecall"), 0644); err != nil {
155 t.Fatalf("Failed to write file: %v\n", err)
156 }
157 main := `package main
158
159 func main() {
160 a()
161 }
162
163 func a()
164 `
165 if err := os.WriteFile(filepath.Join(dir, "largecall.go"), []byte(main), 0644); err != nil {
166 t.Fatalf("failed to write main: %v\n", err)
167 }
168
169
170 buf := bytes.NewBuffer(make([]byte, 0, 7000000))
171 genLargeCall(buf)
172
173 if err := os.WriteFile(filepath.Join(dir, "largecall.s"), buf.Bytes(), 0644); err != nil {
174 t.Fatalf("Failed to write file: %v\n", err)
175 }
176
177
178 cmd := testenv.Command(t, testenv.GoToolPath(t), "build")
179 cmd.Dir = dir
180 out, err := cmd.CombinedOutput()
181 if err != nil {
182 t.Errorf("Build failed: %v, output: %s", err, out)
183 }
184 }
185
186 func genLargeCall(buf *bytes.Buffer) {
187 fmt.Fprintln(buf, "TEXT main·a(SB),0,$0-8")
188 fmt.Fprintln(buf, "CALL b(SB)")
189 for i := 0; i <= ((1 << 26) + 26); i++ {
190 fmt.Fprintln(buf, "ADDV $0, R0, R0")
191 }
192 fmt.Fprintln(buf, "RET")
193 fmt.Fprintln(buf, "TEXT b(SB),0,$0-8")
194 fmt.Fprintln(buf, "ADDV $0, R0, R0")
195 fmt.Fprintln(buf, "RET")
196 }
197
View as plain text