aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cmd/internal/objabi/reloctype.go28
-rw-r--r--src/cmd/internal/objabi/reloctype_string.go55
-rw-r--r--src/cmd/link/internal/ppc64/asm.go204
3 files changed, 182 insertions, 105 deletions
diff --git a/src/cmd/internal/objabi/reloctype.go b/src/cmd/internal/objabi/reloctype.go
index e5d1d5f9e0..590eedb025 100644
--- a/src/cmd/internal/objabi/reloctype.go
+++ b/src/cmd/internal/objabi/reloctype.go
@@ -208,6 +208,15 @@ const (
// (usually called RB in X-form instructions) is assumed to be R13.
R_POWER_TLS
+ // R_POWER_TLS_IE_PCREL34 is similar to R_POWER_TLS_IE, but marks a single MOVD
+ // which has been assembled as a single prefixed load doubleword without using the
+ // TOC.
+ R_POWER_TLS_IE_PCREL34
+
+ // R_POWER_TLS_LE_TPREL34 is similar to R_POWER_TLS_LE, but computes an offset from
+ // the thread pointer in one prefixed instruction.
+ R_POWER_TLS_LE_TPREL34
+
// R_ADDRPOWER_DS is similar to R_ADDRPOWER above, but assumes the second
// instruction is a "DS-form" instruction, which has an immediate field occupying
// bits [15:2] of the instruction word. Bits [15:2] of the address of the
@@ -215,11 +224,14 @@ const (
// bits of the address are not 0.
R_ADDRPOWER_DS
- // R_ADDRPOWER_PCREL relocates a D-form, DS-form instruction sequence like
- // R_ADDRPOWER_DS but inserts the offset of the GOT slot for the referenced symbol
- // from the TOC rather than the symbol's address.
+ // R_ADDRPOWER_GOT relocates a D-form + DS-form instruction sequence by inserting
+ // a relative displacement of referenced symbol's GOT entry to the TOC pointer.
R_ADDRPOWER_GOT
+ // R_ADDRPOWER_GOT_PCREL34 is identical to R_ADDRPOWER_GOT, but uses a PC relative
+ // sequence to generate a GOT symbol addresss.
+ R_ADDRPOWER_GOT_PCREL34
+
// R_ADDRPOWER_PCREL relocates two D-form instructions like R_ADDRPOWER, but
// inserts the displacement from the place being relocated to the address of the
// relocated symbol instead of just its address.
@@ -235,6 +247,16 @@ const (
// relocated symbol rather than the symbol's address.
R_ADDRPOWER_TOCREL_DS
+ // R_ADDRPOWER_D34 relocates a single prefixed D-form load/store operation. All
+ // prefixed forms are D form. The high 18 bits are stored in the prefix,
+ // and the low 16 are stored in the suffix. The address is absolute.
+ R_ADDRPOWER_D34
+
+ // R_ADDPOWER_PCREL34 relates a single prefixed D-form load/store/add operation.
+ // All prefixed forms are D form. The resulting address is relative to the
+ // PC. It is a signed 34 bit offset.
+ R_ADDRPOWER_PCREL34
+
// RISC-V.
// R_RISCV_CALL relocates a J-type instruction with a 21 bit PC-relative
diff --git a/src/cmd/internal/objabi/reloctype_string.go b/src/cmd/internal/objabi/reloctype_string.go
index ccc755e4bb..9ce37d00de 100644
--- a/src/cmd/internal/objabi/reloctype_string.go
+++ b/src/cmd/internal/objabi/reloctype_string.go
@@ -57,34 +57,39 @@ func _() {
_ = x[R_POWER_TLS_LE-47]
_ = x[R_POWER_TLS_IE-48]
_ = x[R_POWER_TLS-49]
- _ = x[R_ADDRPOWER_DS-50]
- _ = x[R_ADDRPOWER_GOT-51]
- _ = x[R_ADDRPOWER_PCREL-52]
- _ = x[R_ADDRPOWER_TOCREL-53]
- _ = x[R_ADDRPOWER_TOCREL_DS-54]
- _ = x[R_RISCV_CALL-55]
- _ = x[R_RISCV_CALL_TRAMP-56]
- _ = x[R_RISCV_PCREL_ITYPE-57]
- _ = x[R_RISCV_PCREL_STYPE-58]
- _ = x[R_RISCV_TLS_IE_ITYPE-59]
- _ = x[R_RISCV_TLS_IE_STYPE-60]
- _ = x[R_PCRELDBL-61]
- _ = x[R_ADDRLOONG64-62]
- _ = x[R_ADDRLOONG64U-63]
- _ = x[R_ADDRLOONG64TLS-64]
- _ = x[R_ADDRLOONG64TLSU-65]
- _ = x[R_CALLLOONG64-66]
- _ = x[R_JMPLOONG64-67]
- _ = x[R_ADDRMIPSU-68]
- _ = x[R_ADDRMIPSTLS-69]
- _ = x[R_ADDRCUOFF-70]
- _ = x[R_WASMIMPORT-71]
- _ = x[R_XCOFFREF-72]
+ _ = x[R_POWER_TLS_IE_PCREL34-50]
+ _ = x[R_POWER_TLS_LE_TPREL34-51]
+ _ = x[R_ADDRPOWER_DS-52]
+ _ = x[R_ADDRPOWER_GOT-53]
+ _ = x[R_ADDRPOWER_GOT_PCREL34-54]
+ _ = x[R_ADDRPOWER_PCREL-55]
+ _ = x[R_ADDRPOWER_TOCREL-56]
+ _ = x[R_ADDRPOWER_TOCREL_DS-57]
+ _ = x[R_ADDRPOWER_D34-58]
+ _ = x[R_ADDRPOWER_PCREL34-59]
+ _ = x[R_RISCV_CALL-60]
+ _ = x[R_RISCV_CALL_TRAMP-61]
+ _ = x[R_RISCV_PCREL_ITYPE-62]
+ _ = x[R_RISCV_PCREL_STYPE-63]
+ _ = x[R_RISCV_TLS_IE_ITYPE-64]
+ _ = x[R_RISCV_TLS_IE_STYPE-65]
+ _ = x[R_PCRELDBL-66]
+ _ = x[R_ADDRLOONG64-67]
+ _ = x[R_ADDRLOONG64U-68]
+ _ = x[R_ADDRLOONG64TLS-69]
+ _ = x[R_ADDRLOONG64TLSU-70]
+ _ = x[R_CALLLOONG64-71]
+ _ = x[R_JMPLOONG64-72]
+ _ = x[R_ADDRMIPSU-73]
+ _ = x[R_ADDRMIPSTLS-74]
+ _ = x[R_ADDRCUOFF-75]
+ _ = x[R_WASMIMPORT-76]
+ _ = x[R_XCOFFREF-77]
}
-const _RelocType_name = "R_ADDRR_ADDRPOWERR_ADDRARM64R_ADDRMIPSR_ADDROFFR_SIZER_CALLR_CALLARMR_CALLARM64R_CALLINDR_CALLPOWERR_CALLMIPSR_CONSTR_PCRELR_TLS_LER_TLS_IER_GOTOFFR_PLT0R_PLT1R_PLT2R_USEFIELDR_USETYPER_USEIFACER_USEIFACEMETHODR_USEGENERICIFACEMETHODR_METHODOFFR_KEEPR_POWER_TOCR_GOTPCRELR_JMPMIPSR_DWARFSECREFR_DWARFFILEREFR_ARM64_TLS_LER_ARM64_TLS_IER_ARM64_GOTPCRELR_ARM64_GOTR_ARM64_PCRELR_ARM64_PCREL_LDST8R_ARM64_PCREL_LDST16R_ARM64_PCREL_LDST32R_ARM64_PCREL_LDST64R_ARM64_LDST8R_ARM64_LDST16R_ARM64_LDST32R_ARM64_LDST64R_ARM64_LDST128R_POWER_TLS_LER_POWER_TLS_IER_POWER_TLSR_ADDRPOWER_DSR_ADDRPOWER_GOTR_ADDRPOWER_PCRELR_ADDRPOWER_TOCRELR_ADDRPOWER_TOCREL_DSR_RISCV_CALLR_RISCV_CALL_TRAMPR_RISCV_PCREL_ITYPER_RISCV_PCREL_STYPER_RISCV_TLS_IE_ITYPER_RISCV_TLS_IE_STYPER_PCRELDBLR_ADDRLOONG64R_ADDRLOONG64UR_ADDRLOONG64TLSR_ADDRLOONG64TLSUR_CALLLOONG64R_JMPLOONG64R_ADDRMIPSUR_ADDRMIPSTLSR_ADDRCUOFFR_WASMIMPORTR_XCOFFREF"
+const _RelocType_name = "R_ADDRR_ADDRPOWERR_ADDRARM64R_ADDRMIPSR_ADDROFFR_SIZER_CALLR_CALLARMR_CALLARM64R_CALLINDR_CALLPOWERR_CALLMIPSR_CONSTR_PCRELR_TLS_LER_TLS_IER_GOTOFFR_PLT0R_PLT1R_PLT2R_USEFIELDR_USETYPER_USEIFACER_USEIFACEMETHODR_USEGENERICIFACEMETHODR_METHODOFFR_KEEPR_POWER_TOCR_GOTPCRELR_JMPMIPSR_DWARFSECREFR_DWARFFILEREFR_ARM64_TLS_LER_ARM64_TLS_IER_ARM64_GOTPCRELR_ARM64_GOTR_ARM64_PCRELR_ARM64_PCREL_LDST8R_ARM64_PCREL_LDST16R_ARM64_PCREL_LDST32R_ARM64_PCREL_LDST64R_ARM64_LDST8R_ARM64_LDST16R_ARM64_LDST32R_ARM64_LDST64R_ARM64_LDST128R_POWER_TLS_LER_POWER_TLS_IER_POWER_TLSR_POWER_TLS_IE_PCREL34R_POWER_TLS_LE_TPREL34R_ADDRPOWER_DSR_ADDRPOWER_GOTR_ADDRPOWER_GOT_PCREL34R_ADDRPOWER_PCRELR_ADDRPOWER_TOCRELR_ADDRPOWER_TOCREL_DSR_ADDRPOWER_D34R_ADDRPOWER_PCREL34R_RISCV_CALLR_RISCV_CALL_TRAMPR_RISCV_PCREL_ITYPER_RISCV_PCREL_STYPER_RISCV_TLS_IE_ITYPER_RISCV_TLS_IE_STYPER_PCRELDBLR_ADDRLOONG64R_ADDRLOONG64UR_ADDRLOONG64TLSR_ADDRLOONG64TLSUR_CALLLOONG64R_JMPLOONG64R_ADDRMIPSUR_ADDRMIPSTLSR_ADDRCUOFFR_WASMIMPORTR_XCOFFREF"
-var _RelocType_index = [...]uint16{0, 6, 17, 28, 38, 47, 53, 59, 68, 79, 88, 99, 109, 116, 123, 131, 139, 147, 153, 159, 165, 175, 184, 194, 210, 233, 244, 250, 261, 271, 280, 293, 307, 321, 335, 351, 362, 375, 394, 414, 434, 454, 467, 481, 495, 509, 524, 538, 552, 563, 577, 592, 609, 627, 648, 660, 678, 697, 716, 736, 756, 766, 779, 793, 809, 826, 839, 851, 862, 875, 886, 898, 908}
+var _RelocType_index = [...]uint16{0, 6, 17, 28, 38, 47, 53, 59, 68, 79, 88, 99, 109, 116, 123, 131, 139, 147, 153, 159, 165, 175, 184, 194, 210, 233, 244, 250, 261, 271, 280, 293, 307, 321, 335, 351, 362, 375, 394, 414, 434, 454, 467, 481, 495, 509, 524, 538, 552, 563, 585, 607, 621, 636, 659, 676, 694, 715, 730, 749, 761, 779, 798, 817, 837, 857, 867, 880, 894, 910, 927, 940, 952, 963, 976, 987, 999, 1009}
func (i RelocType) String() string {
i -= 1
diff --git a/src/cmd/link/internal/ppc64/asm.go b/src/cmd/link/internal/ppc64/asm.go
index bfa7c618e0..db486f29dd 100644
--- a/src/cmd/link/internal/ppc64/asm.go
+++ b/src/cmd/link/internal/ppc64/asm.go
@@ -727,6 +727,10 @@ func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym,
default:
return false
}
+ case objabi.R_ADDRPOWER_D34:
+ out.Write64(uint64(elf.R_PPC64_D34) | uint64(elfsym)<<32)
+ case objabi.R_ADDRPOWER_PCREL34:
+ out.Write64(uint64(elf.R_PPC64_PCREL34) | uint64(elfsym)<<32)
case objabi.R_POWER_TLS:
out.Write64(uint64(elf.R_PPC64_TLS) | uint64(elfsym)<<32)
case objabi.R_POWER_TLS_LE:
@@ -734,6 +738,10 @@ func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym,
out.Write64(uint64(r.Xadd))
out.Write64(uint64(sectoff + 4))
out.Write64(uint64(elf.R_PPC64_TPREL16_LO) | uint64(elfsym)<<32)
+ case objabi.R_POWER_TLS_LE_TPREL34:
+ out.Write64(uint64(elf.R_PPC64_TPREL34) | uint64(elfsym)<<32)
+ case objabi.R_POWER_TLS_IE_PCREL34:
+ out.Write64(uint64(elf.R_PPC64_GOT_TPREL_PCREL34) | uint64(elfsym)<<32)
case objabi.R_POWER_TLS_IE:
out.Write64(uint64(elf.R_PPC64_GOT_TPREL16_HA) | uint64(elfsym)<<32)
out.Write64(uint64(r.Xadd))
@@ -888,48 +896,41 @@ func archrelocaddr(ldr *loader.Loader, target *ld.Target, syms *ld.ArchSyms, r l
if target.IsAIX() {
ldr.Errorf(s, "archrelocaddr called for %s relocation\n", ldr.SymName(rs))
}
- var o1, o2 uint32
- if target.IsBigEndian() {
- o1 = uint32(val >> 32)
- o2 = uint32(val)
- } else {
- o1 = uint32(val)
- o2 = uint32(val >> 32)
- }
-
- // We are spreading a 31-bit address across two instructions, putting the
- // high (adjusted) part in the low 16 bits of the first instruction and the
- // low part in the low 16 bits of the second instruction, or, in the DS case,
- // bits 15-2 (inclusive) of the address into bits 15-2 of the second
- // instruction (it is an error in this case if the low 2 bits of the address
- // are non-zero).
+ o1, o2 := unpackInstPair(target, val)
+ // Verify resulting address fits within a 31 bit (2GB) address space.
+ // This is a restriction arising from the usage of lis (HA) + d-form
+ // (LO) instruction sequences used to implement absolute relocations
+ // on PPC64 prior to ISA 3.1 (P10). For consistency, maintain this
+ // restriction for ISA 3.1 unless it becomes problematic.
t := ldr.SymAddr(rs) + r.Add()
if t < 0 || t >= 1<<31 {
ldr.Errorf(s, "relocation for %s is too big (>=2G): 0x%x", ldr.SymName(s), ldr.SymValue(rs))
}
- if t&0x8000 != 0 {
- t += 0x10000
- }
switch r.Type() {
+ case objabi.R_ADDRPOWER_PCREL34:
+ // S + A - P
+ t -= (ldr.SymValue(s) + int64(r.Off()))
+ o1 |= computePrefix34HI(t)
+ o2 |= computeLO(int32(t))
+ case objabi.R_ADDRPOWER_D34:
+ o1 |= computePrefix34HI(t)
+ o2 |= computeLO(int32(t))
case objabi.R_ADDRPOWER:
- o1 |= (uint32(t) >> 16) & 0xffff
- o2 |= uint32(t) & 0xffff
+ o1 |= computeHA(int32(t))
+ o2 |= computeLO(int32(t))
case objabi.R_ADDRPOWER_DS:
- o1 |= (uint32(t) >> 16) & 0xffff
+ o1 |= computeHA(int32(t))
+ o2 |= computeLO(int32(t))
if t&3 != 0 {
ldr.Errorf(s, "bad DS reloc for %s: %d", ldr.SymName(s), ldr.SymValue(rs))
}
- o2 |= uint32(t) & 0xfffc
default:
return -1
}
- if target.IsBigEndian() {
- return int64(o1)<<32 | int64(o2)
- }
- return int64(o2)<<32 | int64(o1)
+ return packInstPair(target, o1, o2)
}
// Determine if the code was compiled so that the TOC register R2 is initialized and maintained
@@ -1084,6 +1085,61 @@ func gentramp(ctxt *ld.Link, ldr *loader.Loader, tramp *loader.SymbolBuilder, ta
tramp.SetData(P)
}
+// Unpack a pair of 32 bit instruction words from
+// a 64 bit relocation into instN and instN+1 in endian order.
+func unpackInstPair(target *ld.Target, r int64) (uint32, uint32) {
+ if target.IsBigEndian() {
+ return uint32(r >> 32), uint32(r)
+ }
+ return uint32(r), uint32(r >> 32)
+}
+
+// Pack a pair of 32 bit instruction words o1, o2 into 64 bit relocation
+// in endian order.
+func packInstPair(target *ld.Target, o1, o2 uint32) int64 {
+ if target.IsBigEndian() {
+ return (int64(o1) << 32) | int64(o2)
+ }
+ return int64(o1) | (int64(o2) << 32)
+}
+
+// Compute the high-adjusted value (always a signed 32b value) per the ELF ABI.
+// The returned value is always 0 <= x <= 0xFFFF.
+func computeHA(val int32) uint32 {
+ return uint32(uint16((val + 0x8000) >> 16))
+}
+
+// Compute the low value (the lower 16 bits of any 32b value) per the ELF ABI.
+// The returned value is always 0 <= x <= 0xFFFF.
+func computeLO(val int32) uint32 {
+ return uint32(uint16(val))
+}
+
+// Compute the high 18 bits of a signed 34b constant. Used to pack the high 18 bits
+// of a prefix34 relocation field. This assumes the input is already restricted to
+// 34 bits.
+func computePrefix34HI(val int64) uint32 {
+ return uint32((val >> 16) & 0x3FFFF)
+}
+
+func computeTLSLEReloc(target *ld.Target, ldr *loader.Loader, rs, s loader.Sym) int64 {
+ // The thread pointer points 0x7000 bytes after the start of the
+ // thread local storage area as documented in section "3.7.2 TLS
+ // Runtime Handling" of "Power Architecture 64-Bit ELF V2 ABI
+ // Specification".
+ v := ldr.SymValue(rs) - 0x7000
+ if target.IsAIX() {
+ // On AIX, the thread pointer points 0x7800 bytes after
+ // the TLS.
+ v -= 0x800
+ }
+
+ if int64(int32(v)) != v {
+ ldr.Errorf(s, "TLS offset out of range %d", v)
+ }
+ return v
+}
+
func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loader.Reloc, s loader.Sym, val int64) (relocatedOffset int64, nExtReloc int, ok bool) {
rs := r.Sym()
if target.IsExternal() {
@@ -1094,7 +1150,7 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade
if !target.IsAIX() {
return val, nExtReloc, false
}
- case objabi.R_POWER_TLS:
+ case objabi.R_POWER_TLS, objabi.R_POWER_TLS_IE_PCREL34, objabi.R_POWER_TLS_LE_TPREL34:
nExtReloc = 1
return val, nExtReloc, true
case objabi.R_POWER_TLS_LE, objabi.R_POWER_TLS_IE:
@@ -1125,7 +1181,7 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade
if !target.IsAIX() {
return val, nExtReloc, true
}
- case objabi.R_CALLPOWER:
+ case objabi.R_CALLPOWER, objabi.R_ADDRPOWER_D34, objabi.R_ADDRPOWER_PCREL34:
nExtReloc = 1
if !target.IsAIX() {
return val, nExtReloc, true
@@ -1136,7 +1192,7 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade
switch r.Type() {
case objabi.R_ADDRPOWER_TOCREL, objabi.R_ADDRPOWER_TOCREL_DS:
return archreloctoc(ldr, target, syms, r, s, val), nExtReloc, true
- case objabi.R_ADDRPOWER, objabi.R_ADDRPOWER_DS:
+ case objabi.R_ADDRPOWER, objabi.R_ADDRPOWER_DS, objabi.R_ADDRPOWER_D34, objabi.R_ADDRPOWER_PCREL34:
return archrelocaddr(ldr, target, syms, r, s, val), nExtReloc, true
case objabi.R_CALLPOWER:
// Bits 6 through 29 = (S + A - P) >> 2
@@ -1169,16 +1225,10 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade
case objabi.R_ADDRPOWER_PCREL: // S + A - P
t := ldr.SymValue(rs) + r.Add() - (ldr.SymValue(s) + int64(r.Off()))
- ha := uint16(((t + 0x8000) >> 16) & 0xFFFF)
- l := uint16(t)
- if target.IsBigEndian() {
- val |= int64(l)
- val |= int64(ha) << 32
- } else {
- val |= int64(ha)
- val |= int64(l) << 32
- }
- return val, nExtReloc, true
+ ha, l := unpackInstPair(target, val)
+ l |= computeLO(int32(t))
+ ha |= computeHA(int32(t))
+ return packInstPair(target, ha, l), nExtReloc, true
case objabi.R_POWER_TLS:
const OP_ADD = 31<<26 | 266<<1
@@ -1210,50 +1260,48 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade
const OP_ADDI = 14 << 26
const OP_MASK = 0x3F << 26
const OP_RA_MASK = 0x1F << 16
- uval := uint64(val)
// convert r2 to r0, and ld to addi
- if target.IsBigEndian() {
- uval = uval &^ (OP_RA_MASK << 32)
- uval = (uval &^ OP_MASK) | OP_ADDI
- } else {
- uval = uval &^ (OP_RA_MASK)
- uval = (uval &^ (OP_MASK << 32)) | (OP_ADDI << 32)
- }
- val = int64(uval)
- // Treat this like an R_POWER_TLS_LE relocation now.
+ mask := packInstPair(target, OP_RA_MASK, OP_MASK)
+ addi_op := packInstPair(target, 0, OP_ADDI)
+ val &^= mask
+ val |= addi_op
fallthrough
case objabi.R_POWER_TLS_LE:
- // The thread pointer points 0x7000 bytes after the start of the
- // thread local storage area as documented in section "3.7.2 TLS
- // Runtime Handling" of "Power Architecture 64-Bit ELF V2 ABI
- // Specification".
- v := ldr.SymValue(rs) - 0x7000
- if target.IsAIX() {
- // On AIX, the thread pointer points 0x7800 bytes after
- // the TLS.
- v -= 0x800
- }
+ v := computeTLSLEReloc(target, ldr, rs, s)
+ o1, o2 := unpackInstPair(target, val)
+ o1 |= computeHA(int32(v))
+ o2 |= computeLO(int32(v))
+ return packInstPair(target, o1, o2), nExtReloc, true
- var o1, o2 uint32
- if int64(int32(v)) != v {
- ldr.Errorf(s, "TLS offset out of range %d", v)
- }
- if target.IsBigEndian() {
- o1 = uint32(val >> 32)
- o2 = uint32(val)
- } else {
- o1 = uint32(val)
- o2 = uint32(val >> 32)
+ case objabi.R_POWER_TLS_IE_PCREL34:
+ // Convert TLS_IE relocation to TLS_LE if supported.
+ if !(target.IsPIE() && target.IsElf()) {
+ log.Fatalf("cannot handle R_POWER_TLS_IE (sym %s) when linking non-PIE, non-ELF binaries internally", ldr.SymName(s))
}
- o1 |= uint32(((v + 0x8000) >> 16) & 0xFFFF)
- o2 |= uint32(v & 0xFFFF)
+ // We are an ELF binary, we can safely convert to TLS_LE_TPREL34 from:
+ // pld rX, x@got@tprel@pcrel
+ //
+ // to TLS_LE_TPREL32 by converting to:
+ // pla rX, x@tprel
- if target.IsBigEndian() {
- return int64(o1)<<32 | int64(o2), nExtReloc, true
- }
- return int64(o2)<<32 | int64(o1), nExtReloc, true
+ const OP_MASK_PFX = 0xFFFFFFFF // Discard prefix word
+ const OP_MASK = (0x3F << 26) | 0xFFFF // Preserve RT, RA
+ const OP_PFX = 1<<26 | 2<<24
+ const OP_PLA = 14 << 26
+ mask := packInstPair(target, OP_MASK_PFX, OP_MASK)
+ pla_op := packInstPair(target, OP_PFX, OP_PLA)
+ val &^= mask
+ val |= pla_op
+ fallthrough
+
+ case objabi.R_POWER_TLS_LE_TPREL34:
+ v := computeTLSLEReloc(target, ldr, rs, s)
+ o1, o2 := unpackInstPair(target, val)
+ o1 |= computePrefix34HI(v)
+ o2 |= computeLO(int32(v))
+ return packInstPair(target, o1, o2), nExtReloc, true
}
return val, nExtReloc, false
@@ -1354,14 +1402,16 @@ overflow:
func extreloc(target *ld.Target, ldr *loader.Loader, r loader.Reloc, s loader.Sym) (loader.ExtReloc, bool) {
switch r.Type() {
- case objabi.R_POWER_TLS, objabi.R_POWER_TLS_LE, objabi.R_POWER_TLS_IE, objabi.R_CALLPOWER:
+ case objabi.R_POWER_TLS, objabi.R_POWER_TLS_LE, objabi.R_POWER_TLS_IE, objabi.R_POWER_TLS_IE_PCREL34, objabi.R_POWER_TLS_LE_TPREL34, objabi.R_CALLPOWER:
return ld.ExtrelocSimple(ldr, r), true
case objabi.R_ADDRPOWER,
objabi.R_ADDRPOWER_DS,
objabi.R_ADDRPOWER_TOCREL,
objabi.R_ADDRPOWER_TOCREL_DS,
objabi.R_ADDRPOWER_GOT,
- objabi.R_ADDRPOWER_PCREL:
+ objabi.R_ADDRPOWER_PCREL,
+ objabi.R_ADDRPOWER_D34,
+ objabi.R_ADDRPOWER_PCREL34:
return ld.ExtrelocViaOuterSym(ldr, r, s), true
}
return loader.ExtReloc{}, false