]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/internal/obj/mips, cmd/link: add support TLS relocation for mips64x
authorCherry Zhang <lunaria21@gmail.com>
Thu, 28 Apr 2016 02:18:14 +0000 (22:18 -0400)
committerMinux Ma <minux@golang.org>
Sun, 1 May 2016 03:36:19 +0000 (03:36 +0000)
a new relocation R_ADDRMIPSTLS is added, which resolves to 16-bit offset
of a TLS address on mips64x.

Change-Id: Ic60d0e1ba49ff1c433cead242f5884677ab227a5
Reviewed-on: https://go-review.googlesource.com/19804
Reviewed-by: Minux Ma <minux@golang.org>
src/cmd/internal/obj/link.go
src/cmd/internal/obj/mips/a.out.go
src/cmd/internal/obj/mips/anames0.go
src/cmd/internal/obj/mips/asm0.go
src/cmd/link/internal/mips64/asm.go

index 78b96bb4a55c590e10f5af08c454e219995c9d74..a97565e46f1f5b59513ce70080549bbe1df803e5 100644 (file)
@@ -585,6 +585,9 @@ const (
        // R_ADDRMIPSU (only used on mips64) resolves to the sign-adjusted "upper" 16
        // bits (bit 16-31) of an external address, by encoding it into the instruction.
        R_ADDRMIPSU
+       // R_ADDRMIPSTLS (only used on mips64) resolves to the low 16 bits of a TLS
+       // address (offset from thread pointer), by encoding it into the instruction.
+       R_ADDRMIPSTLS
 )
 
 type Auto struct {
index 44add12e86450c3a1fa38ee9564cec46326d433a..57643f920a13425d0dbcf42e6bee6d61396ace5c 100644 (file)
@@ -243,6 +243,7 @@ const (
        C_LACON /* $n(REG) where int16 < n <= int32 */
        C_LECON
        C_DACON /* $n(REG) where int32 < n */
+       C_STCON /* $tlsvar */
        C_SBRA
        C_LBRA
        C_SAUTO
@@ -254,6 +255,7 @@ const (
        C_LOREG
        C_GOK
        C_ADDR
+       C_TLS
        C_TEXTSIZE
 
        C_NCLASS /* must be the last */
index 0fc9b69d842d3e038e2eb3574f07fe7b769f6151..c56d34eaf533a10ff6aa4e01f4c53f1c621424b1 100644 (file)
@@ -26,6 +26,7 @@ var cnames0 = []string{
        "LACON",
        "LECON",
        "DACON",
+       "STCON",
        "SBRA",
        "LBRA",
        "SAUTO",
@@ -37,6 +38,7 @@ var cnames0 = []string{
        "LOREG",
        "GOK",
        "ADDR",
+       "TLS",
        "TEXTSIZE",
        "NCLASS",
 }
index 8643b9874f1b200fef70f2548bcf4d19b9c07868..4a5ff2f3d42e65700feca4024ad3d6501a7dc604 100644 (file)
@@ -141,6 +141,11 @@ var optab = []Optab{
        {AMOVV, C_REG, C_NONE, C_ADDR, 50, 12, 0},
        {AMOVB, C_REG, C_NONE, C_ADDR, 50, 12, 0},
        {AMOVBU, C_REG, C_NONE, C_ADDR, 50, 12, 0},
+       {AMOVW, C_REG, C_NONE, C_TLS, 53, 8, 0},
+       {AMOVWU, C_REG, C_NONE, C_TLS, 53, 8, 0},
+       {AMOVV, C_REG, C_NONE, C_TLS, 53, 8, 0},
+       {AMOVB, C_REG, C_NONE, C_TLS, 53, 8, 0},
+       {AMOVBU, C_REG, C_NONE, C_TLS, 53, 8, 0},
 
        {AMOVW, C_LEXT, C_NONE, C_REG, 36, 12, REGSB},
        {AMOVWU, C_LEXT, C_NONE, C_REG, 36, 12, REGSB},
@@ -162,6 +167,11 @@ var optab = []Optab{
        {AMOVV, C_ADDR, C_NONE, C_REG, 51, 12, 0},
        {AMOVB, C_ADDR, C_NONE, C_REG, 51, 12, 0},
        {AMOVBU, C_ADDR, C_NONE, C_REG, 51, 12, 0},
+       {AMOVW, C_TLS, C_NONE, C_REG, 54, 8, 0},
+       {AMOVWU, C_TLS, C_NONE, C_REG, 54, 8, 0},
+       {AMOVV, C_TLS, C_NONE, C_REG, 54, 8, 0},
+       {AMOVB, C_TLS, C_NONE, C_REG, 54, 8, 0},
+       {AMOVBU, C_TLS, C_NONE, C_REG, 54, 8, 0},
 
        {AMOVW, C_SECON, C_NONE, C_REG, 3, 4, REGSB},
        {AMOVV, C_SECON, C_NONE, C_REG, 3, 4, REGSB},
@@ -175,6 +185,8 @@ var optab = []Optab{
        {AMOVV, C_ADDCON, C_NONE, C_REG, 3, 4, REGZERO},
        {AMOVW, C_ANDCON, C_NONE, C_REG, 3, 4, REGZERO},
        {AMOVV, C_ANDCON, C_NONE, C_REG, 3, 4, REGZERO},
+       {AMOVW, C_STCON, C_NONE, C_REG, 55, 8, 0},
+       {AMOVV, C_STCON, C_NONE, C_REG, 55, 8, 0},
 
        {AMOVW, C_UCON, C_NONE, C_REG, 24, 4, 0},
        {AMOVV, C_UCON, C_NONE, C_REG, 24, 4, 0},
@@ -476,6 +488,9 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int {
                        }
                        ctxt.Instoffset = a.Offset
                        if a.Sym != nil { // use relocation
+                               if a.Sym.Type == obj.STLSBSS {
+                                       return C_TLS
+                               }
                                return C_ADDR
                        }
                        return C_LEXT
@@ -539,6 +554,9 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int {
                        }
 
                        ctxt.Instoffset = a.Offset
+                       if s.Type == obj.STLSBSS {
+                               return C_STCON // address of TLS variable
+                       }
                        return C_LECON
 
                case obj.NAME_AUTO:
@@ -1387,6 +1405,40 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
                rel2.Sym = p.From.Sym
                rel2.Add = p.From.Offset
                rel2.Type = obj.R_ADDRMIPS
+
+       case 53: /* mov r, tlsvar ==> rdhwr + sw o(r3) */
+               // clobbers R3 !
+               // load thread pointer with RDHWR, R3 is used for fast kernel emulation on Linux
+               o1 = (037<<26 + 073) | (29 << 11) | (3 << 16) // rdhwr $29, r3
+               o2 = OP_IRR(opirr(ctxt, p.As), uint32(0), uint32(REG_R3), uint32(p.From.Reg))
+               rel := obj.Addrel(ctxt.Cursym)
+               rel.Off = int32(ctxt.Pc + 4)
+               rel.Siz = 4
+               rel.Sym = p.To.Sym
+               rel.Add = p.To.Offset
+               rel.Type = obj.R_ADDRMIPSTLS
+
+       case 54: /* mov tlsvar, r ==> rdhwr + lw o(r3) */
+               // clobbers R3 !
+               o1 = (037<<26 + 073) | (29 << 11) | (3 << 16) // rdhwr $29, r3
+               o2 = OP_IRR(opirr(ctxt, -p.As), uint32(0), uint32(REG_R3), uint32(p.To.Reg))
+               rel := obj.Addrel(ctxt.Cursym)
+               rel.Off = int32(ctxt.Pc + 4)
+               rel.Siz = 4
+               rel.Sym = p.From.Sym
+               rel.Add = p.From.Offset
+               rel.Type = obj.R_ADDRMIPSTLS
+
+       case 55: /* mov $tlsvar, r ==> rdhwr + add */
+               // clobbers R3 !
+               o1 = (037<<26 + 073) | (29 << 11) | (3 << 16) // rdhwr $29, r3
+               o2 = OP_IRR(opirr(ctxt, AADDVU), uint32(0), uint32(REG_R3), uint32(p.To.Reg))
+               rel := obj.Addrel(ctxt.Cursym)
+               rel.Off = int32(ctxt.Pc + 4)
+               rel.Siz = 4
+               rel.Sym = p.From.Sym
+               rel.Add = p.From.Offset
+               rel.Type = obj.R_ADDRMIPSTLS
        }
 
        out[0] = o1
index 742ea8a7274978215dd6dc15360d3bd54973c23e..68d52ec954ff4cb459c926e90f2fbf4cf2d4c4a0 100644 (file)
@@ -81,6 +81,9 @@ func elfreloc1(r *ld.Reloc, sectoff int64) int {
        case obj.R_ADDRMIPSU:
                ld.Cput(ld.R_MIPS_HI16)
 
+       case obj.R_ADDRMIPSTLS:
+               ld.Cput(ld.R_MIPS_TLS_TPREL_LO16)
+
        case obj.R_CALLMIPS,
                obj.R_JMPMIPS:
                ld.Cput(ld.R_MIPS_26)
@@ -123,7 +126,8 @@ func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int {
 
                        return 0
 
-               case obj.R_CALLMIPS,
+               case obj.R_ADDRMIPSTLS,
+                       obj.R_CALLMIPS,
                        obj.R_JMPMIPS:
                        r.Done = 0
                        r.Xsym = r.Sym
@@ -152,6 +156,16 @@ func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int {
                }
                return 0
 
+       case obj.R_ADDRMIPSTLS:
+               // thread pointer is at 0x7000 offset from the start of TLS data area
+               t := ld.Symaddr(r.Sym) + r.Add - 0x7000
+               if t < -32768 || t >= 32678 {
+                       ld.Diag("TLS offset out of range %d", t)
+               }
+               o1 := ld.SysArch.ByteOrder.Uint32(s.P[r.Off:])
+               *val = int64(o1&0xffff0000 | uint32(t)&0xffff)
+               return 0
+
        case obj.R_CALLMIPS,
                obj.R_JMPMIPS:
                // Low 26 bits = (S + A) >> 2