已开启
Enable the support of buildmode plugin, msan, and asan on linux/loong64 #597
Enable the support of buildmode plugin, msan, and asan on linux/loong64 #597
已开启
abner chenc创建于 1月12日
共 8 个文件变更+3103-2
@@ -0,0 +1,268 @@
1+From 3909b0b85be41e2912e1dc902c0c06fa8fb5ac24 Mon Sep 17 00:00:00 2001
2+From: Xiaolin Zhao <zhaoxiaolin@loongson.cn>
3+Date: Fri, 31 Mar 2023 15:36:59 +0800
4+Subject: [PATCH 002/125] runtime, cmd/go: enable memory sanitizer on
5+ linux/loong64
6+ 
7+Change-Id: If537c5ffb1c9d4b3316b9b3794d411953bc5764b
8+---
9+ src/cmd/go/alldocs.go | 2 +-
10+ src/cmd/go/internal/work/build.go | 2 +-
11+ src/internal/platform/supported.go | 2 +-
12+ src/runtime/cgo/gcc_mmap.c | 2 +-
13+ src/runtime/cgo/mmap.go | 2 +-
14+ src/runtime/cgo_mmap.go | 2 +-
15+ src/runtime/mmap.go | 2 +-
16+ src/runtime/msan/msan.go | 2 +-
17+ src/runtime/msan_loong64.s | 72 ++++++++++++++++++++++++++++++
18+ src/runtime/sys_linux_loong64.s | 37 +++++++++++++--
19+ 10 files changed, 113 insertions(+), 12 deletions(-)
20+ create mode 100644 src/runtime/msan_loong64.s
21+ 
22+diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go
23+index bb28756133..d8377d1fd6 100644
24+--- a/src/cmd/go/alldocs.go
25++++ b/src/cmd/go/alldocs.go
26+@@ -119,7 +119,7 @@
27+ // linux/ppc64le and linux/arm64 (only for 48-bit VMA).
28+ // -msan
29+ // enable interoperation with memory sanitizer.
30+-// Supported only on linux/amd64, linux/arm64, freebsd/amd64
31++// Supported only on linux/amd64, linux/arm64, linux/loong64, freebsd/amd64
32+ // and only with Clang/LLVM as the host C compiler.
33+ // PIE build mode will be used on all platforms except linux/amd64.
34+ // -asan
35+diff --git a/src/cmd/go/internal/work/build.go b/src/cmd/go/internal/work/build.go
36+index e2e0e07299..05e300581c 100644
37+--- a/src/cmd/go/internal/work/build.go
38++++ b/src/cmd/go/internal/work/build.go
39+@@ -76,7 +76,7 @@ and test commands:
40+ linux/ppc64le and linux/arm64 (only for 48-bit VMA).
41+ -msan
42+ enable interoperation with memory sanitizer.
43+- Supported only on linux/amd64, linux/arm64, freebsd/amd64
44++ Supported only on linux/amd64, linux/arm64, linux/loong64, freebsd/amd64
45+ and only with Clang/LLVM as the host C compiler.
46+ PIE build mode will be used on all platforms except linux/amd64.
47+ -asan
48+diff --git a/src/internal/platform/supported.go b/src/internal/platform/supported.go
49+index abab4b0541..b4f8bb5496 100644
50+--- a/src/internal/platform/supported.go
51++++ b/src/internal/platform/supported.go
52+@@ -38,7 +38,7 @@ func RaceDetectorSupported(goos, goarch string) bool {
53+ func MSanSupported(goos, goarch string) bool {
54+ switch goos {
55+ case "linux":
56+- return goarch == "amd64" || goarch == "arm64"
57++ return goarch == "amd64" || goarch == "arm64" || goarch == "loong64"
58+ case "freebsd":
59+ return goarch == "amd64"
60+ default:
61+diff --git a/src/runtime/cgo/gcc_mmap.c b/src/runtime/cgo/gcc_mmap.c
62+index 1fbd5e82a4..eb710a039d 100644
63+--- a/src/runtime/cgo/gcc_mmap.c
64++++ b/src/runtime/cgo/gcc_mmap.c
65+@@ -2,7 +2,7 @@
66+ // Use of this source code is governed by a BSD-style
67+ // license that can be found in the LICENSE file.
68+
69+-//go:build (linux && (amd64 || arm64 || ppc64le)) || (freebsd && amd64)
70++//go:build (linux && (amd64 || arm64 || loong64 || ppc64le)) || (freebsd && amd64)
71+
72+ #include <errno.h>
73+ #include <stdint.h>
74+diff --git a/src/runtime/cgo/mmap.go b/src/runtime/cgo/mmap.go
75+index 2f7e83bcb7..144af2b2ca 100644
76+--- a/src/runtime/cgo/mmap.go
77++++ b/src/runtime/cgo/mmap.go
78+@@ -2,7 +2,7 @@
79+ // Use of this source code is governed by a BSD-style
80+ // license that can be found in the LICENSE file.
81+
82+-//go:build (linux && amd64) || (linux && arm64) || (freebsd && amd64)
83++//go:build (linux && (amd64 || arm64 || loong64)) || (freebsd && amd64)
84+
85+ package cgo
86+
87+diff --git a/src/runtime/cgo_mmap.go b/src/runtime/cgo_mmap.go
88+index 30660f7784..36d776e628 100644
89+--- a/src/runtime/cgo_mmap.go
90++++ b/src/runtime/cgo_mmap.go
91+@@ -4,7 +4,7 @@
92+
93+ // Support for memory sanitizer. See runtime/cgo/mmap.go.
94+
95+-//go:build (linux && amd64) || (linux && arm64) || (freebsd && amd64)
96++//go:build (linux && (amd64 || arm64 || loong64)) || (freebsd && amd64)
97+
98+ package runtime
99+
100+diff --git a/src/runtime/mmap.go b/src/runtime/mmap.go
101+index f0183f61cf..9a7b298562 100644
102+--- a/src/runtime/mmap.go
103++++ b/src/runtime/mmap.go
104+@@ -2,7 +2,7 @@
105+ // Use of this source code is governed by a BSD-style
106+ // license that can be found in the LICENSE file.
107+
108+-//go:build !aix && !darwin && !js && (!linux || !amd64) && (!linux || !arm64) && (!freebsd || !amd64) && !openbsd && !plan9 && !solaris && !windows
109++//go:build !aix && !darwin && !js && !((linux && (amd64 || arm64 || loong64)) || (freebsd && amd64)) && !openbsd && !plan9 && !solaris && !windows
110+
111+ package runtime
112+
113+diff --git a/src/runtime/msan/msan.go b/src/runtime/msan/msan.go
114+index 4e41f8528d..7b3e8e608d 100644
115+--- a/src/runtime/msan/msan.go
116++++ b/src/runtime/msan/msan.go
117+@@ -2,7 +2,7 @@
118+ // Use of this source code is governed by a BSD-style
119+ // license that can be found in the LICENSE file.
120+
121+-//go:build msan && ((linux && (amd64 || arm64)) || (freebsd && amd64))
122++//go:build msan && ((linux && (amd64 || arm64 || loong64)) || (freebsd && amd64))
123+
124+ package msan
125+
126+diff --git a/src/runtime/msan_loong64.s b/src/runtime/msan_loong64.s
127+new file mode 100644
128+index 0000000000..dcd7940ed8
129+--- /dev/null
130++++ b/src/runtime/msan_loong64.s
131+@@ -0,0 +1,72 @@
132++// Copyright 2023 The Go Authors. All rights reserved.
133++// Use of this source code is governed by a BSD-style
134++// license that can be found in the LICENSE file.
135++
136++//go:build msan
137++
138++#include "go_asm.h"
139++#include "textflag.h"
140++
141++#define RARG0 R4
142++#define RARG1 R5
143++#define RARG2 R6
144++#define FARG R7
145++
146++// func runtime·domsanread(addr unsafe.Pointer, sz uintptr)
147++// Called from msanread.
148++TEXT runtime·domsanread(SB), NOSPLIT, $0-16
149++ MOVV addr+0(FP), RARG0
150++ MOVV size+8(FP), RARG1
151++ // void __msan_read_go(void *addr, uintptr_t sz);
152++ MOVV $__msan_read_go(SB), FARG
153++ JMP msancall<>(SB)
154++
155++// func runtime·msanwrite(addr unsafe.Pointer, sz uintptr)
156++// Called from instrumented code.
157++TEXT runtime·msanwrite(SB), NOSPLIT, $0-16
158++ MOVV addr+0(FP), RARG0
159++ MOVV size+8(FP), RARG1
160++ // void __msan_write_go(void *addr, uintptr_t sz);
161++ MOVV $__msan_write_go(SB), FARG
162++ JMP msancall<>(SB)
163++
164++// func runtime·msanmalloc(addr unsafe.Pointer, sz uintptr)
165++TEXT runtime·msanmalloc(SB), NOSPLIT, $0-16
166++ MOVV addr+0(FP), RARG0
167++ MOVV size+8(FP), RARG1
168++ // void __msan_malloc_go(void *addr, uintptr_t sz);
169++ MOVV $__msan_malloc_go(SB), FARG
170++ JMP msancall<>(SB)
171++
172++// func runtime·msanfree(addr unsafe.Pointer, sz uintptr)
173++TEXT runtime·msanfree(SB), NOSPLIT, $0-16
174++ MOVV addr+0(FP), RARG0
175++ MOVV size+8(FP), RARG1
176++ // void __msan_free_go(void *addr, uintptr_t sz);
177++ MOVV $__msan_free_go(SB), FARG
178++ JMP msancall<>(SB)
179++
180++// func runtime·msanmove(dst, src unsafe.Pointer, sz uintptr)
181++TEXT runtime·msanmove(SB), NOSPLIT, $0-24
182++ MOVV dst+0(FP), RARG0
183++ MOVV src+8(FP), RARG1
184++ MOVV size+16(FP), RARG2
185++ // void __msan_memmove(void *dst, void *src, uintptr_t sz);
186++ MOVV $__msan_memmove(SB), FARG
187++ JMP msancall<>(SB)
188++
189++// Switches SP to g0 stack and calls (FARG). Arguments already set.
190++TEXT msancall<>(SB), NOSPLIT, $0-0
191++ MOVV R3, R23 // callee-saved
192++ BEQ g, g0stack // no g, still on a system stack
193++ MOVV g_m(g), R14
194++ MOVV m_g0(R14), R15
195++ BEQ R15, g, g0stack
196++
197++ MOVV (g_sched+gobuf_sp)(R15), R9
198++ MOVV R9, R3
199++
200++g0stack:
201++ JAL (FARG)
202++ MOVV R23, R3
203++ RET
204+diff --git a/src/runtime/sys_linux_loong64.s b/src/runtime/sys_linux_loong64.s
205+index 12e5455345..eba8e1f24c 100644
206+--- a/src/runtime/sys_linux_loong64.s
207++++ b/src/runtime/sys_linux_loong64.s
208+@@ -461,8 +461,8 @@ TEXT runtime·sigtramp(SB),NOSPLIT|TOPFRAME,$168
209+ TEXT runtime·cgoSigtramp(SB),NOSPLIT,$0
210+ JMP runtime·sigtramp(SB)
211+
212+-// func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) (p unsafe.Pointer, err int)
213+-TEXT runtime·mmap(SB),NOSPLIT|NOFRAME,$0
214++// func sysMmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) (p unsafe.Pointer, err int)
215++TEXT runtime·sysMmap(SB),NOSPLIT|NOFRAME,$0
216+ MOVV addr+0(FP), R4
217+ MOVV n+8(FP), R5
218+ MOVW prot+16(FP), R6
219+@@ -483,8 +483,25 @@ ok:
220+ MOVV $0, err+40(FP)
221+ RET
222+
223+-// func munmap(addr unsafe.Pointer, n uintptr)
224+-TEXT runtime·munmap(SB),NOSPLIT|NOFRAME,$0
225++// Call the function stored in _cgo_mmap using the GCC calling convention.
226++// This must be called on the system stack.
227++// func callCgoMmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) uintptr
228++TEXT runtime·callCgoMmap(SB),NOSPLIT,$0
229++ MOVV addr+0(FP), R4
230++ MOVV n+8(FP), R5
231++ MOVW prot+16(FP), R6
232++ MOVW flags+20(FP), R7
233++ MOVW fd+24(FP), R8
234++ MOVW off+28(FP), R9
235++ MOVV _cgo_mmap(SB), R13
236++ SUBV $16, R3 // reserve 16 bytes for sp-8 where fp may be saved.
237++ JAL (R13)
238++ ADDV $16, R3
239++ MOVV R4, ret+32(FP)
240++ RET
241++
242++// func sysMunmap(addr unsafe.Pointer, n uintptr)
243++TEXT runtime·sysMunmap(SB),NOSPLIT|NOFRAME,$0
244+ MOVV addr+0(FP), R4
245+ MOVV n+8(FP), R5
246+ MOVV $SYS_munmap, R11
247+@@ -494,6 +511,18 @@ TEXT runtime·munmap(SB),NOSPLIT|NOFRAME,$0
248+ MOVV R0, 0xf3(R0) // crash
249+ RET
250+
251++// Call the function stored in _cgo_munmap using the GCC calling convention.
252++// This must be called on the system stack.
253++// func callCgoMunmap(addr unsafe.Pointer, n uintptr)
254++TEXT runtime·callCgoMunmap(SB),NOSPLIT,$0
255++ MOVV addr+0(FP), R4
256++ MOVV n+8(FP), R5
257++ MOVV _cgo_munmap(SB), R13
258++ SUBV $16, R3 // reserve 16 bytes for sp-8 where fp may be saved.
259++ JAL (R13)
260++ ADDV $16, R3
261++ RET
262++
263+ // func madvise(addr unsafe.Pointer, n uintptr, flags int32)
264+ TEXT runtime·madvise(SB),NOSPLIT|NOFRAME,$0
265+ MOVV addr+0(FP), R4
266+--
267+2.43.0
268+ 
@@ -0,0 +1,160 @@
1+From 2e27f8c441e18c122acff8179715e891b1a9ead2 Mon Sep 17 00:00:00 2001
2+From: Xiaolin Zhao <zhaoxiaolin@loongson.cn>
3+Date: Fri, 31 Mar 2023 17:08:44 +0800
4+Subject: [PATCH 003/125] runtime, cmd/go: enable address sanitizer on
5+ linux/loong64
6+ 
7+Change-Id: I48a65f2f10e3dc488acd9c02ea1a1f37de192be0
8+---
9+ src/cmd/go/alldocs.go | 5 +-
10+ src/cmd/go/internal/work/build.go | 5 +-
11+ src/internal/platform/supported.go | 2 +-
12+ src/runtime/asan/asan.go | 2 +-
13+ src/runtime/asan_loong64.s | 75 ++++++++++++++++++++++++++++++
14+ 5 files changed, 83 insertions(+), 6 deletions(-)
15+ create mode 100644 src/runtime/asan_loong64.s
16+ 
17+diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go
18+index d8377d1fd6..7de5a066dd 100644
19+--- a/src/cmd/go/alldocs.go
20++++ b/src/cmd/go/alldocs.go
21+@@ -124,9 +124,10 @@
22+ // PIE build mode will be used on all platforms except linux/amd64.
23+ // -asan
24+ // enable interoperation with address sanitizer.
25+-// Supported only on linux/arm64, linux/amd64.
26+-// Supported only on linux/amd64 or linux/arm64 and only with GCC 7 and higher
27++// Supported only on linux/arm64, linux/amd64, linux/loong64.
28++// Supported on linux/amd64 or linux/arm64 and only with GCC 7 and higher
29+ // or Clang/LLVM 9 and higher.
30++// And supported on linux/loong64 only with Clang/LLVM 16 and higher.
31+ // -cover
32+ // enable code coverage instrumentation.
33+ // -covermode set,count,atomic
34+diff --git a/src/cmd/go/internal/work/build.go b/src/cmd/go/internal/work/build.go
35+index 05e300581c..8cb53b95d9 100644
36+--- a/src/cmd/go/internal/work/build.go
37++++ b/src/cmd/go/internal/work/build.go
38+@@ -81,9 +81,10 @@ and test commands:
39+ PIE build mode will be used on all platforms except linux/amd64.
40+ -asan
41+ enable interoperation with address sanitizer.
42+- Supported only on linux/arm64, linux/amd64.
43+- Supported only on linux/amd64 or linux/arm64 and only with GCC 7 and higher
44++ Supported only on linux/arm64, linux/amd64, linux/loong64.
45++ Supported on linux/amd64 or linux/arm64 and only with GCC 7 and higher
46+ or Clang/LLVM 9 and higher.
47++ And supported on linux/loong64 only with Clang/LLVM 16 and higher.
48+ -cover
49+ enable code coverage instrumentation.
50+ -covermode set,count,atomic
51+diff --git a/src/internal/platform/supported.go b/src/internal/platform/supported.go
52+index b4f8bb5496..715bfb5e48 100644
53+--- a/src/internal/platform/supported.go
54++++ b/src/internal/platform/supported.go
55+@@ -51,7 +51,7 @@ func MSanSupported(goos, goarch string) bool {
56+ func ASanSupported(goos, goarch string) bool {
57+ switch goos {
58+ case "linux":
59+- return goarch == "arm64" || goarch == "amd64" || goarch == "riscv64" || goarch == "ppc64le"
60++ return goarch == "arm64" || goarch == "amd64" || goarch == "loong64" || goarch == "riscv64" || goarch == "ppc64le"
61+ default:
62+ return false
63+ }
64+diff --git a/src/runtime/asan/asan.go b/src/runtime/asan/asan.go
65+index 25f15ae45b..ef70b0145b 100644
66+--- a/src/runtime/asan/asan.go
67++++ b/src/runtime/asan/asan.go
68+@@ -2,7 +2,7 @@
69+ // Use of this source code is governed by a BSD-style
70+ // license that can be found in the LICENSE file.
71+
72+-//go:build asan && linux && (arm64 || amd64 || riscv64 || ppc64le)
73++//go:build asan && linux && (arm64 || amd64 || loong64 || riscv64 || ppc64le)
74+
75+ package asan
76+
77+diff --git a/src/runtime/asan_loong64.s b/src/runtime/asan_loong64.s
78+new file mode 100644
79+index 0000000000..8cef686217
80+--- /dev/null
81++++ b/src/runtime/asan_loong64.s
82+@@ -0,0 +1,75 @@
83++// Copyright 2023 The Go Authors. All rights reserved.
84++// Use of this source code is governed by a BSD-style
85++// license that can be found in the LICENSE file.
86++
87++//go:build asan
88++
89++#include "go_asm.h"
90++#include "textflag.h"
91++
92++#define RARG0 R4
93++#define RARG1 R5
94++#define RARG2 R6
95++#define RARG3 R7
96++#define FARG R8
97++
98++// Called from instrumented code.
99++// func runtime·doasanread(addr unsafe.Pointer, sz, sp, pc uintptr)
100++TEXT runtime·doasanread(SB), NOSPLIT, $0-32
101++ MOVV addr+0(FP), RARG0
102++ MOVV size+8(FP), RARG1
103++ MOVV sp+16(FP), RARG2
104++ MOVV pc+24(FP), RARG3
105++ // void __asan_read_go(void *addr, uintptr_t sz, void *sp, void *pc);
106++ MOVV $__asan_read_go(SB), FARG
107++ JMP asancall<>(SB)
108++
109++// func runtime·doasanwrite(addr unsafe.Pointer, sz, sp, pc uintptr)
110++TEXT runtime·doasanwrite(SB), NOSPLIT, $0-32
111++ MOVV addr+0(FP), RARG0
112++ MOVV size+8(FP), RARG1
113++ MOVV sp+16(FP), RARG2
114++ MOVV pc+24(FP), RARG3
115++ // void __asan_write_go(void *addr, uintptr_t sz, void *sp, void *pc);
116++ MOVV $__asan_write_go(SB), FARG
117++ JMP asancall<>(SB)
118++
119++// func runtime·asanunpoison(addr unsafe.Pointer, sz uintptr)
120++TEXT runtime·asanunpoison(SB), NOSPLIT, $0-16
121++ MOVV addr+0(FP), RARG0
122++ MOVV size+8(FP), RARG1
123++ // void __asan_unpoison_go(void *addr, uintptr_t sz);
124++ MOVV $__asan_unpoison_go(SB), FARG
125++ JMP asancall<>(SB)
126++
127++// func runtime·asanpoison(addr unsafe.Pointer, sz uintptr)
128++TEXT runtime·asanpoison(SB), NOSPLIT, $0-16
129++ MOVV addr+0(FP), RARG0
130++ MOVV size+8(FP), RARG1
131++ // void __asan_poison_go(void *addr, uintptr_t sz);
132++ MOVV $__asan_poison_go(SB), FARG
133++ JMP asancall<>(SB)
134++
135++// func runtime·asanregisterglobals(addr unsafe.Pointer, n uintptr)
136++TEXT runtime·asanregisterglobals(SB), NOSPLIT, $0-16
137++ MOVV addr+0(FP), RARG0
138++ MOVV size+8(FP), RARG1
139++ // void __asan_register_globals_go(void *addr, uintptr_t n);
140++ MOVV $__asan_register_globals_go(SB), FARG
141++ JMP asancall<>(SB)
142++
143++// Switches SP to g0 stack and calls (FARG). Arguments already set.
144++TEXT asancall<>(SB), NOSPLIT, $0-0
145++ MOVV R3, R23 // callee-saved
146++ BEQ g, g0stack // no g, still on a system stack
147++ MOVV g_m(g), R14
148++ MOVV m_g0(R14), R15
149++ BEQ R15, g, g0stack
150++
151++ MOVV (g_sched+gobuf_sp)(R15), R9
152++ MOVV R9, R3
153++
154++g0stack:
155++ JAL (FARG)
156++ MOVV R23, R3
157++ RET
158+--
159+2.43.0
160+ 
@@ -0,0 +1,542 @@
1+From d7b52af1dafe2358a81d140e21136ed1d7995b57 Mon Sep 17 00:00:00 2001
2+From: Guoqi Chen <chenguoqi@loongson.cn>
3+Date: Fri, 21 Apr 2023 11:08:09 +0800
4+Subject: [PATCH 007/125] runtime: remove the meaningless offset of 8 for
5+ duffzero on loong64
6+ 
7+Currently we subtract 8 from offset when calling duffzero because 8
8+is added to offset in the duffzero implementation. This operation is
9+meaningless, so remove it.
10+ 
11+Change-Id: I22da26e19353275a9bfae523a9e37f8e4ec26041
12+---
13+ src/cmd/compile/internal/loong64/ggen.go | 23 +-
14+ src/cmd/compile/internal/loong64/ssa.go | 10 +-
15+ .../compile/internal/ssa/_gen/LOONG64Ops.go | 2 +-
16+ src/cmd/compile/internal/ssa/opGen.go | 2 +-
17+ src/runtime/duff_loong64.s | 256 +++++++++---------
18+ src/runtime/mkduff.go | 4 +-
19+ 6 files changed, 148 insertions(+), 149 deletions(-)
20+ 
21+diff --git a/src/cmd/compile/internal/loong64/ggen.go b/src/cmd/compile/internal/loong64/ggen.go
22+index 8a24d2f295..27d318a8bb 100644
23+--- a/src/cmd/compile/internal/loong64/ggen.go
24++++ b/src/cmd/compile/internal/loong64/ggen.go
25+@@ -5,6 +5,7 @@
26+ package loong64
27+
28+ import (
29++ "cmd/compile/internal/base"
30+ "cmd/compile/internal/ir"
31+ "cmd/compile/internal/objw"
32+ "cmd/compile/internal/types"
33+@@ -16,34 +17,38 @@ func zerorange(pp *objw.Progs, p *obj.Prog, off, cnt int64, _ *uint32) *obj.Prog
34+ if cnt == 0 {
35+ return p
36+ }
37++
38++ // Adjust the frame to account for LR.
39++ off += base.Ctxt.Arch.FixedFrameSize
40++
41+ if cnt < int64(4*types.PtrSize) {
42+ for i := int64(0); i < cnt; i += int64(types.PtrSize) {
43+- p = pp.Append(p, loong64.AMOVV, obj.TYPE_REG, loong64.REGZERO, 0, obj.TYPE_MEM, loong64.REGSP, 8+off+i)
44++ p = pp.Append(p, loong64.AMOVV, obj.TYPE_REG, loong64.REGZERO, 0, obj.TYPE_MEM, loong64.REGSP, off+i)
45+ }
46+ } else if cnt <= int64(128*types.PtrSize) {
47+- p = pp.Append(p, loong64.AADDV, obj.TYPE_CONST, 0, 8+off-8, obj.TYPE_REG, loong64.REGRT1, 0)
48++ p = pp.Append(p, loong64.AADDV, obj.TYPE_CONST, 0, off, obj.TYPE_REG, loong64.REGRT1, 0)
49+ p.Reg = loong64.REGSP
50+ p = pp.Append(p, obj.ADUFFZERO, obj.TYPE_NONE, 0, 0, obj.TYPE_MEM, 0, 0)
51+ p.To.Name = obj.NAME_EXTERN
52+ p.To.Sym = ir.Syms.Duffzero
53+ p.To.Offset = 8 * (128 - cnt/int64(types.PtrSize))
54+ } else {
55+- // ADDV $(8+frame+lo-8), SP, r1
56++ // ADDV $(off), SP, r1
57+ // ADDV $cnt, r1, r2
58+ // loop:
59+- // MOVV R0, (Widthptr)r1
60++ // MOVV R0, (r1)
61+ // ADDV $Widthptr, r1
62+- // BNE r1, r2, loop
63+- p = pp.Append(p, loong64.AADDV, obj.TYPE_CONST, 0, 8+off-8, obj.TYPE_REG, loong64.REGRT1, 0)
64++ // BNE r1, r2, loop
65++ p = pp.Append(p, loong64.AADDV, obj.TYPE_CONST, 0, off, obj.TYPE_REG, loong64.REGRT1, 0)
66+ p.Reg = loong64.REGSP
67+ p = pp.Append(p, loong64.AADDV, obj.TYPE_CONST, 0, cnt, obj.TYPE_REG, loong64.REGRT2, 0)
68+ p.Reg = loong64.REGRT1
69+- p = pp.Append(p, loong64.AMOVV, obj.TYPE_REG, loong64.REGZERO, 0, obj.TYPE_MEM, loong64.REGRT1, int64(types.PtrSize))
70+- p1 := p
71++ p = pp.Append(p, loong64.AMOVV, obj.TYPE_REG, loong64.REGZERO, 0, obj.TYPE_MEM, loong64.REGRT1, 0)
72++ loop := p
73+ p = pp.Append(p, loong64.AADDV, obj.TYPE_CONST, 0, int64(types.PtrSize), obj.TYPE_REG, loong64.REGRT1, 0)
74+ p = pp.Append(p, loong64.ABNE, obj.TYPE_REG, loong64.REGRT1, 0, obj.TYPE_BRANCH, 0, 0)
75+ p.Reg = loong64.REGRT2
76+- p.To.SetTarget(p1)
77++ p.To.SetTarget(loop)
78+ }
79+
80+ return p
81+diff --git a/src/cmd/compile/internal/loong64/ssa.go b/src/cmd/compile/internal/loong64/ssa.go
82+index 8193b4e321..574217fd92 100644
83+--- a/src/cmd/compile/internal/loong64/ssa.go
84++++ b/src/cmd/compile/internal/loong64/ssa.go
85+@@ -340,14 +340,8 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
86+ p.To.Type = obj.TYPE_REG
87+ p.To.Reg = v.Reg()
88+ case ssa.OpLOONG64DUFFZERO:
89+- // runtime.duffzero expects start address - 8 in R19
90+- p := s.Prog(loong64.ASUBVU)
91+- p.From.Type = obj.TYPE_CONST
92+- p.From.Offset = 8
93+- p.Reg = v.Args[0].Reg()
94+- p.To.Type = obj.TYPE_REG
95+- p.To.Reg = loong64.REG_R19
96+- p = s.Prog(obj.ADUFFZERO)
97++ // runtime.duffzero expects start address in R19
98++ p := s.Prog(obj.ADUFFZERO)
99+ p.To.Type = obj.TYPE_MEM
100+ p.To.Name = obj.NAME_EXTERN
101+ p.To.Sym = ir.Syms.Duffzero
102+diff --git a/src/cmd/compile/internal/ssa/_gen/LOONG64Ops.go b/src/cmd/compile/internal/ssa/_gen/LOONG64Ops.go
103+index 23f20fddeb..b715b36542 100644
104+--- a/src/cmd/compile/internal/ssa/_gen/LOONG64Ops.go
105++++ b/src/cmd/compile/internal/ssa/_gen/LOONG64Ops.go
106+@@ -289,7 +289,7 @@ func init() {
107+ aux: "Int64",
108+ argLength: 2,
109+ reg: regInfo{
110+- inputs: []regMask{gp},
111++ inputs: []regMask{buildReg("R19")},
112+ clobbers: buildReg("R19 R1"),
113+ },
114+ faultOnNilArg0: true,
115+diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go
116+index e7caf9050c..e95cb250d9 100644
117+--- a/src/cmd/compile/internal/ssa/opGen.go
118++++ b/src/cmd/compile/internal/ssa/opGen.go
119+@@ -24266,7 +24266,7 @@ var opcodeTable = [...]opInfo{
120+ faultOnNilArg0: true,
121+ reg: regInfo{
122+ inputs: []inputInfo{
123+- {0, 1070596088}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R23 R24 R25 R26 R27 R28 R29 R31
124++ {0, 262144}, // R19
125+ },
126+ clobbers: 262146, // R1 R19
127+ },
128+diff --git a/src/runtime/duff_loong64.s b/src/runtime/duff_loong64.s
129+index 7f78e4fa9f..63fa3bcca1 100644
130+--- a/src/runtime/duff_loong64.s
131++++ b/src/runtime/duff_loong64.s
132+@@ -5,261 +5,261 @@
133+ #include "textflag.h"
134+
135+ TEXT runtime·duffzero(SB), NOSPLIT|NOFRAME, $0-0
136+- MOVV R0, 8(R19)
137++ MOVV R0, (R19)
138+ ADDV $8, R19
139+- MOVV R0, 8(R19)
140++ MOVV R0, (R19)
141+ ADDV $8, R19
142+- MOVV R0, 8(R19)
143++ MOVV R0, (R19)
144+ ADDV $8, R19
145+- MOVV R0, 8(R19)
146++ MOVV R0, (R19)
147+ ADDV $8, R19
148+- MOVV R0, 8(R19)
149++ MOVV R0, (R19)
150+ ADDV $8, R19
151+- MOVV R0, 8(R19)
152++ MOVV R0, (R19)
153+ ADDV $8, R19
154+- MOVV R0, 8(R19)
155++ MOVV R0, (R19)
156+ ADDV $8, R19
157+- MOVV R0, 8(R19)
158++ MOVV R0, (R19)
159+ ADDV $8, R19
160+- MOVV R0, 8(R19)
161++ MOVV R0, (R19)
162+ ADDV $8, R19
163+- MOVV R0, 8(R19)
164++ MOVV R0, (R19)
165+ ADDV $8, R19
166+- MOVV R0, 8(R19)
167++ MOVV R0, (R19)
168+ ADDV $8, R19
169+- MOVV R0, 8(R19)
170++ MOVV R0, (R19)
171+ ADDV $8, R19
172+- MOVV R0, 8(R19)
173++ MOVV R0, (R19)
174+ ADDV $8, R19
175+- MOVV R0, 8(R19)
176++ MOVV R0, (R19)
177+ ADDV $8, R19
178+- MOVV R0, 8(R19)
179++ MOVV R0, (R19)
180+ ADDV $8, R19
181+- MOVV R0, 8(R19)
182++ MOVV R0, (R19)
183+ ADDV $8, R19
184+- MOVV R0, 8(R19)
185++ MOVV R0, (R19)
186+ ADDV $8, R19
187+- MOVV R0, 8(R19)
188++ MOVV R0, (R19)
189+ ADDV $8, R19
190+- MOVV R0, 8(R19)
191++ MOVV R0, (R19)
192+ ADDV $8, R19
193+- MOVV R0, 8(R19)
194++ MOVV R0, (R19)
195+ ADDV $8, R19
196+- MOVV R0, 8(R19)
197++ MOVV R0, (R19)
198+ ADDV $8, R19
199+- MOVV R0, 8(R19)
200++ MOVV R0, (R19)
201+ ADDV $8, R19
202+- MOVV R0, 8(R19)
203++ MOVV R0, (R19)
204+ ADDV $8, R19
205+- MOVV R0, 8(R19)
206++ MOVV R0, (R19)
207+ ADDV $8, R19
208+- MOVV R0, 8(R19)
209++ MOVV R0, (R19)
210+ ADDV $8, R19
211+- MOVV R0, 8(R19)
212++ MOVV R0, (R19)
213+ ADDV $8, R19
214+- MOVV R0, 8(R19)
215++ MOVV R0, (R19)
216+ ADDV $8, R19
217+- MOVV R0, 8(R19)
218++ MOVV R0, (R19)
219+ ADDV $8, R19
220+- MOVV R0, 8(R19)
221++ MOVV R0, (R19)
222+ ADDV $8, R19
223+- MOVV R0, 8(R19)
224++ MOVV R0, (R19)
225+ ADDV $8, R19
226+- MOVV R0, 8(R19)
227++ MOVV R0, (R19)
228+ ADDV $8, R19
229+- MOVV R0, 8(R19)
230++ MOVV R0, (R19)
231+ ADDV $8, R19
232+- MOVV R0, 8(R19)
233++ MOVV R0, (R19)
234+ ADDV $8, R19
235+- MOVV R0, 8(R19)
236++ MOVV R0, (R19)
237+ ADDV $8, R19
238+- MOVV R0, 8(R19)
239++ MOVV R0, (R19)
240+ ADDV $8, R19
241+- MOVV R0, 8(R19)
242++ MOVV R0, (R19)
243+ ADDV $8, R19
244+- MOVV R0, 8(R19)
245++ MOVV R0, (R19)
246+ ADDV $8, R19
247+- MOVV R0, 8(R19)
248++ MOVV R0, (R19)
249+ ADDV $8, R19
250+- MOVV R0, 8(R19)
251++ MOVV R0, (R19)
252+ ADDV $8, R19
253+- MOVV R0, 8(R19)
254++ MOVV R0, (R19)
255+ ADDV $8, R19
256+- MOVV R0, 8(R19)
257++ MOVV R0, (R19)
258+ ADDV $8, R19
259+- MOVV R0, 8(R19)
260++ MOVV R0, (R19)
261+ ADDV $8, R19
262+- MOVV R0, 8(R19)
263++ MOVV R0, (R19)
264+ ADDV $8, R19
265+- MOVV R0, 8(R19)
266++ MOVV R0, (R19)
267+ ADDV $8, R19
268+- MOVV R0, 8(R19)
269++ MOVV R0, (R19)
270+ ADDV $8, R19
271+- MOVV R0, 8(R19)
272++ MOVV R0, (R19)
273+ ADDV $8, R19
274+- MOVV R0, 8(R19)
275++ MOVV R0, (R19)
276+ ADDV $8, R19
277+- MOVV R0, 8(R19)
278++ MOVV R0, (R19)
279+ ADDV $8, R19
280+- MOVV R0, 8(R19)
281++ MOVV R0, (R19)
282+ ADDV $8, R19
283+- MOVV R0, 8(R19)
284++ MOVV R0, (R19)
285+ ADDV $8, R19
286+- MOVV R0, 8(R19)
287++ MOVV R0, (R19)
288+ ADDV $8, R19
289+- MOVV R0, 8(R19)
290++ MOVV R0, (R19)
291+ ADDV $8, R19
292+- MOVV R0, 8(R19)
293++ MOVV R0, (R19)
294+ ADDV $8, R19
295+- MOVV R0, 8(R19)
296++ MOVV R0, (R19)
297+ ADDV $8, R19
298+- MOVV R0, 8(R19)
299++ MOVV R0, (R19)
300+ ADDV $8, R19
301+- MOVV R0, 8(R19)
302++ MOVV R0, (R19)
303+ ADDV $8, R19
304+- MOVV R0, 8(R19)
305++ MOVV R0, (R19)
306+ ADDV $8, R19
307+- MOVV R0, 8(R19)
308++ MOVV R0, (R19)
309+ ADDV $8, R19
310+- MOVV R0, 8(R19)
311++ MOVV R0, (R19)
312+ ADDV $8, R19
313+- MOVV R0, 8(R19)
314++ MOVV R0, (R19)
315+ ADDV $8, R19
316+- MOVV R0, 8(R19)
317++ MOVV R0, (R19)
318+ ADDV $8, R19
319+- MOVV R0, 8(R19)
320++ MOVV R0, (R19)
321+ ADDV $8, R19
322+- MOVV R0, 8(R19)
323++ MOVV R0, (R19)
324+ ADDV $8, R19
325+- MOVV R0, 8(R19)
326++ MOVV R0, (R19)
327+ ADDV $8, R19
328+- MOVV R0, 8(R19)
329++ MOVV R0, (R19)
330+ ADDV $8, R19
331+- MOVV R0, 8(R19)
332++ MOVV R0, (R19)
333+ ADDV $8, R19
334+- MOVV R0, 8(R19)
335++ MOVV R0, (R19)
336+ ADDV $8, R19
337+- MOVV R0, 8(R19)
338++ MOVV R0, (R19)
339+ ADDV $8, R19
340+- MOVV R0, 8(R19)
341++ MOVV R0, (R19)
342+ ADDV $8, R19
343+- MOVV R0, 8(R19)
344++ MOVV R0, (R19)
345+ ADDV $8, R19
346+- MOVV R0, 8(R19)
347++ MOVV R0, (R19)
348+ ADDV $8, R19
349+- MOVV R0, 8(R19)
350++ MOVV R0, (R19)
351+ ADDV $8, R19
352+- MOVV R0, 8(R19)
353++ MOVV R0, (R19)
354+ ADDV $8, R19
355+- MOVV R0, 8(R19)
356++ MOVV R0, (R19)
357+ ADDV $8, R19
358+- MOVV R0, 8(R19)
359++ MOVV R0, (R19)
360+ ADDV $8, R19
361+- MOVV R0, 8(R19)
362++ MOVV R0, (R19)
363+ ADDV $8, R19
364+- MOVV R0, 8(R19)
365++ MOVV R0, (R19)
366+ ADDV $8, R19
367+- MOVV R0, 8(R19)
368++ MOVV R0, (R19)
369+ ADDV $8, R19
370+- MOVV R0, 8(R19)
371++ MOVV R0, (R19)
372+ ADDV $8, R19
373+- MOVV R0, 8(R19)
374++ MOVV R0, (R19)
375+ ADDV $8, R19
376+- MOVV R0, 8(R19)
377++ MOVV R0, (R19)
378+ ADDV $8, R19
379+- MOVV R0, 8(R19)
380++ MOVV R0, (R19)
381+ ADDV $8, R19
382+- MOVV R0, 8(R19)
383++ MOVV R0, (R19)
384+ ADDV $8, R19
385+- MOVV R0, 8(R19)
386++ MOVV R0, (R19)
387+ ADDV $8, R19
388+- MOVV R0, 8(R19)
389++ MOVV R0, (R19)
390+ ADDV $8, R19
391+- MOVV R0, 8(R19)
392++ MOVV R0, (R19)
393+ ADDV $8, R19
394+- MOVV R0, 8(R19)
395++ MOVV R0, (R19)
396+ ADDV $8, R19
397+- MOVV R0, 8(R19)
398++ MOVV R0, (R19)
399+ ADDV $8, R19
400+- MOVV R0, 8(R19)
401++ MOVV R0, (R19)
402+ ADDV $8, R19
403+- MOVV R0, 8(R19)
404++ MOVV R0, (R19)
405+ ADDV $8, R19
406+- MOVV R0, 8(R19)
407++ MOVV R0, (R19)
408+ ADDV $8, R19
409+- MOVV R0, 8(R19)
410++ MOVV R0, (R19)
411+ ADDV $8, R19
412+- MOVV R0, 8(R19)
413++ MOVV R0, (R19)
414+ ADDV $8, R19
415+- MOVV R0, 8(R19)
416++ MOVV R0, (R19)
417+ ADDV $8, R19
418+- MOVV R0, 8(R19)
419++ MOVV R0, (R19)
420+ ADDV $8, R19
421+- MOVV R0, 8(R19)
422++ MOVV R0, (R19)
423+ ADDV $8, R19
424+- MOVV R0, 8(R19)
425++ MOVV R0, (R19)
426+ ADDV $8, R19
427+- MOVV R0, 8(R19)
428++ MOVV R0, (R19)
429+ ADDV $8, R19
430+- MOVV R0, 8(R19)
431++ MOVV R0, (R19)
432+ ADDV $8, R19
433+- MOVV R0, 8(R19)
434++ MOVV R0, (R19)
435+ ADDV $8, R19
436+- MOVV R0, 8(R19)
437++ MOVV R0, (R19)
438+ ADDV $8, R19
439+- MOVV R0, 8(R19)
440++ MOVV R0, (R19)
441+ ADDV $8, R19
442+- MOVV R0, 8(R19)
443++ MOVV R0, (R19)
444+ ADDV $8, R19
445+- MOVV R0, 8(R19)
446++ MOVV R0, (R19)
447+ ADDV $8, R19
448+- MOVV R0, 8(R19)
449++ MOVV R0, (R19)
450+ ADDV $8, R19
451+- MOVV R0, 8(R19)
452++ MOVV R0, (R19)
453+ ADDV $8, R19
454+- MOVV R0, 8(R19)
455++ MOVV R0, (R19)
456+ ADDV $8, R19
457+- MOVV R0, 8(R19)
458++ MOVV R0, (R19)
459+ ADDV $8, R19
460+- MOVV R0, 8(R19)
461++ MOVV R0, (R19)
462+ ADDV $8, R19
463+- MOVV R0, 8(R19)
464++ MOVV R0, (R19)
465+ ADDV $8, R19
466+- MOVV R0, 8(R19)
467++ MOVV R0, (R19)
468+ ADDV $8, R19
469+- MOVV R0, 8(R19)
470++ MOVV R0, (R19)
471+ ADDV $8, R19
472+- MOVV R0, 8(R19)
473++ MOVV R0, (R19)
474+ ADDV $8, R19
475+- MOVV R0, 8(R19)
476++ MOVV R0, (R19)
477+ ADDV $8, R19
478+- MOVV R0, 8(R19)
479++ MOVV R0, (R19)
480+ ADDV $8, R19
481+- MOVV R0, 8(R19)
482++ MOVV R0, (R19)
483+ ADDV $8, R19
484+- MOVV R0, 8(R19)
485++ MOVV R0, (R19)
486+ ADDV $8, R19
487+- MOVV R0, 8(R19)
488++ MOVV R0, (R19)
489+ ADDV $8, R19
490+- MOVV R0, 8(R19)
491++ MOVV R0, (R19)
492+ ADDV $8, R19
493+- MOVV R0, 8(R19)
494++ MOVV R0, (R19)
495+ ADDV $8, R19
496+- MOVV R0, 8(R19)
497++ MOVV R0, (R19)
498+ ADDV $8, R19
499+- MOVV R0, 8(R19)
500++ MOVV R0, (R19)
501+ ADDV $8, R19
502+- MOVV R0, 8(R19)
503++ MOVV R0, (R19)
504+ ADDV $8, R19
505+- MOVV R0, 8(R19)
506++ MOVV R0, (R19)
507+ ADDV $8, R19
508+- MOVV R0, 8(R19)
509++ MOVV R0, (R19)
510+ ADDV $8, R19
511+- MOVV R0, 8(R19)
512++ MOVV R0, (R19)
513+ ADDV $8, R19
514+- MOVV R0, 8(R19)
515++ MOVV R0, (R19)
516+ ADDV $8, R19
517+- MOVV R0, 8(R19)
518++ MOVV R0, (R19)
519+ ADDV $8, R19
520+ RET
521+
522+diff --git a/src/runtime/mkduff.go b/src/runtime/mkduff.go
523+index cc58558a56..e8d4fcc93e 100644
524+--- a/src/runtime/mkduff.go
525++++ b/src/runtime/mkduff.go
526+@@ -179,11 +179,11 @@ func copyARM64(w io.Writer) {
527+
528+ func zeroLOONG64(w io.Writer) {
529+ // R0: always zero
530+- // R19 (aka REGRT1): ptr to memory to be zeroed - 8
531++ // R19 (aka REGRT1): ptr to memory to be zeroed
532+ // On return, R19 points to the last zeroed dword.
533+ fmt.Fprintln(w, "TEXT runtime·duffzero(SB), NOSPLIT|NOFRAME, $0-0")
534+ for i := 0; i < 128; i++ {
535+- fmt.Fprintln(w, "\tMOVV\tR0, 8(R19)")
536++ fmt.Fprintln(w, "\tMOVV\tR0, (R19)")
537+ fmt.Fprintln(w, "\tADDV\t$8, R19")
538+ }
539+ fmt.Fprintln(w, "\tRET")
540+--
541+2.43.0
542+ 
@@ -0,0 +1,312 @@
1+From c5acdd7b6e8b67b089cb6d1a79fcad2683e15ae2 Mon Sep 17 00:00:00 2001
2+From: Guoqi Chen <chenguoqi@loongson.cn>
3+Date: Tue, 25 Apr 2023 03:27:23 +0800
4+Subject: [PATCH 008/125] cmd/compiler: remove the meaningless offset of 8 for
5+ Lowered{Zero,Move} on loong64
6+ 
7+Like the CL 487295, remove the meaningless +/- offset operation in the
8+LoweredZero and LoweredMove implementation.
9+ 
10+Change LoweredMove's Rarg0 register to R20, consistent with duffcopy.
11+ 
12+Change-Id: I19203c428ab25e7ecf657e2ea8ebb0bca77f49ee
13+---
14+ src/cmd/compile/internal/loong64/ssa.go | 168 ++++++++----------
15+ .../compile/internal/ssa/_gen/LOONG64Ops.go | 28 ++-
16+ src/cmd/compile/internal/ssa/opGen.go | 6 +-
17+ 3 files changed, 91 insertions(+), 111 deletions(-)
18+ 
19+diff --git a/src/cmd/compile/internal/loong64/ssa.go b/src/cmd/compile/internal/loong64/ssa.go
20+index 574217fd92..f74f90fb5f 100644
21+--- a/src/cmd/compile/internal/loong64/ssa.go
22++++ b/src/cmd/compile/internal/loong64/ssa.go
23+@@ -80,6 +80,28 @@ func storeByType(t *types.Type, r int16) obj.As {
24+ panic("bad store type")
25+ }
26+
27++// largestMove returns the largest move instruction possible and its size,
28++// given the alignment of the total size of the move.
29++//
30++// e.g., a 16-byte move may use MOVV, but an 11-byte move must use MOVB.
31++//
32++// Note that the moves may not be on naturally aligned addresses depending on
33++// the source and destination.
34++//
35++// This matches the calculation in ssa.moveSize.
36++func largestMove(alignment int64) (obj.As, int64) {
37++ switch {
38++ case alignment%8 == 0:
39++ return loong64.AMOVV, 8
40++ case alignment%4 == 0:
41++ return loong64.AMOVW, 4
42++ case alignment%2 == 0:
43++ return loong64.AMOVH, 2
44++ default:
45++ return loong64.AMOVB, 1
46++ }
47++}
48++
49+ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
50+ switch v.Op {
51+ case ssa.OpCopy, ssa.OpLOONG64MOVVreg:
52+@@ -347,49 +369,29 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
53+ p.To.Sym = ir.Syms.Duffzero
54+ p.To.Offset = v.AuxInt
55+ case ssa.OpLOONG64LoweredZero:
56+- // SUBV $8, R19
57+- // MOVV R0, 8(R19)
58+- // ADDV $8, R19
59+- // BNE Rarg1, R19, -2(PC)
60+- // arg1 is the address of the last element to zero
61+- var sz int64
62+- var mov obj.As
63+- switch {
64+- case v.AuxInt%8 == 0:
65+- sz = 8
66+- mov = loong64.AMOVV
67+- case v.AuxInt%4 == 0:
68+- sz = 4
69+- mov = loong64.AMOVW
70+- case v.AuxInt%2 == 0:
71+- sz = 2
72+- mov = loong64.AMOVH
73+- default:
74+- sz = 1
75+- mov = loong64.AMOVB
76+- }
77+- p := s.Prog(loong64.ASUBVU)
78+- p.From.Type = obj.TYPE_CONST
79+- p.From.Offset = sz
80+- p.To.Type = obj.TYPE_REG
81+- p.To.Reg = loong64.REG_R19
82+- p2 := s.Prog(mov)
83+- p2.From.Type = obj.TYPE_REG
84+- p2.From.Reg = loong64.REGZERO
85+- p2.To.Type = obj.TYPE_MEM
86+- p2.To.Reg = loong64.REG_R19
87+- p2.To.Offset = sz
88+- p3 := s.Prog(loong64.AADDVU)
89+- p3.From.Type = obj.TYPE_CONST
90+- p3.From.Offset = sz
91+- p3.To.Type = obj.TYPE_REG
92+- p3.To.Reg = loong64.REG_R19
93+- p4 := s.Prog(loong64.ABNE)
94+- p4.From.Type = obj.TYPE_REG
95+- p4.From.Reg = v.Args[1].Reg()
96+- p4.Reg = loong64.REG_R19
97+- p4.To.Type = obj.TYPE_BRANCH
98+- p4.To.SetTarget(p2)
99++ // MOVx R0, (Rarg0)
100++ // ADDV $sz, Rarg0
101++ // BGEU Rarg1, Rarg0, -2(PC)
102++ mov, sz := largestMove(v.AuxInt)
103++ p := s.Prog(mov)
104++ p.From.Type = obj.TYPE_REG
105++ p.From.Reg = loong64.REGZERO
106++ p.To.Type = obj.TYPE_MEM
107++ p.To.Reg = v.Args[0].Reg()
108++
109++ p2 := s.Prog(loong64.AADDVU)
110++ p2.From.Type = obj.TYPE_CONST
111++ p2.From.Offset = sz
112++ p2.To.Type = obj.TYPE_REG
113++ p2.To.Reg = v.Args[0].Reg()
114++
115++ p3 := s.Prog(loong64.ABGEU)
116++ p3.From.Type = obj.TYPE_REG
117++ p3.From.Reg = v.Args[1].Reg()
118++ p3.Reg = v.Args[0].Reg()
119++ p3.To.Type = obj.TYPE_BRANCH
120++ p3.To.SetTarget(p)
121++
122+ case ssa.OpLOONG64DUFFCOPY:
123+ p := s.Prog(obj.ADUFFCOPY)
124+ p.To.Type = obj.TYPE_MEM
125+@@ -397,61 +399,43 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
126+ p.To.Sym = ir.Syms.Duffcopy
127+ p.To.Offset = v.AuxInt
128+ case ssa.OpLOONG64LoweredMove:
129+- // SUBV $8, R19
130+- // MOVV 8(R19), Rtmp
131+- // MOVV Rtmp, (R4)
132+- // ADDV $8, R19
133+- // ADDV $8, R4
134+- // BNE Rarg2, R19, -4(PC)
135+- // arg2 is the address of the last element of src
136+- var sz int64
137+- var mov obj.As
138+- switch {
139+- case v.AuxInt%8 == 0:
140+- sz = 8
141+- mov = loong64.AMOVV
142+- case v.AuxInt%4 == 0:
143+- sz = 4
144+- mov = loong64.AMOVW
145+- case v.AuxInt%2 == 0:
146+- sz = 2
147+- mov = loong64.AMOVH
148+- default:
149+- sz = 1
150+- mov = loong64.AMOVB
151+- }
152+- p := s.Prog(loong64.ASUBVU)
153+- p.From.Type = obj.TYPE_CONST
154+- p.From.Offset = sz
155++ // MOVx (Rarg1), Rtmp
156++ // MOVx Rtmp, (Rarg0)
157++ // ADDV $sz, Rarg1
158++ // ADDV $sz, Rarg0
159++ // BGEU Rarg2, Rarg0, -4(PC)
160++ mov, sz := largestMove(v.AuxInt)
161++ p := s.Prog(mov)
162++ p.From.Type = obj.TYPE_MEM
163++ p.From.Reg = v.Args[1].Reg()
164+ p.To.Type = obj.TYPE_REG
165+- p.To.Reg = loong64.REG_R19
166++ p.To.Reg = loong64.REGTMP
167++
168+ p2 := s.Prog(mov)
169+- p2.From.Type = obj.TYPE_MEM
170+- p2.From.Reg = loong64.REG_R19
171+- p2.From.Offset = sz
172+- p2.To.Type = obj.TYPE_REG
173+- p2.To.Reg = loong64.REGTMP
174+- p3 := s.Prog(mov)
175+- p3.From.Type = obj.TYPE_REG
176+- p3.From.Reg = loong64.REGTMP
177+- p3.To.Type = obj.TYPE_MEM
178+- p3.To.Reg = loong64.REG_R4
179++ p2.From.Type = obj.TYPE_REG
180++ p2.From.Reg = loong64.REGTMP
181++ p2.To.Type = obj.TYPE_MEM
182++ p2.To.Reg = v.Args[0].Reg()
183++
184++ p3 := s.Prog(loong64.AADDVU)
185++ p3.From.Type = obj.TYPE_CONST
186++ p3.From.Offset = sz
187++ p3.To.Type = obj.TYPE_REG
188++ p3.To.Reg = v.Args[1].Reg()
189++
190+ p4 := s.Prog(loong64.AADDVU)
191+ p4.From.Type = obj.TYPE_CONST
192+ p4.From.Offset = sz
193+ p4.To.Type = obj.TYPE_REG
194+- p4.To.Reg = loong64.REG_R19
195+- p5 := s.Prog(loong64.AADDVU)
196+- p5.From.Type = obj.TYPE_CONST
197+- p5.From.Offset = sz
198+- p5.To.Type = obj.TYPE_REG
199+- p5.To.Reg = loong64.REG_R4
200+- p6 := s.Prog(loong64.ABNE)
201+- p6.From.Type = obj.TYPE_REG
202+- p6.From.Reg = v.Args[2].Reg()
203+- p6.Reg = loong64.REG_R19
204+- p6.To.Type = obj.TYPE_BRANCH
205+- p6.To.SetTarget(p2)
206++ p4.To.Reg = v.Args[0].Reg()
207++
208++ p5 := s.Prog(loong64.ABGEU)
209++ p5.From.Type = obj.TYPE_REG
210++ p5.From.Reg = v.Args[2].Reg()
211++ p5.Reg = v.Args[1].Reg()
212++ p5.To.Type = obj.TYPE_BRANCH
213++ p5.To.SetTarget(p)
214++
215+ case ssa.OpLOONG64CALLstatic, ssa.OpLOONG64CALLclosure, ssa.OpLOONG64CALLinter:
216+ s.Call(v)
217+ case ssa.OpLOONG64CALLtail:
218+diff --git a/src/cmd/compile/internal/ssa/_gen/LOONG64Ops.go b/src/cmd/compile/internal/ssa/_gen/LOONG64Ops.go
219+index b715b36542..cb058f45c0 100644
220+--- a/src/cmd/compile/internal/ssa/_gen/LOONG64Ops.go
221++++ b/src/cmd/compile/internal/ssa/_gen/LOONG64Ops.go
222+@@ -319,10 +319,9 @@ func init() {
223+ // arg2 = mem
224+ // auxint = alignment
225+ // returns mem
226+- // SUBV $8, R19
227+- // MOVV R0, 8(R19)
228+- // ADDV $8, R19
229+- // BNE Rarg1, R19, -2(PC)
230++ // MOVx R0, (R19)
231++ // ADDV $sz, R19
232++ // BGEU Rarg1, R19, -2(PC)
233+ {
234+ name: "LoweredZero",
235+ aux: "Int64",
236+@@ -331,32 +330,31 @@ func init() {
237+ inputs: []regMask{buildReg("R19"), gp},
238+ clobbers: buildReg("R19"),
239+ },
240+- clobberFlags: true,
241++ typ: "Mem",
242+ faultOnNilArg0: true,
243+ },
244+
245+ // large or unaligned move
246+- // arg0 = address of dst memory (in R4, changed as side effect)
247++ // arg0 = address of dst memory (in R20, changed as side effect)
248+ // arg1 = address of src memory (in R19, changed as side effect)
249+ // arg2 = address of the last element of src
250+ // arg3 = mem
251+ // auxint = alignment
252+ // returns mem
253+- // SUBV $8, R19
254+- // MOVV 8(R19), Rtmp
255+- // MOVV Rtmp, (R4)
256+- // ADDV $8, R19
257+- // ADDV $8, R4
258+- // BNE Rarg2, R19, -4(PC)
259++ // MOVx (R19), Rtmp
260++ // MOVx Rtmp, (R20)
261++ // ADDV $sz, R19
262++ // ADDV $sz, R20
263++ // BGEU Rarg2, R19, -4(PC)
264+ {
265+ name: "LoweredMove",
266+ aux: "Int64",
267+ argLength: 4,
268+ reg: regInfo{
269+- inputs: []regMask{buildReg("R4"), buildReg("R19"), gp},
270+- clobbers: buildReg("R19 R4"),
271++ inputs: []regMask{buildReg("R20"), buildReg("R19"), gp},
272++ clobbers: buildReg("R19 R20"),
273+ },
274+- clobberFlags: true,
275++ typ: "Mem",
276+ faultOnNilArg0: true,
277+ faultOnNilArg1: true,
278+ },
279+diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go
280+index e95cb250d9..2b712a1189 100644
281+--- a/src/cmd/compile/internal/ssa/opGen.go
282++++ b/src/cmd/compile/internal/ssa/opGen.go
283+@@ -24289,7 +24289,6 @@ var opcodeTable = [...]opInfo{
284+ name: "LoweredZero",
285+ auxType: auxInt64,
286+ argLen: 3,
287+- clobberFlags: true,
288+ faultOnNilArg0: true,
289+ reg: regInfo{
290+ inputs: []inputInfo{
291+@@ -24303,16 +24302,15 @@ var opcodeTable = [...]opInfo{
292+ name: "LoweredMove",
293+ auxType: auxInt64,
294+ argLen: 4,
295+- clobberFlags: true,
296+ faultOnNilArg0: true,
297+ faultOnNilArg1: true,
298+ reg: regInfo{
299+ inputs: []inputInfo{
300+- {0, 8}, // R4
301++ {0, 524288}, // R20
302+ {1, 262144}, // R19
303+ {2, 1070596088}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R23 R24 R25 R26 R27 R28 R29 R31
304+ },
305+- clobbers: 262152, // R4 R19
306++ clobbers: 786432, // R19 R20
307+ },
308+ },
309+ {
310+--
311+2.43.0
312+ 
@@ -0,0 +1,319 @@
1+From 4965540ad00ad9251c3f22d14cc8240160a5a233 Mon Sep 17 00:00:00 2001
2+From: Guoqi Chen <chenguoqi@loongson.cn>
3+Date: Sat, 1 Apr 2023 03:43:20 +0800
4+Subject: [PATCH 009/125] cmd/internal/obj/loong64: add atomic memory access
5+ instructions support
6+MIME-Version: 1.0
7+Content-Type: text/plain; charset=UTF-8
8+Content-Transfer-Encoding: 8bit
9+ 
10+The AM* atomic access instruction performs a sequence of “read-modify-write”
11+operations on a memory cell atomically. Specifically, it retrieves the old
12+value at the specified address in memory and writes it to the general register
13+rd, performs some simple operations on the old value in memory and the value
14+in the general register rk, and then write the result of the operation back
15+to the memory address pointed to by general register rj.
16+ 
17+Go asm syntax:
18+ AM{SWAP/ADD/AND/OR/XOR/MAX/MIN}[DB]{W/V} RK, (RJ), RD
19+ AM{MAX/MIN}[DB]{WU/VU} RK, (RJ), RD
20+ 
21+Equivalent platform assembler syntax:
22+ am{swap/add/and/or/xor/max/min}[_db].{w/d} rd, rk, rj
23+ am{max/min}[_db].{wu/du} rd, rk, rj
24+ 
25+Ref: https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html
26+Change-Id: I1707c484c3b2a0cf523255c80f566480a77432fb
27+---
28+ src/cmd/asm/internal/arch/loong64.go | 4 ++
29+ src/cmd/asm/internal/asm/asm.go | 14 +++-
30+ .../asm/internal/asm/testdata/loong64enc1.s | 38 +++++++++++
31+ src/cmd/internal/obj/loong64/a.out.go | 38 +++++++++++
32+ src/cmd/internal/obj/loong64/anames.go | 36 ++++++++++
33+ src/cmd/internal/obj/loong64/asm.go | 67 +++++++++++++++++++
34+ 6 files changed, 194 insertions(+), 3 deletions(-)
35+ 
36+diff --git a/src/cmd/asm/internal/arch/loong64.go b/src/cmd/asm/internal/arch/loong64.go
37+index 2958ee1a86..bf34a94f07 100644
38+--- a/src/cmd/asm/internal/arch/loong64.go
39++++ b/src/cmd/asm/internal/arch/loong64.go
40+@@ -55,6 +55,10 @@ func IsLoong64RDTIME(op obj.As) bool {
41+ return false
42+ }
43+
44++func IsLoong64AMO(op obj.As) bool {
45++ return loong64.IsAtomicInst(op)
46++}
47++
48+ func loong64RegisterNumber(name string, n int16) (int16, bool) {
49+ switch name {
50+ case "F":
51+diff --git a/src/cmd/asm/internal/asm/asm.go b/src/cmd/asm/internal/asm/asm.go
52+index 563e794706..c8fff8e574 100644
53+--- a/src/cmd/asm/internal/asm/asm.go
54++++ b/src/cmd/asm/internal/asm/asm.go
55+@@ -664,9 +664,17 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) {
56+ prog.Reg = p.getRegister(prog, op, &a[1])
57+ prog.To = a[2]
58+ case sys.Loong64:
59+- prog.From = a[0]
60+- prog.Reg = p.getRegister(prog, op, &a[1])
61+- prog.To = a[2]
62++ switch {
63++ // Loong64 atomic instructions with one input and two outputs.
64++ case arch.IsLoong64AMO(op):
65++ prog.From = a[0]
66++ prog.To = a[1]
67++ prog.RegTo2 = a[2].Reg
68++ default:
69++ prog.From = a[0]
70++ prog.Reg = p.getRegister(prog, op, &a[1])
71++ prog.To = a[2]
72++ }
73+ case sys.ARM:
74+ // Special cases.
75+ if arch.IsARMSTREX(op) {
76+diff --git a/src/cmd/asm/internal/asm/testdata/loong64enc1.s b/src/cmd/asm/internal/asm/testdata/loong64enc1.s
77+index ea6c569f9d..288408b010 100644
78+--- a/src/cmd/asm/internal/asm/testdata/loong64enc1.s
79++++ b/src/cmd/asm/internal/asm/testdata/loong64enc1.s
80+@@ -233,3 +233,41 @@ lable2:
81+
82+ MOVV FCC0, R4 // 04dc1401
83+ MOVV R4, FCC0 // 80d81401
84++
85++ // Loong64 atomic memory access instructions
86++ AMSWAPW R14, (R13), R12 // ac396038
87++ AMSWAPV R14, (R13), R12 // acb96038
88++ AMADDW R14, (R13), R12 // ac396138
89++ AMADDV R14, (R13), R12 // acb96138
90++ AMANDW R14, (R13), R12 // ac396238
91++ AMANDV R14, (R13), R12 // acb96238
92++ AMORW R14, (R13), R12 // ac396338
93++ AMORV R14, (R13), R12 // acb96338
94++ AMXORW R14, (R13), R12 // ac396438
95++ AMXORV R14, (R13), R12 // acb96438
96++ AMMAXW R14, (R13), R12 // ac396538
97++ AMMAXV R14, (R13), R12 // acb96538
98++ AMMINW R14, (R13), R12 // ac396638
99++ AMMINV R14, (R13), R12 // acb96638
100++ AMMAXWU R14, (R13), R12 // ac396738
101++ AMMAXVU R14, (R13), R12 // acb96738
102++ AMMINWU R14, (R13), R12 // ac396838
103++ AMMINVU R14, (R13), R12 // acb96838
104++ AMSWAPDBW R14, (R13), R12 // ac396938
105++ AMSWAPDBV R14, (R13), R12 // acb96938
106++ AMADDDBW R14, (R13), R12 // ac396a38
107++ AMADDDBV R14, (R13), R12 // acb96a38
108++ AMANDDBW R14, (R13), R12 // ac396b38
109++ AMANDDBV R14, (R13), R12 // acb96b38
110++ AMORDBW R14, (R13), R12 // ac396c38
111++ AMORDBV R14, (R13), R12 // acb96c38
112++ AMXORDBW R14, (R13), R12 // ac396d38
113++ AMXORDBV R14, (R13), R12 // acb96d38
114++ AMMAXDBW R14, (R13), R12 // ac396e38
115++ AMMAXDBV R14, (R13), R12 // acb96e38
116++ AMMINDBW R14, (R13), R12 // ac396f38
117++ AMMINDBV R14, (R13), R12 // acb96f38
118++ AMMAXDBWU R14, (R13), R12 // ac397038
119++ AMMAXDBVU R14, (R13), R12 // acb97038
120++ AMMINDBWU R14, (R13), R12 // ac397138
121++ AMMINDBVU R14, (R13), R12 // acb97138
122+diff --git a/src/cmd/internal/obj/loong64/a.out.go b/src/cmd/internal/obj/loong64/a.out.go
123+index 9527e99b56..3ed15fc7e7 100644
124+--- a/src/cmd/internal/obj/loong64/a.out.go
125++++ b/src/cmd/internal/obj/loong64/a.out.go
126+@@ -394,6 +394,44 @@ const (
127+ AMOVVF
128+ AMOVVD
129+
130++ // 2.2.7. Atomic Memory Access Instructions
131++ AAMSWAPW
132++ AAMSWAPV
133++ AAMADDW
134++ AAMADDV
135++ AAMANDW
136++ AAMANDV
137++ AAMORW
138++ AAMORV
139++ AAMXORW
140++ AAMXORV
141++ AAMMAXW
142++ AAMMAXV
143++ AAMMINW
144++ AAMMINV
145++ AAMMAXWU
146++ AAMMAXVU
147++ AAMMINWU
148++ AAMMINVU
149++ AAMSWAPDBW
150++ AAMSWAPDBV
151++ AAMADDDBW
152++ AAMADDDBV
153++ AAMANDDBW
154++ AAMANDDBV
155++ AAMORDBW
156++ AAMORDBV
157++ AAMXORDBW
158++ AAMXORDBV
159++ AAMMAXDBW
160++ AAMMAXDBV
161++ AAMMINDBW
162++ AAMMINDBV
163++ AAMMAXDBWU
164++ AAMMAXDBVU
165++ AAMMINDBWU
166++ AAMMINDBVU
167++
168+ // 2.2.10. Other Miscellaneous Instructions
169+ ARDTIMELW
170+ ARDTIMEHW
171+diff --git a/src/cmd/internal/obj/loong64/anames.go b/src/cmd/internal/obj/loong64/anames.go
172+index f61756e7a8..d48ff8a281 100644
173+--- a/src/cmd/internal/obj/loong64/anames.go
174++++ b/src/cmd/internal/obj/loong64/anames.go
175+@@ -131,6 +131,42 @@ var Anames = []string{
176+ "MOVDV",
177+ "MOVVF",
178+ "MOVVD",
179++ "AMSWAPW",
180++ "AMSWAPV",
181++ "AMADDW",
182++ "AMADDV",
183++ "AMANDW",
184++ "AMANDV",
185++ "AMORW",
186++ "AMORV",
187++ "AMXORW",
188++ "AMXORV",
189++ "AMMAXW",
190++ "AMMAXV",
191++ "AMMINW",
192++ "AMMINV",
193++ "AMMAXWU",
194++ "AMMAXVU",
195++ "AMMINWU",
196++ "AMMINVU",
197++ "AMSWAPDBW",
198++ "AMSWAPDBV",
199++ "AMADDDBW",
200++ "AMADDDBV",
201++ "AMANDDBW",
202++ "AMANDDBV",
203++ "AMORDBW",
204++ "AMORDBV",
205++ "AMXORDBW",
206++ "AMXORDBV",
207++ "AMMAXDBW",
208++ "AMMAXDBV",
209++ "AMMINDBW",
210++ "AMMINDBV",
211++ "AMMAXDBWU",
212++ "AMMAXDBVU",
213++ "AMMINDBWU",
214++ "AMMINDBVU",
215+ "RDTIMELW",
216+ "RDTIMEHW",
217+ "RDTIMED",
218+diff --git a/src/cmd/internal/obj/loong64/asm.go b/src/cmd/internal/obj/loong64/asm.go
219+index c8d00413a0..638bd1139f 100644
220+--- a/src/cmd/internal/obj/loong64/asm.go
221++++ b/src/cmd/internal/obj/loong64/asm.go
222+@@ -363,6 +363,8 @@ var optab = []Optab{
223+ {ARDTIMEHW, C_NONE, C_NONE, C_NONE, C_REG, C_REG, 62, 4, 0, 0},
224+ {ARDTIMED, C_NONE, C_NONE, C_NONE, C_REG, C_REG, 62, 4, 0, 0},
225+
226++ {AAMSWAPW, C_REG, C_NONE, C_NONE, C_ZOREG, C_REG, 66, 4, 0, 0},
227++
228+ {obj.AUNDEF, C_NONE, C_NONE, C_NONE, C_NONE, C_NONE, 49, 4, 0, 0},
229+ {obj.APCALIGN, C_SCON, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0},
230+ {obj.APCDATA, C_LCON, C_NONE, C_NONE, C_LCON, C_NONE, 0, 0, 0, 0},
231+@@ -379,6 +381,51 @@ var optab = []Optab{
232+ {obj.AXXX, C_NONE, C_NONE, C_NONE, C_NONE, C_NONE, 0, 4, 0, 0},
233+ }
234+
235++var atomicInst = map[obj.As]uint32{
236++ AAMSWAPW: 0x070C0 << 15, // amswap.w
237++ AAMSWAPV: 0x070C1 << 15, // amswap.d
238++ AAMADDW: 0x070C2 << 15, // amadd.w
239++ AAMADDV: 0x070C3 << 15, // amadd.d
240++ AAMANDW: 0x070C4 << 15, // amand.w
241++ AAMANDV: 0x070C5 << 15, // amand.d
242++ AAMORW: 0x070C6 << 15, // amor.w
243++ AAMORV: 0x070C7 << 15, // amor.d
244++ AAMXORW: 0x070C8 << 15, // amxor.w
245++ AAMXORV: 0x070C9 << 15, // amxor.d
246++ AAMMAXW: 0x070CA << 15, // ammax.w
247++ AAMMAXV: 0x070CB << 15, // ammax.d
248++ AAMMINW: 0x070CC << 15, // ammin.w
249++ AAMMINV: 0x070CD << 15, // ammin.d
250++ AAMMAXWU: 0x070CE << 15, // ammax.wu
251++ AAMMAXVU: 0x070CF << 15, // ammax.du
252++ AAMMINWU: 0x070D0 << 15, // ammin.wu
253++ AAMMINVU: 0x070D1 << 15, // ammin.du
254++ AAMSWAPDBW: 0x070D2 << 15, // amswap_db.w
255++ AAMSWAPDBV: 0x070D3 << 15, // amswap_db.d
256++ AAMADDDBW: 0x070D4 << 15, // amadd_db.w
257++ AAMADDDBV: 0x070D5 << 15, // amadd_db.d
258++ AAMANDDBW: 0x070D6 << 15, // amand_db.w
259++ AAMANDDBV: 0x070D7 << 15, // amand_db.d
260++ AAMORDBW: 0x070D8 << 15, // amor_db.w
261++ AAMORDBV: 0x070D9 << 15, // amor_db.d
262++ AAMXORDBW: 0x070DA << 15, // amxor_db.w
263++ AAMXORDBV: 0x070DB << 15, // amxor_db.d
264++ AAMMAXDBW: 0x070DC << 15, // ammax_db.w
265++ AAMMAXDBV: 0x070DD << 15, // ammax_db.d
266++ AAMMINDBW: 0x070DE << 15, // ammin_db.w
267++ AAMMINDBV: 0x070DF << 15, // ammin_db.d
268++ AAMMAXDBWU: 0x070E0 << 15, // ammax_db.wu
269++ AAMMAXDBVU: 0x070E1 << 15, // ammax_db.du
270++ AAMMINDBWU: 0x070E2 << 15, // ammin_db.wu
271++ AAMMINDBVU: 0x070E3 << 15, // ammin_db.du
272++}
273++
274++func IsAtomicInst(as obj.As) bool {
275++ _, ok := atomicInst[as]
276++
277++ return ok
278++}
279++
280+ // pcAlignPadLength returns the number of bytes required to align pc to alignedValue,
281+ // reporting an error if alignedValue is not a power of two or is out of range.
282+ func pcAlignPadLength(ctxt *obj.Link, pc int64, alignedValue int64) int {
283+@@ -1172,6 +1219,14 @@ func buildop(ctxt *obj.Link) {
284+
285+ case AMASKEQZ:
286+ opset(AMASKNEZ, r0)
287++
288++ case AAMSWAPW:
289++ for i := range atomicInst {
290++ if i == AAMSWAPW {
291++ continue
292++ }
293++ opset(i, r0)
294++ }
295+ }
296+ }
297+ }
298+@@ -1797,6 +1852,18 @@ func (c *ctxt0) asmout(p *obj.Prog, o *Optab, out []uint32) {
299+ rel2.Sym = p.From.Sym
300+ rel2.Type = objabi.R_LOONG64_GOT_LO
301+ rel2.Add = 0x0
302++
303++ case 66: // am* From, To, RegTo2 ==> am* RegTo2, From, To
304++ rk := p.From.Reg
305++ rj := p.To.Reg
306++ rd := p.RegTo2
307++
308++ // See section 2.2.7.1 of https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html
309++ // for the register usage constraints.
310++ if rd == rj || rd == rk {
311++ c.ctxt.Diag("illegal register combination: %v\n", p)
312++ }
313++ o1 = OP_RRR(atomicInst[p.As], uint32(rk), uint32(rj), uint32(rd))
314+ }
315+
316+ out[0] = o1
317+--
318+2.43.0
319+ 
@@ -0,0 +1,164 @@
1+From 162fe27a6efa8701f8a2aa258237fb560187ceff Mon Sep 17 00:00:00 2001
2+From: Guoqi Chen <chenguoqi@loongson.cn>
3+Date: Sat, 1 Apr 2023 08:49:58 +0800
4+Subject: [PATCH 010/125] cmd/compiler,runtime/internal/atomic: optimize xchg
5+ and xchg64 on loong64
6+MIME-Version: 1.0
7+Content-Type: text/plain; charset=UTF-8
8+Content-Transfer-Encoding: 8bit
9+ 
10+Use Loong64's atomic operation instruction AMSWAPx to implement Xchg and Xchg64
11+ 
12+goos: linux
13+goarch: loong64
14+pkg: runtime/internal/atomic
15+ │ bench.old │ bench.new │
16+ │ sec/op │ sec/op vs base │
17+Xchg 30.06n ± 0% 13.66n ± 0% -54.56% (p=0.000 n=20)
18+Xchg-2 37.43n ± 6% 23.55n ± 1% -37.06% (p=0.000 n=20)
19+Xchg-4 37.16n ± 5% 33.25n ± 2% -10.55% (p=0.000 n=20)
20+Xchg-8 37.81n ± 3% 32.12n ± 1% -15.04% (p=0.000 n=20)
21+Xchg-16 37.55n ± 0% 33.70n ± 0% -10.25% (p=0.000 n=20)
22+Xchg64 30.05n ± 0% 14.13n ± 0% -52.96% (p=0.000 n=20)
23+Xchg64-2 37.42n ± 1% 21.80n ± 0% -41.74% (p=0.000 n=20)
24+Xchg64-4 38.17n ± 6% 31.95n ± 1% -16.30% (p=0.000 n=20)
25+Xchg64-8 37.44n ± 1% 32.12n ± 2% -14.18% (p=0.000 n=20)
26+Xchg64-16 37.56n ± 0% 33.65n ± 0% -10.41% (p=0.000 n=20)
27+geomean 36.54n 25.65n -28.61%
28+ 
29+Updates #59120.
30+ 
31+Change-Id: I1f78f547b818ea6ead9480254c05745e2eee4d68
32+---
33+ src/cmd/compile/internal/loong64/ssa.go | 38 ++++---------------
34+ .../compile/internal/ssa/_gen/LOONG64Ops.go | 6 ---
35+ src/runtime/internal/atomic/atomic_loong64.s | 30 +++++++--------
36+ 3 files changed, 22 insertions(+), 52 deletions(-)
37+ 
38+diff --git a/src/cmd/compile/internal/loong64/ssa.go b/src/cmd/compile/internal/loong64/ssa.go
39+index f74f90fb5f..e103c896e6 100644
40+--- a/src/cmd/compile/internal/loong64/ssa.go
41++++ b/src/cmd/compile/internal/loong64/ssa.go
42+@@ -495,40 +495,18 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
43+ p.To.Reg = v.Args[0].Reg()
44+ s.Prog(loong64.ADBAR)
45+ case ssa.OpLOONG64LoweredAtomicExchange32, ssa.OpLOONG64LoweredAtomicExchange64:
46+- // DBAR
47+- // MOVV Rarg1, Rtmp
48+- // LL (Rarg0), Rout
49+- // SC Rtmp, (Rarg0)
50+- // BEQ Rtmp, -3(PC)
51+- // DBAR
52+- ll := loong64.ALLV
53+- sc := loong64.ASCV
54++ // AMSWAPx Rarg1, (Rarg0), Rout
55++ amswapx := loong64.AAMSWAPV
56+ if v.Op == ssa.OpLOONG64LoweredAtomicExchange32 {
57+- ll = loong64.ALL
58+- sc = loong64.ASC
59++ amswapx = loong64.AAMSWAPW
60+ }
61+- s.Prog(loong64.ADBAR)
62+- p := s.Prog(loong64.AMOVV)
63++ p := s.Prog(amswapx)
64+ p.From.Type = obj.TYPE_REG
65+ p.From.Reg = v.Args[1].Reg()
66+- p.To.Type = obj.TYPE_REG
67+- p.To.Reg = loong64.REGTMP
68+- p1 := s.Prog(ll)
69+- p1.From.Type = obj.TYPE_MEM
70+- p1.From.Reg = v.Args[0].Reg()
71+- p1.To.Type = obj.TYPE_REG
72+- p1.To.Reg = v.Reg0()
73+- p2 := s.Prog(sc)
74+- p2.From.Type = obj.TYPE_REG
75+- p2.From.Reg = loong64.REGTMP
76+- p2.To.Type = obj.TYPE_MEM
77+- p2.To.Reg = v.Args[0].Reg()
78+- p3 := s.Prog(loong64.ABEQ)
79+- p3.From.Type = obj.TYPE_REG
80+- p3.From.Reg = loong64.REGTMP
81+- p3.To.Type = obj.TYPE_BRANCH
82+- p3.To.SetTarget(p)
83+- s.Prog(loong64.ADBAR)
84++ p.To.Type = obj.TYPE_MEM
85++ p.To.Reg = v.Args[0].Reg()
86++ p.RegTo2 = v.Reg0()
87++
88+ case ssa.OpLOONG64LoweredAtomicAdd32, ssa.OpLOONG64LoweredAtomicAdd64:
89+ // DBAR
90+ // LL (Rarg0), Rout
91+diff --git a/src/cmd/compile/internal/ssa/_gen/LOONG64Ops.go b/src/cmd/compile/internal/ssa/_gen/LOONG64Ops.go
92+index cb058f45c0..09c3df6af2 100644
93+--- a/src/cmd/compile/internal/ssa/_gen/LOONG64Ops.go
94++++ b/src/cmd/compile/internal/ssa/_gen/LOONG64Ops.go
95+@@ -377,12 +377,6 @@ func init() {
96+
97+ // atomic exchange.
98+ // store arg1 to arg0. arg2=mem. returns <old content of *arg0, memory>.
99+- // DBAR
100+- // LL (Rarg0), Rout
101+- // MOVV Rarg1, Rtmp
102+- // SC Rtmp, (Rarg0)
103+- // BEQ Rtmp, -3(PC)
104+- // DBAR
105+ {name: "LoweredAtomicExchange32", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
106+ {name: "LoweredAtomicExchange64", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
107+
108+diff --git a/src/runtime/internal/atomic/atomic_loong64.s b/src/runtime/internal/atomic/atomic_loong64.s
109+index 34193add3e..ec34d254fc 100644
110+--- a/src/runtime/internal/atomic/atomic_loong64.s
111++++ b/src/runtime/internal/atomic/atomic_loong64.s
112+@@ -121,35 +121,33 @@ TEXT ·Xadd64(SB), NOSPLIT, $0-24
113+ DBAR
114+ RET
115+
116++// func Xchg(ptr *uint32, new uint32) uint32
117+ TEXT ·Xchg(SB), NOSPLIT, $0-20
118+ MOVV ptr+0(FP), R4
119+ MOVW new+8(FP), R5
120+-
121+- DBAR
122+- MOVV R5, R6
123+- LL (R4), R7
124+- SC R6, (R4)
125+- BEQ R6, -3(PC)
126+- MOVW R7, ret+16(FP)
127+- DBAR
128++ AMSWAPW R5, (R4), R6
129++ MOVW R6, ret+16(FP)
130+ RET
131+
132++// func Xchg64(ptr *uint64, new uint64) uint64
133+ TEXT ·Xchg64(SB), NOSPLIT, $0-24
134+ MOVV ptr+0(FP), R4
135+ MOVV new+8(FP), R5
136+-
137+- DBAR
138+- MOVV R5, R6
139+- LLV (R4), R7
140+- SCV R6, (R4)
141+- BEQ R6, -3(PC)
142+- MOVV R7, ret+16(FP)
143+- DBAR
144++ AMSWAPV R5, (R4), R6
145++ MOVV R6, ret+16(FP)
146+ RET
147+
148+ TEXT ·Xchguintptr(SB), NOSPLIT, $0-24
149+ JMP ·Xchg64(SB)
150+
151++// func Xchgint32(ptr *int32, new int32) int32
152++TEXT ·Xchgint32(SB), NOSPLIT, $0-20
153++ JMP ·Xchg(SB)
154++
155++// func Xchgint64(ptr *int64, new int64) int64
156++TEXT ·Xchgint64(SB), NOSPLIT, $0-24
157++ JMP ·Xchg64(SB)
158++
159+ TEXT ·StorepNoWB(SB), NOSPLIT, $0-16
160+ JMP ·Store64(SB)
161+
162+--
163+2.43.0
164+ 
@@ -66,7 +66,7 @@
66 66 
67Name: golang67Name: golang
68Version: 1.21.468Version: 1.21.4
69-Release: 4169+Release: 42
70Summary: The Go Programming Language70Summary: The Go Programming Language
71License: BSD and Public Domain71License: BSD and Public Domain
72URL: https://golang.org/72URL: https://golang.org/
@@ -170,12 +170,23 @@ Patch6047: backport-0047-CVE-2025-61729-crypto-x509-prevent-Hostname.patch
170Patch6048: backport-0048-CVE-2025-61727-crypto-x509-excluded-subdomain.patch170Patch6048: backport-0048-CVE-2025-61727-crypto-x509-excluded-subdomain.patch
171 171 
172# Part 8001 ~ 8999172# Part 8001 ~ 8999
173-# Developed optimization features173+# Developed optimization features for kunpeng
174Patch8001: 8001-runtime-add-kunpeng-malloc-optimize.patch174Patch8001: 8001-runtime-add-kunpeng-malloc-optimize.patch
175Patch8002: 8002-cmd-go-Use-AI-to-guide-optimization.patch175Patch8002: 8002-cmd-go-Use-AI-to-guide-optimization.patch
176Patch8003: 8003-internal-buildcfg-add-Kunpeng-atomic-optimize.patch176Patch8003: 8003-internal-buildcfg-add-Kunpeng-atomic-optimize.patch
177Patch8004: 8004-runtime-add-gcRatio-option.patch177Patch8004: 8004-runtime-add-gcRatio-option.patch
178 178 
179+ 
180+# Part 9001 ~ 9999
181+# Developed optimization features for loong64
182+Patch9001: 9001-cmd-dist-cmd-link-internal-runtime-add-buildmode-plu.patch
183+Patch9002: 9002-runtime-cmd-go-enable-memory-sanitizer-on-linux-loon.patch
184+Patch9003: 9003-runtime-cmd-go-enable-address-sanitizer-on-linux-loo.patch
185+Patch9004: 9004-runtime-remove-the-meaningless-offset-of-8-for-duffz.patch
186+Patch9005: 9005-cmd-compiler-remove-the-meaningless-offset-of-8-for-.patch
187+Patch9006: 9006-cmd-internal-obj-loong64-add-atomic-memory-access-in.patch
188+Patch9007: 9007-cmd-compiler-runtime-internal-atomic-optimize-xchg-a.patch
189+ 
179ExclusiveArch: %{golang_arches}190ExclusiveArch: %{golang_arches}
180 191 
181%description192%description
@@ -413,6 +424,13 @@ fi
413%files devel -f go-tests.list -f go-misc.list -f go-src.list424%files devel -f go-tests.list -f go-misc.list -f go-src.list
414 425 
415%changelog426%changelog
427+* Mon Jan 12 2026 chenguoqi <chenguoqi@loongson.cn> - 1.21.4-42
428+- Type:Feature
429+- CVE:NA
430+- SUG:NA
431+- DESC: Enable the support of buildmode plugin, msan, and asan on loong64, and
432+ optimize the implementation of duffcopy, duffzero, and atomic.xchg
433+ 
416* Thu Dec 4 2025 huzhangying <huzhangying@huawei.com> - 1.21.4-41434* Thu Dec 4 2025 huzhangying <huzhangying@huawei.com> - 1.21.4-41
417- Type:CVE435- Type:CVE
418- CVE:CVE-2025-61729,CVE-2025-61727436- CVE:CVE-2025-61729,CVE-2025-61727