Skip to content

Commit 1046a9c

Browse files
committed
cmd/link,cmd/internal/obj/riscv: implement archreloc for riscv64
Based on the riscv-go port. Updates #27532 Change-Id: I478254306441c253d3a2c09c10932ad1ac0be3c6 Reviewed-on: https://go-review.googlesource.com/c/go/+/204625 Reviewed-by: Cherry Zhang <[email protected]> Run-TryBot: Cherry Zhang <[email protected]> TryBot-Result: Gobot Gobot <[email protected]>
1 parent 2d8c199 commit 1046a9c

File tree

2 files changed

+72
-5
lines changed

2 files changed

+72
-5
lines changed

src/cmd/internal/obj/riscv/obj.go

+24-3
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ func rewriteMOV(ctxt *obj.Link, newprog obj.ProgAlloc, p *obj.Prog) {
324324
off := p.From.Offset
325325
to := p.To
326326

327-
low, high, err := split32BitImmediate(off)
327+
low, high, err := Split32BitImmediate(off)
328328
if err != nil {
329329
ctxt.Diag("%v: constant %d too large: %v", p, off, err)
330330
}
@@ -512,11 +512,11 @@ func signExtend(val int64, bit uint) int64 {
512512
return val << (64 - bit) >> (64 - bit)
513513
}
514514

515-
// split32BitImmediate splits a signed 32-bit immediate into a signed 20-bit
515+
// Split32BitImmediate splits a signed 32-bit immediate into a signed 20-bit
516516
// upper immediate and a signed 12-bit lower immediate to be added to the upper
517517
// result. For example, high may be used in LUI and low in a following ADDI to
518518
// generate a full 32-bit constant.
519-
func split32BitImmediate(imm int64) (low, high int64, err error) {
519+
func Split32BitImmediate(imm int64) (low, high int64, err error) {
520520
if !immIFits(imm, 32) {
521521
return 0, 0, fmt.Errorf("immediate does not fit in 32-bits: %d", imm)
522522
}
@@ -909,6 +909,27 @@ func encodeRaw(p *obj.Prog) uint32 {
909909
return uint32(a.Offset)
910910
}
911911

912+
func EncodeIImmediate(imm int64) (int64, error) {
913+
if !immIFits(imm, 12) {
914+
return 0, fmt.Errorf("immediate %#x does not fit in 12 bits", imm)
915+
}
916+
return imm << 20, nil
917+
}
918+
919+
func EncodeSImmediate(imm int64) (int64, error) {
920+
if !immIFits(imm, 12) {
921+
return 0, fmt.Errorf("immediate %#x does not fit in 12 bits", imm)
922+
}
923+
return ((imm >> 5) << 25) | ((imm & 0x1f) << 7), nil
924+
}
925+
926+
func EncodeUImmediate(imm int64) (int64, error) {
927+
if !immUFits(imm, 20) {
928+
return 0, fmt.Errorf("immediate %#x does not fit in 20 bits", imm)
929+
}
930+
return imm << 12, nil
931+
}
932+
912933
type encoding struct {
913934
encode func(*obj.Prog) uint32 // encode returns the machine code for an *obj.Prog
914935
validate func(*obj.Prog) // validate validates an *obj.Prog, calling ctxt.Diag for any issues

src/cmd/link/internal/riscv64/asm.go

+48-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package riscv64
66

77
import (
8+
"cmd/internal/obj/riscv"
89
"cmd/internal/objabi"
910
"cmd/internal/sys"
1011
"cmd/link/internal/ld"
@@ -40,8 +41,53 @@ func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, se
4041
}
4142

4243
func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
43-
// TODO(jsing): Implement.
44-
log.Fatalf("archreloc not implemented")
44+
switch r.Type {
45+
case objabi.R_CALLRISCV:
46+
// Nothing to do.
47+
return val, true
48+
49+
case objabi.R_RISCV_PCREL_ITYPE, objabi.R_RISCV_PCREL_STYPE:
50+
pc := s.Value + int64(r.Off)
51+
off := ld.Symaddr(r.Sym) + r.Add - pc
52+
53+
// Generate AUIPC and second instruction immediates.
54+
low, high, err := riscv.Split32BitImmediate(off)
55+
if err != nil {
56+
ld.Errorf(s, "R_RISCV_PCREL_ relocation does not fit in 32-bits: %d", off)
57+
}
58+
59+
auipcImm, err := riscv.EncodeUImmediate(high)
60+
if err != nil {
61+
ld.Errorf(s, "cannot encode R_RISCV_PCREL_ AUIPC relocation offset for %s: %v", r.Sym.Name, err)
62+
}
63+
64+
var secondImm, secondImmMask int64
65+
switch r.Type {
66+
case objabi.R_RISCV_PCREL_ITYPE:
67+
secondImmMask = riscv.ITypeImmMask
68+
secondImm, err = riscv.EncodeIImmediate(low)
69+
if err != nil {
70+
ld.Errorf(s, "cannot encode R_RISCV_PCREL_ITYPE I-type instruction relocation offset for %s: %v", r.Sym.Name, err)
71+
}
72+
case objabi.R_RISCV_PCREL_STYPE:
73+
secondImmMask = riscv.STypeImmMask
74+
secondImm, err = riscv.EncodeSImmediate(low)
75+
if err != nil {
76+
ld.Errorf(s, "cannot encode R_RISCV_PCREL_STYPE S-type instruction relocation offset for %s: %v", r.Sym.Name, err)
77+
}
78+
default:
79+
panic(fmt.Sprintf("Unknown relocation type: %v", r.Type))
80+
}
81+
82+
auipc := int64(uint32(val))
83+
second := int64(uint32(val >> 32))
84+
85+
auipc = (auipc &^ riscv.UTypeImmMask) | int64(uint32(auipcImm))
86+
second = (second &^ secondImmMask) | int64(uint32(secondImm))
87+
88+
return second<<32 | auipc, true
89+
}
90+
4591
return val, false
4692
}
4793

0 commit comments

Comments
 (0)