public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
From: Martin Schwidefsky <schwidefsky@de.ibm.com>
To: binutils@sources.redhat.com
Subject: [PATCH] s390 brasl TLS code morphing.
Date: Fri, 05 May 2006 15:46:00 -0000	[thread overview]
Message-ID: <20060505132431.GA21010@skybase> (raw)

Hi,
if a 32 bit libc is compiled with the option -march=z990 gcc will
use a "brasl" instruction instead of a "bas" for the function call
to __tls_get_offset in the general dynamic and local dynamic TLS
model. The 32 bit elf bfd can only optimize the "bas" instruction
and generates broken code if a "brasl" instruction is used.
This patch adds the code morphing for the "brasl" instruction to
the 32 bit elf bfd and sets an error in invalid_tls_insn for the
32 and 64 bit bfds if an unknown instruction has been found in the
tls code morphing. 

blue skies,
  Martin.

2006-05-05  Martin Schwidefsky  <schwidefsky@de.ibm.com>

	* elf32-s390.c (invalid_tls_insn): Call bfd_set_error.
	(elf_s390_relocate_section): Add code to do the GD->LE and
	LD->LE TLS linker optimizations if a brasl instruction is used
	for the __tls_get_offset function call.
	* elf64-s390.c (invalid_tls_insn): Call bfd_set_error.

diff -urpN src/bfd/elf32-s390.c src-s390/bfd/elf32-s390.c
--- src/bfd/elf32-s390.c	2006-03-23 11:36:06.000000000 +0100
+++ src-s390/bfd/elf32-s390.c	2006-05-05 14:13:39.000000000 +0200
@@ -2268,6 +2268,7 @@ invalid_tls_insn (input_bfd, input_secti
      input_section,
      (long) rel->r_offset,
      howto->name);
+  bfd_set_error (bfd_error_bad_value);
 }
 
 /* Relocate a 390 ELF section.  */
@@ -2982,16 +2983,44 @@ elf_s390_relocate_section (output_bfd, i
 	      unsigned int insn;
 
 	      insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
-	      if ((insn & 0xff000fff) != 0x4d000000)
+	      if ((insn & 0xff000fff) != 0x4d000000 &&
+		  (insn & 0xffff0000) != 0xc0e50000)
 		invalid_tls_insn (input_bfd, input_section, rel);
 	      if (!info->shared && (h == NULL || h->dynindx == -1))
-		/* GD->LE transition.
-		   bas %r14,0(%rx,%r13) -> bc 0,0  */
-		insn = 0x47000000;
+		{
+		  if ((insn & 0xff000000) == 0x4d000000)
+		    {
+		      /* GD->LE transition.
+			 bas %r14,0(%rx,%r13) -> bc 0,0  */
+		      insn = 0x47000000;
+		    }
+		  else
+		    {
+		      /* GD->LE transition.
+			 brasl %r14,_tls_get_addr@plt -> brcl 0,.  */
+		      insn = 0xc0040000;
+		      bfd_put_16 (output_bfd, 0x0000,
+				  contents + rel->r_offset + 4);
+		    }
+		}
 	      else
-		/* GD->IE transition.
-		   bas %r14,0(%rx,%r13) -> l %r2,0(%r2,%r12)  */
-		insn = 0x5822c000;
+		{
+		  if ((insn & 0xff000000) == 0x4d000000)
+		    {
+		      /* GD->IE transition.
+			 bas %r14,0(%rx,%r13) -> l %r2,0(%r2,%r12)  */
+		      insn = 0x5822c000;
+		    }
+		  else
+		    {
+		      /* GD->IE transition.
+			 brasl %r14,__tls_get_addr@plt ->
+			 	l %r2,0(%r2,%r12) ; bcr 0,0 */
+		      insn = 0x5822c000;
+		      bfd_put_16 (output_bfd, 0x0700,
+				  contents + rel->r_offset + 4);
+		    }
+		}
 	      bfd_put_32 (output_bfd, insn, contents + rel->r_offset);
 	    }
 	  else if (r_type == R_390_TLS_LDCALL)
@@ -3001,11 +3030,23 @@ elf_s390_relocate_section (output_bfd, i
 		  unsigned int insn;
 
 		  insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
-		  if ((insn & 0xff000fff) != 0x4d000000)
+		  if ((insn & 0xff000fff) != 0x4d000000 &&
+		      (insn & 0xffff0000) != 0xc0e50000)
 		    invalid_tls_insn (input_bfd, input_section, rel);
-		  /* LD->LE transition.
-		     bas %r14,0(%rx,%r13) -> bc 0,0  */
-		  insn = 0x47000000;
+		  if ((insn & 0xff000000) == 0x4d000000)
+		    {
+		      /* LD->LE transition.
+			 bas %r14,0(%rx,%r13) -> bc 0,0  */
+		      insn = 0x47000000;
+		    }
+		  else
+		    {
+		      /* LD->LE transition.
+			 brasl %r14,__tls_get_addr@plt -> brcl 0,. */
+		      insn = 0xc0040000;
+		      bfd_put_16 (output_bfd, 0x0000,
+				  contents + rel->r_offset + 4);
+		    }
 		  bfd_put_32 (output_bfd, insn, contents + rel->r_offset);
 		}
 	    }
diff -urpN src/bfd/elf64-s390.c src-s390/bfd/elf64-s390.c
--- src/bfd/elf64-s390.c	2006-05-05 14:14:58.000000000 +0200
+++ src-s390/bfd/elf64-s390.c	2006-05-05 14:13:08.000000000 +0200
@@ -2240,6 +2240,7 @@ invalid_tls_insn (input_bfd, input_secti
      input_section,
      (long) rel->r_offset,
      howto->name);
+  bfd_set_error (bfd_error_bad_value);
 }
 
 /* Relocate a 390 ELF section.  */

                 reply	other threads:[~2006-05-05 13:24 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20060505132431.GA21010@skybase \
    --to=schwidefsky@de.ibm.com \
    --cc=binutils@sources.redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).