GAS support for CRIS TLS

Hans-Peter Nilsson hans-peter.nilsson@axis.com
Sat Oct 4 17:27:00 GMT 2008


Here are the GAS changes necessary for TLS support for CRIS.  Right,
this is just the first step.  There's not much really interesting in
here, no BFD changes to actually perform or transform the relocations.
I don't think this is appropriate for the 2.19 branch, but I don't see
why, in the name of transparentness, to withhold this for the trunk.
Until I have everything working, I can't be sure I haven't missed or
misunderstood something, so the CRIS TLS specification isn't really
final and I won't post it yet.  Nevertheless I believe there were a
few general improvement opportunities here and there, taken care of
in the tentative CRIS TLS "psABI" specification:

    * Like for s390, a separate __tls_get_addr equivalent function
    that adds the GOT to the argument rather than for each caller to
    do it before the call

    * A single relocation, R_CRIS_DTP, for both the module number and
    symbol offset, as both are always needed together for a
    general-dynamic reference

    * When needed, put the module number in a GOT location with a
    constant index (number four, the first previously unreserved slot)

    * Make use of that constant GOT index by using another separate
    __tls_get_addr function without parameters to get the base TLS
    offset for the module

    * Automatically generate the R_CRIS_DTPMOD relocation in the
    linker when the offset of a local-dynamic TLS symbol is requested
    by use of R_CRIS_32_DTPREL or R_CRIS_16_DTPREL.  (Perhaps better
    not have this relocation and make ld.so put the module ID there
    always.)

(You'll have to understand Drepper's generic TLS spec at
<http://people.redhat.com/drepper/tls.pdf> for the above to be
understandable.)  Otherwise much like other TLS specifications, variant 2
but with additive (negative) TLS offsets.  Some details are hinted by
the include/elf/cris.h patch below.  No linker optimizations planned;
without evidence, I doubt TLS linker optimizations actually pay off in
noticeable performance for real applications.  Despite the test-cases,
there will probably be TLS just for CRIS v32, not earlier variants (of
which the only Linux-capable is CRIS v10, as in ETRAX 100 LX).  We'll
likely use special register $PID to hold the thread context in its 24
upper bits (as intended), so it has to be aligned on 256-byte boundary.

Tested cross to cris-axis-elf and cris-axis-linux-gnu and for sanity
(since generic header files were regenerated) also cross to arm-linux.
Committed.

bfd:
	* elf32-cris.c (TLSHOWTO32, TLSHOWTO16): New macros.
	(cris_elf_howto_table): Add entries for R_CRIS_32_GOT_GD,
	R_CRIS_16_GOT_GD, R_CRIS_32_GD, R_CRIS_DTP, R_CRIS_32_DTPREL,
	R_CRIS_16_DTPREL, R_CRIS_DTPMOD, R_CRIS_32_GOT_TPREL,
	R_CRIS_16_GOT_TPREL,  R_CRIS_32_TPREL,  R_CRIS_16_TPREL.
	(cris_reloc_map): Similarly.
	* reloc.c (bfd_reloc_code_type): Add entries for
	BFD_RELOC_CRIS_32_GOT_GD, BFD_RELOC_CRIS_16_GOT_GD,
	BFD_RELOC_CRIS_32_GD, BFD_RELOC_CRIS_DTP,
	BFD_RELOC_CRIS_32_DTPREL, BFD_RELOC_CRIS_16_DTPREL,
	BFD_RELOC_CRIS_DTPMOD, BFD_RELOC_CRIS_32_GOT_TPREL,
	BFD_RELOC_CRIS_16_GOT_TPREL, BFD_RELOC_CRIS_32_TPREL,
	BFD_RELOC_CRIS_16_TPREL.
	* libbfd.h, bfd-in2.h: Regenerate.

gas/testsuite:
	* gas/cris/rd-tls-1.s, gas/cris/rd-tls-1.d, gas/cris/rd-tls-2.s,
	gas/cris/rd-tls-2.d, gas/cris/tls-err-1.s, gas/cris/tls-err-2.s,
	gas/cris/tls-err-3.s: New tests.

gas:
	* config/tc-cris.c: Update all comments regarding explicit relocations
	to, besides PIC, also imply TLS or to say "relocation specifier" or
	similar.
	(RELOC_SUFFIX_CHAR): Rename from PIC_SUFFIX_CHAR.  Change all callers.
	(cris_get_reloc_suffix): Rename from cris_get_pic_suffix.  Change all
	callers.  Also handle TLS relocs.
	(cris_get_specified_reloc_size): Rename from cris_get_pic_reloc_size.
	Change all callers.  Also handle TLS relocs.
	(tls): New constant.
	(cris_process_instruction): Check for non-PIC TLS relocations and
	adjust message when emitting error message about relocation not
	fitting.
	(get_autoinc_prefix_or_indir_op): Also check for relocation suffix
	when tls is true.
	(get_3op_or_dip_prefix_op): Ditto.
	(cris_number_to_imm, tc_gen_reloc): Handle TLS relocs like PIC relocs.

include/elf:
	* cris.h (R_CRIS_32_GOT_GD, R_CRIS_16_GOT_GD, R_CRIS_32_GD)
	(R_CRIS_DTP, R_CRIS_32_DTPREL, R_CRIS_16_DTPREL, R_CRIS_DTPMOD)
	(R_CRIS_32_GOT_TPREL, R_CRIS_16_GOT_TPREL, R_CRIS_32_TPREL)
	(R_CRIS_16_TPREL): New relocations.

