powerpc64: Implement TLS using PC-relative addressing

Message ID 20200930195512.724059-1-tuliom@linux.ibm.com
State Superseded
Delegated to: Andreas Schwab
Headers
Series powerpc64: Implement TLS using PC-relative addressing |

Commit Message

Tulio Magno Quites Machado Filho Sept. 30, 2020, 7:55 p.m. UTC
  As the TOC pointer becomes optional on POWER, TLS access has to be
modified in order to use PC-relative addressing instead of depending on
the TOC pointer availability.

This patch also changes old TLS code to use the new syntax.  It's a
purely aesthetical change: the old code still works and the new syntax
helps to move the argument setup instruction away from the call, which
is not used in an inline assembly.

Suggested-by: Alan Modra <amodra@gmail.com>
---
 sysdeps/powerpc/mod-tlsopt-powerpc.c   |  7 ++++
 sysdeps/powerpc/powerpc64/tls-macros.h | 54 ++++++++++++++++++++++----
 2 files changed, 53 insertions(+), 8 deletions(-)
  

Comments

Florian Weimer Oct. 1, 2020, 8:49 a.m. UTC | #1
* Tulio Magno Quites Machado Filho via Libc-alpha:

> diff --git a/sysdeps/powerpc/mod-tlsopt-powerpc.c b/sysdeps/powerpc/mod-tlsopt-powerpc.c
> index ee0db12a73..5856dab60b 100644
> --- a/sysdeps/powerpc/mod-tlsopt-powerpc.c
> +++ b/sysdeps/powerpc/mod-tlsopt-powerpc.c
> @@ -24,7 +24,14 @@ tls_get_addr_opt_test (void)
>    tls_index *tls_arg;
>  #ifdef __powerpc64__
>    register unsigned long thread_pointer __asm__ ("r13");
> +  /* PC-relative addressing is available when compiling with -mpcrel.
> +     The first releases of GCC 10 do support -mpcrel, but do not export
> +     __PCREL__.  */
> +# if defined(__PCREL__) || __GNUC__ <= 10 && defined(_ARCH_PWR10)
> +  asm ("pla %0,foo@got@tlsgd@pcrel" : "=r" (tls_arg));
> +# else
>    asm ("addi %0,2,foo@got@tlsgd" : "=r" (tls_arg));
> +# endif

Should this check for binutils support for @pcrel?  Or won't GCC enable
_ARCH_PWR10 in this case?

Thanks,
Florian
  
Andreas Schwab Oct. 1, 2020, 9:01 a.m. UTC | #2
On Sep 30 2020, Tulio Magno Quites Machado Filho via Libc-alpha wrote:

> diff --git a/sysdeps/powerpc/mod-tlsopt-powerpc.c b/sysdeps/powerpc/mod-tlsopt-powerpc.c
> index ee0db12a73..5856dab60b 100644
> --- a/sysdeps/powerpc/mod-tlsopt-powerpc.c
> +++ b/sysdeps/powerpc/mod-tlsopt-powerpc.c
> @@ -24,7 +24,14 @@ tls_get_addr_opt_test (void)
>    tls_index *tls_arg;
>  #ifdef __powerpc64__
>    register unsigned long thread_pointer __asm__ ("r13");
> +  /* PC-relative addressing is available when compiling with -mpcrel.
> +     The first releases of GCC 10 do support -mpcrel, but do not export
> +     __PCREL__.  */
> +# if defined(__PCREL__) || __GNUC__ <= 10 && defined(_ARCH_PWR10)

Space after defined, and remove the parens.

Andreas.
  
Alan Modra Oct. 1, 2020, 11:15 a.m. UTC | #3
On Thu, Oct 01, 2020 at 10:49:43AM +0200, Florian Weimer wrote:
> * Tulio Magno Quites Machado Filho via Libc-alpha:
> 
> > diff --git a/sysdeps/powerpc/mod-tlsopt-powerpc.c b/sysdeps/powerpc/mod-tlsopt-powerpc.c
> > index ee0db12a73..5856dab60b 100644
> > --- a/sysdeps/powerpc/mod-tlsopt-powerpc.c
> > +++ b/sysdeps/powerpc/mod-tlsopt-powerpc.c
> > @@ -24,7 +24,14 @@ tls_get_addr_opt_test (void)
> >    tls_index *tls_arg;
> >  #ifdef __powerpc64__
> >    register unsigned long thread_pointer __asm__ ("r13");
> > +  /* PC-relative addressing is available when compiling with -mpcrel.
> > +     The first releases of GCC 10 do support -mpcrel, but do not export
> > +     __PCREL__.  */
> > +# if defined(__PCREL__) || __GNUC__ <= 10 && defined(_ARCH_PWR10)
> > +  asm ("pla %0,foo@got@tlsgd@pcrel" : "=r" (tls_arg));
> > +# else
> >    asm ("addi %0,2,foo@got@tlsgd" : "=r" (tls_arg));
> > +# endif
> 
> Should this check for binutils support for @pcrel?  Or won't GCC enable
> _ARCH_PWR10 in this case?

Right, gcc doesn't support power10 without the requisite binutils
support.  In any case, this file is only used when running the
testsuite so it hardly seems worth the bother of configure checks.
The patch looks good to me.
  

Patch

