// inserts the displacement from the place being relocated to the address of the
// the relocated symbol instead of just its address.
R_ADDRPOWER_PCREL
+
+ // R_ADDRPOWER_TOCREL relocates two D-form instructions like R_ADDRPOWER, but
+ // inserts the offset from the TOC to the address of the the relocated symbol
+ // rather than the symbol's address.
+ R_ADDRPOWER_TOCREL
+
+ // R_ADDRPOWER_TOCREL relocates a D-form, DS-form instruction sequence like
+ // R_ADDRPOWER_DS but inserts the offset from the TOC to the address of the the
+ // relocated symbol rather than the symbol's address.
+ R_ADDRPOWER_TOCREL_DS
)
type Auto struct {
// Encode instructions and create relocation for accessing s+d according to the
// instruction op with source or destination (as appropriate) register reg.
func symbolAccess(ctxt *obj.Link, s *obj.LSym, d int64, reg int16, op int32) (o1, o2 uint32) {
+ var base uint32
form := opform(ctxt, op)
- o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, 0)
+ if ctxt.Flag_shared != 0 {
+ base = REG_R2
+ } else {
+ base = REG_R0
+ }
+ o1 = AOP_IRR(OP_ADDIS, REGTMP, base, 0)
o2 = AOP_IRR(uint32(op), uint32(reg), REGTMP, 0)
rel := obj.Addrel(ctxt.Cursym)
rel.Off = int32(ctxt.Pc)
rel.Siz = 8
rel.Sym = s
rel.Add = d
- switch form {
- case D_FORM:
- rel.Type = obj.R_ADDRPOWER
- case DS_FORM:
- rel.Type = obj.R_ADDRPOWER_DS
+ if ctxt.Flag_shared != 0 {
+ switch form {
+ case D_FORM:
+ rel.Type = obj.R_ADDRPOWER_TOCREL
+ case DS_FORM:
+ rel.Type = obj.R_ADDRPOWER_TOCREL_DS
+ }
+
+ } else {
+ switch form {
+ case D_FORM:
+ rel.Type = obj.R_ADDRPOWER
+ case DS_FORM:
+ rel.Type = obj.R_ADDRPOWER_DS
+ }
}
return
}
ld.Thearch.Vput(ld.R_PPC64_REL16_LO | uint64(elfsym)<<32)
r.Xadd += 4
+ case obj.R_ADDRPOWER_TOCREL:
+ ld.Thearch.Vput(ld.R_PPC64_TOC16_HA | uint64(elfsym)<<32)
+ ld.Thearch.Vput(uint64(r.Xadd))
+ ld.Thearch.Vput(uint64(sectoff + 4))
+ ld.Thearch.Vput(ld.R_PPC64_TOC16_LO | uint64(elfsym)<<32)
+
+ case obj.R_ADDRPOWER_TOCREL_DS:
+ ld.Thearch.Vput(ld.R_PPC64_TOC16_HA | uint64(elfsym)<<32)
+ ld.Thearch.Vput(uint64(r.Xadd))
+ ld.Thearch.Vput(uint64(sectoff + 4))
+ ld.Thearch.Vput(ld.R_PPC64_TOC16_LO_DS | uint64(elfsym)<<32)
+
case obj.R_CALLPOWER:
if r.Siz != 4 {
return -1
case obj.R_ADDRPOWER,
obj.R_ADDRPOWER_DS,
+ obj.R_ADDRPOWER_TOCREL,
+ obj.R_ADDRPOWER_TOCREL_DS,
obj.R_ADDRPOWER_PCREL:
r.Done = 0