-
Notifications
You must be signed in to change notification settings - Fork 122
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
lang/go: add support for openbsd/riscv64
This adds support for Go on openbsd/riscv64. Requested by and ok jca@ ok abieber@
- Loading branch information
Showing
55 changed files
with
11,880 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
15 changes: 15 additions & 0 deletions
15
lang/go/patches/patch-src_cmd_asm_internal_asm_endtoend_test_go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
24
lang/go/patches/patch-src_cmd_asm_internal_asm_testdata_riscv64_s
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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, |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
204
lang/go/patches/patch-src_cmd_internal_obj_riscv_obj_go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.