Index: include/elf/cris.h
===================================================================
RCS file: /cvs/src/src/include/elf/cris.h,v
retrieving revision 1.7
diff -p -u -r1.7 cris.h
--- include/elf/cris.h	10 May 2005 10:21:10 -0000	1.7
+++ include/elf/cris.h	3 Oct 2008 01:37:25 -0000
@@ -91,6 +91,82 @@ START_RELOC_NUMBERS (elf_cris_reloc_type
      The BFD equivalent is BFD_RELOC_CRIS_32_PLT_PCREL.  */
   RELOC_NUMBER (R_CRIS_32_PLT_PCREL, 19)
 
+  /* An assembler-generated-only relocation, instructing the linker to
+     reserve two GOT slots, carrying the R_CRIS_DTP relocation for the
+     symbol (pointing to the first slot, the relocation fills in
+     both).  The value is a 32-bit-value, relative to the start of the
+     GOT.  Assembly syntax: "sym:GDGOTREL".  */
+  RELOC_NUMBER (R_CRIS_32_GOT_GD, 20)
+
+  /* Similar to R_CRIS_32_GOT_GD, but the value is a 16-bit unsigned
+     number, limiting access to 65536/4 global symbols per module (or
+     65536/8 thread variables; loosely speaking G*4+T*8 < 65536, where
+     T is the number of thread variables and G is the number of other
+     external global variables and functions).  Assembly syntax:
+     "sym:GDGOTREL16".  */
+  RELOC_NUMBER (R_CRIS_16_GOT_GD, 21)
+
+  /* Similar to R_CRIS_32_GOT_GD, but the value is the absolute
+     address of the GOT entry.  Disallowed in DSOs created with
+     -shared.  Assembly syntax: "sym:GD".  */
+  RELOC_NUMBER (R_CRIS_32_GD, 22)
+
+  /* A linker-generated-only relocation, instructing the dynamic
+     linker to fill in the module ID and module-relative-TLS-block
+     offset of the symbol in question, used for GOT entries.  Note
+     that this relocation instructs to fill in two 32-bit values.  */
+  RELOC_NUMBER (R_CRIS_DTP, 23)
+
+  /* An assembler-generated-only relocation, instructing the linker to
+     reserve the first two GOT slots, and attach the R_CRIS_DTPMOD
+     relocation(*) for the module to the first slot, the second
+     containing zero.  The value is 32 bits, the offset from the start
+     of the TLS block of the module to the thread-local symbol
+     mentioned in the relocation.  This relocation must only be applied
+     to module-local symbols.  Assembly syntax: "expr:DTPREL".  */
+  RELOC_NUMBER (R_CRIS_32_DTPREL, 24)
+
+  /* Similar to R_CRIS_32_DTPREL, but the value is a 16-bit signed
+     number, limiting the size of thread-variables of the DSO to 32768
+     bytes.  (Note: matches both model 1 and 2 and allows use of addo.w
+     as the instruction where this relocation is used.)  Assembly
+     syntax: "expr:DTPREL16".  */
+  RELOC_NUMBER (R_CRIS_16_DTPREL, 25)
+
+  /* An assembler-generated-only relocation, instructing the linker to
+     reserve a GOT slot and attach the R_CRIS_32_TPREL relocation for
+     the symbol in question.  The value is 32 bits, which is the
+     GOT-relative offset of the slot.  Assembly syntax:
+     "sym:TPOFFGOT".  */
+  RELOC_NUMBER (R_CRIS_32_GOT_TPREL, 26)
+
+  /* Similar to R_CRIS_32_TPREL, but the value is a 16-bit positive
+     number, limiting the number of thread- and global variables of
+     the DSO to 32768/4.  Assembly syntax: "sym:TPOFFGOT16".  */
+  RELOC_NUMBER (R_CRIS_16_GOT_TPREL, 27)
+
+  /* An assembler- and linker-generated relocation, instructing to
+     resolve the symbol in question yielding the TLS offset of the
+     thread variable; relative to the module's TLS data if in a DSO,
+     but relative to the executable's thread data if in an
+     executable. Not allowed as input when generating a DSO.  Assembly
+     syntax: "expr:TPOFF".  */
+  RELOC_NUMBER (R_CRIS_32_TPREL, 28)
+
+  /* Similar to R_CRIS_32_TPREL, but only applicable to executables
+     compiled with -msmall-tls. Not allowed in a DSO. The value is a
+     16-bit signed number, limiting the size of thread-variables of
+     the executable to 32768 bytes. (Note: being signed makes it match
+     both model 1 and 2 and allows use of addo.w as the instruction
+     where this relocation is applied.)  Assembly syntax:
+     "expr:TPOFF16".  */
+  RELOC_NUMBER (R_CRIS_16_TPREL, 29)
+
+  /* A linker-generated-only relocation, instructing the dynamic
+     linker to fill in the current module ID, used for GOT entries
+     (always the fourth one).  */
+  RELOC_NUMBER (R_CRIS_DTPMOD, 30)
+
   /* No other relocs must be visible outside the assembler.  */
 
 END_RELOC_NUMBERS (R_CRIS_max)

Index: bfd/elf32-cris.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-cris.c,v
retrieving revision 1.85
diff -p -u -r1.85 elf32-cris.c
--- bfd/elf32-cris.c	11 Jan 2008 09:07:03 -0000	1.85
+++ bfd/elf32-cris.c	3 Oct 2008 01:37:21 -0000
@@ -409,7 +409,31 @@ static reloc_howto_type cris_elf_howto_t
 	 FALSE,			/* partial_inplace */
 	 0,			/* src_mask */
 	 0xffffffff,		/* dst_mask */
-	 TRUE)			/* pcrel_offset */
+	 TRUE),			/* pcrel_offset */
+
+  /* We don't handle these in any special manner and cross-format
+     linking is not supported; just recognize them enough to pass them
+     around.  FIXME: do the same for most PIC relocs and add sanity
+     tests to actually refuse gracefully to handle these and PIC
+     relocs for cross-format linking.  */
+#define TLSHOWTO32(name) \
+ HOWTO (name, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, \
+        bfd_elf_generic_reloc, #name, FALSE, 0, 0xffffffff, FALSE)
+#define TLSHOWTO16(name) \
+ HOWTO (name, 0, 1, 16, FALSE, 0, complain_overflow_bitfield, \
+        bfd_elf_generic_reloc, #name, FALSE, 0, 0xffff, FALSE)
+
+  TLSHOWTO32 (R_CRIS_32_GOT_GD),
+  TLSHOWTO16 (R_CRIS_16_GOT_GD),
+  TLSHOWTO32 (R_CRIS_32_GD),
+  TLSHOWTO32 (R_CRIS_DTP),
+  TLSHOWTO32 (R_CRIS_32_DTPREL),
+  TLSHOWTO16 (R_CRIS_16_DTPREL),
+  TLSHOWTO32 (R_CRIS_32_GOT_TPREL),
+  TLSHOWTO16 (R_CRIS_16_GOT_TPREL),
+  TLSHOWTO32 (R_CRIS_32_TPREL),
+  TLSHOWTO16 (R_CRIS_16_TPREL),
+  TLSHOWTO32 (R_CRIS_DTPMOD)
 };
 

 /* Map BFD reloc types to CRIS ELF reloc types.  */
@@ -441,7 +465,18 @@ static const struct cris_reloc_map cris_
   { BFD_RELOC_CRIS_32_GOTPLT,	R_CRIS_32_GOTPLT },
   { BFD_RELOC_CRIS_32_GOTREL,	R_CRIS_32_GOTREL },
   { BFD_RELOC_CRIS_32_PLT_GOTREL, R_CRIS_32_PLT_GOTREL },
-  { BFD_RELOC_CRIS_32_PLT_PCREL, R_CRIS_32_PLT_PCREL }
+  { BFD_RELOC_CRIS_32_PLT_PCREL, R_CRIS_32_PLT_PCREL },
+  { BFD_RELOC_CRIS_32_GOT_GD,	R_CRIS_32_GOT_GD },
+  { BFD_RELOC_CRIS_16_GOT_GD,	R_CRIS_16_GOT_GD },
+  { BFD_RELOC_CRIS_32_GD,	R_CRIS_32_GD },
+  { BFD_RELOC_CRIS_DTP,	R_CRIS_DTP },
+  { BFD_RELOC_CRIS_32_DTPREL,	R_CRIS_32_DTPREL },
+  { BFD_RELOC_CRIS_16_DTPREL,	R_CRIS_16_DTPREL },
+  { BFD_RELOC_CRIS_32_GOT_TPREL, R_CRIS_32_GOT_TPREL },
+  { BFD_RELOC_CRIS_16_GOT_TPREL, R_CRIS_16_GOT_TPREL },
+  { BFD_RELOC_CRIS_32_TPREL,	R_CRIS_32_TPREL },
+  { BFD_RELOC_CRIS_16_TPREL,	R_CRIS_16_TPREL },
+  { BFD_RELOC_CRIS_DTPMOD,	R_CRIS_DTPMOD }
 };
 
 static reloc_howto_type *
