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>
This commit is contained in:
Joel Sing 2023-08-27 19:35:33 +10:00
parent a087dea869
commit b9ef0633f6
5 changed files with 25 additions and 11 deletions

View 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
}

View 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,

View file

@ -7,7 +7,7 @@ package goarch
const (
_ArchFamily = RISCV64
_DefaultPhysPageSize = 4096
_PCQuantum = 4
_PCQuantum = 2
_MinFrameSize = 8
_StackAlign = PtrSize
)

View 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

View 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
}