+2019-11-12 Alan Modra <amodra@gmail.com>
+
+ * config/rs6000/predicates.md (unspec_tls): Allow const0_rtx for got
+ element of unspec vec.
+ * config/rs6000/rs6000.c (rs6000_legitimize_tls_address): Support
+ PC-relative TLS.
+ * config/rs6000/rs6000.md (UNSPEC_TLSTLS_PCREL): New unspec.
+ (tls_gd_pcrel, tls_ld_pcrel): New insns.
+ (tls_dtprel, tls_tprel): Set attr prefixed when tls_size is not 16.
+ (tls_got_tprel_pcrel, tls_tls_pcrel): New insns.
+
2019-11-12 Alan Modra <amodra@gmail.com>
* config/rs6000/rs6000.opt (mtls-markers): Delete.
return rs6000_legitimize_tls_address_aix (addr, model);
dest = gen_reg_rtx (Pmode);
- if (model == TLS_MODEL_LOCAL_EXEC && rs6000_tls_size == 16)
+ if (model == TLS_MODEL_LOCAL_EXEC
+ && (rs6000_tls_size == 16 || rs6000_pcrel_p (cfun)))
{
rtx tlsreg;
them in the .got section. So use a pointer to the .got section,
not one to secondary TOC sections used by 64-bit -mminimal-toc,
or to secondary GOT sections used by 32-bit -fPIC. */
- if (TARGET_64BIT)
+ if (rs6000_pcrel_p (cfun))
+ got = const0_rtx;
+ else if (TARGET_64BIT)
got = gen_rtx_REG (Pmode, 2);
else
{
rtx uns = gen_rtx_UNSPEC (Pmode, vec, UNSPEC_TLS_GET_ADDR);
set_unique_reg_note (get_last_insn (), REG_EQUAL, uns);
- if (rs6000_tls_size == 16)
+ if (rs6000_tls_size == 16 || rs6000_pcrel_p (cfun))
{
if (TARGET_64BIT)
insn = gen_tls_dtprel_64 (dest, tmp1, addr);
else
insn = gen_tls_got_tprel_32 (tmp2, got, addr);
emit_insn (insn);
- if (TARGET_64BIT)
+ if (rs6000_pcrel_p (cfun))
+ {
+ if (TARGET_64BIT)
+ insn = gen_tls_tls_pcrel_64 (dest, tmp2, addr);
+ else
+ insn = gen_tls_tls_pcrel_32 (dest, tmp2, addr);
+ }
+ else if (TARGET_64BIT)
insn = gen_tls_tls_64 (dest, tmp2, addr);
else
insn = gen_tls_tls_32 (dest, tmp2, addr);
UNSPEC_TLSTPRELLO
UNSPEC_TLSGOTTPREL
UNSPEC_TLSTLS
+ UNSPEC_TLSTLS_PCREL
UNSPEC_FIX_TRUNC_TF ; fadd, rounding towards zero
UNSPEC_STFIWX
UNSPEC_POPCNTB
\f
;; TLS support.
+(define_insn "*tls_gd_pcrel<bits>"
+ [(set (match_operand:P 0 "gpc_reg_operand" "=b")
+ (unspec:P [(match_operand:P 1 "rs6000_tls_symbol_ref" "")
+ (const_int 0)]
+ UNSPEC_TLSGD))]
+ "HAVE_AS_TLS && TARGET_ELF"
+ "la %0,%1@got@tlsgd@pcrel"
+ [(set_attr "prefixed" "yes")])
+
(define_insn_and_split "*tls_gd<bits>"
[(set (match_operand:P 0 "gpc_reg_operand" "=b")
(unspec:P [(match_operand:P 1 "rs6000_tls_symbol_ref" "")
"HAVE_AS_TLS && TARGET_ELF && TARGET_CMODEL != CMODEL_SMALL"
"addi %0,%1,%2@got@tlsgd@l")
+(define_insn "*tls_ld_pcrel<bits>"
+ [(set (match_operand:P 0 "gpc_reg_operand" "=b")
+ (unspec:P [(const_int 0)]
+ UNSPEC_TLSLD))]
+ "HAVE_AS_TLS && TARGET_ELF"
+ "la %0,%&@got@tlsld@pcrel"
+ [(set_attr "prefixed" "yes")])
+
(define_insn_and_split "*tls_ld<bits>"
[(set (match_operand:P 0 "gpc_reg_operand" "=b")
(unspec:P [(match_operand:P 1 "gpc_reg_operand" "b")]
(match_operand:P 2 "rs6000_tls_symbol_ref" "")]
UNSPEC_TLSDTPREL))]
"HAVE_AS_TLS"
- "addi %0,%1,%2@dtprel")
+ "addi %0,%1,%2@dtprel"
+ [(set (attr "prefixed")
+ (if_then_else (match_test "rs6000_tls_size == 16")
+ (const_string "no")
+ (const_string "yes")))])
(define_insn "tls_dtprel_ha_<bits>"
[(set (match_operand:P 0 "gpc_reg_operand" "=r")
(match_operand:P 2 "rs6000_tls_symbol_ref" "")]
UNSPEC_TLSTPREL))]
"HAVE_AS_TLS"
- "addi %0,%1,%2@tprel")
+ "addi %0,%1,%2@tprel"
+ [(set (attr "prefixed")
+ (if_then_else (match_test "rs6000_tls_size == 16")
+ (const_string "no")
+ (const_string "yes")))])
(define_insn "tls_tprel_ha_<bits>"
[(set (match_operand:P 0 "gpc_reg_operand" "=r")
"HAVE_AS_TLS"
"addi %0,%1,%2@tprel@l")
+(define_insn "*tls_got_tprel_pcrel_<bits>"
+ [(set (match_operand:P 0 "gpc_reg_operand" "=b")
+ (unspec:P [(const_int 0)
+ (match_operand:P 1 "rs6000_tls_symbol_ref" "")]
+ UNSPEC_TLSGOTTPREL))]
+ "HAVE_AS_TLS"
+ "<ptrload> %0,%1@got@tprel@pcrel"
+ [(set_attr "prefixed" "yes")])
+
;; "b" output constraint here and on tls_tls input to support linker tls
;; optimization. The linker may edit the instructions emitted by a
;; tls_got_tprel/tls_tls pair to addis,addi.
"HAVE_AS_TLS && TARGET_CMODEL != CMODEL_SMALL"
"<ptrload> %0,%2@got@tprel@l(%1)")
+(define_insn "tls_tls_pcrel_<bits>"
+ [(set (match_operand:P 0 "gpc_reg_operand" "=r")
+ (unspec:P [(match_operand:P 1 "gpc_reg_operand" "b")
+ (match_operand:P 2 "rs6000_tls_symbol_ref" "")]
+ UNSPEC_TLSTLS_PCREL))]
+ "TARGET_ELF && HAVE_AS_TLS"
+ "add %0,%1,%2@tls@pcrel")
+
(define_insn "tls_tls_<bits>"
[(set (match_operand:P 0 "gpc_reg_operand" "=r")
(unspec:P [(match_operand:P 1 "gpc_reg_operand" "b")