diff options
| author | Joel Sing <joel@sing.id.au> | 2023-08-27 19:35:33 +1000 |
|---|---|---|
| committer | Joel Sing <joel@sing.id.au> | 2025-11-17 23:33:36 -0800 |
| commit | b9ef0633f6117c74fabcd7247a76b4feb86df086 (patch) | |
| tree | e72455efe805092171cecbae5349b0b066a0e1e8 /src | |
| parent | a087dea8692eee879e8226b70eb691dea7758b0b (diff) | |
| download | go-b9ef0633f6117c74fabcd7247a76b4feb86df086.tar.xz | |
cmd/internal/sys,internal/goarch,runtime: enable the use of compressed instructions on riscv64
Enable the use of compressed instructions on riscv64 by reducing
the PC quantum to two bytes and reducing the minimum instruction
length to two bytes. Change gostartcall on riscv64 to land at
two times the PC quantum into goexit, so that we retain four byte
alignment and revise the NOP instructions in goexit to ensure that
they are never compressed. Additionally, adjust PCALIGN so that it
correctly handles two byte offsets.
Fixes #47560
Updates #71105
Cq-Include-Trybots: luci.golang.try:gotip-linux-riscv64
Change-Id: I4329a8fbfcb4de636aadaeadabb826bc22698640
Reviewed-on: https://go-review.googlesource.com/c/go/+/523477
Reviewed-by: Junyang Shao <shaojunyang@google.com>
Reviewed-by: Mark Freeman <markfreeman@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Mark Ryan <markdryan@rivosinc.com>
Diffstat (limited to 'src')
| -rw-r--r-- | src/cmd/internal/obj/riscv/obj.go | 11 | ||||
| -rw-r--r-- | src/cmd/internal/sys/arch.go | 2 | ||||
| -rw-r--r-- | src/internal/goarch/goarch_riscv64.go | 2 | ||||
| -rw-r--r-- | src/runtime/asm_riscv64.s | 10 | ||||
| -rw-r--r-- | src/runtime/sys_riscv64.go | 11 |
5 files changed, 25 insertions, 11 deletions
diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go index 3deab34d31..8b9be5d78b 100644 --- a/src/cmd/internal/obj/riscv/obj.go +++ b/src/cmd/internal/obj/riscv/obj.go @@ -4799,10 +4799,17 @@ func assemble(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { v := pcAlignPadLength(p.Pc, alignedValue) offset := p.Pc for ; v >= 4; v -= 4 { - // NOP - cursym.WriteBytes(ctxt, offset, []byte{0x13, 0, 0, 0}) + // NOP (ADDI $0, X0, X0) + cursym.WriteBytes(ctxt, offset, []byte{0x13, 0x00, 0x00, 0x00}) offset += 4 } + if v == 2 { + // CNOP + cursym.WriteBytes(ctxt, offset, []byte{0x01, 0x00}) + offset += 2 + } else if v != 0 { + ctxt.Diag("bad PCALIGN pad length") + } continue } diff --git a/src/cmd/internal/sys/arch.go b/src/cmd/internal/sys/arch.go index 3c92a6bbf2..14b1cde22b 100644 --- a/src/cmd/internal/sys/arch.go +++ b/src/cmd/internal/sys/arch.go @@ -236,7 +236,7 @@ var ArchRISCV64 = &Arch{ ByteOrder: binary.LittleEndian, PtrSize: 8, RegSize: 8, - MinLC: 4, + MinLC: 2, Alignment: 8, // riscv unaligned loads work, but are really slow (trap + simulated by OS) CanMergeLoads: false, HasLR: true, diff --git a/src/internal/goarch/goarch_riscv64.go b/src/internal/goarch/goarch_riscv64.go index 3b6da1e02f..468f9a6374 100644 --- a/src/internal/goarch/goarch_riscv64.go +++ b/src/internal/goarch/goarch_riscv64.go @@ -7,7 +7,7 @@ package goarch const ( _ArchFamily = RISCV64 _DefaultPhysPageSize = 4096 - _PCQuantum = 4 + _PCQuantum = 2 _MinFrameSize = 8 _StackAlign = PtrSize ) diff --git a/src/runtime/asm_riscv64.s b/src/runtime/asm_riscv64.s index 5bd16181ee..428701a503 100644 --- a/src/runtime/asm_riscv64.s +++ b/src/runtime/asm_riscv64.s @@ -623,14 +623,14 @@ TEXT _cgo_topofstack(SB),NOSPLIT,$8 RET // func goexit(neverCallThisFunction) -// The top-most function running on a goroutine -// returns to goexit+PCQuantum. +// The top-most function running on a goroutine, returns to goexit+PCQuantum*2. +// Note that the NOPs are written in a manner that will not be compressed, +// since the offset must be known by the runtime. TEXT runtime·goexit(SB),NOSPLIT|NOFRAME|TOPFRAME,$0-0 - MOV ZERO, ZERO // NOP + WORD $0x00000013 // NOP JMP runtime·goexit1(SB) // does not return // traceback from goexit1 must hit code range of goexit - MOV ZERO, ZERO // NOP - + WORD $0x00000013 // NOP // This is called from .init_array and follows the platform, not the Go ABI. TEXT runtime·addmoduledata(SB),NOSPLIT,$0-0 diff --git a/src/runtime/sys_riscv64.go b/src/runtime/sys_riscv64.go index e710840819..65dc684c33 100644 --- a/src/runtime/sys_riscv64.go +++ b/src/runtime/sys_riscv64.go @@ -4,7 +4,12 @@ package runtime -import "unsafe" +import ( + "unsafe" + + "internal/abi" + "internal/runtime/sys" +) // adjust Gobuf as if it executed a call to fn with context ctxt // and then did an immediate Gosave. @@ -12,7 +17,9 @@ func gostartcall(buf *gobuf, fn, ctxt unsafe.Pointer) { if buf.lr != 0 { throw("invalid use of gostartcall") } - buf.lr = buf.pc + // Use double the PC quantum on riscv64, so that we retain + // four byte alignment and use non-compressed instructions. + buf.lr = abi.FuncPCABI0(goexit) + sys.PCQuantum*2 buf.pc = uintptr(fn) buf.ctxt = ctxt } |