Index: bfd/reloc.c
===================================================================
RCS file: /cvs/src/src/bfd/reloc.c,v
retrieving revision 1.177
diff -p -u -r1.177 reloc.c
--- bfd/reloc.c	20 Aug 2008 23:28:58 -0000	1.177
+++ bfd/reloc.c	3 Oct 2008 01:37:23 -0000
@@ -4719,6 +4719,31 @@ ENUMDOC
   32-bit offset to symbol with PLT entry, relative to this relocation.
 
 ENUM
+  BFD_RELOC_CRIS_32_GOT_GD
+ENUMX
+  BFD_RELOC_CRIS_16_GOT_GD
+ENUMX
+  BFD_RELOC_CRIS_32_GD
+ENUMX
+  BFD_RELOC_CRIS_DTP
+ENUMX
+  BFD_RELOC_CRIS_32_DTPREL
+ENUMX
+  BFD_RELOC_CRIS_16_DTPREL
+ENUMX
+  BFD_RELOC_CRIS_32_GOT_TPREL
+ENUMX
+  BFD_RELOC_CRIS_16_GOT_TPREL
+ENUMX
+  BFD_RELOC_CRIS_32_TPREL
+ENUMX
+  BFD_RELOC_CRIS_16_TPREL
+ENUMX
+  BFD_RELOC_CRIS_DTPMOD
+ENUMDOC
+  Relocs used in TLS code for CRIS.
+
+ENUM
   BFD_RELOC_860_COPY
 ENUMX
   BFD_RELOC_860_GLOB_DAT
Index: gas/config/tc-cris.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-cris.c,v
retrieving revision 1.39
diff -p -u -r1.39 tc-cris.c
--- gas/config/tc-cris.c	3 Jul 2007 11:01:04 -0000	1.39
+++ gas/config/tc-cris.c	3 Oct 2008 01:37:23 -0000
@@ -52,7 +52,7 @@
 
 /* Like in ":GOT", ":GOTOFF" etc.  Other ports use '@', but that's in
    line_separator_chars for CRIS, so we avoid it.  */
-#define PIC_SUFFIX_CHAR ':'
+#define RELOC_SUFFIX_CHAR ':'
 
 /* This might be CRIS_INSN_NONE if we're assembling a prefix-insn only.
    Note that some prefix-insns might be assembled as CRIS_INSN_NORMAL.  */
@@ -150,9 +150,9 @@ static void s_cris_loc (int);
 static void s_cris_arch (int);
 
 /* Get ":GOT", ":GOTOFF", ":PLT" etc. suffixes.  */
-static void cris_get_pic_suffix (char **, bfd_reloc_code_real_type *,
-				 expressionS *);
-static unsigned int cris_get_pic_reloc_size (bfd_reloc_code_real_type);
+static void cris_get_reloc_suffix (char **, bfd_reloc_code_real_type *,
+				   expressionS *);
+static unsigned int cris_get_specified_reloc_size (bfd_reloc_code_real_type);
 
 /* All the .syntax functions.  */
 static void cris_force_reg_prefix (void);
@@ -183,6 +183,9 @@ static bfd_boolean symbols_have_leading_
 /* Whether or not we allow PIC, and expand to PIC-friendly constructs.  */
 static bfd_boolean pic = FALSE;
 
