Skip to content

Commit

Permalink
lang/go: add support for openbsd/riscv64
Browse files Browse the repository at this point in the history
This adds support for Go on openbsd/riscv64.

Requested by and ok jca@

ok abieber@
  • Loading branch information
4a6f656c committed Sep 20, 2022
1 parent bbcc2ba commit 799c178
Show file tree
Hide file tree
Showing 55 changed files with 11,880 additions and 22 deletions.
5 changes: 4 additions & 1 deletion lang/go/Makefile
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
ONLY_FOR_ARCHS = ${GO_ARCHS}

BIN_BOOTSTRAP_GOARCHS = 386 amd64 arm arm64 mips64
BIN_BOOTSTRAP_GOARCHS = 386 amd64 arm arm64 mips64 riscv64
BIN_BOOTSTRAP_VERSION = 1.18.4

COMMENT = Go programming language

VERSION = 1.19.1
REVISION = 0
DISTNAME = go${VERSION}.src
PKGNAME = go-${VERSION}
PKGSPEC = ${FULLPKGNAME:S/go-/go-=/}
Expand Down Expand Up @@ -56,6 +57,8 @@ GOARCH = arm64
GOARCH = 386
.elif ${MACHINE_ARCH} == "mips64"
GOARCH = mips64
.elif ${MACHINE_ARCH} == "riscv64"
GOARCH = riscv64
.endif

# We cannot assume that the machine running the built code will have SSE,
Expand Down
2 changes: 2 additions & 0 deletions lang/go/distinfo
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ SHA256 (go-openbsd-amd64-bootstrap-1.18.4.tar.gz) = ireh8OvOgYBMUJcdsMLjGHyqYorn
SHA256 (go-openbsd-arm-bootstrap-1.18.4.tar.gz) = oxYr3cphgkHHW3fhD4MWmZy6wWGRxHL1/HgXGoR0deE=
SHA256 (go-openbsd-arm64-bootstrap-1.18.4.tar.gz) = M7OML+r3ofvr5UaIoZ12jqDBB4ogT3sePUVDR+l2mwY=
SHA256 (go-openbsd-mips64-bootstrap-1.18.4.tar.gz) = voP9dDKZ3hcXjyqF9r3jBSxGMZwgeBt27p41GzCKoEI=
SHA256 (go-openbsd-riscv64-bootstrap-1.18.4.tar.gz) = je0AbR0bVy+KMXzcmzkJ3pRBUfXoQUI44LjrrdIQOOQ=
SHA256 (go1.19.1.src.tar.gz) = J4cbqkkPNAFBSteT+6SQhvbIVbHFhDhe13ceEgTH4Xk=
SIZE (go-openbsd-386-bootstrap-1.18.4.tar.gz) = 148679005
SIZE (go-openbsd-amd64-bootstrap-1.18.4.tar.gz) = 149910861
SIZE (go-openbsd-arm-bootstrap-1.18.4.tar.gz) = 145777001
SIZE (go-openbsd-arm64-bootstrap-1.18.4.tar.gz) = 144201762
SIZE (go-openbsd-mips64-bootstrap-1.18.4.tar.gz) = 148034418
SIZE (go-openbsd-riscv64-bootstrap-1.18.4.tar.gz) = 142272942
SIZE (go1.19.1.src.tar.gz) = 26527375
15 changes: 15 additions & 0 deletions lang/go/patches/patch-src_cmd_asm_internal_asm_endtoend_test_go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Index: src/cmd/asm/internal/asm/endtoend_test.go
--- src/cmd/asm/internal/asm/endtoend_test.go.orig
+++ src/cmd/asm/internal/asm/endtoend_test.go
@@ -69,6 +69,11 @@ Diff:
continue
}

