Commit 1046a9cb authored by Joel Sing's avatar Joel Sing

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/+/204625Reviewed-by: default avatarCherry Zhang <cherryyz@google.com>
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent 2d8c1995
...@@ -324,7 +324,7 @@ func rewriteMOV(ctxt *obj.Link, newprog obj.ProgAlloc, p *obj.Prog) { ...@@ -324,7 +324,7 @@ func rewriteMOV(ctxt *obj.Link, newprog obj.ProgAlloc, p *obj.Prog) {
off := p.From.Offset off := p.From.Offset
to := p.To to := p.To
low, high, err := split32BitImmediate(off) low, high, err := Split32BitImmediate(off)
if err != nil { if err != nil {
ctxt.Diag("%v: constant %d too large: %v", p, off, err) ctxt.Diag("%v: constant %d too large: %v", p, off, err)
} }
...@@ -512,11 +512,11 @@ func signExtend(val int64, bit uint) int64 { ...@@ -512,11 +512,11 @@ func signExtend(val int64, bit uint) int64 {
return val << (64 - bit) >> (64 - bit) return val << (64 - bit) >> (64 - bit)
} }
// split32BitImmediate splits a signed 32-bit immediate into a signed 20-bit // Split32BitImmediate splits a signed 32-bit immediate into a signed 20-bit
// upper immediate and a signed 12-bit lower immediate to be added to the upper // upper immediate and a signed 12-bit lower immediate to be added to the upper
// result. For example, high may be used in LUI and low in a following ADDI to // result. For example, high may be used in LUI and low in a following ADDI to
// generate a full 32-bit constant. // generate a full 32-bit constant.
func split32BitImmediate(imm int64) (low, high int64, err error) { func Split32BitImmediate(imm int64) (low, high int64, err error) {
if !immIFits(imm, 32) { if !immIFits(imm, 32) {
return 0, 0, fmt.Errorf("immediate does not fit in 32-bits: %d", imm) return 0, 0, fmt.Errorf("immediate does not fit in 32-bits: %d", imm)
} }
...@@ -909,6 +909,27 @@ func encodeRaw(p *obj.Prog) uint32 { ...@@ -909,6 +909,27 @@ func encodeRaw(p *obj.Prog) uint32 {
return uint32(a.Offset) return uint32(a.Offset)
} }
func EncodeIImmediate(imm int64) (int64, error) {
if !immIFits(imm, 12) {
return 0, fmt.Errorf("immediate %#x does not fit in 12 bits", imm)
}
return imm << 20, nil
}
func EncodeSImmediate(imm int64) (int64, error) {
if !immIFits(imm, 12) {
return 0, fmt.Errorf("immediate %#x does not fit in 12 bits", imm)
}
return ((imm >> 5) << 25) | ((imm & 0x1f) << 7), nil
}
func EncodeUImmediate(imm int64) (int64, error) {
if !immUFits(imm, 20) {
return 0, fmt.Errorf("immediate %#x does not fit in 20 bits", imm)
}
return imm << 12, nil
}
type encoding struct { type encoding struct {
encode func(*obj.Prog) uint32 // encode returns the machine code for an *obj.Prog encode func(*obj.Prog) uint32 // encode returns the machine code for an *obj.Prog
validate func(*obj.Prog) // validate validates an *obj.Prog, calling ctxt.Diag for any issues validate func(*obj.Prog) // validate validates an *obj.Prog, calling ctxt.Diag for any issues
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
package riscv64 package riscv64
import ( import (
"cmd/internal/obj/riscv"
"cmd/internal/objabi" "cmd/internal/objabi"
"cmd/internal/sys" "cmd/internal/sys"
"cmd/link/internal/ld" "cmd/link/internal/ld"
...@@ -40,8 +41,53 @@ func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, se ...@@ -40,8 +41,53 @@ func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, se
} }
func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) { func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
// TODO(jsing): Implement. switch r.Type {
log.Fatalf("archreloc not implemented") case objabi.R_CALLRISCV:
// Nothing to do.
return val, true
case objabi.R_RISCV_PCREL_ITYPE, objabi.R_RISCV_PCREL_STYPE:
pc := s.Value + int64(r.Off)
off := ld.Symaddr(r.Sym) + r.Add - pc
// Generate AUIPC and second instruction immediates.
low, high, err := riscv.Split32BitImmediate(off)
if err != nil {
ld.Errorf(s, "R_RISCV_PCREL_ relocation does not fit in 32-bits: %d", off)
}
auipcImm, err := riscv.EncodeUImmediate(high)
if err != nil {
ld.Errorf(s, "cannot encode R_RISCV_PCREL_ AUIPC relocation offset for %s: %v", r.Sym.Name, err)
}
var secondImm, secondImmMask int64
switch r.Type {
case objabi.R_RISCV_PCREL_ITYPE:
secondImmMask = riscv.ITypeImmMask
secondImm, err = riscv.EncodeIImmediate(low)
if err != nil {
ld.Errorf(s, "cannot encode R_RISCV_PCREL_ITYPE I-type instruction relocation offset for %s: %v", r.Sym.Name, err)
}
case objabi.R_RISCV_PCREL_STYPE:
secondImmMask = riscv.STypeImmMask
secondImm, err = riscv.EncodeSImmediate(low)
if err != nil {
ld.Errorf(s, "cannot encode R_RISCV_PCREL_STYPE S-type instruction relocation offset for %s: %v", r.Sym.Name, err)
}
default:
panic(fmt.Sprintf("Unknown relocation type: %v", r.Type))
}
auipc := int64(uint32(val))
second := int64(uint32(val >> 32))
auipc = (auipc &^ riscv.UTypeImmMask) | int64(uint32(auipcImm))
second = (second &^ secondImmMask) | int64(uint32(secondImm))
return second<<32 | auipc, true
}
return val, false return val, false
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment