]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/internal/sys,internal/goarch,runtime: enable the use of compressed instructions...
authorJoel Sing <joel@sing.id.au>
Sun, 27 Aug 2023 09:35:33 +0000 (19:35 +1000)
committerJoel Sing <joel@sing.id.au>
Tue, 18 Nov 2025 07:33:36 +0000 (23:33 -0800)
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>
src/cmd/internal/obj/riscv/obj.go
src/cmd/internal/sys/arch.go
src/internal/goarch/goarch_riscv64.go
src/runtime/asm_riscv64.s
src/runtime/sys_riscv64.go

index 3deab34d312eab354748529fb0e0b117fd24f5b4..8b9be5d78bc5af6f63f5dfbd4e9796d49df8afae 100644 (file)
@@ -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
                }
 
index 3c92a6bbf2561981e9eeb6bba1c8357f00a174f2..14b1cde22b0dc2c691707d769d5fb3c8cee06a96 100644 (file)
@@ -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,
index 3b6da1e02fe9b8c04dc10d7a16e4f0afd472b859..468f9a6374b9ac0fb5ef2412641d70afaf1bee9a 100644 (file)
@@ -7,7 +7,7 @@ package goarch
 const (
        _ArchFamily          = RISCV64
        _DefaultPhysPageSize = 4096
-       _PCQuantum           = 4
+       _PCQuantum           = 2
        _MinFrameSize        = 8
        _StackAlign          = PtrSize
 )
index 5bd16181ee2b8759772a0feb781203fdbe8afc1d..428701a5030610d90537559a8c625c31de31ca9c 100644 (file)
@@ -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
index e710840819c94e67ea3f4fdee094af02690f58d7..65dc684c332066ee113521e1fdfd4db473a49b83 100644 (file)
@@ -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
 }