+ // Ignore GLOBL.
+ if strings.HasPrefix(line, "GLOBL ") {
+ continue
+ }
+
// The general form of a test input line is:
// // comment
// INST args [// printed form] [// hex encoding]
24 changes: 24 additions & 0 deletions lang/go/patches/patch-src_cmd_asm_internal_asm_testdata_riscv64_s
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
Index: src/cmd/asm/internal/asm/testdata/riscv64.s
--- src/cmd/asm/internal/asm/testdata/riscv64.s.orig
+++ src/cmd/asm/internal/asm/testdata/riscv64.s
@@ -352,6 +352,14 @@ start:
MOVD F0, 4(X5) // 27b20200
MOVD F0, F1 // d3000022

+ // TLS load with local-exec (LUI + ADDIW + ADD of TP + load)
+ MOV tls(SB), X5 // b70f00009b8f0f00b38f4f0083b20f00
+ MOVB tls(SB), X5 // b70f00009b8f0f00b38f4f0083820f00
+
+ // TLS store with local-exec (LUI + ADDIW + ADD of TP + store)
+ MOV X5, tls(SB) // b70f00009b8f0f00b38f4f0023b05f00
+ MOVB X5, tls(SB) // b70f00009b8f0f00b38f4f0023805f00
+
// NOT pseudo-instruction
NOT X5 // 93c2f2ff
NOT X5, X6 // 13c3f2ff
@@ -405,3 +413,5 @@ start:
FLTD F0, F1, X5 // d39200a2
FLED F0, F1, X5 // d38200a2
FEQD F0, F1, X5 // d3a200a2
+
+GLOBL tls(SB), TLSBSS, $8
11 changes: 11 additions & 0 deletions lang/go/patches/patch-src_cmd_dist_build_go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Index: src/cmd/dist/build.go
--- src/cmd/dist/build.go.orig
+++ src/cmd/dist/build.go
@@ -1589,6 +1589,7 @@ var cgoEnabled = map[string]bool{
"openbsd/arm": true,
"openbsd/arm64": true,
"openbsd/mips64": true,
+ "openbsd/riscv64": true,
"plan9/386": false,
"plan9/amd64": false,
"plan9/arm": false,
32 changes: 32 additions & 0 deletions lang/go/patches/patch-src_cmd_internal_obj_riscv_cpu_go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
Index: src/cmd/internal/obj/riscv/cpu.go
--- src/cmd/internal/obj/riscv/cpu.go.orig
+++ src/cmd/internal/obj/riscv/cpu.go
@@ -632,13 +632,25 @@ 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.
204 changes: 204 additions & 0 deletions lang/go/patches/patch-src_cmd_internal_obj_riscv_obj_go
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
Index: src/cmd/internal/obj/riscv/obj.go
--- src/cmd/internal/obj/riscv/obj.go.orig
+++ src/cmd/internal/obj/riscv/obj.go
@@ -1264,6 +1264,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)
@@ -1273,7 +1278,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.
@@ -1316,16 +1321,67 @@ 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 extractAndShift(imm int64, bit, pos int) int64 {
+ return ((imm >> (bit - 1)) & 1) << (pos - 1)
+}
+
+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)
+ }
+ imm = imm >> 1
+
+ // Bit order - [8|4:3|7:6|2:1|5]
+ bits := extractAndShift(imm, 8, 8)
+ bits |= extractAndShift(imm, 4, 7)
+ bits |= extractAndShift(imm, 3, 6)
+ bits |= extractAndShift(imm, 7, 5)
+ bits |= extractAndShift(imm, 6, 4)
+ bits |= extractAndShift(imm, 2, 3)
+ bits |= extractAndShift(imm, 1, 2)
+ bits |= extractAndShift(imm, 5, 1)
+
+ return (bits>>5)<<10 | (bits&0x1f)<<2, 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)
+ }
+ imm = imm >> 1
+
+ // Bit order - [11|4|9:8|10|6|7|3:1|5]
+ bits := extractAndShift(imm, 11, 11)
+ bits |= extractAndShift(imm, 4, 10)
+ bits |= extractAndShift(imm, 9, 9)
+ bits |= extractAndShift(imm, 8, 8)
+ bits |= extractAndShift(imm, 10, 7)
+ bits |= extractAndShift(imm, 6, 6)
+ bits |= extractAndShift(imm, 7, 5)
+ bits |= extractAndShift(imm, 3, 4)
+ bits |= extractAndShift(imm, 2, 3)
+ bits |= extractAndShift(imm, 1, 2)
+ bits |= extractAndShift(imm, 5, 1)
+
+ return bits << 2, nil
+}
+
func EncodeIImmediate(imm int64) (int64, error) {
if !immIFits(imm, 12) {
return 0, fmt.Errorf("immediate %#x does not fit in 12 bits", imm)
@@ -1333,6 +1389,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)
@@ -1819,6 +1885,53 @@ func instructionsForStore(p *obj.Prog, as obj.As, rd i
return []*instruction{insLUI, insADD, ins}
}

+func instructionsForTLS(p *obj.Prog, ins *instruction) []*instruction {
+ insAddTP := &instruction{as: AADD, rd: REG_TMP, rs1: REG_TMP, rs2: REG_TP}
+
+ var inss []*instruction
+ if p.Ctxt.Flag_shared {
+ // TLS initial-exec mode - load TLS offset from GOT, add the thread pointer
+ // register, then load from or store to the resulting memory location.
+ insAUIPC := &instruction{as: AAUIPC, rd: REG_TMP}
+ insLoadTLSOffset := &instruction{as: ALD, rd: REG_TMP, rs1: REG_TMP}
+ inss = []*instruction{insAUIPC, insLoadTLSOffset, insAddTP, ins}
+ } else {
+ // TLS local-exec mode - load upper TLS offset, add the lower TLS offset,
+ // add the thread pointer register, then load from or store to the resulting
+ // memory location. Note that this differs from the suggested three
+ // instruction sequence, as the Go linker does not currently have an
+ // easy way to handle relocation across 12 bytes of machine code.
+ insLUI := &instruction{as: ALUI, rd: REG_TMP}
+ insADDIW := &instruction{as: AADDIW, rd: REG_TMP, rs1: REG_TMP}
+ inss = []*instruction{insLUI, insADDIW, insAddTP, ins}
+ }
+ return inss
+}
+
+func instructionsForTLSLoad(p *obj.Prog) []*instruction {
+ if p.From.Sym.Type != objabi.STLSBSS {
+ p.Ctxt.Diag("%v: %v is not a TLS symbol", p, p.From.Sym)
+ return nil
+ }
+
+ ins := instructionForProg(p)
+ ins.as, ins.rs1, ins.rs2, ins.imm = movToLoad(p.As), REG_TMP, obj.REG_NONE, 0
+
+ return instructionsForTLS(p, ins)
+}
+
+func instructionsForTLSStore(p *obj.Prog) []*instruction {
+ if p.To.Sym.Type != objabi.STLSBSS {
+ p.Ctxt.Diag("%v: %v is not a TLS symbol", p, p.To.Sym)
+ return nil
+ }
+
+ ins := instructionForProg(p)
+ ins.as, ins.rd, ins.rs1, ins.rs2, ins.imm = movToStore(p.As), REG_TMP, uint32(p.From.Reg), obj.REG_NONE, 0
+
+ return instructionsForTLS(p, ins)
+}
+
// instructionsForMOV returns the machine instructions for an *obj.Prog that
// uses a MOV pseudo-instruction.
func instructionsForMOV(p *obj.Prog) []*instruction {
@@ -1908,6 +2021,10 @@ func instructionsForMOV(p *obj.Prog) []*instruction {
inss = instructionsForLoad(p, movToLoad(p.As), addrToReg(p.From))

case obj.NAME_EXTERN, obj.NAME_STATIC:
+ if p.From.Sym.Type == objabi.STLSBSS {
+ return instructionsForTLSLoad(p)
+ }
+
// Note that the values for $off_hi and $off_lo are currently
// zero and will be assigned during relocation.
//
@@ -1935,6 +2052,10 @@ func instructionsForMOV(p *obj.Prog) []*instruction {
inss = instructionsForStore(p, movToStore(p.As), addrToReg(p.To))

case obj.NAME_EXTERN, obj.NAME_STATIC:
+ if p.To.Sym.Type == objabi.STLSBSS {
+ return instructionsForTLSStore(p)
+ }
+
// Note that the values for $off_hi and $off_lo are currently
// zero and will be assigned during relocation.
//
@@ -2198,10 +2319,10 @@ func assemble(ctxt *obj.Link, cursym *obj.LSym, newpro
break
}
if addr.Sym.Type == objabi.STLSBSS {
- if rt == objabi.R_RISCV_PCREL_ITYPE {
- rt = objabi.R_RISCV_TLS_IE_ITYPE
- } else if rt == objabi.R_RISCV_PCREL_STYPE {
- rt = objabi.R_RISCV_TLS_IE_STYPE
+ if ctxt.Flag_shared {
+ rt = objabi.R_RISCV_TLS_IE
+ } else {
+ rt = objabi.R_RISCV_TLS_LE
}
}

52 changes: 51 additions & 1 deletion lang/go/patches/patch-src_cmd_internal_objabi_reloctype_go
Original file line number Diff line number Diff line change
@@ -1,7 +1,57 @@
Index: src/cmd/internal/objabi/reloctype.go
--- src/cmd/internal/objabi/reloctype.go.orig
+++ src/cmd/internal/objabi/reloctype.go
@@ -279,9 +279,24 @@ const (
@@ -238,14 +238,43 @@ const (
// AUIPC + S-type instruction pair.
R_RISCV_PCREL_STYPE

- // R_RISCV_TLS_IE_ITYPE resolves a 32-bit TLS initial-exec TOC offset
- // address using an AUIPC + I-type instruction pair.
- R_RISCV_TLS_IE_ITYPE
+ // R_RISCV_TLS_IE resolves a 32-bit TLS initial-exec address using an
+ // AUIPC + I-type instruction pair.
+ R_RISCV_TLS_IE

- // R_RISCV_TLS_IE_STYPE resolves a 32-bit TLS initial-exec TOC offset
- // address using an AUIPC + S-type instruction pair.
- R_RISCV_TLS_IE_STYPE
+ // R_RISCV_TLS_LE_ITYPE resolves a 32-bit TLS local-exec address using an
+ // LUI + I-type instruction sequence.
+ R_RISCV_TLS_LE

+ // R_RISCV_GOT_HI20 resolves the high 20 bits of a 32-bit PC-relative GOT
+ // address.
+ R_RISCV_GOT_HI20
+
+ // R_RISCV_PCREL_32 resolves a 32-bit PC-relative address to an absolute
+ // value.
+ R_RISCV_PCREL_32
+
+ // R_RISCV_PCREL_HI20 resolves the high 20 bits of a 32-bit PC-relative
+ // address.
+ R_RISCV_PCREL_HI20
+
+ // R_RISCV_PCREL_LO12_I resolves the low 12 bits of a 32-bit PC-relative
+ // address using an I-type instruction.
+ R_RISCV_PCREL_LO12_I
+
+ // R_RISCV_PCREL_LO12_S resolves the low 12 bits of a 32-bit PC-relative
+ // address using an S-type instruction.
+ R_RISCV_PCREL_LO12_S
+
+ // R_RISCV_BRANCH resolves a 12-bit PC-relative branch offset.
+ R_RISCV_BRANCH
+
+ // R_RISCV_RVC_BRANCH resolves an 8-bit PC-relative branch offset.
+ R_RISCV_RVC_BRANCH
+
+ // R_RISCV_RVC_JUMP resolves an 11-bit PC-relative jump offset.
+ R_RISCV_RVC_JUMP
+
// R_PCRELDBL relocates s390x 2-byte aligned PC-relative addresses.
// TODO(mundaym): remove once variants can be serialized - see issue 14218.
R_PCRELDBL
@@ -279,9 +308,24 @@ const (
// R_ADDRMIPSU (only used on mips/mips64) resolves to the sign-adjusted "upper" 16
// bits (bit 16-31) of an external address, by encoding it into the instruction.
R_ADDRMIPSU
Expand Down
Loading

0 comments on commit 799c178

Please sign in to comment.