aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/internal/obj
diff options
context:
space:
mode:
authorJoel Sing <joel@sing.id.au>2022-08-31 18:18:19 +1000
committerJoel Sing <joel@sing.id.au>2023-08-23 05:58:20 +0000
commite68c027204d410ebca5bf1a9660605f2bd737748 (patch)
treefcbf30f57a10f50750298895ba77e2c93e3eccf9 /src/cmd/internal/obj
parent70a8a41e97246b82fa4a39cb27a7c47e7af55a57 (diff)
downloadgo-e68c027204d410ebca5bf1a9660605f2bd737748.tar.xz
cmd/internal/obj/riscv,cmd/link: add support for internal cgo linking on riscv64
Make it possible to internally link cgo on riscv64, which also adds support for SDYNIMPORT calls without external linking being required. This reduces the time of an ./all.bash run on a Sifive Hifive Unleashed by approximately 20% (~140 minutes down to ~110 minutes). Change-Id: I43f1348de31672718ae8676cc82f6fdc1dfee054 Reviewed-on: https://go-review.googlesource.com/c/go/+/431104 TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Cherry Mui <cherryyz@google.com> Run-TryBot: Joel Sing <joel@sing.id.au> Reviewed-by: Than McIntosh <thanm@google.com>
Diffstat (limited to 'src/cmd/internal/obj')
-rw-r--r--src/cmd/internal/obj/riscv/cpu.go18
-rw-r--r--src/cmd/internal/obj/riscv/obj.go82
2 files changed, 92 insertions, 8 deletions
diff --git a/src/cmd/internal/obj/riscv/cpu.go b/src/cmd/internal/obj/riscv/cpu.go
index dde1231e15..bfd5153da4 100644
--- a/src/cmd/internal/obj/riscv/cpu.go
+++ b/src/cmd/internal/obj/riscv/cpu.go
@@ -619,14 +619,26 @@ var unaryDst = map[obj.As]bool{
// Instruction encoding masks.
const (
- // JTypeImmMask is a mask including only the immediate portion of
- // J-type instructions.
- JTypeImmMask = 0xfffff000
+ // BTypeImmMask is a mask including only the immediate portion of
+ // B-type instructions.
+ BTypeImmMask = 0xfe000f80
+
+ // CBTypeImmMask is a mask including only the immediate portion of
+ // CB-type instructions.
+ CBTypeImmMask = 0x1c7c
+
+ // CJTypeImmMask is a mask including only the immediate portion of
+ // CJ-type instructions.
+ CJTypeImmMask = 0x1f7c
// ITypeImmMask is a mask including only the immediate portion of
// I-type instructions.
ITypeImmMask = 0xfff00000
+ // JTypeImmMask is a mask including only the immediate portion of
+ // J-type instructions.
+ JTypeImmMask = 0xfffff000
+
// STypeImmMask is a mask including only the immediate portion of
// S-type instructions.
STypeImmMask = 0xfe000f80
diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go
index 2e55fac812..776c3a8df6 100644
--- a/src/cmd/internal/obj/riscv/obj.go
+++ b/src/cmd/internal/obj/riscv/obj.go
@@ -1181,6 +1181,12 @@ func validateRaw(ctxt *obj.Link, ins *instruction) {
}
}
+// extractBitAndShift extracts the specified bit from the given immediate,
+// before shifting it to the requested position and returning it.
+func extractBitAndShift(imm uint32, bit, pos int) uint32 {
+ return ((imm >> bit) & 1) << pos
+}
+
// encodeR encodes an R-type RISC-V instruction.
func encodeR(as obj.As, rs1, rs2, rd, funct3, funct7 uint32) uint32 {
enc := encode(as)
@@ -1272,6 +1278,11 @@ func encodeSF(ins *instruction) uint32 {
return encodeS(ins.as, regI(ins.rd), regF(ins.rs1), uint32(ins.imm))
}
+// encodeBImmediate encodes an immediate for a B-type RISC-V instruction.
+func encodeBImmediate(imm uint32) uint32 {
+ return (imm>>12)<<31 | ((imm>>5)&0x3f)<<25 | ((imm>>1)&0xf)<<8 | ((imm>>11)&0x1)<<7
+}
+
// encodeB encodes a B-type RISC-V instruction.
func encodeB(ins *instruction) uint32 {
imm := immI(ins.as, ins.imm, 13)
@@ -1281,7 +1292,7 @@ func encodeB(ins *instruction) uint32 {
if enc == nil {
panic("encodeB: could not encode instruction")
}
- return (imm>>12)<<31 | ((imm>>5)&0x3f)<<25 | rs2<<20 | rs1<<15 | enc.funct3<<12 | ((imm>>1)&0xf)<<8 | ((imm>>11)&0x1)<<7 | enc.opcode
+ return encodeBImmediate(imm) | rs2<<20 | rs1<<15 | enc.funct3<<12 | enc.opcode
}
// encodeU encodes a U-type RISC-V instruction.
@@ -1315,6 +1326,37 @@ func encodeJ(ins *instruction) uint32 {
return encodeJImmediate(imm) | rd<<7 | enc.opcode
}
+// encodeCBImmediate encodes an immediate for a CB-type RISC-V instruction.
+func encodeCBImmediate(imm uint32) uint32 {
+ // Bit order - [8|4:3|7:6|2:1|5]
+ bits := extractBitAndShift(imm, 8, 7)
+ bits |= extractBitAndShift(imm, 4, 6)
+ bits |= extractBitAndShift(imm, 3, 5)
+ bits |= extractBitAndShift(imm, 7, 4)
+ bits |= extractBitAndShift(imm, 6, 3)
+ bits |= extractBitAndShift(imm, 2, 2)
+ bits |= extractBitAndShift(imm, 1, 1)
+ bits |= extractBitAndShift(imm, 5, 0)
+ return (bits>>5)<<10 | (bits&0x1f)<<2
+}
+
+// encodeCJImmediate encodes an immediate for a CJ-type RISC-V instruction.
+func encodeCJImmediate(imm uint32) uint32 {
+ // Bit order - [11|4|9:8|10|6|7|3:1|5]
+ bits := extractBitAndShift(imm, 11, 10)
+ bits |= extractBitAndShift(imm, 4, 9)
+ bits |= extractBitAndShift(imm, 9, 8)
+ bits |= extractBitAndShift(imm, 8, 7)
+ bits |= extractBitAndShift(imm, 10, 6)
+ bits |= extractBitAndShift(imm, 6, 5)
+ bits |= extractBitAndShift(imm, 7, 4)
+ bits |= extractBitAndShift(imm, 3, 3)
+ bits |= extractBitAndShift(imm, 2, 2)
+ bits |= extractBitAndShift(imm, 1, 1)
+ bits |= extractBitAndShift(imm, 5, 0)
+ return bits << 2
+}
+
func encodeRawIns(ins *instruction) uint32 {
// Treat the raw value specially as a 32-bit unsigned integer.
// Nobody wants to enter negative machine code.
@@ -1324,14 +1366,34 @@ func encodeRawIns(ins *instruction) uint32 {
return uint32(ins.imm)
}
-func EncodeJImmediate(imm int64) (int64, error) {
- if !immIFits(imm, 21) {
- return 0, fmt.Errorf("immediate %#x does not fit in 21 bits", imm)
+func EncodeBImmediate(imm int64) (int64, error) {
+ if !immIFits(imm, 13) {
+ return 0, fmt.Errorf("immediate %#x does not fit in 13 bits", imm)
}
if imm&1 != 0 {
return 0, fmt.Errorf("immediate %#x is not a multiple of two", imm)
}
- return int64(encodeJImmediate(uint32(imm))), nil
+ return int64(encodeBImmediate(uint32(imm))), nil
+}
+
+func EncodeCBImmediate(imm int64) (int64, error) {
+ if !immIFits(imm, 9) {
+ return 0, fmt.Errorf("immediate %#x does not fit in 9 bits", imm)
+ }
+ if imm&1 != 0 {
+ return 0, fmt.Errorf("immediate %#x is not a multiple of two", imm)
+ }
+ return int64(encodeCBImmediate(uint32(imm))), nil
+}
+
+func EncodeCJImmediate(imm int64) (int64, error) {
+ if !immIFits(imm, 12) {
+ return 0, fmt.Errorf("immediate %#x does not fit in 12 bits", imm)
+ }
+ if imm&1 != 0 {
+ return 0, fmt.Errorf("immediate %#x is not a multiple of two", imm)
+ }
+ return int64(encodeCJImmediate(uint32(imm))), nil
}
func EncodeIImmediate(imm int64) (int64, error) {
@@ -1341,6 +1403,16 @@ func EncodeIImmediate(imm int64) (int64, error) {
return imm << 20, nil
}
+func EncodeJImmediate(imm int64) (int64, error) {
+ if !immIFits(imm, 21) {
+ return 0, fmt.Errorf("immediate %#x does not fit in 21 bits", imm)
+ }
+ if imm&1 != 0 {
+ return 0, fmt.Errorf("immediate %#x is not a multiple of two", imm)
+ }
+ return int64(encodeJImmediate(uint32(imm))), nil
+}
+
func EncodeSImmediate(imm int64) (int64, error) {
if !immIFits(imm, 12) {
return 0, fmt.Errorf("immediate %#x does not fit in 12 bits", imm)