diff --git a/sysdeps/powerpc/mod-tlsopt-powerpc.c b/sysdeps/powerpc/mod-tlsopt-powerpc.c
index ee0db12a73..5856dab60b 100644
--- a/sysdeps/powerpc/mod-tlsopt-powerpc.c
+++ b/sysdeps/powerpc/mod-tlsopt-powerpc.c
@@ -24,7 +24,14 @@  tls_get_addr_opt_test (void)
   tls_index *tls_arg;
 #ifdef __powerpc64__
   register unsigned long thread_pointer __asm__ ("r13");
+  /* PC-relative addressing is available when compiling with -mpcrel.
+     The first releases of GCC 10 do support -mpcrel, but do not export
+     __PCREL__.  */
+# if defined(__PCREL__) || __GNUC__ <= 10 && defined(_ARCH_PWR10)
+  asm ("pla %0,foo@got@tlsgd@pcrel" : "=r" (tls_arg));
+# else
   asm ("addi %0,2,foo@got@tlsgd" : "=r" (tls_arg));
+# endif
 #else
   register unsigned long thread_pointer __asm__ ("r2");
   asm ("bcl 20,31,1f\n1:\t"
diff --git a/sysdeps/powerpc/powerpc64/tls-macros.h b/sysdeps/powerpc/powerpc64/tls-macros.h
index 79a0b2579c..955f8e88da 100644
--- a/sysdeps/powerpc/powerpc64/tls-macros.h
+++ b/sysdeps/powerpc/powerpc64/tls-macros.h
@@ -9,20 +9,56 @@ 
 	  : "=b" (__result) );						      \
      __result;								      \
   })
-/* PowerPC64 Initial Exec TLS access.  */
-#define TLS_IE(x)							      \
+
+/* PC-relative addressing is available when compiling with -mpcrel.
+   The first releases of GCC 10 do support -mpcrel, but do not export
+   __PCREL__.  */
+#if defined(__PCREL__) || __GNUC__ <= 10 && defined(_ARCH_PWR10)
+/* PowerPC64 Initial Exec TLS access, PC-relative addressing.  */
+# define TLS_IE(x)							      \
   ({ int * __result;							      \
-     asm ("ld  %0," #x "@got@tprel(2)\n\t"				      \
-	  "add %0,%0," #x "@tls"					      \
+     asm ("pld  %0," #x "@got@tprel@pcrel\n\t"				      \
+	  "add %0,%0," #x "@tls@pcrel"					      \
 	  : "=r" (__result) );						      \
      __result;								      \
   })
 
+/* PowerPC64 Local Dynamic TLS access, PC-relative addressing.  */
+# define TLS_LD(x)							      \
+  ({ int * __result;							      \
+     asm ("pla   3, " #x "@got@tlsld@pcrel\n\t"				      \
+	  "bl    __tls_get_addr@notoc(" #x "@tlsld)\n\t"		      \
+	  "addis %0,3," #x "@dtprel@ha\n\t"				      \
+	  "addi  %0,%0," #x "@dtprel@l"					      \
+	  : "=b" (__result) :						      \
+	  : "3", __TLS_CALL_CLOBBERS);					      \
+     __result;								      \
+  })
+
+/* PowerPC64 General Dynamic TLS access, PC-relative addressing.  */
+# define TLS_GD(x)							      \
+  ({ register int *__result __asm__ ("r3");				      \
+    asm ("pla   3," #x "@got@tlsgd@pcrel\n\t"				      \
+	 "bl    __tls_get_addr@notoc(" #x "@tlsgd)"			      \
+	 : "=r" (__result) :						      \
+	 : __TLS_CALL_CLOBBERS);					      \
+    __result;								      \
+  })
+#else
+/* PowerPC64 Initial Exec TLS access.  */
+# define TLS_IE(x)							      \
+  ({ int * __result;							      \
+    asm ("ld  %0," #x "@got@tprel(2)\n\t"				      \
+	 "add %0,%0," #x "@tls"						      \
+	 : "=r" (__result) );						      \
+    __result;								      \
+  })
+
 /* PowerPC64 Local Dynamic TLS access.  */
-#define TLS_LD(x)							      \
+# define TLS_LD(x)							      \
   ({ int * __result;							      \
      asm ("addi  3,2," #x "@got@tlsld\n\t"				      \
-	  "bl    __tls_get_addr\n\t"					      \
+	  "bl    __tls_get_addr(" #x "@tlsld)\n\t"			      \
 	  "nop   \n\t"							      \
 	  "addis %0,3," #x "@dtprel@ha\n\t"				      \
 	  "addi  %0,%0," #x "@dtprel@l"					      \
@@ -30,13 +66,15 @@ 
 	  : "3", __TLS_CALL_CLOBBERS);					      \
      __result;								      \
   })
+
 /* PowerPC64 General Dynamic TLS access.  */
-#define TLS_GD(x)							      \
+# define TLS_GD(x)							      \
   ({ register int *__result __asm__ ("r3");				      \
      asm ("addi  3,2," #x "@got@tlsgd\n\t"				      \
-	  "bl    __tls_get_addr\n\t"					      \
+	  "bl    __tls_get_addr(" #x "@tlsgd)\n\t"			      \
 	  "nop   "							      \
 	  : "=r" (__result) :						      \
 	  : __TLS_CALL_CLOBBERS);					      \
      __result;								      \
   })
+#endif