+/* Whether or not we allow TLS suffixes.  For the moment, we always do.  */
+static const bfd_boolean tls = TRUE;
+
 /* If we're configured for "cris", default to allow all v0..v10
    instructions and register names.  */
 #ifndef DEFAULT_CRIS_ARCH
@@ -1252,7 +1255,7 @@ md_assemble (char *str)
       /* When the expression is unknown for a BDAP, it can need 0, 2 or 4
 	 extra bytes, so we handle it separately.  */
     case PREFIX_BDAP_IMM:
-      /* We only do it if the relocation is unspecified, i.e. not a PIC
+      /* We only do it if the relocation is unspecified, i.e. not a PIC or TLS
 	 relocation.  */
       if (prefix.reloc == BFD_RELOC_NONE)
 	{
@@ -1269,13 +1272,13 @@ md_assemble (char *str)
       md_number_to_chars (opcodep, (long) prefix.opcode, 2);
 
       /* Having a specified reloc only happens for DIP and for BDAP with
-	 PIC operands, but it is ok to drop through here for the other
+	 PIC or TLS operands, but it is ok to drop through here for the other
 	 prefixes as they can have no relocs specified.  */
       if (prefix.reloc != BFD_RELOC_NONE)
 	{
 	  unsigned int relocsize
 	    = (prefix.kind == PREFIX_DIP
-	       ? 4 : cris_get_pic_reloc_size (prefix.reloc));
+	       ? 4 : cris_get_specified_reloc_size (prefix.reloc));
 
 	  p = frag_more (relocsize);
 	  fix_new_exp (frag_now, (p - frag_now->fr_literal), relocsize,
@@ -1889,7 +1892,7 @@ cris_process_instruction (char *insn_tex
 			 whether or not this is autoincrement mode.  */
 		      out_insnp->opcode |= (mode << 10);
 
-		      /* If there was a PIC reloc specifier, then it was
+		      /* If there was a reloc specifier, then it was
 			 attached to the prefix.  Note that we can't check
 			 that the reloc size matches, since we don't have
 			 all the operands yet in all cases.  */
@@ -1903,8 +1906,8 @@ cris_process_instruction (char *insn_tex
 
 	    case 'N':
 	    case 'Y':
-	      /* Like 's', but immediate operand only.  Also does not
-		 modify insn.  There are no insns where a PIC reloc
+	      /* Like 's', but immediate operand only.  Also do not
+		 modify insn.  There are no insns where an explicit reloc
 		 specifier makes sense.  */
 	      if (cris_get_expression (&s, &out_insnp->expr))
 		{
@@ -1927,9 +1930,10 @@ cris_process_instruction (char *insn_tex
 		     relocation.  */
 		  out_insnp->expr.X_add_number += 6;
 
-		  if (pic && *s == PIC_SUFFIX_CHAR)
-		    cris_get_pic_suffix (&s, &out_insnp->reloc,
-					 &out_insnp->expr);
+		  /* TLS specifiers do not make sense here.  */
+		  if (pic && *s == RELOC_SUFFIX_CHAR)
+		    cris_get_reloc_suffix (&s, &out_insnp->reloc,
+					   &out_insnp->expr);
 
 		  continue;
 		}
@@ -2194,13 +2198,17 @@ cris_process_instruction (char *insn_tex
 		}
 
 	      /* If there was a relocation specified for the immediate
-		 expression (i.e. it had a PIC modifier) check that the
-		 size of the PIC relocation matches the size specified by
+		 expression (i.e. it had a PIC or TLS modifier) check that the
+		 size of the relocation matches the size specified by
 		 the opcode.  */
 	      if (out_insnp->reloc != BFD_RELOC_NONE
-		  && (cris_get_pic_reloc_size (out_insnp->reloc)
+		  && (cris_get_specified_reloc_size (out_insnp->reloc)
 		      != (unsigned int) out_insnp->imm_oprnd_size))
-		as_bad (_("PIC relocation size does not match operand size"));
+		as_bad (out_insnp->reloc == BFD_RELOC_CRIS_32_GD
+			|| out_insnp->reloc == BFD_RELOC_CRIS_32_TPREL
+			|| out_insnp->reloc == BFD_RELOC_CRIS_16_TPREL
+			? _("TLS relocation size does not match operand size")
+			: _("PIC relocation size does not match operand size"));
 	    }
 	  else if (instruction->op == cris_muls_op
 		   || instruction->op == cris_mulu_op)
@@ -2715,8 +2723,8 @@ get_autoinc_prefix_or_indir_op (char **c
 
 			  /* We tentatively put an opcode corresponding to
 			     a 32-bit operand here, although it may be
-			     relaxed when there's no PIC specifier for the
-			     operand.  */
+			     relaxed when there's no relocation
+			     specifier for the operand.  */
 			  prefixp->opcode
 			    = (BDAP_INDIR_OPCODE
 			       | (prefixp->base_reg_number << 12)
@@ -2726,18 +2734,18 @@ get_autoinc_prefix_or_indir_op (char **c
 
 			  /* This can have a PIC suffix, specifying reloc
 			     type to use.  */
-			  if (pic && **cPP == PIC_SUFFIX_CHAR)
+			  if ((pic || tls) && **cPP == RELOC_SUFFIX_CHAR)
 			    {
 			      unsigned int relocsize;
 
-			      cris_get_pic_suffix (cPP, &prefixp->reloc,
-						   &prefixp->expr);
+			      cris_get_reloc_suffix (cPP, &prefixp->reloc,
+						     &prefixp->expr);
 
 			      /* Tweak the size of the immediate operand
 				 in the prefix opcode if it isn't what we
 				 set.  */
 			      relocsize
-				= cris_get_pic_reloc_size (prefixp->reloc);
+				= cris_get_specified_reloc_size (prefixp->reloc);
 			      if (relocsize != 4)
 				prefixp->opcode
 				  = ((prefixp->opcode & ~(3 << 4))
@@ -2763,8 +2771,9 @@ get_autoinc_prefix_or_indir_op (char **c
 			     in the blanks and break out to match the
 			     final ']'.
 
-			     Note that we don't allow a PIC suffix for an
-			     operand with a minus sign.  */
+			     Note that we don't allow a relocation
+			     suffix for an operand with a minus
+			     sign.  */
 			  prefixp->kind = PREFIX_BDAP_IMM;
 			  break;
 			}
@@ -2802,8 +2811,8 @@ get_autoinc_prefix_or_indir_op (char **c
 
       /* This can have a PIC suffix, specifying reloc type to use.  The
 	 caller must check that the reloc size matches the operand size.  */
-      if (pic && **cPP == PIC_SUFFIX_CHAR)
-	cris_get_pic_suffix (cPP, &prefixp->reloc, imm_exprP);
+      if ((pic || tls) && **cPP == RELOC_SUFFIX_CHAR)
+	cris_get_reloc_suffix (cPP, &prefixp->reloc, imm_exprP);
 
       return 1;
     }
@@ -2971,15 +2980,15 @@ get_3op_or_dip_prefix_op (char **cPP, st
 		   | REG_PC /* << 0 */);
 
 	      /* This can have a PIC suffix, specifying reloc type to use.  */
-	      if (pic && **cPP == PIC_SUFFIX_CHAR)
+	      if ((pic || tls) && **cPP == RELOC_SUFFIX_CHAR)
 		{
 		  unsigned int relocsize;
 
-		  cris_get_pic_suffix (cPP, &prefixp->reloc, &prefixp->expr);
+		  cris_get_reloc_suffix (cPP, &prefixp->reloc, &prefixp->expr);
 
 		  /* Tweak the size of the immediate operand in the prefix
 		     opcode if it isn't what we set.  */
-		  relocsize = cris_get_pic_reloc_size (prefixp->reloc);
+		  relocsize = cris_get_specified_reloc_size (prefixp->reloc);
 		  if (relocsize != 4)
 		    prefixp->opcode
 		      = ((prefixp->opcode & ~(3 << 4))
@@ -3426,13 +3435,19 @@ gen_cond_branch_32 (char *opcodep, char 
     md_number_to_chars (writep + 8, MOVE_PC_INCR_OPCODE_SUFFIX, 2);
 }
 
-/* Get the size of an immediate-reloc in bytes.  Only valid for PIC
-   relocs.  */
+/* Get the size of an immediate-reloc in bytes.  Only valid for
+   specified relocs (TLS, PIC).  */
 
 static unsigned int
-cris_get_pic_reloc_size (bfd_reloc_code_real_type reloc)
+cris_get_specified_reloc_size (bfd_reloc_code_real_type reloc)
 {
-  return reloc == BFD_RELOC_CRIS_16_GOTPLT || reloc == BFD_RELOC_CRIS_16_GOT
+  return
+    reloc == BFD_RELOC_CRIS_16_GOTPLT
+    || reloc == BFD_RELOC_CRIS_16_GOT
+    || reloc == BFD_RELOC_CRIS_16_GOT_GD
+    || reloc == BFD_RELOC_CRIS_16_DTPREL
+    || reloc == BFD_RELOC_CRIS_16_GOT_TPREL
+    || reloc == BFD_RELOC_CRIS_16_TPREL
     ? 2 : 4;
 }
 
@@ -3440,8 +3455,8 @@ cris_get_pic_reloc_size (bfd_reloc_code_
    Adjust *EXPRP with any addend found after the PIC suffix.  */
 
 static void
-cris_get_pic_suffix (char **cPP, bfd_reloc_code_real_type *relocp,
-		     expressionS *exprP)
+cris_get_reloc_suffix (char **cPP, bfd_reloc_code_real_type *relocp,
+		       expressionS *exprP)
 {
   char *s = *cPP;
   unsigned int i;
@@ -3452,10 +3467,14 @@ cris_get_pic_suffix (char **cPP, bfd_rel
     const char *const suffix;
     unsigned int len;
     bfd_reloc_code_real_type reloc;
+    bfd_boolean pic_p;
+    bfd_boolean tls_p;
   } pic_suffixes[] =
     {
 #undef PICMAP
-#define PICMAP(s, r) {s, sizeof (s) - 1, r}
+#define PICMAP(s, r) {s, sizeof (s) - 1, r, TRUE, FALSE}
+#define PICTLSMAP(s, r) {s, sizeof (s) - 1, r, TRUE, TRUE}
+#define TLSMAP(s, r) {s, sizeof (s) - 1, r, FALSE, TRUE}
       /* Keep this in order with longest unambiguous prefix first.  */
       PICMAP ("GOTPLT16", BFD_RELOC_CRIS_16_GOTPLT),
       PICMAP ("GOTPLT", BFD_RELOC_CRIS_32_GOTPLT),
@@ -3463,7 +3482,16 @@ cris_get_pic_suffix (char **cPP, bfd_rel
       PICMAP ("PLT", BFD_RELOC_CRIS_32_PLT_PCREL),
       PICMAP ("GOTOFF", BFD_RELOC_CRIS_32_GOTREL),
       PICMAP ("GOT16", BFD_RELOC_CRIS_16_GOT),
-      PICMAP ("GOT", BFD_RELOC_CRIS_32_GOT)
+      PICMAP ("GOT", BFD_RELOC_CRIS_32_GOT),
+      PICTLSMAP ("GDGOTREL16", BFD_RELOC_CRIS_16_GOT_GD),
+      PICTLSMAP ("GDGOTREL", BFD_RELOC_CRIS_32_GOT_GD),
+      TLSMAP ("GD", BFD_RELOC_CRIS_32_GD),
+      PICTLSMAP ("DTPREL16", BFD_RELOC_CRIS_16_DTPREL),
+      PICTLSMAP ("DTPREL", BFD_RELOC_CRIS_32_DTPREL),
+      PICTLSMAP ("TPOFFGOT16", BFD_RELOC_CRIS_16_GOT_TPREL),
+      PICTLSMAP ("TPOFFGOT", BFD_RELOC_CRIS_32_GOT_TPREL),
+      TLSMAP ("TPOFF16", BFD_RELOC_CRIS_16_TPREL),
+      TLSMAP ("TPOFF", BFD_RELOC_CRIS_32_TPREL)
     };
 
   /* We've already seen the ':', so consume it.  */
@@ -3472,7 +3500,11 @@ cris_get_pic_suffix (char **cPP, bfd_rel
   for (i = 0; i < sizeof (pic_suffixes)/sizeof (pic_suffixes[0]); i++)
     {
       if (strncmp (s, pic_suffixes[i].suffix, pic_suffixes[i].len) == 0
-	  && ! is_part_of_name (s[pic_suffixes[i].len]))
+	  && ! is_part_of_name (s[pic_suffixes[i].len])
+	  /* PIC and non-PIC relocations are exclusive.  */
+	  && (pic != 0) == (pic_suffixes[i].pic_p != 0)
+	  /* But TLS can be active for non-TLS relocations too.  */
+	  && (pic_suffixes[i].tls_p == 0 || tls))
 	{
 	  /* We have a match.  Consume the suffix and set the relocation
 	     type.   */
@@ -3599,6 +3631,15 @@ cris_number_to_imm (char *bufp, long val
     case BFD_RELOC_CRIS_32_GOTPLT:
     case BFD_RELOC_CRIS_32_PLT_GOTREL:
     case BFD_RELOC_CRIS_32_PLT_PCREL:
+    case BFD_RELOC_CRIS_32_GOT_GD:
+    case BFD_RELOC_CRIS_16_GOT_GD:
+    case BFD_RELOC_CRIS_32_GD:
+    case BFD_RELOC_CRIS_32_DTPREL:
+    case BFD_RELOC_CRIS_16_DTPREL:
+    case BFD_RELOC_CRIS_32_GOT_TPREL:
+    case BFD_RELOC_CRIS_16_GOT_TPREL:
+    case BFD_RELOC_CRIS_32_TPREL:
+    case BFD_RELOC_CRIS_16_TPREL:
       /* We don't want to put in any kind of non-zero bits in the data
 	 being relocated for these.  */
       break;
@@ -3870,6 +3911,15 @@ tc_gen_reloc (asection *section ATTRIBUT
     case BFD_RELOC_CRIS_UNSIGNED_8:
     case BFD_RELOC_CRIS_UNSIGNED_16:
     case BFD_RELOC_CRIS_LAPCQ_OFFSET:
+    case BFD_RELOC_CRIS_32_GOT_GD:
+    case BFD_RELOC_CRIS_16_GOT_GD:
+    case BFD_RELOC_CRIS_32_GD:
+    case BFD_RELOC_CRIS_32_DTPREL:
+    case BFD_RELOC_CRIS_16_DTPREL:
+    case BFD_RELOC_CRIS_32_GOT_TPREL:
+    case BFD_RELOC_CRIS_16_GOT_TPREL:
+    case BFD_RELOC_CRIS_32_TPREL:
+    case BFD_RELOC_CRIS_16_TPREL:
       code = fixP->fx_r_type;
       break;
     default:
Index: gas/testsuite/gas/cris/rd-tls-1.d
===================================================================
RCS file: gas/testsuite/gas/cris/rd-tls-1.d
diff -N gas/testsuite/gas/cris/rd-tls-1.d
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/cris/rd-tls-1.d	3 Oct 2008 01:37:23 -0000
@@ -0,0 +1,28 @@
+#objdump: -dr
+#as: --em=criself
+#name: TLS non-PIC relocs.
+
+.*:     file format .*-cris
+
+Disassembly of section \.text:
+
+0+ <start>:
+[ 	]+0:[ 	]+af1e 0000 0000[ 	]+sub\.d 0 <start>,\$?r1
+[ 	]+2:[ 	]+R_CRIS_32_GD	\.text
+[ 	]+6:[ 	]+2f9e 0000 0000[ 	]+add\.d 0 <start>,\$?r9
+[ 	]+8:[ 	]+R_CRIS_32_GD	extsym2
+[ 	]+c:[ 	]+6f3d 0000 0000 6aaa[ 	]+move\.d \[\$?r3\+0 <start>\],\$?r10
+[ 	]+e:[ 	]+R_CRIS_32_TPREL	extsym
+[ 	]+14:[ 	]+5fae 0000[ 	]+move\.w 0x0,\$?r10
+[ 	]+16:[ 	]+R_CRIS_16_TPREL	extsym14\+0x4d
+[ 	]+18:[ 	]+af9e 0000 0000[ 	]+sub\.d 0 <start>,\$?r9
+[ 	]+1a:[ 	]+R_CRIS_32_GD	extsym4\+0x2a
+[ 	]+1e:[ 	]+af3e 0000 0000[ 	]+sub\.d 0 <start>,\$?r3
+[ 	]+20:[ 	]+R_CRIS_32_GD	extsym4\+0xffffffa0
+[ 	]+24:[ 	]+6f3d 0000 0000 67de[ 	]+move\.d \[\$?r7=\$?r3\+0 <start>\],\$?r13
+[ 	]+26:[ 	]+R_CRIS_32_GD	extsym10\+0xfffffeb6
+[ 	]+2c:[ 	]+5fbd 0000 699a[ 	]+move\.d \[\$?r11\+0\],\$?r9
+[ 	]+2e:[ 	]+R_CRIS_16_TPREL	extsym14\+0xffffff00
+[ 	]+32:[ 	]+6fad 0000 0000 287a[ 	]+add\.d \[\$?r10\+0 <start>\],\$?r7,\$?r8
+[ 	]+34:[ 	]+R_CRIS_32_TPREL	extsym3\+0x38
+[ 	]+\.\.\.
Index: gas/testsuite/gas/cris/rd-tls-1.s
===================================================================
RCS file: gas/testsuite/gas/cris/rd-tls-1.s
diff -N gas/testsuite/gas/cris/rd-tls-1.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/cris/rd-tls-1.s	3 Oct 2008 01:37:23 -0000
@@ -0,0 +1,16 @@
+; Check that non-PIC TLS operands get their right relocation type.
+; First some expected uses, similar to what GCC will emit.
+	.text
+	.syntax no_register_prefix
+start:
+	sub.d .:GD,r1
+	add.d extsym2:GD,r9
+	move.d [r3+extsym:TPOFF],r10
+	move.w extsym14:TPOFF16+77,r10
+
+; Other for GAS valid operands (some with questionable PIC semantics).
+	sub.d extsym4:GD+42,r9
+	sub.d extsym4:GD-96,r3
+	move.d [r7=r3+extsym10:GD-330],r13
+	move.d [r11+extsym14:TPOFF16-256],r9
+	add.d [r10+extsym3:TPOFF+56],r7,r8
Index: gas/testsuite/gas/cris/rd-tls-2.d
===================================================================
RCS file: gas/testsuite/gas/cris/rd-tls-2.d
diff -N gas/testsuite/gas/cris/rd-tls-2.d
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/cris/rd-tls-2.d	3 Oct 2008 01:37:23 -0000
@@ -0,0 +1,48 @@
+#objdump: -dr
+#as: --em=criself --pic
+#name: TLS PIC relocs.
+
+.*:     file format .*-cris
+
+Disassembly of section \.text:
+
+0+ <start>:
+[ 	]+0:	6f3d 0000 0000 6aaa[ 	]+move\.d \[\$?r3\+0 <start>\],\$?r10
+[ 	]+2: R_CRIS_32_GOT_TPREL	extsym
+[ 	]+8:	6f8e 0000 0000[ 	]+move\.d 0 <start>,\$?r8
+[ 	]+a: R_CRIS_32_GOT_TPREL	extsym5
+[ 	]+e:	5f8e 0000[ 	]+move\.w 0x0,\$?r8
+[ 	]+10: R_CRIS_16_GOT_TPREL	extsym9
+[ 	]+12:	6f3d 0000 0000 6aaa[ 	]+move\.d \[\$?r3\+0 <start>\],\$?r10
+[ 	]+14: R_CRIS_32_GOT_GD	extsym
+[ 	]+1a:	5fdd 0000 6aaa[ 	]+move\.d \[\$?r13\+0\],\$?r10
+[ 	]+1c: R_CRIS_16_GOT_TPREL	extsym13
+[ 	]+20:	5fae 0000[ 	]+move\.w 0x0,\$?r10
+[ 	]+22: R_CRIS_16_GOT_GD	extsym14
+[ 	]+24:	af9e 0000 0000[ 	]+sub\.d 0 <start>,\$?r9
+[ 	]+26: R_CRIS_32_DTPREL	extsym4\+0x16
+[ 	]+2a:	9f3e 0000[ 	]+sub\.w 0x0,\$?r3
+[ 	]+2c: R_CRIS_16_DTPREL	extsym4\+0xffffffaa
+[ 	]+2e:	6f3d 0000 0000 aa4a[ 	]+sub\.d \[\$?r3\+0 <start>\],\$?r4,\$?r10
+[ 	]+30: R_CRIS_32_GOT_TPREL	extsym3
+[ 	]+36:	af9e 0000 0000[ 	]+sub\.d 0 <start>,\$?r9
+[ 	]+38: R_CRIS_32_GOT_GD	extsym4\+0x2a
+[ 	]+3c:	af3e 0000 0000[ 	]+sub\.d 0 <start>,\$?r3
+[ 	]+3e: R_CRIS_32_GOT_TPREL	extsym4\+0xffffffa0
+[ 	]+42:	6fad 0000 0000 287a[ 	]+add\.d \[\$?r10\+0 <start>\],\$?r7,\$?r8
+[ 	]+44: R_CRIS_32_GOT_TPREL	extsym3\+0x38
+[ 	]+4a:	6f5d 0000 0000 611a[ 	]+move\.d \[\$?r5\+0 <start>\],\$?r1
+[ 	]+4c: R_CRIS_32_GOT_TPREL	extsym6\+0xa
+[ 	]+52:	6fad 0000 0000 284a[ 	]+add\.d \[\$?r10\+0 <start>\],\$?r4,\$?r8
+[ 	]+54: R_CRIS_32_GOT_TPREL	extsym3\+0xfffffdd0
+[ 	]+5a:	6f5d 0000 0000 6cca[ 	]+move\.d \[\$?r5\+0 <start>\],\$?r12
+[ 	]+5c: R_CRIS_32_GOT_TPREL	extsym6\+0xffffff92
+[ 	]+62:	6f5d 0000 0000 69ce[ 	]+move\.d \[\$?r9=\$?r5\+0 <start>\],\$?r12
+[ 	]+64: R_CRIS_32_GOT_TPREL	extsym6\+0xffffff24
+[ 	]+6a:	5fcd 0000 a89a[ 	]+sub\.d \[\$?r12\+0\],\$?r9,\$?r8
+[ 	]+6c: R_CRIS_16_GOT_TPREL	extsym3\+0xffffff64
+[ 	]+70:	5fbd 0000 699a[ 	]+move\.d \[\$?r11\+0\],\$?r9
+[ 	]+72: R_CRIS_16_GOT_GD	extsym14\+0xffffff00
+[ 	]+76:	6fad 0000 0000 287a[ 	]+add\.d \[\$?r10\+0 <start>\],\$?r7,\$?r8
+[ 	]+78: R_CRIS_32_GOT_GD	extsym3\+0x38
+[ 	]+\.\.\.
Index: gas/testsuite/gas/cris/rd-tls-2.s
===================================================================
RCS file: gas/testsuite/gas/cris/rd-tls-2.s
diff -N gas/testsuite/gas/cris/rd-tls-2.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/cris/rd-tls-2.s	3 Oct 2008 01:37:23 -0000
@@ -0,0 +1,26 @@
+; Check that TLS PIC operands get their right relocation type.
+; First some expected uses, similar to what GCC will emit.
+	.text
+	.syntax no_register_prefix
+start:
+	move.d [r3+extsym:TPOFFGOT],r10
+	move.d extsym5:TPOFFGOT,r8
+	move.w extsym9:TPOFFGOT16,r8
+	move.d [r3+extsym:GDGOTREL],r10
+	move.d [r13+extsym13:TPOFFGOT16],r10
+	move.w extsym14:GDGOTREL16,r10
+	sub.d extsym4:DTPREL+22,r9
+	sub.w extsym4:DTPREL16-86,r3
+
+; Other for GAS valid operands (some with questionable PIC semantics).
+	sub.d [r3+extsym3:TPOFFGOT],r4,r10
+	sub.d extsym4:GDGOTREL+42,r9
+	sub.d extsym4:TPOFFGOT-96,r3
+	add.d [r10+extsym3:TPOFFGOT+56],r7,r8
+	move.d [r5+extsym6:TPOFFGOT+10],r1
+	add.d [r10+extsym3:TPOFFGOT-560],r4,r8
+	move.d [r5+extsym6:TPOFFGOT-110],r12
+	move.d [r9=r5+extsym6:TPOFFGOT-220],r12
+	sub.d [r12+extsym3:TPOFFGOT16-156],r9,r8
+	move.d [r11+extsym14:GDGOTREL16-256],r9
+	add.d [r10+extsym3:GDGOTREL+56],r7,r8
Index: gas/testsuite/gas/cris/tls-err-1.s
===================================================================
RCS file: gas/testsuite/gas/cris/tls-err-1.s
diff -N gas/testsuite/gas/cris/tls-err-1.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/cris/tls-err-1.s	3 Oct 2008 01:37:23 -0000
@@ -0,0 +1,16 @@
+; Like pic-err-1.s but for non-pic TLS suffixes.
+
+; { dg-do assemble }
+; { dg-options "--no-underscore --em=criself" }
+
+ .syntax no_register_prefix
+ .text
+start:
+ move.b extsym:TPOFF16,r4	; { dg-error "TLS relocation size does not match" "" { xfail *-*-* } }
+ move.b extsym12:TPOFF,r5	; { dg-error "TLS relocation size does not match" }
+ move.w extsym2:TPOFF,r5	; { dg-error "TLS relocation size does not match" }
+ move.d extsym3:TPOFF16,r6	; { dg-error "TLS relocation size does not match" }
+ move extsym4:TPOFF16,srp	; { dg-error "TLS relocation size does not match" }
+ move.b extsym15:GD,r7		; { dg-error "TLS relocation size does not match" }
+ move.w extsym6:GD,r5		; { dg-error "TLS relocation size does not match" }
+ move extsym8:TPOFF16,srp	; { dg-error "TLS relocation size does not match" }
Index: gas/testsuite/gas/cris/tls-err-2.s
===================================================================
RCS file: gas/testsuite/gas/cris/tls-err-2.s
diff -N gas/testsuite/gas/cris/tls-err-2.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/cris/tls-err-2.s	3 Oct 2008 01:37:23 -0000
@@ -0,0 +1,19 @@
+; Like tls-err-1.s but for PIC TLS suffixes.
+
+; { dg-do assemble }
+; { dg-options "--pic --no-underscore --em=criself" }
+
+ .syntax no_register_prefix
+ .text
+start:
+ move.b extsym:GDGOTREL16,r4	; { dg-error "PIC relocation size does not match" "" { xfail *-*-* } }
+ move.b extsym12:GDGOTREL,r5	; { dg-error "PIC relocation size does not match" }
+ move.w extsym2:GDGOTREL,r5	; { dg-error "PIC relocation size does not match" }
+ move.d extsym3:GDGOTREL16,r6	; { dg-error "PIC relocation size does not match" }
+ move extsym4:GDGOTREL16,srp	; { dg-error "PIC relocation size does not match" }
+ move.b extsym5:TPOFFGOT16,r4	; { dg-error "PIC relocation size does not match" "" { xfail *-*-* } }
+ move.b extsym15:TPOFFGOT,r7	; { dg-error "PIC relocation size does not match" }
+ move.w extsym6:DTPREL,r5	; { dg-error "PIC relocation size does not match" }
+ move.d extsym7:DTPREL16,r6	; { dg-error "PIC relocation size does not match" }
+ move.d extsym7:TPOFFGOT16,r6	; { dg-error "PIC relocation size does not match" }
+ move extsym8:TPOFFGOT16,srp	; { dg-error "PIC relocation size does not match" }
Index: gas/testsuite/gas/cris/tls-err-3.s
===================================================================
RCS file: gas/testsuite/gas/cris/tls-err-3.s
diff -N gas/testsuite/gas/cris/tls-err-3.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/cris/tls-err-3.s	3 Oct 2008 01:37:23 -0000
@@ -0,0 +1,14 @@
+; Check that TLS PIC suffixes aren't accepted when non-PIC.
+
+; { dg-do assemble }
+; { dg-options "--no-underscore --em=criself" }
+
+ .syntax no_register_prefix
+ .text
+start:
+ move.d extsym2:GDGOTREL,r5	; { dg-error "operand" }
+ move.w extsym2:GDGOTREL16,r5	; { dg-error "operand" }
+ move.d extsym1:DTPREL,r4	; { dg-error "operand" }
+ move.w extsym3:DTPREL16,r6	; { dg-error "operand" }
+ move.w extsym13:TPOFFGOT16,r10	; { dg-error "operand" }
+ move extsym4:TPOFFGOT,srp	; { dg-error "operand" }

brgds, H-P



More information about the Binutils mailing list